/src/wireshark/epan/guid-utils.c
Line | Count | Source |
1 | | /* guid-utils.c |
2 | | * GUID handling |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | |
14 | | #include <string.h> |
15 | | |
16 | | #include <glib.h> |
17 | | #include <epan/epan.h> |
18 | | #include <wsutil/unicode-utils.h> |
19 | | #include <epan/wmem_scopes.h> |
20 | | #include "guid-utils.h" |
21 | | #include "uuid_types.h" |
22 | | |
23 | | #ifdef _WIN32 |
24 | | #include <tchar.h> |
25 | | #include <windows.h> |
26 | | #include <strsafe.h> |
27 | | #endif |
28 | | |
29 | | static int guid_id; |
30 | | |
31 | | #ifdef _WIN32 |
32 | | /* try to resolve an DCE/RPC interface name to its name using the Windows registry entries */ |
33 | | /* XXX - might be better to fill all interfaces into our database at startup instead of searching each time */ |
34 | | static int |
35 | | ResolveWin32UUID(e_guid_t if_id, char *uuid_name, int uuid_name_max_len) |
36 | | { |
37 | | TCHAR *reg_uuid_name; |
38 | | HKEY hKey = NULL; |
39 | | DWORD uuid_max_size = MAX_PATH; |
40 | | TCHAR *reg_uuid_str; |
41 | | |
42 | | reg_uuid_name=wmem_alloc(NULL, (MAX_PATH*sizeof(TCHAR))+1); |
43 | | reg_uuid_str=wmem_alloc(NULL, (MAX_PATH*sizeof(TCHAR))+1); |
44 | | |
45 | | if(uuid_name_max_len < 2){ |
46 | | return 0; |
47 | | } |
48 | | reg_uuid_name[0] = '\0'; |
49 | | StringCchPrintf(reg_uuid_str, MAX_PATH, _T("SOFTWARE\\Classes\\Interface\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"), |
50 | | if_id.data1, if_id.data2, if_id.data3, |
51 | | if_id.data4[0], if_id.data4[1], |
52 | | if_id.data4[2], if_id.data4[3], |
53 | | if_id.data4[4], if_id.data4[5], |
54 | | if_id.data4[6], if_id.data4[7]); |
55 | | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_uuid_str, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { |
56 | | if (RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)reg_uuid_name, &uuid_max_size) == ERROR_SUCCESS && uuid_max_size <= MAX_PATH) { |
57 | | snprintf(uuid_name, uuid_name_max_len, "%s", utf_16to8(reg_uuid_name)); |
58 | | RegCloseKey(hKey); |
59 | | wmem_free(NULL, reg_uuid_name); |
60 | | wmem_free(NULL, reg_uuid_str); |
61 | | return (int) strlen(uuid_name); |
62 | | } |
63 | | RegCloseKey(hKey); |
64 | | } |
65 | | wmem_free(NULL, reg_uuid_name); |
66 | | wmem_free(NULL, reg_uuid_str); |
67 | | return 0; /* we didn't find anything anyhow. Please don't use the string! */ |
68 | | |
69 | | } |
70 | | #endif |
71 | | |
72 | | /* Wrapper of guid_hash to use in uuid_type_dissector_register() */ |
73 | | static unsigned |
74 | | uuid_guid_hash(const void* guid) |
75 | 7.39k | { |
76 | 7.39k | return guid_hash((const e_guid_t*)guid); |
77 | 7.39k | } |
78 | | |
79 | | /* Wrapper of guid_cmp to use in uuid_type_dissector_register() */ |
80 | | static gboolean |
81 | | uuid_guid_equal(const void* g1, const void* g2) |
82 | 1.84k | { |
83 | 1.84k | return (guid_cmp((const e_guid_t*)g1, (const e_guid_t*)g2) == 0); |
84 | 1.84k | } |
85 | | |
86 | | /* Wrapper of guids_get_guid_name to use in uuid_type_dissector_register() */ |
87 | | static const char* |
88 | | uuid_guid_to_str(void* uuid, wmem_allocator_t* scope) |
89 | 0 | { |
90 | 0 | return guids_get_guid_name((const e_guid_t*)uuid, scope); |
91 | 0 | } |
92 | | |
93 | | void |
94 | | guids_init(void) |
95 | 16 | { |
96 | 16 | guid_id = uuid_type_dissector_register("guid_global", uuid_guid_hash, uuid_guid_equal, uuid_guid_to_str); |
97 | | /* XXX here is a good place to read a config file with wellknown guids */ |
98 | 16 | } |
99 | | |
100 | | void |
101 | | guids_add_guid(const e_guid_t* guid, const char* name) |
102 | 5.00k | { |
103 | | /* The previous implementation used a wmem_tree with an array |
104 | | * of 32-bit keys, allowing callers to pass in a pointer to a |
105 | | * e_guid_t allocated on the stack. To insert into a map, the |
106 | | * e_guid_t key needs to be copied to heap-allocated memory. |
107 | | */ |
108 | 5.00k | e_guid_t* guid_key = wmem_new(wmem_epan_scope(), e_guid_t); |
109 | 5.00k | *guid_key = *guid; |
110 | 5.00k | uuid_type_insert(guid_id, (void*)guid_key, (void*)name); |
111 | 5.00k | } |
112 | | |
113 | | void |
114 | | guids_delete_guid(const e_guid_t* guid) |
115 | 0 | { |
116 | 0 | uuid_type_remove_if_present(guid_id, (void*)guid); |
117 | 0 | } |
118 | | |
119 | | const char* |
120 | | guids_get_guid_name(const e_guid_t* guid, wmem_allocator_t* scope _U_) |
121 | 2.38k | { |
122 | 2.38k | char* name; |
123 | | #ifdef _WIN32 |
124 | | static char* uuid_name; |
125 | | #endif |
126 | | |
127 | 2.38k | if ((name = (char*)uuid_type_lookup(guid_id, (void*)guid))) { |
128 | 692 | return name; |
129 | 692 | } |
130 | | |
131 | | #ifdef _WIN32 |
132 | | /* try to resolve the mapping from the Windows registry */ |
133 | | /* XXX - prefill the resolving database with all the Windows registry entries once at init only (instead of searching each time)? */ |
134 | | uuid_name = wmem_alloc(scope, 128); |
135 | | if (ResolveWin32UUID(*guid, uuid_name, 128)) { |
136 | | return uuid_name; |
137 | | } |
138 | | #endif |
139 | | |
140 | 1.69k | return NULL; |
141 | 2.38k | } |
142 | | |
143 | | const char * |
144 | | guids_resolve_guid_to_str(const e_guid_t *guid, wmem_allocator_t *scope) |
145 | 605 | { |
146 | 605 | const char *name; |
147 | | |
148 | 605 | name=guids_get_guid_name(guid, scope); |
149 | 605 | if(name){ |
150 | 406 | return name; |
151 | 406 | } |
152 | | |
153 | 199 | return wmem_strdup_printf(scope, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
154 | 199 | guid->data1, guid->data2, guid->data3, |
155 | 199 | guid->data4[0], guid->data4[1], |
156 | 199 | guid->data4[2], guid->data4[3], |
157 | 199 | guid->data4[4], guid->data4[5], |
158 | 199 | guid->data4[6], guid->data4[7]); |
159 | 605 | } |
160 | | |
161 | | int guid_cmp(const e_guid_t *g1, const e_guid_t *g2) |
162 | 1.84k | { |
163 | 1.84k | if (g1->data1 != g2->data1) { |
164 | 720 | return (g1->data1 < g2->data1) ? -1 : 1; |
165 | 720 | } |
166 | | |
167 | 1.12k | if (g1->data2 != g2->data2) { |
168 | 0 | return (g1->data2 < g2->data2) ? -1 : 1; |
169 | 0 | } |
170 | | |
171 | 1.12k | if (g1->data3 != g2->data3) { |
172 | 0 | return (g1->data3 < g2->data3) ? -1 : 1; |
173 | 0 | } |
174 | | |
175 | 1.12k | return memcmp(&g1->data4[0], &g2->data4[0], 8); |
176 | 1.12k | } |
177 | | |
178 | | unsigned guid_hash(const e_guid_t *guid) |
179 | 7.39k | { |
180 | 7.39k | return g_int64_hash((const int64_t *)guid); |
181 | 7.39k | } |
182 | | |
183 | | /* |
184 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
185 | | * |
186 | | * Local variables: |
187 | | * c-basic-offset: 8 |
188 | | * tab-width: 8 |
189 | | * indent-tabs-mode: t |
190 | | * End: |
191 | | * |
192 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
193 | | * :indentSize=8:tabSize=8:noTabs=false: |
194 | | */ |