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