| File: | builds/wireshark/wireshark/wiretap/procmon.c |
| Warning: | line 790, column 32 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /** procmon.c | |||
| 2 | * | |||
| 3 | * Implements reading of MS Procmon files | |||
| 4 | * Used a lot of information from https://github.com/eronnen/procmon-parser | |||
| 5 | * | |||
| 6 | * Wiretap Library | |||
| 7 | * Copyright (c) 1998 by Gilbert Ramirez <[email protected]> | |||
| 8 | * | |||
| 9 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
| 10 | */ | |||
| 11 | ||||
| 12 | #include "config.h" | |||
| 13 | #define WS_LOG_DOMAIN"Wiretap" LOG_DOMAIN_WIRETAP"Wiretap" | |||
| 14 | ||||
| 15 | #include "procmon.h" | |||
| 16 | #include "file_wrappers.h" | |||
| 17 | #include "wtap_module.h" | |||
| 18 | #include "pcapng_module.h" | |||
| 19 | ||||
| 20 | #include <wsutil/buffer.h> | |||
| 21 | ||||
| 22 | // To do: | |||
| 23 | // - Figure out module timestamps | |||
| 24 | // - Read the ports array? Is there any advantage to doing that vs our built in | |||
| 25 | // port number resolution? | |||
| 26 | ||||
| 27 | #pragma pack(push,1) | |||
| 28 | typedef struct procmon_header_s { | |||
| 29 | uint32_t signature; // Magic Signature - 'PML_' | |||
| 30 | uint32_t version; // Version of the PML file. 9 in the current version. | |||
| 31 | uint32_t system_bitness; // System bitness: 1 if the system is 64 bit, 0 otherwise. | |||
| 32 | uint16_t computer_name[16]; // Name of the computer (that did the capture). | |||
| 33 | uint16_t system_root_path[260]; // System root path (e.g. "C:\Windows"). | |||
| 34 | uint32_t num_events; // Total number of events in the log file. | |||
| 35 | uint64_t unused; // ? (seems to be unused) | |||
| 36 | uint64_t start_events_offset; // File offset to the start of the events array. | |||
| 37 | uint64_t event_offsets_array_offset;// File offset to an array of offsets to all the events. | |||
| 38 | uint64_t process_array_offset; // File offset to the array of processes. | |||
| 39 | uint64_t string_array_offset; // File offset to the array of strings. | |||
| 40 | uint64_t icon_array_offset; // File offset to the icons array. | |||
| 41 | uint64_t maximum_user_address; // SYSTEM_INFO.lpMaximumApplicationAddress: Maximum User Address | |||
| 42 | uint32_t os_version_info_size; // OSVERSIONINFOEXW.dwOSVersionInfoSize: sizeof(OSVERSIONINFOEXW) | |||
| 43 | uint32_t major_version; // OSVERSIONINFOEXW.dwMajorVersion: Major version number of the operating system. | |||
| 44 | uint32_t minor_version; // OSVERSIONINFOEXW.dwMinorVersion: Minor version number of the operating system. | |||
| 45 | uint32_t build_number; // OSVERSIONINFOEXW.dwBuildNumber: Build number of the operating system. | |||
| 46 | uint32_t platform_id; // OSVERSIONINFOEXW.dwPlatformId: Operating system platform. | |||
| 47 | uint16_t csd_version[128]; // OSVERSIONINFOEXW.szCSDVersion: Indicates the latest Service Pack installed. | |||
| 48 | uint16_t service_pack_major; // OSVERSIONINFOEXW.wServicePackMajor: Major version number of the latest Service Pack. | |||
| 49 | uint16_t service_pack_minor; // OSVERSIONINFOEXW.wServicePackMinor: Minor version number of the latest Service Pack. | |||
| 50 | uint16_t suite_mask; // OSVERSIONINFOEXW.wSuiteMask: Bit mask that identifies the product suites available. | |||
| 51 | uint8_t product_type; // OSVERSIONINFOEXW.wProductType: Additional information about the system. | |||
| 52 | uint8_t version_reserved; // OSVERSIONINFOEXW.wReserved: Reserved for future use. | |||
| 53 | uint32_t num_processors; // SYSTEM_INFO.dwNumberOfProcessors: Number of logical processors. | |||
| 54 | uint64_t total_physical_memory; // MEMORYSTATUSEX.ullTotalPhys: Total physical memory (in bytes). | |||
| 55 | uint64_t start_events_offset_dup; // File offset to the start of the events array (again). | |||
| 56 | uint64_t host_port_array_offset; // File offset to hosts and ports arrays. | |||
| 57 | } procmon_header_t; | |||
| 58 | ||||
| 59 | typedef enum { | |||
| 60 | PROCMON_EVENT_TYPE_UNKNOWN = 0, | |||
| 61 | PROCMON_EVENT_TYPE_PROCESS = 1, | |||
| 62 | PROCMON_EVENT_TYPE_REGISTRY = 2, | |||
| 63 | PROCMON_EVENT_TYPE_FILE_SYSTEM = 3, | |||
| 64 | PROCMON_EVENT_TYPE_PROFILING = 4, | |||
| 65 | PROCMON_EVENT_TYPE_NETWORK = 5, | |||
| 66 | } procmon_event_class_type_t; | |||
| 67 | ||||
| 68 | typedef struct procmon_event_header_s { | |||
| 69 | uint32_t process_index; // The index to the process of the event. | |||
| 70 | uint32_t thread_id; // Thread Id. | |||
| 71 | uint32_t event_class; // Event class (of type procmon_event_class_type_t) | |||
| 72 | uint16_t operation_type; // Operation type (dependent on the event class) | |||
| 73 | uint8_t unknown[6]; // Unknown | |||
| 74 | uint64_t duration; // Duration of the operation in 100 nanoseconds interval. | |||
| 75 | uint64_t timestamp; // The time when the event was captured (in FILETIME format) | |||
| 76 | uint32_t event_result; // The value of the event result. | |||
| 77 | uint16_t stack_trace_depth; // The depth of the captured stack trace. | |||
| 78 | uint16_t unknown3; // Unknown | |||
| 79 | uint32_t details_size; // The size of the specific detail structure (contains path and other details) | |||
| 80 | uint32_t extra_details_offset; // The offset from the start of the event to extra detail structure (not necessarily continuous with this structure). | |||
| 81 | ||||
| 82 | } procmon_event_header_t; | |||
| 83 | #pragma pack(pop) | |||
| 84 | ||||
| 85 | typedef struct { | |||
| 86 | uint32_t process_index; | |||
| 87 | uint32_t process_id; | |||
| 88 | uint32_t parent_process_id; | |||
| 89 | uint32_t parent_process_index; | |||
| 90 | uint64_t authentication_id; | |||
| 91 | uint32_t session_number; | |||
| 92 | uint32_t unknown1; | |||
| 93 | uint64_t start_time; // FILETIME | |||
| 94 | uint64_t end_time; // FILETIME | |||
| 95 | uint32_t is_virtualized; | |||
| 96 | uint32_t is_64_bit; | |||
| 97 | uint32_t integrity_si; | |||
| 98 | uint32_t user_name_si; | |||
| 99 | uint32_t process_name_si; | |||
| 100 | uint32_t image_path_si; | |||
| 101 | uint32_t command_line_si; | |||
| 102 | uint32_t company_si; | |||
| 103 | uint32_t version_si; | |||
| 104 | uint32_t description_si; | |||
| 105 | uint32_t icon_index_big; | |||
| 106 | uint32_t icon_index_small; | |||
| 107 | } procmon_raw_process_t; | |||
| 108 | ||||
| 109 | typedef struct { | |||
| 110 | uint32_t unknown1; | |||
| 111 | uint32_t base_address; | |||
| 112 | uint32_t size; | |||
| 113 | uint32_t image_path_si; | |||
| 114 | uint32_t version_si; | |||
| 115 | uint32_t company_si; | |||
| 116 | uint32_t description_si; | |||
| 117 | uint32_t timestamp; | |||
| 118 | uint64_t unknown2[3]; | |||
| 119 | } procmon_raw_module_32_t; | |||
| 120 | ||||
| 121 | typedef struct { | |||
| 122 | uint64_t unknown1; | |||
| 123 | uint64_t base_address; | |||
| 124 | uint32_t size; | |||
| 125 | uint32_t image_path_si; | |||
| 126 | uint32_t version_si; | |||
| 127 | uint32_t company_si; | |||
| 128 | uint32_t description_si; | |||
| 129 | uint32_t timestamp; | |||
| 130 | uint64_t unknown2[3]; | |||
| 131 | } procmon_raw_module_64_t; | |||
| 132 | ||||
| 133 | typedef struct { | |||
| 134 | procmon_header_t header; | |||
| 135 | uint32_t *event_offsets; | |||
| 136 | uint32_t cur_event; | |||
| 137 | const char **string_array; | |||
| 138 | size_t string_array_size; | |||
| 139 | uint32_t *process_index_map; /* Map of process index to process array index */ | |||
| 140 | size_t process_index_map_size; | |||
| 141 | struct procmon_process_t *process_array; | |||
| 142 | size_t process_array_size; | |||
| 143 | } procmon_file_info_t; | |||
| 144 | ||||
| 145 | #define COMMON_EVENT_STRUCT_SIZE52 52 | |||
| 146 | // Most of these are arbitrary | |||
| 147 | #define MAX_PROCMON_EVENTS(500 * 1000 * 1000) (500 * 1000 * 1000) | |||
| 148 | #define MAX_PROCMON_STRINGS(1000 * 1000) (1000 * 1000) | |||
| 149 | #define MAX_PROCMON_STRING_LENGTH8192 8192 | |||
| 150 | #define MAX_PROCMON_PROCESSES(500 * 1000) (500 * 1000) | |||
| 151 | #define MAX_PROCMON_MODULES1000 1000 | |||
| 152 | ||||
| 153 | static int procmon_file_type_subtype = -1; | |||
| 154 | ||||
| 155 | void register_procmon(void); | |||
| 156 | ||||
| 157 | static void file_info_cleanup(procmon_file_info_t* file_info) | |||
| 158 | { | |||
| 159 | g_free(file_info->event_offsets); | |||
| 160 | g_free(file_info->string_array); | |||
| 161 | g_free(file_info->process_index_map); | |||
| 162 | if (file_info->process_array
| |||
| 163 | for (size_t idx = 0; idx < file_info->process_array_size; idx++) { | |||
| 164 | g_free(file_info->process_array[idx].modules); | |||
| 165 | } | |||
| 166 | g_free(file_info->process_array); | |||
| 167 | } | |||
| 168 | g_free(file_info); | |||
| 169 | } | |||
| 170 | ||||
| 171 | static const char *procmon_string(procmon_file_info_t* file_info, uint32_t str_index) | |||
| 172 | { | |||
| 173 | if (str_index >= file_info->string_array_size) { | |||
| 174 | return "<unknown>"; | |||
| 175 | } | |||
| 176 | return file_info->string_array[str_index]; | |||
| 177 | } | |||
| 178 | ||||
| 179 | static char *procmon_read_string(FILE_T fh, gunichar2 *str_buf, int *err, char **err_info) | |||
| 180 | { | |||
| 181 | uint32_t cur_str_size; | |||
| 182 | if (!wtap_read_bytes_or_eof(fh, &cur_str_size, sizeof(cur_str_size), err, err_info)) | |||
| 183 | { | |||
| 184 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 184, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 185 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 186 | { | |||
| 187 | // Short read or EOF. | |||
| 188 | *err = 0; | |||
| 189 | g_free(*err_info); | |||
| 190 | *err_info = NULL((void*)0); | |||
| 191 | } | |||
| 192 | return NULL((void*)0); | |||
| 193 | } | |||
| 194 | cur_str_size = GUINT32_FROM_LE(cur_str_size)(((guint32) (cur_str_size))); | |||
| 195 | if (cur_str_size > MAX_PROCMON_STRING_LENGTH8192) | |||
| 196 | { | |||
| 197 | if (file_seek(fh, cur_str_size - MAX_PROCMON_STRING_LENGTH8192, SEEK_CUR1, err) == -1) | |||
| 198 | { | |||
| 199 | ws_debug("Failed to skip excess string data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 199, __func__, "Failed to skip excess string data"); } } while (0); | |||
| 200 | return NULL((void*)0); | |||
| 201 | } | |||
| 202 | ws_debug("Truncating string from %u bytes to %u", cur_str_size, MAX_PROCMON_STRING_LENGTH)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 202, __func__, "Truncating string from %u bytes to %u", cur_str_size , 8192); } } while (0); | |||
| 203 | cur_str_size = MAX_PROCMON_STRING_LENGTH8192; | |||
| 204 | } | |||
| 205 | // XXX Make sure cur_str_size is even? | |||
| 206 | if (!wtap_read_bytes_or_eof(fh, str_buf, cur_str_size, err, err_info)) | |||
| 207 | { | |||
| 208 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 208, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 209 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 210 | { | |||
| 211 | // Short read or EOF. | |||
| 212 | *err = 0; | |||
| 213 | g_free(*err_info); | |||
| 214 | *err_info = NULL((void*)0); | |||
| 215 | } | |||
| 216 | return NULL((void*)0); | |||
| 217 | } | |||
| 218 | return g_utf16_to_utf8(str_buf, cur_str_size, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
| 219 | } | |||
| 220 | ||||
| 221 | // Read the hosts array. Assume failures here are non-fatal. | |||
| 222 | static void procmon_read_hosts(wtap *wth, int64_t host_port_array_offset, int *err, char **err_info) | |||
| 223 | { | |||
| 224 | if (!(wth->add_new_ipv4 && wth->add_new_ipv6)) { | |||
| 225 | return; | |||
| 226 | } | |||
| 227 | ||||
| 228 | if (file_seek(wth->fh, host_port_array_offset, SEEK_SET0, err) == -1) | |||
| 229 | { | |||
| 230 | ws_debug("Failed to locate procmon hosts+ports data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 230, __func__, "Failed to locate procmon hosts+ports data") ; } } while (0); | |||
| 231 | return; | |||
| 232 | } | |||
| 233 | uint32_t num_hosts; | |||
| 234 | if (!wtap_read_bytes_or_eof(wth->fh, &num_hosts, sizeof(num_hosts), err, err_info)) | |||
| 235 | { | |||
| 236 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 236, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 237 | return; | |||
| 238 | } | |||
| 239 | num_hosts = GUINT32_FROM_LE(num_hosts)(((guint32) (num_hosts))); | |||
| 240 | if (num_hosts > MAX_PROCMON_STRINGS(1000 * 1000)) | |||
| 241 | { | |||
| 242 | ws_debug("Truncating hosts from %u to %u", num_hosts, MAX_PROCMON_STRINGS)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 242, __func__, "Truncating hosts from %u to %u", num_hosts, (1000 * 1000)); } } while (0); | |||
| 243 | num_hosts = MAX_PROCMON_STRINGS(1000 * 1000); | |||
| 244 | } | |||
| 245 | gunichar2 *str_buf = g_new(gunichar2, MAX_PROCMON_STRING_LENGTH)((gunichar2 *) g_malloc_n ((8192), sizeof (gunichar2))); | |||
| 246 | // Procmon appears to use the hosts table to store ASCII representations of | |||
| 247 | // addresses, so skip those. | |||
| 248 | GRegex *numeric_re = g_regex_new("^([0-9.]+|.*:.*)$", (GRegexCompileFlags)(G_REGEX_CASELESS | G_REGEX_RAW | G_REGEX_OPTIMIZE), (GRegexMatchFlags)0, NULL((void*)0)); | |||
| 249 | for (unsigned idx = 0; idx < num_hosts; idx++) | |||
| 250 | { | |||
| 251 | ws_in6_addr addr; | |||
| 252 | if (!wtap_read_bytes_or_eof(wth->fh, &addr, sizeof(addr), err, err_info)) | |||
| 253 | { | |||
| 254 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 254, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 255 | return; | |||
| 256 | } | |||
| 257 | char *name = procmon_read_string(wth->fh, str_buf, err, err_info); | |||
| 258 | if (!name) { | |||
| 259 | continue; | |||
| 260 | } | |||
| 261 | if (g_regex_match(numeric_re, name, (GRegexMatchFlags)0, NULL((void*)0))) | |||
| 262 | { | |||
| 263 | g_free(name); | |||
| 264 | continue; | |||
| 265 | } | |||
| 266 | // The PML format gives us a 16 byte blob with no indication as to | |||
| 267 | // whether or not the blob is a v4 or v6 address. Given that there are | |||
| 268 | // several pingable v6 addresses that end with 12 bytes of zeroes (at | |||
| 269 | // the time of this writing 2600::, 2409::, 2a09::, and 2a11:: are all | |||
| 270 | // pingable), let's assume that all addresses are v6 and ones that end | |||
| 271 | // with 12 bytes of zeroes are also v4. | |||
| 272 | wth->add_new_ipv6(&addr, name, false0); | |||
| 273 | if (!*(uint32_t*)(&addr.bytes[4]) && !*(uint64_t*)(&addr.bytes[8])) { | |||
| 274 | ws_in4_addr v4addr = *(uint32_t *)(&addr.bytes[4]); | |||
| 275 | wth->add_new_ipv4(v4addr, name, false0); | |||
| 276 | } | |||
| 277 | g_free(name); | |||
| 278 | } | |||
| 279 | g_regex_unref(numeric_re); | |||
| 280 | g_free(str_buf); | |||
| 281 | } | |||
| 282 | ||||
| 283 | static bool_Bool procmon_read_event(FILE_T fh, wtap_rec* rec, procmon_file_info_t* file_info, int* err, char** err_info) | |||
| 284 | { | |||
| 285 | wtapng_block_t wblock; | |||
| 286 | procmon_event_header_t event_header; | |||
| 287 | ||||
| 288 | wblock.rec = rec; | |||
| 289 | ||||
| 290 | wblock.block = wtap_block_create(WTAP_BLOCK_FT_SPECIFIC_EVENT); | |||
| 291 | ||||
| 292 | wblock.rec->presence_flags = WTAP_HAS_CAP_LEN0x00000002; | |||
| 293 | wblock.rec->tsprec = WTAP_TSPREC_NSEC9; | |||
| 294 | ||||
| 295 | /* Read the event header */ | |||
| 296 | if (!wtap_read_bytes(fh, &event_header, sizeof event_header, err, err_info)) { | |||
| 297 | ws_debug("Failed to read procmon process index")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 297, __func__, "Failed to read procmon process index"); } } while (0); | |||
| 298 | return false0; | |||
| 299 | } | |||
| 300 | ||||
| 301 | /* Append the raw data of the event header */ | |||
| 302 | ws_buffer_append(&wblock.rec->data, (const uint8_t*)&event_header, sizeof event_header); | |||
| 303 | ||||
| 304 | wblock.rec->presence_flags |= WTAP_HAS_TS0x00000001; | |||
| 305 | filetime_to_nstime(&wblock.rec->ts, GUINT64_FROM_LE(event_header.timestamp)(((guint64) (event_header.timestamp)))); | |||
| 306 | ||||
| 307 | /* Read stack trace data */ | |||
| 308 | uint32_t sizeof_stacktrace = event_header.stack_trace_depth * (file_info->header.system_bitness ? 8 : 4); | |||
| 309 | ||||
| 310 | /* Append the size of the stack trace data so the dissector doesn't need to know about system bitness */ | |||
| 311 | ws_buffer_append(&wblock.rec->data, (const uint8_t*)&sizeof_stacktrace, sizeof sizeof_stacktrace); | |||
| 312 | ||||
| 313 | if (!wtap_read_bytes_buffer(fh, &wblock.rec->data, sizeof_stacktrace, err, err_info)) { | |||
| 314 | ws_debug("Failed to read procmon stack trace data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 314, __func__, "Failed to read procmon stack trace data"); } } while (0); | |||
| 315 | return false0; | |||
| 316 | } | |||
| 317 | ||||
| 318 | /* Read detail data */ | |||
| 319 | if (!wtap_read_bytes_buffer(fh, &wblock.rec->data, event_header.details_size, err, err_info)) { | |||
| 320 | ws_debug("Failed to read procmon detail data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 320, __func__, "Failed to read procmon detail data"); } } while (0); | |||
| 321 | return false0; | |||
| 322 | } | |||
| 323 | ||||
| 324 | if (event_header.extra_details_offset > 0) | |||
| 325 | { | |||
| 326 | int64_t current_offset = file_tell(fh); | |||
| 327 | ||||
| 328 | /* The extra details structure surprisingly can be separated from the event structure */ | |||
| 329 | int64_t real_details_offset = event_header.extra_details_offset - (COMMON_EVENT_STRUCT_SIZE52 + event_header.details_size + sizeof_stacktrace); | |||
| 330 | if (file_seek(fh, real_details_offset, SEEK_CUR1, err) == -1) { | |||
| 331 | ws_debug("Failed to locate procmon extra details data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 331, __func__, "Failed to locate procmon extra details data" ); } } while (0); | |||
| 332 | return false0; | |||
| 333 | } | |||
| 334 | /* However, pass the record data up as if it's consecutive */ | |||
| 335 | uint16_t extra_details_stream_size; | |||
| 336 | if (!wtap_read_bytes(fh, &extra_details_stream_size, sizeof extra_details_stream_size, err, err_info)) { | |||
| 337 | ws_debug("Failed to read procmon extra details offset")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 337, __func__, "Failed to read procmon extra details offset" ); } } while (0); | |||
| 338 | return false0; | |||
| 339 | } | |||
| 340 | ws_buffer_append(&wblock.rec->data, (const uint8_t*)&extra_details_stream_size, sizeof extra_details_stream_size); | |||
| 341 | ||||
| 342 | if (!wtap_read_bytes_buffer(fh, &wblock.rec->data, extra_details_stream_size, err, err_info)) { | |||
| 343 | ws_debug("Failed to read procmon extra detail data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 343, __func__, "Failed to read procmon extra detail data"); } } while (0); | |||
| 344 | return false0; | |||
| 345 | } | |||
| 346 | ||||
| 347 | /* If the extra data doesn't immediately follow the other data */ | |||
| 348 | if (real_details_offset != 0) | |||
| 349 | { | |||
| 350 | if (file_seek(fh, current_offset, SEEK_SET0, err) == -1) { | |||
| 351 | ws_debug("Failed to restore procmon event data location")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 351, __func__, "Failed to restore procmon event data location" ); } } while (0); | |||
| 352 | return false0; | |||
| 353 | } | |||
| 354 | } | |||
| 355 | } | |||
| 356 | ||||
| 357 | /* | |||
| 358 | * We return these to the caller in procmon_read(). | |||
| 359 | */ | |||
| 360 | wtap_setup_ft_specific_event_rec(wblock.rec, procmon_file_type_subtype, event_header.event_class); | |||
| 361 | wblock.rec->rec_header.ft_specific_header.record_len = (uint32_t)ws_buffer_length(&wblock.rec->data); | |||
| 362 | wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.process_index_map = file_info->process_index_map; | |||
| 363 | wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.process_index_map_size = file_info->process_index_map_size; | |||
| 364 | wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.process_array = file_info->process_array; | |||
| 365 | wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.process_array_size = file_info->process_array_size; | |||
| 366 | wblock.rec->rec_header.ft_specific_header.pseudo_header.procmon.system_bitness = (file_info->header.system_bitness != 0); | |||
| 367 | wblock.internal = false0; | |||
| 368 | ||||
| 369 | /* | |||
| 370 | * We want dissectors (particularly packet_frame) to be able to | |||
| 371 | * access packet comments and whatnot that are in the block. wblock->block | |||
| 372 | * will be unref'd by procmon_seek_read(), so move the block to where | |||
| 373 | * dissectors can find it. | |||
| 374 | */ | |||
| 375 | wblock.rec->block = wblock.block; | |||
| 376 | wblock.block = NULL((void*)0); | |||
| 377 | return true1; | |||
| 378 | } | |||
| 379 | ||||
| 380 | static bool_Bool procmon_read(wtap *wth, wtap_rec *rec, | |||
| 381 | int *err, char **err_info, int64_t *data_offset) | |||
| 382 | { | |||
| 383 | procmon_file_info_t* file_info = (procmon_file_info_t*)wth->priv; | |||
| 384 | ||||
| 385 | // file.c and strato.c call wtap_set_cb_new_ipv{4,6} after calling | |||
| 386 | // wtap_open_offline, so read our hosts array here. | |||
| 387 | if (file_info->cur_event == 0) { | |||
| 388 | procmon_read_hosts(wth, file_info->header.host_port_array_offset, err, err_info); | |||
| 389 | } | |||
| 390 | ||||
| 391 | *data_offset = file_info->event_offsets[file_info->cur_event]; | |||
| 392 | ws_noisy("file offset is %" PRId64 " array offset is %" PRId64, file_tell(wth->fh), *data_offset)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/procmon.c" , 392, __func__, "file offset is %" "l" "d" " array offset is %" "l" "d", file_tell(wth->fh), *data_offset); } } while (0); | |||
| 393 | ||||
| 394 | if (file_seek(wth->fh, *data_offset, SEEK_SET0, err) == -1) | |||
| 395 | { | |||
| 396 | ws_debug("Failed to seek to event %u at offsets %" PRId64, file_info->cur_event, *data_offset)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 396, __func__, "Failed to seek to event %u at offsets %" "l" "d", file_info->cur_event, *data_offset); } } while (0); | |||
| 397 | return false0; | |||
| 398 | } | |||
| 399 | ||||
| 400 | /* Stop processing once offset reaches past events */ | |||
| 401 | if (file_info->cur_event >= file_info->header.num_events) | |||
| 402 | { | |||
| 403 | ws_debug("end of events")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 403, __func__, "end of events"); } } while (0); | |||
| 404 | return false0; | |||
| 405 | } | |||
| 406 | file_info->cur_event++; | |||
| 407 | ||||
| 408 | // if (*data_offset+COMMON_EVENT_STRUCT_SIZE >= (int64_t)file_info->header.event_offsets_array_offset) { | |||
| 409 | // *err = WTAP_ERR_BAD_FILE; | |||
| 410 | // *err_info = ws_strdup_printf("procmon: Not enough room for event content at offset %" PRIi64, *data_offset); | |||
| 411 | // return false; | |||
| 412 | // } | |||
| 413 | ||||
| 414 | return procmon_read_event(wth->fh, rec, file_info, err, err_info); | |||
| 415 | } | |||
| 416 | ||||
| 417 | static bool_Bool procmon_seek_read(wtap *wth, int64_t seek_off, wtap_rec *rec, | |||
| 418 | int *err, char **err_info) | |||
| 419 | { | |||
| 420 | procmon_file_info_t* file_info = (procmon_file_info_t*)wth->priv; | |||
| 421 | ||||
| 422 | /* seek to the right file position */ | |||
| 423 | if (file_seek(wth->random_fh, seek_off, SEEK_SET0, err) < 0) { | |||
| 424 | return false0; /* Seek error */ | |||
| 425 | } | |||
| 426 | ws_noisy("reading at offset %" PRIu64, seek_off)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_NOISY, "wiretap/procmon.c" , 426, __func__, "reading at offset %" "l" "u", seek_off); } } while (0); | |||
| 427 | ||||
| 428 | return procmon_read_event(wth->random_fh, rec, file_info, err, err_info); | |||
| 429 | } | |||
| 430 | ||||
| 431 | static const uint8_t procmon_magic[] = { 'P', 'M', 'L', '_' }; | |||
| 432 | ||||
| 433 | wtap_open_return_val procmon_open(wtap *wth, int *err, char **err_info) | |||
| 434 | { | |||
| 435 | procmon_file_info_t* file_info = g_new0(procmon_file_info_t, 1)((procmon_file_info_t *) g_malloc0_n ((1), sizeof (procmon_file_info_t ))); | |||
| 436 | procmon_header_t* header = &file_info->header; | |||
| 437 | ||||
| 438 | ws_debug("opening file")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 438, __func__, "opening file"); } } while (0); | |||
| ||||
| 439 | /* | |||
| 440 | * First, try to read the procmon header. | |||
| 441 | */ | |||
| 442 | if (!wtap_read_bytes_or_eof(wth->fh, header, sizeof(procmon_header_t), err, err_info)) | |||
| 443 | { | |||
| 444 | file_info_cleanup(file_info); | |||
| 445 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 445, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 446 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) { | |||
| 447 | /* | |||
| 448 | * Short read or EOF. | |||
| 449 | * | |||
| 450 | * We're reading this as part of an open, so | |||
| 451 | * the file is too short to be a procmon file. | |||
| 452 | */ | |||
| 453 | *err = 0; | |||
| 454 | g_free(*err_info); | |||
| 455 | *err_info = NULL((void*)0); | |||
| 456 | } | |||
| 457 | return WTAP_OPEN_NOT_MINE; | |||
| 458 | } | |||
| 459 | ||||
| 460 | if (memcmp(&header->signature, procmon_magic, sizeof(procmon_magic))) | |||
| 461 | { | |||
| 462 | file_info_cleanup(file_info); | |||
| 463 | return WTAP_OPEN_NOT_MINE; | |||
| 464 | } | |||
| 465 | ||||
| 466 | #if G_BYTE_ORDER1234 == G_BIG_ENDIAN4321 | |||
| 467 | header->version = GUINT32_SWAP_LE_BE(header->version)(((guint32) ( (((guint32) (header->version) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (header->version ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header ->version) & (guint32) 0x00ff0000U) >> 8) | (((guint32 ) (header->version) & (guint32) 0xff000000U) >> 24 )))); | |||
| 468 | header->system_bitness = GUINT32_SWAP_LE_BE(header->system_bitness)(((guint32) ( (((guint32) (header->system_bitness) & ( guint32) 0x000000ffU) << 24) | (((guint32) (header-> system_bitness) & (guint32) 0x0000ff00U) << 8) | (( (guint32) (header->system_bitness) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (header->system_bitness) & (guint32) 0xff000000U) >> 24)))); | |||
| 469 | header->num_events = GUINT32_SWAP_LE_BE(header->num_events)(((guint32) ( (((guint32) (header->num_events) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (header->num_events ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header ->num_events) & (guint32) 0x00ff0000U) >> 8) | ( ((guint32) (header->num_events) & (guint32) 0xff000000U ) >> 24)))); | |||
| 470 | header->start_events_offset = GUINT64_SWAP_LE_BE(header->start_events_offset)(((guint64) ( (((guint64) (header->start_events_offset) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64) (header->start_events_offset) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (header->start_events_offset ) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64 ) (header->start_events_offset) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (header->start_events_offset) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64 ) (header->start_events_offset) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (header->start_events_offset ) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64 ) (header->start_events_offset) & (guint64) (0xff00000000000000UL )) >> 56)))); | |||
| 471 | header->event_offsets_array_offset = GUINT64_SWAP_LE_BE(header->event_offsets_array_offset)(((guint64) ( (((guint64) (header->event_offsets_array_offset ) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64 ) (header->event_offsets_array_offset) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (header->event_offsets_array_offset ) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64 ) (header->event_offsets_array_offset) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (header->event_offsets_array_offset ) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64 ) (header->event_offsets_array_offset) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (header->event_offsets_array_offset ) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64 ) (header->event_offsets_array_offset) & (guint64) (0xff00000000000000UL )) >> 56)))); | |||
| 472 | header->process_array_offset = GUINT64_SWAP_LE_BE(header->process_array_offset)(((guint64) ( (((guint64) (header->process_array_offset) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64) (header->process_array_offset) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (header->process_array_offset ) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64 ) (header->process_array_offset) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (header->process_array_offset ) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64 ) (header->process_array_offset) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (header->process_array_offset ) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64 ) (header->process_array_offset) & (guint64) (0xff00000000000000UL )) >> 56)))); | |||
| 473 | header->string_array_offset = GUINT64_SWAP_LE_BE(header->string_array_offset)(((guint64) ( (((guint64) (header->string_array_offset) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64) (header->string_array_offset) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (header->string_array_offset ) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64 ) (header->string_array_offset) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (header->string_array_offset) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64 ) (header->string_array_offset) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (header->string_array_offset ) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64 ) (header->string_array_offset) & (guint64) (0xff00000000000000UL )) >> 56)))); | |||
| 474 | header->icon_array_offset = GUINT64_SWAP_LE_BE(header->icon_array_offset)(((guint64) ( (((guint64) (header->icon_array_offset) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64) (header->icon_array_offset) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (header->icon_array_offset) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64) (header->icon_array_offset) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (header->icon_array_offset) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64) ( header->icon_array_offset) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (header->icon_array_offset) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64) (header->icon_array_offset) & (guint64) (0xff00000000000000UL )) >> 56)))); | |||
| 475 | header->maximum_user_address = GUINT64_SWAP_LE_BE(header->maximum_user_address)(((guint64) ( (((guint64) (header->maximum_user_address) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64) (header->maximum_user_address) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (header->maximum_user_address ) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64 ) (header->maximum_user_address) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (header->maximum_user_address ) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64 ) (header->maximum_user_address) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (header->maximum_user_address ) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64 ) (header->maximum_user_address) & (guint64) (0xff00000000000000UL )) >> 56)))); | |||
| 476 | header->os_version_info_size = GUINT32_SWAP_LE_BE(header->os_version_info_size)(((guint32) ( (((guint32) (header->os_version_info_size) & (guint32) 0x000000ffU) << 24) | (((guint32) (header-> os_version_info_size) & (guint32) 0x0000ff00U) << 8 ) | (((guint32) (header->os_version_info_size) & (guint32 ) 0x00ff0000U) >> 8) | (((guint32) (header->os_version_info_size ) & (guint32) 0xff000000U) >> 24)))); | |||
| 477 | header->major_version = GUINT32_SWAP_LE_BE(header->major_version)(((guint32) ( (((guint32) (header->major_version) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (header->major_version ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header ->major_version) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (header->major_version) & (guint32) 0xff000000U ) >> 24)))); | |||
| 478 | header->minor_version = GUINT32_SWAP_LE_BE(header->minor_version)(((guint32) ( (((guint32) (header->minor_version) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (header->minor_version ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header ->minor_version) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (header->minor_version) & (guint32) 0xff000000U ) >> 24)))); | |||
| 479 | header->build_number = GUINT32_SWAP_LE_BE(header->build_number)(((guint32) ( (((guint32) (header->build_number) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (header->build_number ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header ->build_number) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (header->build_number) & (guint32) 0xff000000U ) >> 24)))); | |||
| 480 | header->platform_id = GUINT32_SWAP_LE_BE(header->platform_id)(((guint32) ( (((guint32) (header->platform_id) & (guint32 ) 0x000000ffU) << 24) | (((guint32) (header->platform_id ) & (guint32) 0x0000ff00U) << 8) | (((guint32) (header ->platform_id) & (guint32) 0x00ff0000U) >> 8) | ( ((guint32) (header->platform_id) & (guint32) 0xff000000U ) >> 24)))); | |||
| 481 | header->service_pack_major = GUINT16_SWAP_LE_BE(header->service_pack_major)(((guint16) ( (guint16) ((guint16) (header->service_pack_major ) >> 8) | (guint16) ((guint16) (header->service_pack_major ) << 8)))); | |||
| 482 | header->service_pack_minor = GUINT16_SWAP_LE_BE(header->service_pack_minor)(((guint16) ( (guint16) ((guint16) (header->service_pack_minor ) >> 8) | (guint16) ((guint16) (header->service_pack_minor ) << 8)))); | |||
| 483 | header->suite_mask = GUINT16_SWAP_LE_BE(header->suite_mask)(((guint16) ( (guint16) ((guint16) (header->suite_mask) >> 8) | (guint16) ((guint16) (header->suite_mask) << 8 )))); | |||
| 484 | header->num_processors = GUINT32_SWAP_LE_BE(header->num_processors)(((guint32) ( (((guint32) (header->num_processors) & ( guint32) 0x000000ffU) << 24) | (((guint32) (header-> num_processors) & (guint32) 0x0000ff00U) << 8) | (( (guint32) (header->num_processors) & (guint32) 0x00ff0000U ) >> 8) | (((guint32) (header->num_processors) & (guint32) 0xff000000U) >> 24)))); | |||
| 485 | header->total_physical_memory = GUINT64_SWAP_LE_BE(header->total_physical_memory)(((guint64) ( (((guint64) (header->total_physical_memory) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64) (header->total_physical_memory) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (header->total_physical_memory ) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64 ) (header->total_physical_memory) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (header->total_physical_memory ) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64 ) (header->total_physical_memory) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (header->total_physical_memory ) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64 ) (header->total_physical_memory) & (guint64) (0xff00000000000000UL )) >> 56)))); | |||
| 486 | header->start_events_offset_dup = GUINT64_SWAP_LE_BE(header->start_events_offset_dup)(((guint64) ( (((guint64) (header->start_events_offset_dup ) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64 ) (header->start_events_offset_dup) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (header->start_events_offset_dup ) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64 ) (header->start_events_offset_dup) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (header->start_events_offset_dup ) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64 ) (header->start_events_offset_dup) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (header->start_events_offset_dup ) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64 ) (header->start_events_offset_dup) & (guint64) (0xff00000000000000UL )) >> 56)))); | |||
| 487 | header->host_port_array_offset = GUINT64_SWAP_LE_BE(header->host_port_array_offset)(((guint64) ( (((guint64) (header->host_port_array_offset) & (guint64) (0x00000000000000ffUL)) << 56) | (((guint64 ) (header->host_port_array_offset) & (guint64) (0x000000000000ff00UL )) << 40) | (((guint64) (header->host_port_array_offset ) & (guint64) (0x0000000000ff0000UL)) << 24) | (((guint64 ) (header->host_port_array_offset) & (guint64) (0x00000000ff000000UL )) << 8) | (((guint64) (header->host_port_array_offset ) & (guint64) (0x000000ff00000000UL)) >> 8) | (((guint64 ) (header->host_port_array_offset) & (guint64) (0x0000ff0000000000UL )) >> 24) | (((guint64) (header->host_port_array_offset ) & (guint64) (0x00ff000000000000UL)) >> 40) | (((guint64 ) (header->host_port_array_offset) & (guint64) (0xff00000000000000UL )) >> 56)))); | |||
| 488 | #endif | |||
| 489 | ||||
| 490 | if (header->num_events > MAX_PROCMON_EVENTS(500 * 1000 * 1000)) { | |||
| 491 | ws_debug("Truncating events from %u to %u", header->num_events, MAX_PROCMON_EVENTS)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 491, __func__, "Truncating events from %u to %u", header-> num_events, (500 * 1000 * 1000)); } } while (0); | |||
| 492 | header->num_events = MAX_PROCMON_EVENTS(500 * 1000 * 1000); | |||
| 493 | } | |||
| 494 | ||||
| 495 | // Read the event offsets array, which we use in procmon_read(). It's not clear | |||
| 496 | // if we really need this; in a test capture here the offsets in the array were | |||
| 497 | // identical to the file positions we end up with if we just read sequentially. | |||
| 498 | if (file_seek(wth->fh, header->event_offsets_array_offset, SEEK_SET0, err) == -1) | |||
| 499 | { | |||
| 500 | file_info_cleanup(file_info); | |||
| 501 | ws_debug("Failed to locate event offsets data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 501, __func__, "Failed to locate event offsets data"); } } while (0); | |||
| 502 | return WTAP_OPEN_NOT_MINE; | |||
| 503 | } | |||
| 504 | file_info->event_offsets = g_new(uint32_t, header->num_events)((uint32_t *) g_malloc_n ((header->num_events), sizeof (uint32_t ))); | |||
| 505 | for (unsigned idx = 0; idx
| |||
| 506 | uint32_t event_offset; | |||
| 507 | // Each offset entry is a uint32_t offset followed by a uint8_t maybe-flags | |||
| 508 | if (!wtap_read_bytes_or_eof(wth->fh, &event_offset, sizeof(event_offset), err, err_info)) | |||
| 509 | { | |||
| 510 | file_info_cleanup(file_info); | |||
| 511 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 511, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 512 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 513 | { | |||
| 514 | // Short read or EOF. | |||
| 515 | *err = 0; | |||
| 516 | g_free(*err_info); | |||
| 517 | *err_info = NULL((void*)0); | |||
| 518 | } | |||
| 519 | return WTAP_OPEN_NOT_MINE; | |||
| 520 | } | |||
| 521 | if (file_seek(wth->fh, 1, SEEK_CUR1, err) == -1) | |||
| 522 | { | |||
| 523 | file_info_cleanup(file_info); | |||
| 524 | ws_debug("Failed to skip flags")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 524, __func__, "Failed to skip flags"); } } while (0); | |||
| 525 | return WTAP_OPEN_NOT_MINE; | |||
| 526 | } | |||
| 527 | file_info->event_offsets[idx] = GUINT32_FROM_LE(event_offset)(((guint32) (event_offset))); | |||
| 528 | } | |||
| 529 | ||||
| 530 | if (file_seek(wth->fh, header->string_array_offset, SEEK_SET0, err) == -1) | |||
| 531 | { | |||
| 532 | ws_debug("Failed to locate procmon string data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 532, __func__, "Failed to locate procmon string data"); } } while (0); | |||
| 533 | return WTAP_OPEN_NOT_MINE; | |||
| 534 | } | |||
| 535 | ||||
| 536 | uint32_t num_strings; | |||
| 537 | if (!wtap_read_bytes_or_eof(wth->fh, &num_strings, sizeof(num_strings), err, err_info)) | |||
| 538 | { | |||
| 539 | file_info_cleanup(file_info); | |||
| 540 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 540, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 541 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 542 | { | |||
| 543 | // Short read or EOF. | |||
| 544 | *err = 0; | |||
| 545 | g_free(*err_info); | |||
| 546 | *err_info = NULL((void*)0); | |||
| 547 | } | |||
| 548 | return WTAP_OPEN_NOT_MINE; | |||
| 549 | } | |||
| 550 | num_strings = GUINT32_FROM_LE(num_strings)(((guint32) (num_strings))); | |||
| 551 | if (num_strings > MAX_PROCMON_STRINGS(1000 * 1000)) { | |||
| 552 | ws_debug("Truncating strings from %u to %u", num_strings, MAX_PROCMON_STRINGS)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 552, __func__, "Truncating strings from %u to %u", num_strings , (1000 * 1000)); } } while (0); | |||
| 553 | num_strings = MAX_PROCMON_STRINGS(1000 * 1000); | |||
| 554 | } | |||
| 555 | ||||
| 556 | // Strings aren't necessarily contiguous (or even in order?) | |||
| 557 | uint32_t *str_offsets = g_new(uint32_t, num_strings)((uint32_t *) g_malloc_n ((num_strings), sizeof (uint32_t))); | |||
| 558 | if (!wtap_read_bytes_or_eof(wth->fh, str_offsets, sizeof(uint32_t) * num_strings, err, err_info)) | |||
| 559 | { | |||
| 560 | file_info_cleanup(file_info); | |||
| 561 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 561, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 562 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 563 | { | |||
| 564 | // Short read or EOF. | |||
| 565 | *err = 0; | |||
| 566 | g_free(*err_info); | |||
| 567 | *err_info = NULL((void*)0); | |||
| 568 | } | |||
| 569 | g_free(str_offsets); | |||
| 570 | return WTAP_OPEN_NOT_MINE; | |||
| 571 | } | |||
| 572 | #if G_BYTE_ORDER1234 == G_BIG_ENDIAN4321 | |||
| 573 | for (unsigned idx = 0; idx < num_strings; idx++) | |||
| 574 | { | |||
| 575 | str_offsets[idx] = GUINT32_SWAP_LE_BE(str_offsets[idx])(((guint32) ( (((guint32) (str_offsets[idx]) & (guint32) 0x000000ffU ) << 24) | (((guint32) (str_offsets[idx]) & (guint32 ) 0x0000ff00U) << 8) | (((guint32) (str_offsets[idx]) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (str_offsets [idx]) & (guint32) 0xff000000U) >> 24)))); | |||
| 576 | } | |||
| 577 | #endif | |||
| 578 | ||||
| 579 | file_info->string_array_size = num_strings; | |||
| 580 | file_info->string_array = g_new0(const char *, num_strings)((const char * *) g_malloc0_n ((num_strings), sizeof (const char *))); | |||
| 581 | gunichar2 *str_buf = g_new(gunichar2, MAX_PROCMON_STRING_LENGTH)((gunichar2 *) g_malloc_n ((8192), sizeof (gunichar2))); | |||
| 582 | for (unsigned idx = 0; idx
| |||
| 583 | if (file_seek(wth->fh, header->string_array_offset + str_offsets[idx], SEEK_SET0, err) == -1) | |||
| 584 | { | |||
| 585 | file_info_cleanup(file_info); | |||
| 586 | g_free(str_offsets); | |||
| 587 | g_free(str_buf); | |||
| 588 | ws_debug("Failed to locate procmon string %u", idx)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 588, __func__, "Failed to locate procmon string %u", idx); } } while (0); | |||
| 589 | return WTAP_OPEN_NOT_MINE; | |||
| 590 | } | |||
| 591 | ||||
| 592 | const char *cur_str = procmon_read_string(wth->fh, str_buf, err, err_info); | |||
| 593 | if (!cur_str) { | |||
| 594 | file_info_cleanup(file_info); | |||
| 595 | g_free(str_offsets); | |||
| 596 | g_free(str_buf); | |||
| 597 | ws_debug("Failed to read procmon string %u", idx)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 597, __func__, "Failed to read procmon string %u", idx); } } while (0); | |||
| 598 | return WTAP_OPEN_NOT_MINE; | |||
| 599 | } | |||
| 600 | ||||
| 601 | file_info->string_array[idx] = cur_str; | |||
| 602 | } | |||
| 603 | g_free(str_offsets); | |||
| 604 | g_free(str_buf); | |||
| 605 | ||||
| 606 | if (file_seek(wth->fh, header->process_array_offset, SEEK_SET0, err) == -1) | |||
| 607 | { | |||
| 608 | ws_debug("Failed to locate procmon process data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 608, __func__, "Failed to locate procmon process data"); } } while (0); | |||
| 609 | return WTAP_OPEN_NOT_MINE; | |||
| 610 | } | |||
| 611 | ||||
| 612 | uint32_t num_processes; | |||
| 613 | if (!wtap_read_bytes_or_eof(wth->fh, &num_processes, sizeof(num_processes), err, err_info)) | |||
| 614 | { | |||
| 615 | file_info_cleanup(file_info); | |||
| 616 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 616, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 617 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 618 | { | |||
| 619 | // Short read or EOF. | |||
| 620 | *err = 0; | |||
| 621 | g_free(*err_info); | |||
| 622 | *err_info = NULL((void*)0); | |||
| 623 | } | |||
| 624 | return WTAP_OPEN_NOT_MINE; | |||
| 625 | } | |||
| 626 | num_processes = GUINT32_FROM_LE(num_processes)(((guint32) (num_processes))); | |||
| 627 | if (num_processes > MAX_PROCMON_PROCESSES(500 * 1000)) { | |||
| 628 | ws_debug("Truncating processes from %u to %u", num_processes, MAX_PROCMON_PROCESSES)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 628, __func__, "Truncating processes from %u to %u", num_processes , (500 * 1000)); } } while (0); | |||
| 629 | num_processes = MAX_PROCMON_PROCESSES(500 * 1000); | |||
| 630 | } | |||
| 631 | ||||
| 632 | uint32_t *process_indices = g_new(uint32_t, num_processes)((uint32_t *) g_malloc_n ((num_processes), sizeof (uint32_t)) ); | |||
| 633 | if (!wtap_read_bytes_or_eof(wth->fh, process_indices, sizeof(uint32_t) * num_processes, err, err_info)) | |||
| 634 | { | |||
| 635 | file_info_cleanup(file_info); | |||
| 636 | g_free(process_indices); | |||
| 637 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 637, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 638 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 639 | { | |||
| 640 | // Short read or EOF. | |||
| 641 | *err = 0; | |||
| 642 | g_free(*err_info); | |||
| 643 | *err_info = NULL((void*)0); | |||
| 644 | } | |||
| 645 | return WTAP_OPEN_NOT_MINE; | |||
| 646 | } | |||
| 647 | ||||
| 648 | uint32_t max_process_index = 0; | |||
| 649 | for (unsigned idx = 0; idx
| |||
| 650 | process_indices[idx] = GUINT32_FROM_LE(process_indices[idx])(((guint32) (process_indices[idx]))); | |||
| 651 | max_process_index = MAX(max_process_index, process_indices[idx])(((max_process_index) > (process_indices[idx])) ? (max_process_index ) : (process_indices[idx])); | |||
| 652 | } | |||
| 653 | g_free(process_indices); | |||
| 654 | if (max_process_index > MAX_PROCMON_PROCESSES(500 * 1000) * 2) { | |||
| 655 | ws_debug("Truncating max process index from %u to %u", max_process_index, MAX_PROCMON_PROCESSES * 2)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 655, __func__, "Truncating max process index from %u to %u" , max_process_index, (500 * 1000) * 2); } } while (0); | |||
| 656 | max_process_index = MAX_PROCMON_PROCESSES(500 * 1000) * 2; | |||
| 657 | } | |||
| 658 | file_info->process_index_map = g_new(uint32_t, max_process_index + 1)((uint32_t *) g_malloc_n ((max_process_index + 1), sizeof (uint32_t ))); | |||
| 659 | // Try to make invalid entries obvious. | |||
| 660 | memset(file_info->process_index_map, 0xff, sizeof(uint32_t) * (max_process_index + 1)); | |||
| 661 | file_info->process_index_map_size = max_process_index + 1; | |||
| 662 | ||||
| 663 | uint32_t *proc_offsets = g_new(uint32_t, num_processes)((uint32_t *) g_malloc_n ((num_processes), sizeof (uint32_t)) ); | |||
| 664 | if (!wtap_read_bytes_or_eof(wth->fh, proc_offsets, sizeof(uint32_t) * num_processes, err, err_info)) | |||
| 665 | { | |||
| 666 | file_info_cleanup(file_info); | |||
| 667 | g_free(proc_offsets); | |||
| 668 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 668, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 669 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 670 | { | |||
| 671 | // Short read or EOF. | |||
| 672 | *err = 0; | |||
| 673 | g_free(*err_info); | |||
| 674 | *err_info = NULL((void*)0); | |||
| 675 | } | |||
| 676 | return WTAP_OPEN_NOT_MINE; | |||
| 677 | } | |||
| 678 | ||||
| 679 | file_info->process_array = g_new(procmon_process_t, num_processes)((procmon_process_t *) g_malloc_n ((num_processes), sizeof (procmon_process_t ))); | |||
| 680 | file_info->process_array_size = num_processes; | |||
| 681 | for (unsigned idx = 0; idx < num_processes; idx++) { | |||
| 682 | if (file_seek(wth->fh, header->process_array_offset + proc_offsets[idx], SEEK_SET0, err) == -1) | |||
| 683 | { | |||
| 684 | file_info_cleanup(file_info); | |||
| 685 | g_free(proc_offsets); | |||
| 686 | ws_debug("Failed to locate procmon process %u", idx)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 686, __func__, "Failed to locate procmon process %u", idx); } } while (0); | |||
| 687 | return WTAP_OPEN_NOT_MINE; | |||
| 688 | } | |||
| 689 | procmon_raw_process_t cur_raw_process; | |||
| 690 | if (!wtap_read_bytes_or_eof(wth->fh, &cur_raw_process, sizeof(cur_raw_process), err, err_info)) | |||
| 691 | { | |||
| 692 | file_info_cleanup(file_info); | |||
| 693 | g_free(proc_offsets); | |||
| 694 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 694, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 695 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 696 | { | |||
| 697 | // Short read or EOF. | |||
| 698 | *err = 0; | |||
| 699 | g_free(*err_info); | |||
| 700 | *err_info = NULL((void*)0); | |||
| 701 | } | |||
| 702 | return WTAP_OPEN_NOT_MINE; | |||
| 703 | } | |||
| 704 | uint32_t process_index = GUINT32_FROM_LE(cur_raw_process.process_index)(((guint32) (cur_raw_process.process_index))); | |||
| 705 | if (process_index <= max_process_index) { | |||
| 706 | file_info->process_index_map[process_index] = idx; | |||
| 707 | } else { | |||
| 708 | ws_debug("Process %u index %u exceeds max process index %u", idx, process_index, max_process_index)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 708, __func__, "Process %u index %u exceeds max process index %u" , idx, process_index, max_process_index); } } while (0); | |||
| 709 | } | |||
| 710 | procmon_process_t *cur_process = &file_info->process_array[idx]; | |||
| 711 | cur_raw_process.start_time = GUINT64_FROM_LE(cur_raw_process.start_time)(((guint64) (cur_raw_process.start_time))); | |||
| 712 | cur_raw_process.end_time = GUINT64_FROM_LE(cur_raw_process.end_time)(((guint64) (cur_raw_process.end_time))); | |||
| 713 | uint64_t filetime = GUINT64_FROM_LE(cur_raw_process.start_time)(((guint64) (cur_raw_process.start_time))); | |||
| 714 | filetime_to_nstime(&cur_process->start_time, filetime); | |||
| 715 | filetime = GUINT64_FROM_LE(cur_raw_process.end_time)(((guint64) (cur_raw_process.end_time))); | |||
| 716 | filetime_to_nstime(&cur_process->end_time, filetime); | |||
| 717 | ||||
| 718 | cur_process->process_id = GUINT32_FROM_LE(cur_raw_process.process_id)(((guint32) (cur_raw_process.process_id))); | |||
| 719 | cur_process->parent_process_id = GUINT32_FROM_LE(cur_raw_process.parent_process_id)(((guint32) (cur_raw_process.parent_process_id))); | |||
| 720 | cur_process->parent_process_index = MAX(GUINT32_FROM_LE(cur_raw_process.parent_process_index), max_process_index)((((((guint32) (cur_raw_process.parent_process_index)))) > (max_process_index)) ? ((((guint32) (cur_raw_process.parent_process_index )))) : (max_process_index)); | |||
| 721 | cur_process->authentication_id = GUINT64_FROM_LE(cur_raw_process.authentication_id)(((guint64) (cur_raw_process.authentication_id))); | |||
| 722 | cur_process->session_number = GUINT32_FROM_LE(cur_raw_process.session_number)(((guint32) (cur_raw_process.session_number))); | |||
| 723 | cur_process->is_virtualized = cur_raw_process.is_virtualized != 0; | |||
| 724 | cur_process->is_64_bit = cur_raw_process.is_64_bit != 0; | |||
| 725 | cur_process->integrity = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.integrity_si)(((guint32) (cur_raw_process.integrity_si)))); | |||
| 726 | cur_process->user_name = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.user_name_si)(((guint32) (cur_raw_process.user_name_si)))); | |||
| 727 | cur_process->process_name = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.process_name_si)(((guint32) (cur_raw_process.process_name_si)))); | |||
| 728 | cur_process->image_path = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.image_path_si)(((guint32) (cur_raw_process.image_path_si)))); | |||
| 729 | cur_process->command_line = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.command_line_si)(((guint32) (cur_raw_process.command_line_si)))); | |||
| 730 | cur_process->company = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.company_si)(((guint32) (cur_raw_process.company_si)))); | |||
| 731 | cur_process->version = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.version_si)(((guint32) (cur_raw_process.version_si)))); | |||
| 732 | cur_process->description = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_process.description_si)(((guint32) (cur_raw_process.description_si)))); | |||
| 733 | if (file_seek(wth->fh, header->system_bitness ? 8 : 4, SEEK_CUR1, err) == -1) | |||
| 734 | { | |||
| 735 | file_info_cleanup(file_info); | |||
| 736 | g_free(proc_offsets); | |||
| 737 | ws_debug("Failed to locate number of modules %u", idx)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 737, __func__, "Failed to locate number of modules %u", idx ); } } while (0); | |||
| 738 | return WTAP_OPEN_NOT_MINE; | |||
| 739 | } | |||
| 740 | uint32_t num_modules; | |||
| 741 | if (!wtap_read_bytes_or_eof(wth->fh, &num_modules, sizeof(num_modules), err, err_info)) | |||
| 742 | { | |||
| 743 | file_info_cleanup(file_info); | |||
| 744 | g_free(proc_offsets); | |||
| 745 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 745, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 746 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 747 | { | |||
| 748 | // Short read or EOF. | |||
| 749 | *err = 0; | |||
| 750 | g_free(*err_info); | |||
| 751 | *err_info = NULL((void*)0); | |||
| 752 | } | |||
| 753 | return WTAP_OPEN_NOT_MINE; | |||
| 754 | } | |||
| 755 | ||||
| 756 | cur_process->num_modules = MIN(GUINT32_FROM_LE(num_modules), MAX_PROCMON_MODULES)((((((guint32) (num_modules)))) < (1000)) ? ((((guint32) ( num_modules)))) : (1000)); | |||
| 757 | if (cur_process->num_modules
| |||
| 758 | cur_process->modules = g_new(procmon_module_t, cur_process->num_modules)((procmon_module_t *) g_malloc_n ((cur_process->num_modules ), sizeof (procmon_module_t))); | |||
| 759 | for (unsigned mod_idx = 0; mod_idx < cur_process->num_modules; mod_idx++) { | |||
| 760 | if (cur_process->is_64_bit
| |||
| 761 | procmon_raw_module_64_t cur_raw_module; | |||
| 762 | if (!wtap_read_bytes_or_eof(wth->fh, &cur_raw_module, sizeof(cur_raw_module), err, err_info)) { | |||
| 763 | file_info_cleanup(file_info); | |||
| 764 | g_free(proc_offsets); | |||
| 765 | g_free(cur_process->modules); | |||
| 766 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 766, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 767 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 768 | { | |||
| 769 | // Short read or EOF. | |||
| 770 | *err = 0; | |||
| 771 | g_free(*err_info); | |||
| 772 | *err_info = NULL((void*)0); | |||
| 773 | } | |||
| 774 | return WTAP_OPEN_NOT_MINE; | |||
| 775 | } | |||
| 776 | procmon_module_t *cur_module = &cur_process->modules[mod_idx]; | |||
| 777 | cur_module->base_address = GUINT64_FROM_LE(cur_raw_module.base_address)(((guint64) (cur_raw_module.base_address))); | |||
| 778 | cur_module->size = GUINT32_FROM_LE(cur_raw_module.size)(((guint32) (cur_raw_module.size))); | |||
| 779 | cur_module->image_path = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.image_path_si)(((guint32) (cur_raw_module.image_path_si)))); | |||
| 780 | cur_module->version = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.version_si)(((guint32) (cur_raw_module.version_si)))); | |||
| 781 | cur_module->company = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.company_si)(((guint32) (cur_raw_module.company_si)))); | |||
| 782 | cur_module->description = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.description_si)(((guint32) (cur_raw_module.description_si)))); | |||
| 783 | // filetime = GUINT64_FROM_LE(cur_raw_module.timestamp); | |||
| 784 | // filetime_to_nstime(&cur_module->timestamp, filetime); | |||
| 785 | } else { | |||
| 786 | procmon_raw_module_32_t cur_raw_module; | |||
| 787 | if (!wtap_read_bytes_or_eof(wth->fh, &cur_raw_module, sizeof(cur_raw_module), err, err_info)) { | |||
| 788 | file_info_cleanup(file_info); | |||
| 789 | g_free(proc_offsets); | |||
| 790 | g_free(cur_process->modules); | |||
| ||||
| 791 | ws_debug("wtap_read_bytes_or_eof() failed, err = %d.", *err)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 791, __func__, "wtap_read_bytes_or_eof() failed, err = %d." , *err); } } while (0); | |||
| 792 | if (*err == 0 || *err == WTAP_ERR_SHORT_READ-12) | |||
| 793 | { | |||
| 794 | // Short read or EOF. | |||
| 795 | *err = 0; | |||
| 796 | g_free(*err_info); | |||
| 797 | *err_info = NULL((void*)0); | |||
| 798 | } | |||
| 799 | return WTAP_OPEN_NOT_MINE; | |||
| 800 | } | |||
| 801 | procmon_module_t *cur_module = &cur_process->modules[mod_idx]; | |||
| 802 | cur_module->base_address = GUINT32_FROM_LE(cur_raw_module.base_address)(((guint32) (cur_raw_module.base_address))); | |||
| 803 | cur_module->size = GUINT32_FROM_LE(cur_raw_module.size)(((guint32) (cur_raw_module.size))); | |||
| 804 | cur_module->image_path = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.image_path_si)(((guint32) (cur_raw_module.image_path_si)))); | |||
| 805 | cur_module->version = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.version_si)(((guint32) (cur_raw_module.version_si)))); | |||
| 806 | cur_module->company = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.company_si)(((guint32) (cur_raw_module.company_si)))); | |||
| 807 | cur_module->description = procmon_string(file_info, GUINT32_FROM_LE(cur_raw_module.description_si)(((guint32) (cur_raw_module.description_si)))); | |||
| 808 | // filetime = GUINT64_FROM_LE(cur_raw_module.timestamp); | |||
| 809 | // filetime_to_nstime(&cur_module->timestamp, filetime); | |||
| 810 | } | |||
| 811 | } | |||
| 812 | } else { | |||
| 813 | cur_process->modules = NULL((void*)0); | |||
| 814 | } | |||
| 815 | } | |||
| 816 | g_free(proc_offsets); | |||
| 817 | ||||
| 818 | if (file_seek(wth->fh, header->start_events_offset, SEEK_SET0, err) == -1) | |||
| 819 | { | |||
| 820 | ws_debug("Failed to locate procmon events data")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_DEBUG, "wiretap/procmon.c" , 820, __func__, "Failed to locate procmon events data"); } } while (0); | |||
| 821 | return WTAP_OPEN_NOT_MINE; | |||
| 822 | } | |||
| 823 | ||||
| 824 | wth->meta_events = g_array_new(false0, false0, sizeof(wtap_block_t)); | |||
| 825 | ||||
| 826 | wth->priv = file_info; | |||
| 827 | wth->file_type_subtype = procmon_file_type_subtype; | |||
| 828 | wth->file_encap = WTAP_ENCAP_PROCMON227; | |||
| 829 | ||||
| 830 | wth->snapshot_length = 0; | |||
| 831 | wth->file_tsprec = WTAP_TSPREC_SEC0; | |||
| 832 | ||||
| 833 | wth->subtype_read = procmon_read; | |||
| 834 | wth->subtype_seek_read = procmon_seek_read; | |||
| 835 | ||||
| 836 | return WTAP_OPEN_MINE; | |||
| 837 | } | |||
| 838 | ||||
| 839 | /* Options for meta event blocks. */ | |||
| 840 | static const struct supported_option_type ft_specific_event_block_options_supported[] = { | |||
| 841 | { OPT_COMMENT1, MULTIPLE_OPTIONS_SUPPORTED }, | |||
| 842 | { OPT_CUSTOM_STR_COPY2988, MULTIPLE_OPTIONS_SUPPORTED }, | |||
| 843 | { OPT_CUSTOM_BIN_COPY2989, MULTIPLE_OPTIONS_SUPPORTED }, | |||
| 844 | { OPT_CUSTOM_STR_NO_COPY19372, MULTIPLE_OPTIONS_SUPPORTED }, | |||
| 845 | { OPT_CUSTOM_BIN_NO_COPY19373, MULTIPLE_OPTIONS_SUPPORTED } | |||
| 846 | }; | |||
| 847 | ||||
| 848 | static const struct supported_block_type procmon_blocks_supported[] = { | |||
| 849 | ||||
| 850 | /* Multiple file-type specific events (including local ones). */ | |||
| 851 | { WTAP_BLOCK_FT_SPECIFIC_EVENT, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(ft_specific_event_block_options_supported)(sizeof (ft_specific_event_block_options_supported) / sizeof ( ft_specific_event_block_options_supported)[0]), ft_specific_event_block_options_supported }, | |||
| 852 | ||||
| 853 | /* Multiple custom blocks. */ | |||
| 854 | { WTAP_BLOCK_CUSTOM, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED0, ((void*)0) }, | |||
| 855 | }; | |||
| 856 | ||||
| 857 | static const struct file_type_subtype_info procmon_info = { | |||
| 858 | "MS Procmon files", "procmon", NULL((void*)0), NULL((void*)0), | |||
| 859 | false0, BLOCKS_SUPPORTED(procmon_blocks_supported)(sizeof (procmon_blocks_supported) / sizeof (procmon_blocks_supported )[0]), procmon_blocks_supported, | |||
| 860 | NULL((void*)0), NULL((void*)0), NULL((void*)0) | |||
| 861 | }; | |||
| 862 | ||||
| 863 | void register_procmon(void) | |||
| 864 | { | |||
| 865 | procmon_file_type_subtype = wtap_register_file_type_subtype(&procmon_info); | |||
| 866 | ||||
| 867 | /* | |||
| 868 | * Register name for backwards compatibility with the | |||
| 869 | * wtap_filetypes table in Lua. | |||
| 870 | */ | |||
| 871 | wtap_register_backwards_compatibility_lua_name("Procmon", procmon_file_type_subtype); | |||
| 872 | } | |||
| 873 | ||||
| 874 | /* | |||
| 875 | * Editor modelines - https://www.wireshark.org/tools/modelines.html | |||
| 876 | * | |||
| 877 | * Local Variables: | |||
| 878 | * c-basic-offset: 4 | |||
| 879 | * tab-width: 8 | |||
| 880 | * indent-tabs-mode: nil | |||
| 881 | * End: | |||
| 882 | * | |||
| 883 | * vi: set shiftwidth=4 tabstop=8 expandtab: | |||
| 884 | * :indentSize=4:tabSize=8:noTabs=true: | |||
| 885 | */ |