├── .github
└── FUNDING.yml
├── README
├── USBPcapCMD
├── SOURCES
├── USBPcapCMD.manifest
├── USBPcapCMD.rc
├── cmd.c
├── descriptors.c
├── descriptors.h
├── enum.c
├── enum.h
├── filters.c
├── filters.h
├── getopt.c
├── getopt.h
├── iocontrol.c
├── iocontrol.h
├── roothubs.c
├── roothubs.h
├── thread.c
├── thread.h
└── version.h
├── USBPcapDriver
├── SOURCES
├── USBPcap.inx
├── USBPcap.rc
├── USBPcapBuffer.c
├── USBPcapBuffer.h
├── USBPcapDeviceControl.c
├── USBPcapFilterManager.c
├── USBPcapGenReq.c
├── USBPcapHelperFunctions.c
├── USBPcapHelperFunctions.h
├── USBPcapMain.c
├── USBPcapMain.h
├── USBPcapPnP.c
├── USBPcapPower.c
├── USBPcapQueue.c
├── USBPcapQueue.h
├── USBPcapRootHubControl.c
├── USBPcapRootHubControl.h
├── USBPcapTables.c
├── USBPcapTables.h
├── USBPcapURB.c
├── USBPcapURB.h
├── include
│ └── USBPcap.h
└── makefile.inc
├── appveyor_build.bat
├── build_release.bat
├── certificates
├── Certum Trusted Network CA.crt
├── Readme.txt
├── USBPcapTestCert.cer
├── USBPcapTestCert.pfx
├── USBPcapTestCert.pvk
└── VeriSign Class 3 Public Primary Certification Authority - G5.cer
├── config.bat
├── dirs
├── driver_attestation_signing.bat
├── driver_build.bat
├── driver_build_win7_64bit.bat
├── driver_build_win8.bat
├── nsis
├── SysRestore.dll
├── USBPcap.nsi
├── bsd-2clause.txt
├── build_installer.bat
└── gpl-2.0.txt
└── wix
├── USBPcap.wxs
├── build.bat
└── gpl-2.0.rtf
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [desowin]
2 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | USBPcap - USB Packet capture for Windows
2 |
3 | End-user installer is available at: http://desowin.org/usbpcap
4 | Following informations are intended for developers and power users only.
5 |
6 | Directory overview:
7 | USBPcapCMD - sample user space application
8 | USBPcapDriver - filter driver used to capture data
9 |
10 | Build instructions:
11 | Download and install Windows Driver Kit 7.1.0 from Microsoft
12 | http://www.microsoft.com/en-us/download/details.aspx?id=11800
13 |
14 | Adjust driver_build_win7_64bit.bat (first line of that file):
15 | * To change to checked build: replace 'fre' with 'chk'
16 | * To build for x86: replace 'x64' with 'x86'
17 | * To build for Windows XP: replace 'WIN7' with 'WXP'
18 |
19 | Windows 8 Build instructions:
20 | In order to compile for Windows 8, you need to have Visual Studio 2013
21 | Community and install Windows Driver Kit 8.1 Update.
22 | To create solution file use the following command from Visual Studio 2013
23 | Command Prompt (while being chdired into usbpcap sources directory):
24 | > Nmake2MsBuild dirs
25 |
26 | This will create solution dirs.sln. You can build the driver from the
27 | Visual Studio 2013 Command Prompt:
28 | > MSBuild dirs.sln /p:Configuration="Win8 Debug"
29 |
30 | Installation:
31 | TESTSIGNING must be enabled in order to install this driver on 64 bit
32 | Windows. To do so, issue following command (as administrator):
33 | Bcdedit.exe -set TESTSIGNING ON
34 | and reboot.
35 |
36 | Right click on the USBPcap.inf file and select Install.
37 |
38 | After installing, reboot.
39 |
40 | Usage:
41 | Currently there is no capture engine dll.
42 | You can use the USBPcapCMD.exe to select the filter instance (there is one
43 | instance per root hub) and specify the output pcap file name.
44 |
45 | Licensing:
46 | USBPcapDriver is licensed under GPLv2 license.
47 | USBPcapCMD is licensed under BSD 2-Clause license.
48 |
49 |
--------------------------------------------------------------------------------
/USBPcapCMD/SOURCES:
--------------------------------------------------------------------------------
1 | TARGETNAME = USBPcapCMD
2 | TARGETTYPE = PROGRAM
3 |
4 | _NT_TARGET_VERSION = $(_NT_TARGET_VERSION_WINXP)
5 |
6 | USE_MSVCRT = 1
7 |
8 | UMTYPE = windows
9 | UMBASE = 0x01000000
10 |
11 | SXS_APPLICATION_MANIFEST=USBPcapCMD.manifest
12 | SXS_ASSEMBLY_VERSION=1.0
13 | SXS_ASSEMBLY_NAME=USBPcapCMD
14 | SXS_ASSEMBLY_LANGUAGE=0000
15 |
16 | INCLUDES = $(DDK_INC_PATH);..\USBPcapDriver\include
17 |
18 | TARGETLIBS = $(SDK_LIB_PATH)\hid.lib \
19 | $(SDK_LIB_PATH)\setupapi.lib \
20 | $(SDK_LIB_PATH)\comdlg32.lib \
21 | $(DDK_LIB_PATH)\advapi32.lib \
22 | $(DDK_LIB_PATH)\Cfgmgr32.lib \
23 | $(DDK_LIB_PATH)\Shell32.lib \
24 | $(DDK_LIB_PATH)\Shlwapi.lib
25 |
26 | SOURCES = USBPcapCMD.rc \
27 | cmd.c \
28 | descriptors.c \
29 | enum.c \
30 | filters.c \
31 | getopt.c \
32 | iocontrol.c \
33 | roothubs.c \
34 | thread.c
35 |
--------------------------------------------------------------------------------
/USBPcapCMD/USBPcapCMD.manifest:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 | USBPcapCMD
9 |
10 |
11 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/USBPcapCMD/USBPcapCMD.rc:
--------------------------------------------------------------------------------
1 | #include "Windows.h"
2 | #include "version.h"
3 |
4 | 1 VERSIONINFO
5 | FILEVERSION USBPCAPCMD_VERSION_MAJOR,USBPCAPCMD_VERSION_MINOR,USBPCAPCMD_VERSION_REVISION,USBPCAPCMD_VERSION_BUILD
6 | PRODUCTVERSION USBPCAPCMD_VERSION_MAJOR,USBPCAPCMD_VERSION_MINOR,USBPCAPCMD_VERSION_REVISION,USBPCAPCMD_VERSION_BUILD
7 | FILEFLAGSMASK 0
8 | FILEFLAGS (VS_FF_PRIVATEBUILD|VS_FF_PRERELEASE|VS_FF_DEBUG)
9 | FILEOS VOS__WINDOWS32
10 | FILETYPE VFT_APP
11 | FILESUBTYPE 0
12 | BEGIN
13 | BLOCK "StringFileInfo"
14 | BEGIN
15 | BLOCK "040904E4"
16 | BEGIN
17 | VALUE "CompanyName", "USBPcap"
18 | VALUE "FileDescription", "USBPcap commandline interface"
19 | VALUE "FileVersion", USBPCAPCMD_VERSION_STR
20 | VALUE "InternalName", "USBPcap"
21 | VALUE "LegalCopyright", "(c) 2013-2020 Tomasz Mon"
22 | VALUE "OriginalFilename", "USBPcapCMD.exe"
23 | VALUE "ProductName", "USBPcap"
24 | VALUE "ProductVersion", USBPCAPCMD_VERSION_STR
25 | END
26 | END
27 |
28 | BLOCK "VarFileInfo"
29 | BEGIN
30 | VALUE "Translation", 0x409, 1252
31 | END
32 | END
33 |
--------------------------------------------------------------------------------
/USBPcapCMD/descriptors.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/USBPcapCMD/descriptors.c
--------------------------------------------------------------------------------
/USBPcapCMD/descriptors.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/USBPcapCMD/descriptors.h
--------------------------------------------------------------------------------
/USBPcapCMD/enum.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 | #ifndef USBPCAP_CMD_ENUM_H
8 | #define USBPCAP_CMD_ENUM_H
9 |
10 | #include
11 | #include
12 |
13 | #define EXTCAP_ARGNUM_MULTICHECK 99
14 |
15 | typedef void (*EnumConnectedPortCallback)(HANDLE hub, ULONG port, USHORT deviceAddress, PUSB_DEVICE_DESCRIPTOR desc, void *ctx);
16 |
17 | void enumerate_print_usbpcap_interactive(const char *filter);
18 | void enumerate_print_extcap_config(const char *filter);
19 | void enumerate_all_connected_devices(const char *filter, EnumConnectedPortCallback cb, void *ctx);
20 |
21 | #endif /* USBPCAP_CMD_ENUM_H */
22 |
--------------------------------------------------------------------------------
/USBPcapCMD/filters.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "filters.h"
12 |
13 | struct filters **usbpcapFilters = NULL;
14 |
15 | struct list_entry;
16 |
17 | struct list
18 | {
19 | struct list_entry *head;
20 | struct list_entry *tail;
21 | int count;
22 | };
23 |
24 | struct list_entry
25 | {
26 | char *device;
27 | struct list_entry *next;
28 | };
29 |
30 | #define BUFFER_SIZE 0x1000
31 |
32 | /* Following typedefs and defines are for UNDOCUMENTED functions */
33 | #define NTSTATUS ULONG
34 | #define STATUS_SUCCESS 0x00000000
35 |
36 | typedef struct _LSA_UNICODE_STRING
37 | {
38 | USHORT Length;
39 | USHORT MaximumLength;
40 | PWSTR Buffer;
41 | } UNICODE_STRING, *PUNICODE_STRING;
42 |
43 | typedef struct _OBJDIR_INFORMATION
44 | {
45 | UNICODE_STRING ObjectName;
46 | UNICODE_STRING ObjectTypeName;
47 | BYTE Data[1];
48 | } OBJDIR_INFORMATION, *POBJDIR_INFORMATION;
49 |
50 | typedef struct _OBJECT_ATTRIBUTES
51 | {
52 | ULONG Length;
53 | HANDLE RootDirectory;
54 | UNICODE_STRING *ObjectName;
55 | ULONG Attributes;
56 | PVOID SecurityDescriptor;
57 | PVOID SecurityQualityOfService;
58 | } OBJECT_ATTRIBUTES;
59 |
60 | typedef NTSTATUS (WINAPI* NTQUERYDIRECTORYOBJECT)(HANDLE,
61 | OBJDIR_INFORMATION*,
62 | DWORD,
63 | DWORD,
64 | DWORD,
65 | DWORD*,
66 | DWORD*);
67 |
68 | typedef NTSTATUS (WINAPI* NTOPENDIRECTORYOBJECT)(HANDLE*,
69 | DWORD,
70 | OBJECT_ATTRIBUTES*);
71 |
72 | #define InitializeObjectAttributes(p, n, a, r, s) { \
73 | (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
74 | (p)->RootDirectory = r; \
75 | (p)->Attributes = a; \
76 | (p)->ObjectName = n; \
77 | (p)->SecurityDescriptor = s; \
78 | (p)->SecurityQualityOfService = NULL; \
79 | }
80 |
81 | typedef NTSTATUS (WINAPI* NTCLOSE)(HANDLE);
82 |
83 | static HMODULE ntdll_handle;
84 | NTQUERYDIRECTORYOBJECT NtQueryDirectoryObject;
85 | NTOPENDIRECTORYOBJECT NtOpenDirectoryObject;
86 | NTCLOSE NtClose;
87 |
88 | #define DIRECTORY_QUERY 0x0001
89 |
90 | static void __cdecl unload_undocumented(void)
91 | {
92 | FreeLibrary(ntdll_handle);
93 | }
94 |
95 | /* Initialize handles to undocumented functions
96 | *
97 | * Returns TRUE on success, FALSE otherwise
98 | */
99 | static BOOL init_undocumented()
100 | {
101 | ntdll_handle = LoadLibrary(_T("ntdll.dll"));
102 |
103 | if (ntdll_handle == NULL)
104 | {
105 | return FALSE;
106 | }
107 |
108 | atexit(unload_undocumented);
109 |
110 | NtQueryDirectoryObject =
111 | (NTQUERYDIRECTORYOBJECT) GetProcAddress(ntdll_handle,
112 | "NtQueryDirectoryObject");
113 |
114 | if (NtQueryDirectoryObject == NULL)
115 | {
116 | return FALSE;
117 | }
118 |
119 | NtOpenDirectoryObject =
120 | (NTOPENDIRECTORYOBJECT) GetProcAddress(ntdll_handle,
121 | "NtOpenDirectoryObject");
122 | if (NtOpenDirectoryObject == NULL)
123 | {
124 | return FALSE;
125 | }
126 |
127 | NtClose = (NTCLOSE) GetProcAddress(ntdll_handle, "NtClose");
128 | if (NtClose == NULL)
129 | {
130 | return FALSE;
131 | }
132 |
133 | return TRUE;
134 | }
135 |
136 | /* Searches \Device for USBPcap filters.
137 | * init_undocumented() must be called prior this function.
138 | *
139 | * Returns TRUE on success, FALSE otherwise
140 | */
141 | static BOOL find_usbpcap_filters(struct list *list,
142 | void (*callback)(struct list *list,
143 | PUNICODE_STRING str))
144 | {
145 | UNICODE_STRING str;
146 | OBJECT_ATTRIBUTES attr;
147 | DWORD index;
148 | DWORD written;
149 | HANDLE handle;
150 | NTSTATUS status;
151 | POBJDIR_INFORMATION info;
152 | PWSTR path = L"\\Device";
153 |
154 | str.Length = wcslen(path)*2;
155 | str.MaximumLength = wcslen(path)*2+2;
156 | str.Buffer = path;
157 |
158 | InitializeObjectAttributes(&attr,
159 | &str,
160 | 0, /* No Attributes */
161 | NULL, /* No Root Directory */
162 | NULL); /* No Security Descriptor */
163 |
164 | index = 0;
165 | written = 0;
166 |
167 | info = (POBJDIR_INFORMATION) HeapAlloc(GetProcessHeap(),
168 | 0,
169 | BUFFER_SIZE);
170 |
171 | if (info == NULL)
172 | {
173 | fprintf(stderr, "HeapAlloc() failed\n");
174 | return FALSE;
175 | }
176 |
177 | status = NtOpenDirectoryObject(&handle,
178 | DIRECTORY_QUERY,
179 | &attr);
180 | if (status != 0)
181 | {
182 | fprintf(stderr, "NtOpenDirectoryObject() failed\n");
183 | HeapFree(GetProcessHeap(), 0, info);
184 | return FALSE;
185 | }
186 |
187 | status = NtQueryDirectoryObject(handle,
188 | info,
189 | BUFFER_SIZE,
190 | TRUE, /* Get Next Index */
191 | TRUE, /* Ignore Input Index */
192 | &index,
193 | &written);
194 |
195 | if (status != 0)
196 | {
197 | fprintf(stderr, "NtQueryDirectoryObject() failed\n");
198 | HeapFree(GetProcessHeap(), 0, info);
199 | return FALSE;
200 | }
201 |
202 | while (NtQueryDirectoryObject(handle, info, BUFFER_SIZE,
203 | TRUE, FALSE, &index, &written) == 0)
204 | {
205 | const wchar_t *prefix = L"USBPcap";
206 | size_t prefix_chars = 7;
207 |
208 | if (wcsncmp(prefix, info->ObjectName.Buffer, prefix_chars) == 0)
209 | {
210 | callback(list, &info->ObjectName);
211 | }
212 | }
213 |
214 | NtClose(handle);
215 | HeapFree(GetProcessHeap(), 0, info);
216 |
217 | return TRUE;
218 | }
219 |
220 | static void list_insert(struct list *list, struct list_entry *entry)
221 | {
222 | if (list->head == NULL)
223 | {
224 | list->head = entry;
225 | list->tail = entry;
226 | list->count = 1;
227 | }
228 | else
229 | {
230 | list->tail->next = entry;
231 | list->tail = entry;
232 | list->count++;
233 | }
234 | }
235 |
236 | static void list_free(struct list *list, BOOL free_data)
237 | {
238 | struct list_entry *entry;
239 | struct list_entry *next;
240 |
241 | entry = list->head;
242 | while (entry != NULL)
243 | {
244 | next = entry->next;
245 | if (free_data == TRUE)
246 | {
247 | free(entry->device);
248 | }
249 | free(entry);
250 | entry = next;
251 | }
252 |
253 | list->head = NULL;
254 | list->tail = NULL;
255 | list->count = 0;
256 | }
257 |
258 | static void add_to_list(struct list *list,
259 | PUNICODE_STRING str)
260 | {
261 | char *device;
262 | const char *prefix = "\\\\.\\";
263 | int prefix_len = 4;
264 | int i;
265 | int len;
266 | struct list_entry *entry;
267 |
268 | len = str->Length / sizeof(WCHAR);
269 | device = malloc(len + 1 + prefix_len);
270 |
271 | for (i = 0; i < prefix_len; i++)
272 | {
273 | device[i] = prefix[i];
274 | }
275 |
276 | for (i = 0; i < len; i++)
277 | {
278 | device[i+prefix_len] = (char)str->Buffer[i];
279 | }
280 | device[prefix_len+len] = '\0';
281 |
282 | entry = malloc(sizeof(struct list_entry));
283 | entry->device = device;
284 | entry->next = NULL;
285 |
286 | list_insert(list, entry);
287 | }
288 |
289 | void filters_initialize()
290 | {
291 | struct list list;
292 | struct list_entry *entry;
293 | int i;
294 |
295 | list.head = NULL;
296 | list.tail = NULL;
297 | list.count = 0;
298 |
299 | init_undocumented();
300 | find_usbpcap_filters(&list, add_to_list);
301 |
302 | usbpcapFilters = (struct filters**)malloc(sizeof(struct filters*) * (list.count + 1));
303 | entry = list.head;
304 | for (i = 0; i < list.count && entry != NULL; i++)
305 | {
306 | usbpcapFilters[i] = (struct filters*)malloc(sizeof(struct filters));
307 | usbpcapFilters[i]->device = entry->device;
308 |
309 | entry = entry->next;
310 | }
311 | usbpcapFilters[list.count] = NULL;
312 |
313 | list_free(&list, FALSE);
314 | }
315 |
316 | void filters_free()
317 | {
318 | int i = 0;
319 |
320 | if (usbpcapFilters == NULL)
321 | {
322 | return;
323 | }
324 |
325 | while (usbpcapFilters[i] != NULL)
326 | {
327 | free(usbpcapFilters[i]->device);
328 | free(usbpcapFilters[i]);
329 | i++;
330 | }
331 | free(usbpcapFilters);
332 | }
333 |
334 | BOOL is_usbpcap_upper_filter_installed()
335 | {
336 | LONG regVal;
337 | HKEY hkey;
338 | LONG length;
339 | DWORD type;
340 | LPTSTR multisz;
341 |
342 | PTSTR lookup = _T("\0USBPcap\0");
343 | int i, j;
344 |
345 | regVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
346 | _T("System\\CurrentControlSet\\Control\\Class\\{36FC9E60-C465-11CF-8056-444553540000}"),
347 | 0, KEY_QUERY_VALUE, &hkey);
348 |
349 | if (regVal != ERROR_SUCCESS)
350 | {
351 | fprintf(stderr, "Failed to open USB Class registry key! Code %d\n", regVal);
352 | return FALSE;
353 | }
354 |
355 | regVal = RegQueryValueEx(hkey, _T("UpperFilters"),
356 | NULL, &type, NULL, &length);
357 |
358 | if (regVal != ERROR_SUCCESS)
359 | {
360 | fprintf(stderr, "Failed to query UpperFilters value size! Code %d\n", regVal);
361 | RegCloseKey(hkey);
362 | return FALSE;
363 | }
364 |
365 | if (type != REG_MULTI_SZ)
366 | {
367 | fprintf(stderr, "Invalid UpperFilters type (%d)!\n", type);
368 | RegCloseKey(hkey);
369 | return FALSE;
370 | }
371 |
372 | if (length <= 0)
373 | {
374 | RegCloseKey(hkey);
375 | return FALSE;
376 | }
377 |
378 | multisz = (LPTSTR)malloc(length);
379 | regVal = RegQueryValueEx(hkey, _T("UpperFilters"),
380 | NULL, NULL, multisz, &length);
381 |
382 | if (regVal != ERROR_SUCCESS)
383 | {
384 | fprintf(stderr, "Failed to read UpperFilters value! Code %d\n", regVal);
385 | free(multisz);
386 | RegCloseKey(hkey);
387 | return FALSE;
388 | }
389 |
390 | RegCloseKey(hkey);
391 |
392 | /* i walks over multisz, j walks over lookup.
393 | * j starts from 1 as the multisz does not start with '\0'.
394 | */
395 | for (i = 0, j = 1; i < length; i++)
396 | {
397 | if (multisz[i] == lookup[j])
398 | {
399 | j++;
400 | if (j == 9) /* whole lookup string */
401 | {
402 | free(multisz);
403 | return TRUE;
404 | }
405 | }
406 | else
407 | {
408 | /* when first character does not match start searching from
409 | * beginning (including '\0' as it has to be new substring)
410 | */
411 | j = 0;
412 | }
413 | }
414 |
415 | free(multisz);
416 | return FALSE;
417 | }
418 |
--------------------------------------------------------------------------------
/USBPcapCMD/filters.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 | #ifndef USBPCAP_CMD_FILTERS_H
8 | #define USBPCAP_CMD_FILTERS_H
9 |
10 | struct filters
11 | {
12 | char *device; /* \\.\USBPcapX */
13 | };
14 |
15 | /* NULL-terminated array of pointers to struct filters */
16 | extern struct filters **usbpcapFilters;
17 |
18 | void filters_initialize();
19 | void filters_free();
20 |
21 | BOOL is_usbpcap_upper_filter_installed();
22 |
23 | #endif /* USBPCAP_CMD_FILTERS_H */
24 |
--------------------------------------------------------------------------------
/USBPcapCMD/getopt.h:
--------------------------------------------------------------------------------
1 | #ifndef __GETOPT_H__
2 | /**
3 | * DISCLAIMER
4 | * This file has no copyright assigned and is placed in the Public Domain.
5 | * This file is a part of the w64 mingw-runtime package.
6 | *
7 | * The w64 mingw-runtime package and its code is distributed in the hope that it
8 | * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
9 | * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
10 | * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | */
12 |
13 | #define __GETOPT_H__
14 |
15 | /* All the headers include this file. */
16 | #include
17 |
18 | #if defined( WINGETOPT_SHARED_LIB )
19 | # if defined( BUILDING_WINGETOPT_DLL )
20 | # define WINGETOPT_API __declspec(dllexport)
21 | # else
22 | # define WINGETOPT_API __declspec(dllimport)
23 | # endif
24 | #else
25 | # define WINGETOPT_API
26 | #endif
27 |
28 | #ifdef __cplusplus
29 | extern "C" {
30 | #endif
31 |
32 | WINGETOPT_API extern int optind; /* index of first non-option in argv */
33 | WINGETOPT_API extern int optopt; /* single option character, as parsed */
34 | WINGETOPT_API extern int opterr; /* flag to enable built-in diagnostics... */
35 | /* (user may set to zero, to suppress) */
36 |
37 | WINGETOPT_API extern char *optarg; /* pointer to argument of current option */
38 |
39 | extern int getopt(int nargc, char * const *nargv, const char *options);
40 |
41 | #ifdef _BSD_SOURCE
42 | /*
43 | * BSD adds the non-standard `optreset' feature, for reinitialisation
44 | * of `getopt' parsing. We support this feature, for applications which
45 | * proclaim their BSD heritage, before including this header; however,
46 | * to maintain portability, developers are advised to avoid it.
47 | */
48 | # define optreset __mingw_optreset
49 | extern int optreset;
50 | #endif
51 | #ifdef __cplusplus
52 | }
53 | #endif
54 | /*
55 | * POSIX requires the `getopt' API to be specified in `unistd.h';
56 | * thus, `unistd.h' includes this header. However, we do not want
57 | * to expose the `getopt_long' or `getopt_long_only' APIs, when
58 | * included in this manner. Thus, close the standard __GETOPT_H__
59 | * declarations block, and open an additional __GETOPT_LONG_H__
60 | * specific block, only when *not* __UNISTD_H_SOURCED__, in which
61 | * to declare the extended API.
62 | */
63 | #endif /* !defined(__GETOPT_H__) */
64 |
65 | #if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
66 | #define __GETOPT_LONG_H__
67 |
68 | #ifdef __cplusplus
69 | extern "C" {
70 | #endif
71 |
72 | struct option /* specification for a long form option... */
73 | {
74 | const char *name; /* option name, without leading hyphens */
75 | int has_arg; /* does it take an argument? */
76 | int *flag; /* where to save its status, or NULL */
77 | int val; /* its associated status value */
78 | };
79 |
80 | enum /* permitted values for its `has_arg' field... */
81 | {
82 | no_argument = 0, /* option never takes an argument */
83 | required_argument, /* option always requires an argument */
84 | optional_argument /* option may take an argument */
85 | };
86 |
87 | extern int getopt_long(int nargc, char * const *nargv, const char *options,
88 | const struct option *long_options, int *idx);
89 | extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
90 | const struct option *long_options, int *idx);
91 | /*
92 | * Previous MinGW implementation had...
93 | */
94 | #ifndef HAVE_DECL_GETOPT
95 | /*
96 | * ...for the long form API only; keep this for compatibility.
97 | */
98 | # define HAVE_DECL_GETOPT 1
99 | #endif
100 |
101 | #ifdef __cplusplus
102 | }
103 | #endif
104 |
105 | #endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
106 |
--------------------------------------------------------------------------------
/USBPcapCMD/iocontrol.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 | #include "iocontrol.h"
11 |
12 | /*
13 | * Determines range and index for given address.
14 | *
15 | * Returns TRUE on success (address is within <0; 127>), FALSE otherwise.
16 | */
17 | static BOOLEAN USBPcapGetAddressRangeAndIndex(int address, UINT8 *range, UINT8 *index)
18 | {
19 | if ((address < 0) || (address > 127))
20 | {
21 | fprintf(stderr, "Invalid address: %d\n", address);
22 | return FALSE;
23 | }
24 |
25 | *range = address / 32;
26 | *index = address % 32;
27 | return TRUE;
28 | }
29 |
30 | BOOLEAN USBPcapIsDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address)
31 | {
32 | BOOLEAN filtered = FALSE;
33 | UINT8 range;
34 | UINT8 index;
35 |
36 | if (filter->filterAll == TRUE)
37 | {
38 | /* Do not check individual bit if all devices are filtered. */
39 | return TRUE;
40 | }
41 |
42 | if (USBPcapGetAddressRangeAndIndex(address, &range, &index) == FALSE)
43 | {
44 | /* Assume that invalid addresses are filtered. */
45 | return TRUE;
46 | }
47 |
48 | if (filter->addresses[range] & (1 << index))
49 | {
50 | filtered = TRUE;
51 | }
52 |
53 | return filtered;
54 | }
55 |
56 | BOOLEAN USBPcapSetDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address)
57 | {
58 | UINT8 range;
59 | UINT8 index;
60 |
61 | if (USBPcapGetAddressRangeAndIndex(address, &range, &index) == FALSE)
62 | {
63 | return FALSE;
64 | }
65 |
66 | filter->addresses[range] |= (1 << index);
67 | return TRUE;
68 | }
69 |
70 | /*
71 | * Initializes address filter with given NULL-terminated, comma separated list of addresses.
72 | *
73 | * Returns TRUE on success, FALSE otherwise (malformed list or invalid filter pointer).
74 | */
75 | BOOLEAN USBPcapInitAddressFilter(PUSBPCAP_ADDRESS_FILTER filter, PCHAR list, BOOLEAN filterAll)
76 | {
77 | USBPCAP_ADDRESS_FILTER tmp;
78 |
79 | if (filter == NULL)
80 | {
81 | return FALSE;
82 | }
83 |
84 | memset(&tmp, 0, sizeof(USBPCAP_ADDRESS_FILTER));
85 | tmp.filterAll = filterAll;
86 |
87 | if (list != NULL)
88 | {
89 | while (*list)
90 | {
91 | if (isdigit(*list))
92 | {
93 | int number;
94 | number = atoi(list);
95 |
96 | if (USBPcapSetDeviceFiltered(&tmp, number) == FALSE)
97 | {
98 | /* Address list contains invalid address. */
99 | return FALSE;
100 | }
101 |
102 | /* Move past number. */
103 | do
104 | {
105 | list++;
106 | }
107 | while (isdigit(*list));
108 | }
109 | else if (*list == ',')
110 | {
111 | /* Found valid separator, advance to next number. */
112 | list++;
113 | }
114 | else
115 | {
116 | fprintf(stderr, "Malformed address list. Invalid character: %c.\n", *list);
117 | return FALSE;
118 | }
119 | }
120 | }
121 |
122 | /* Address list was valid. Copy resulting structure. */
123 | memcpy(filter, &tmp, sizeof(USBPCAP_ADDRESS_FILTER));
124 | return TRUE;
125 | }
126 |
--------------------------------------------------------------------------------
/USBPcapCMD/iocontrol.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 | #ifndef USBPCAP_CMD_IOCONTROL_H
8 | #define USBPCAP_CMD_IOCONTROL_H
9 |
10 | #include
11 | #include
12 | #include "USBPcap.h"
13 |
14 | BOOLEAN USBPcapIsDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address);
15 | BOOLEAN USBPcapSetDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address);
16 | BOOLEAN USBPcapInitAddressFilter(PUSBPCAP_ADDRESS_FILTER filter, PCHAR list, BOOLEAN filterAll);
17 |
18 | #endif /* USBPCAP_CMD_IOCONTROL_H */
19 |
--------------------------------------------------------------------------------
/USBPcapCMD/roothubs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Tomasz Moń
3 | *
4 | * Based on devcon sample
5 | * Copyright (c) Microsoft Corporation
6 | *
7 | * SPDX-License-Identifier: BSD-2-Clause
8 | */
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | typedef struct {
19 | LPTSTR *array;
20 | int used;
21 | int size;
22 | } StringArray;
23 |
24 | static StringArray non_standard_hwids; /* Stores non standard HWIDs. */
25 |
26 | static void init_string_array(StringArray *a, int initial_size)
27 | {
28 | a->array = (LPTSTR *)malloc(initial_size * sizeof(LPTSTR));
29 | a->used = 0;
30 | a->size = initial_size;
31 | }
32 |
33 | static void insert_string_array(StringArray *a, LPTSTR hwid)
34 | {
35 | if (a->used == a->size)
36 | {
37 | LPTSTR *tmp;
38 |
39 | a->size *= 2;
40 | tmp = (LPTSTR *)realloc(a->array, a->size * sizeof(LPTSTR));
41 | if (tmp == NULL)
42 | {
43 | fprintf(stderr, "failed to insert %s to string array!\n",
44 | hwid);
45 | return;
46 | }
47 | a->array = tmp;
48 | }
49 |
50 | a->array[a->used++] = _tcsdup(hwid);
51 | }
52 |
53 | static void free_string_array(StringArray *a)
54 | {
55 | int i;
56 | for (i = 0; i < a->used; i++)
57 | {
58 | free(a->array[i]);
59 | }
60 | free(a->array);
61 | a->array = NULL;
62 | a->used = a->size = 0;
63 | }
64 |
65 | static BOOL is_standard_hwid(LPTSTR hwid)
66 | {
67 | if (hwid == NULL)
68 | {
69 | return FALSE;
70 | }
71 | else if (_tcscmp("USB\\ROOT_HUB", hwid) == 0)
72 | {
73 | return TRUE;
74 | }
75 | else if (_tcscmp("USB\\ROOT_HUB20", hwid) == 0)
76 | {
77 | return TRUE;
78 | }
79 | else if (_tcscmp("USB\\ROOT_HUB30", hwid) == 0)
80 | {
81 | return TRUE;
82 | }
83 |
84 | return FALSE;
85 | }
86 |
87 | static void add_non_standard_hwid(LPTSTR hwid)
88 | {
89 | insert_string_array(&non_standard_hwids, hwid);
90 | }
91 |
92 | static BOOL is_non_standard_hwid_known(LPTSTR hwid)
93 | {
94 | int i;
95 | for (i = 0; i < non_standard_hwids.used; i++)
96 | {
97 | if (_tcscmp(non_standard_hwids.array[i], hwid) == 0)
98 | {
99 | return TRUE;
100 | }
101 | }
102 |
103 | return FALSE;
104 | }
105 |
106 | static PTSTR build_non_standard_reg_multi_sz(StringArray *a,
107 | int *length)
108 | {
109 | PTSTR multi_sz;
110 | PTSTR ptr;
111 |
112 | int i;
113 | int len;
114 |
115 | for (len=1, i=0; iused; i++)
116 | {
117 | len += _tcslen(a->array[i]) + 1;
118 | }
119 |
120 | len *= sizeof(TCHAR);
121 |
122 | multi_sz = malloc(len);
123 | memset(multi_sz, 0, len);
124 |
125 | for (ptr = multi_sz, i = 0; i < a->used; i++)
126 | {
127 | _tcscpy_s(ptr, len - (ptr - multi_sz), a->array[i]);
128 | ptr += _tcslen(a->array[i]) + 1;
129 | }
130 |
131 | *length = len;
132 | return multi_sz;
133 | }
134 |
135 | static void set_non_standard_hwids_reg_key(PTSTR multi_sz, int length)
136 | {
137 | HKEY hkey;
138 | LONG regVal;
139 |
140 | regVal = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
141 | _T("SYSTEM\\CurrentControlSet\\services\\USBPcap"),
142 | 0,
143 | KEY_SET_VALUE,
144 | &hkey);
145 |
146 | if (regVal == ERROR_SUCCESS)
147 | {
148 | regVal = RegSetValueEx(hkey,
149 | _T("NonStandardHWIDs"),
150 | 0,
151 | REG_MULTI_SZ,
152 | (const BYTE*)multi_sz,
153 | length);
154 |
155 | if (regVal != ERROR_SUCCESS)
156 | {
157 | fprintf(stderr, "Failed to set NonStandardHWIDs value\n");
158 | }
159 |
160 | RegCloseKey(hkey);
161 | }
162 | else
163 | {
164 | fprintf(stderr, "Failed to open USBPcap service key\n");
165 | }
166 | }
167 |
168 | /*
169 | * Returns index array for given MultiSz.
170 | *
171 | * Returns NULL-terminated array of strings on success.
172 | * Array must be freed using DelMultiSz().
173 | * Returns NULL on failure.
174 | */
175 | __drv_allocatesMem(object)
176 | static LPTSTR * GetMultiSzIndexArray(__in __drv_aliasesMem LPTSTR MultiSz)
177 | {
178 | LPTSTR scan;
179 | LPTSTR *array;
180 | int elements;
181 |
182 | for (scan = MultiSz, elements = 0; scan[0] ;elements++)
183 | {
184 | scan += lstrlen(scan)+1;
185 | }
186 | array = (LPTSTR*)malloc(sizeof(LPTSTR) * (elements+2));
187 | if(!array)
188 | {
189 | return NULL;
190 | }
191 | array[0] = MultiSz;
192 | array++;
193 | if (elements)
194 | {
195 | for (scan = MultiSz, elements = 0; scan[0]; elements++)
196 | {
197 | array[elements] = scan;
198 | scan += lstrlen(scan) + 1;
199 | }
200 | }
201 | array[elements] = NULL;
202 | return array;
203 | }
204 |
205 | /*
206 | * Retrieves multi-sz devnode registry property for given DEVINST.
207 | *
208 | * Returns NULL-terminated array of strings on success.
209 | * Array must be freed using DelMultiSz().
210 | * Returns NULL on failure.
211 | */
212 | __drv_allocatesMem(object)
213 | static LPTSTR *GetDevMultiSz(DEVINST roothub, ULONG property)
214 | {
215 | LPTSTR buffer;
216 | ULONG size;
217 | ULONG dataType;
218 | LPTSTR * array;
219 | DWORD szChars;
220 | CONFIGRET ret;
221 |
222 | size = 0;
223 | buffer = NULL;
224 |
225 | ret = CM_Get_DevNode_Registry_Property(roothub, property, &dataType,
226 | buffer, &size, 0);
227 |
228 | if (ret != CR_BUFFER_SMALL || dataType != REG_MULTI_SZ)
229 | {
230 | goto failed;
231 | }
232 |
233 | if (size == 0)
234 | {
235 | goto failed;
236 | }
237 | buffer = malloc(sizeof(TCHAR)*((size/sizeof(TCHAR))+2));
238 | if (!buffer)
239 | {
240 | goto failed;
241 | }
242 |
243 | ret = CM_Get_DevNode_Registry_Property(roothub, property, &dataType,
244 | buffer, &size, 0);
245 |
246 | if (ret == CR_SUCCESS)
247 | {
248 | szChars = size/sizeof(TCHAR);
249 | buffer[szChars] = TEXT('\0');
250 | buffer[szChars+1] = TEXT('\0');
251 | array = GetMultiSzIndexArray(buffer);
252 | if (array)
253 | {
254 | return array;
255 | }
256 | }
257 |
258 | failed:
259 | if (buffer)
260 | {
261 | free(buffer);
262 | }
263 | return NULL;
264 | }
265 |
266 | /*
267 | * Frees array allocated by GetDevMultiSz()
268 | */
269 | static void DelMultiSz(__in_opt __drv_freesMem(object) LPTSTR* Array)
270 | {
271 | if(Array)
272 | {
273 | Array--;
274 | if(Array[0])
275 | {
276 | free(Array[0]);
277 | }
278 | free(Array);
279 | }
280 | }
281 |
282 |
283 | void find_non_standard_hwids(HDEVINFO devs,
284 | PSP_DEVINFO_DATA devInfo,
285 | PSP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail)
286 | {
287 | LPTSTR *hwIds = NULL;
288 | LPTSTR *compatIds = NULL;
289 | LPTSTR *tmpIds = NULL;
290 | CONFIGRET cr;
291 | DEVINST roothub;
292 |
293 | /* Assume that all host controller children are Root Hubs */
294 | cr = CM_Get_Child(&roothub, devInfo->DevInst, 0);
295 |
296 | while (cr == CR_SUCCESS)
297 | {
298 | BOOL standard = FALSE;
299 |
300 | hwIds = GetDevMultiSz(roothub, CM_DRP_HARDWAREID);
301 | compatIds = GetDevMultiSz(roothub, CM_DRP_COMPATIBLEIDS);
302 |
303 | if (hwIds)
304 | {
305 | for (tmpIds = hwIds; tmpIds[0] != NULL; tmpIds++)
306 | {
307 | printf("Hardware ID: %s\n", tmpIds[0]);
308 | if (is_standard_hwid(tmpIds[0]) == TRUE)
309 | {
310 | printf("Found standard HWID\n");
311 | standard = TRUE;
312 | }
313 | }
314 |
315 | if (standard == FALSE)
316 | {
317 | printf("RootHub does not have standard HWID! ");
318 |
319 | if (is_non_standard_hwid_known(hwIds[0]) == TRUE)
320 | {
321 | printf("%s is already in the non-standard list.\n", hwIds[0]);
322 | }
323 | else
324 | {
325 | add_non_standard_hwid(hwIds[0]);
326 | printf("Added %s to non-standard list.\n", hwIds[0]);
327 | }
328 | }
329 | }
330 |
331 | if (compatIds)
332 | {
333 | for (tmpIds = compatIds; tmpIds[0] != NULL; tmpIds++)
334 | {
335 | printf("Compatible ID: %s\n", tmpIds[0]);
336 | }
337 | }
338 |
339 | DelMultiSz(hwIds);
340 | DelMultiSz(compatIds);
341 |
342 | cr = CM_Get_Sibling(&roothub, roothub, 0);
343 | }
344 | }
345 |
346 | void restart_device(HDEVINFO devs,
347 | PSP_DEVINFO_DATA devInfo,
348 | PSP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail)
349 | {
350 | SP_PROPCHANGE_PARAMS pcp;
351 | SP_DEVINSTALL_PARAMS devParams;
352 | TCHAR devID[MAX_DEVICE_ID_LEN];
353 |
354 | if (CM_Get_Device_ID_Ex(devInfo->DevInst, devID, MAX_DEVICE_ID_LEN, 0, devInfoListDetail->RemoteMachineHandle) != CR_SUCCESS)
355 | {
356 | devID[0] = TEXT('\0');
357 | printf("Unknown instance ID: ");
358 | }
359 | else
360 | {
361 | printf("%s: ", devID);
362 | }
363 |
364 | pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
365 | pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
366 | pcp.StateChange = DICS_PROPCHANGE;
367 | pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
368 | pcp.HwProfile = 0;
369 |
370 | if (!SetupDiSetClassInstallParams(devs, devInfo, &pcp.ClassInstallHeader, sizeof(pcp)) ||
371 | !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, devs, devInfo))
372 | {
373 | fprintf(stderr, "Failed to invoke DIF_PROPERTYCHANGE! Please reboot.\n");
374 | }
375 | else
376 | {
377 | devParams.cbSize = sizeof(devParams);
378 |
379 | if (SetupDiGetDeviceInstallParams(devs,devInfo,&devParams) &&
380 | (devParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT)))
381 | {
382 | printf("Reboot required.\n");
383 | }
384 | else
385 | {
386 | printf("Restarted.\n");
387 | }
388 | }
389 | }
390 |
391 | static void foreach_host_controller(
392 | void (*callback)(HDEVINFO devs,
393 | PSP_DEVINFO_DATA devInfo,
394 | PSP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail))
395 | {
396 | HDEVINFO devs = INVALID_HANDLE_VALUE;
397 | DWORD devIndex;
398 | SP_DEVINFO_DATA devInfo;
399 | SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
400 |
401 | devs = SetupDiGetClassDevsEx(&GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
402 | NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT,
403 | NULL, NULL, NULL);
404 |
405 | if(devs == INVALID_HANDLE_VALUE)
406 | {
407 | fprintf(stderr, "SetupDiCreateDeviceInfoListEx() failed\n");
408 | goto final;
409 | }
410 |
411 | devInfoListDetail.cbSize = sizeof(devInfoListDetail);
412 | if (!SetupDiGetDeviceInfoListDetail(devs, &devInfoListDetail))
413 | {
414 | fprintf(stderr, "SetupDiGetDeviceInfoListDetail() failed\n");
415 | goto final;
416 | }
417 |
418 | devInfo.cbSize = sizeof(devInfo);
419 | for (devIndex = 0; SetupDiEnumDeviceInfo(devs, devIndex, &devInfo); devIndex++)
420 | {
421 | callback(devs, &devInfo, &devInfoListDetail);
422 | }
423 |
424 | final:
425 | if (devs != INVALID_HANDLE_VALUE)
426 | {
427 | SetupDiDestroyDeviceInfoList(devs);
428 | }
429 | }
430 |
431 | void init_non_standard_roothub_hwid()
432 | {
433 | int length;
434 | PTSTR multi_sz;
435 |
436 | init_string_array(&non_standard_hwids, 1);
437 |
438 | foreach_host_controller(find_non_standard_hwids);
439 |
440 | if (non_standard_hwids.used > 0)
441 | {
442 | multi_sz = build_non_standard_reg_multi_sz(&non_standard_hwids, &length);
443 | set_non_standard_hwids_reg_key(multi_sz, length);
444 | free(multi_sz);
445 | }
446 |
447 | free_string_array(&non_standard_hwids);
448 | }
449 |
450 | void restart_all_usb_devices()
451 | {
452 | foreach_host_controller(restart_device);
453 | }
454 |
--------------------------------------------------------------------------------
/USBPcapCMD/roothubs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 | #ifndef USBPCAP_CMD_ROOTHUBS_H
8 | #define USBPCAP_CMD_ROOTHUBS_H
9 |
10 | void init_non_standard_roothub_hwid();
11 | void restart_all_usb_devices();
12 |
13 | #endif /* USBPCAP_CMD_ROOTHUBS_H */
14 |
--------------------------------------------------------------------------------
/USBPcapCMD/thread.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "USBPcap.h"
12 | #include "thread.h"
13 | #include "iocontrol.h"
14 | #include "descriptors.h"
15 |
16 | HANDLE create_filter_read_handle(struct thread_data *data)
17 | {
18 | HANDLE filter_handle = INVALID_HANDLE_VALUE;
19 | char* inBuf = NULL;
20 | DWORD inBufSize = 0;
21 | DWORD bytes_ret;
22 |
23 | if (data->capture_new)
24 | {
25 | USBPcapSetDeviceFiltered(&data->filter, 0);
26 | }
27 |
28 | filter_handle = CreateFileA(data->device,
29 | GENERIC_READ|GENERIC_WRITE,
30 | 0,
31 | 0,
32 | OPEN_EXISTING,
33 | FILE_FLAG_OVERLAPPED,
34 | 0);
35 |
36 | if (filter_handle == INVALID_HANDLE_VALUE)
37 | {
38 | fprintf(stderr, "Couldn't open device - %d\n", GetLastError());
39 | goto finish;
40 | }
41 |
42 | inBuf = malloc(sizeof(USBPCAP_IOCTL_SIZE));
43 | ((PUSBPCAP_IOCTL_SIZE)inBuf)->size = data->snaplen;
44 | inBufSize = sizeof(USBPCAP_IOCTL_SIZE);
45 |
46 | if (!DeviceIoControl(filter_handle,
47 | IOCTL_USBPCAP_SET_SNAPLEN_SIZE,
48 | inBuf,
49 | inBufSize,
50 | NULL,
51 | 0,
52 | &bytes_ret,
53 | 0))
54 | {
55 | fprintf(stderr, "DeviceIoControl failed with %d status (supplimentary code %d)\n",
56 | GetLastError(),
57 | bytes_ret);
58 | goto finish;
59 | }
60 |
61 | ((PUSBPCAP_IOCTL_SIZE)inBuf)->size = data->bufferlen;
62 |
63 | if (!DeviceIoControl(filter_handle,
64 | IOCTL_USBPCAP_SETUP_BUFFER,
65 | inBuf,
66 | inBufSize,
67 | NULL,
68 | 0,
69 | &bytes_ret,
70 | 0))
71 | {
72 | fprintf(stderr, "DeviceIoControl failed with %d status (supplimentary code %d)\n",
73 | GetLastError(),
74 | bytes_ret);
75 | goto finish;
76 | }
77 |
78 | if (!DeviceIoControl(filter_handle,
79 | IOCTL_USBPCAP_START_FILTERING,
80 | (char*)&data->filter,
81 | sizeof(USBPCAP_ADDRESS_FILTER),
82 | NULL,
83 | 0,
84 | &bytes_ret,
85 | 0))
86 | {
87 | fprintf(stderr, "DeviceIoControl failed with %d status (supplimentary code %d)\n",
88 | GetLastError(),
89 | bytes_ret);
90 | goto finish;
91 | }
92 |
93 | free(inBuf);
94 | return filter_handle;
95 |
96 | finish:
97 | if (inBuf != NULL)
98 | {
99 | free(inBuf);
100 | }
101 |
102 | if (filter_handle != INVALID_HANDLE_VALUE)
103 | {
104 | CloseHandle(filter_handle);
105 | }
106 |
107 | return INVALID_HANDLE_VALUE;
108 | }
109 |
110 | static void write_data(struct thread_data* data, LPOVERLAPPED write_overlapped,
111 | void *buffer, DWORD bytes)
112 | {
113 | /* Write data to the end of the file. */
114 | write_overlapped->Offset = 0xFFFFFFFF;
115 | write_overlapped->OffsetHigh = 0xFFFFFFFF;
116 | if (!WriteFile(data->write_handle, buffer, bytes, NULL, write_overlapped))
117 | {
118 | DWORD err = GetLastError();
119 | if (err == ERROR_IO_PENDING)
120 | {
121 | DWORD written;
122 | if (!GetOverlappedResult(data->write_handle, write_overlapped, &written, TRUE))
123 | {
124 | fprintf(stderr, "GetOverlappedResult() on write handle failed: %d\n", GetLastError());
125 | }
126 | else if (written != bytes)
127 | {
128 | fprintf(stderr, "Wrote %d bytes instead of %d. Stopping capture.\n", written, bytes);
129 | data->process = FALSE;
130 | }
131 | }
132 | else
133 | {
134 | /* Failed to write to output. Quit. */
135 | fprintf(stderr, "Write failed (%d). Stopping capture.\n", err);
136 | data->process = FALSE;
137 | }
138 | }
139 | FlushFileBuffers(data->write_handle);
140 | ResetEvent(write_overlapped->hEvent);
141 | }
142 |
143 | static void process_data(struct thread_data* data, LPOVERLAPPED write_overlapped,
144 | unsigned char *buffer, DWORD bytes)
145 | {
146 | if (data->descriptors.buf_written < sizeof(pcap_hdr_t))
147 | {
148 | DWORD to_write = sizeof(pcap_hdr_t) - data->descriptors.buf_written;
149 | if (to_write > bytes)
150 | {
151 | to_write = bytes;
152 | }
153 | memcpy(&data->descriptors.buf[data->descriptors.buf_written], buffer, to_write);
154 | data->descriptors.buf_written += to_write;
155 |
156 | if (data->descriptors.buf_written == sizeof(pcap_hdr_t))
157 | {
158 | pcap_hdr_t *hdr = (pcap_hdr_t *)data->descriptors.buf;
159 | write_data(data, write_overlapped, data->descriptors.buf, sizeof(pcap_hdr_t));
160 | if ((hdr->magic_number == 0xA1B2C3D4) && (hdr->network == DLT_USBPCAP) && (data->descriptors.descriptors_len > 0))
161 | {
162 | write_data(data, write_overlapped, data->descriptors.descriptors, data->descriptors.descriptors_len);
163 | }
164 | }
165 | buffer += to_write;
166 | bytes -= to_write;
167 |
168 | if (bytes == 0)
169 | {
170 | /* Nothing more to write */
171 | return;
172 | }
173 | }
174 | write_data(data, write_overlapped, buffer, bytes);
175 | }
176 |
177 | DWORD WINAPI read_thread(LPVOID param)
178 | {
179 | struct thread_data* data = (struct thread_data*)param;
180 | unsigned char* buffer;
181 | DWORD dummy_read;
182 | unsigned char dummy_buf;
183 | OVERLAPPED read_overlapped;
184 | OVERLAPPED write_overlapped;
185 | OVERLAPPED connect_overlapped;
186 | OVERLAPPED write_handle_read_overlapped; /* Used to detect broken pipe. */
187 | DWORD read;
188 | DWORD err;
189 | HANDLE table[5];
190 | int table_count = 0;
191 |
192 | memset(&table, 0, sizeof(table));
193 |
194 | buffer = malloc(data->bufferlen);
195 | if (buffer == NULL)
196 | {
197 | fprintf(stderr, "Failed to allocate user-mode buffer (length %d)\n",
198 | data->bufferlen);
199 | goto finish;
200 | }
201 |
202 | if (data->read_handle == INVALID_HANDLE_VALUE)
203 | {
204 | fprintf(stderr, "Thread started with invalid read handle!\n");
205 | goto finish;
206 | }
207 |
208 | if (data->write_handle == INVALID_HANDLE_VALUE)
209 | {
210 | fprintf(stderr, "Thread started with invalid write handle!\n");
211 | goto finish;
212 | }
213 |
214 | memset(&read_overlapped, 0, sizeof(read_overlapped));
215 | memset(&connect_overlapped, 0, sizeof(connect_overlapped));
216 | memset(&write_overlapped, 0, sizeof(write_overlapped));
217 | memset(&write_handle_read_overlapped, 0, sizeof(write_handle_read_overlapped));
218 | read_overlapped.hEvent = CreateEvent(NULL,
219 | TRUE /* Manual Reset */,
220 | FALSE /* Default non signaled */,
221 | NULL /* No name */);
222 | connect_overlapped.hEvent = CreateEvent(NULL,
223 | TRUE /* Manual Reset */,
224 | FALSE /* Default non signaled */,
225 | NULL /* No name */);
226 | write_overlapped.hEvent = CreateEvent(NULL,
227 | TRUE /* Manual Reset */,
228 | FALSE /* Default non signaled */,
229 | NULL /* No name */);
230 | write_handle_read_overlapped.hEvent = CreateEvent(NULL,
231 | TRUE /* Manual Reset */,
232 | FALSE /* Default non signaled */,
233 | NULL /* No name */);
234 | table[table_count] = read_overlapped.hEvent;
235 | table_count++;
236 | table[table_count] = write_overlapped.hEvent;
237 | table_count++;
238 | if (GetFileType(data->write_handle) == FILE_TYPE_PIPE)
239 | {
240 | /* Setup dummy reads from write handle so we can detect broken pipe
241 | * even ifthere isn't any data read from read handle.
242 | */
243 | table[table_count] = write_handle_read_overlapped.hEvent;
244 | table_count++;
245 | ReadFile(data->write_handle, &dummy_buf, sizeof(dummy_buf), NULL, &write_handle_read_overlapped);
246 | }
247 | if (data->exit_event != INVALID_HANDLE_VALUE)
248 | {
249 | table[table_count] = data->exit_event;
250 | table_count++;
251 | }
252 |
253 | if (GetFileType(data->read_handle) == FILE_TYPE_PIPE)
254 | {
255 | table[table_count] = connect_overlapped.hEvent;
256 | table_count++;
257 | if (!ConnectNamedPipe(data->read_handle, &connect_overlapped))
258 | {
259 | err = GetLastError();
260 | if ((err != ERROR_IO_PENDING) && (err != ERROR_PIPE_CONNECTED))
261 | {
262 | fprintf(stderr, "ConnectNamedPipe() failed with code %d\n", err);
263 | data->process = FALSE;
264 | }
265 | }
266 | }
267 | else
268 | {
269 | ReadFile(data->read_handle, (PVOID)buffer, data->bufferlen, NULL, &read_overlapped);
270 | }
271 |
272 | for (; data->process == TRUE;)
273 | {
274 | DWORD dw;
275 |
276 | dw = WaitForMultipleObjects(table_count,
277 | table,
278 | FALSE,
279 | INFINITE);
280 | #pragma warning(default : 4296)
281 | if ((dw >= WAIT_OBJECT_0) && dw < (WAIT_OBJECT_0 + table_count))
282 | {
283 | int i = dw - WAIT_OBJECT_0;
284 | if (table[i] == read_overlapped.hEvent)
285 | {
286 | GetOverlappedResult(data->read_handle, &read_overlapped, &read, TRUE);
287 | ResetEvent(read_overlapped.hEvent);
288 | process_data(data, &write_overlapped, buffer, read);
289 | /* Start new read. */
290 | ReadFile(data->read_handle, (PVOID)buffer, data->bufferlen, &read, &read_overlapped);
291 | }
292 | else if (table[i] == write_overlapped.hEvent)
293 | {
294 | ResetEvent(write_overlapped.hEvent);
295 | }
296 | else if (table[i] == write_handle_read_overlapped.hEvent)
297 | {
298 | /* Most likely broken pipe detected */
299 | GetOverlappedResult(data->write_handle, &write_handle_read_overlapped, &dummy_read, TRUE);
300 | err = GetLastError();
301 | ResetEvent(write_handle_read_overlapped.hEvent);
302 | if (err == ERROR_BROKEN_PIPE)
303 | {
304 | /* We should quit. */
305 | data->process = FALSE;
306 | }
307 | else
308 | {
309 | /* Don't care about result. Start read again. */
310 | ReadFile(data->write_handle, &dummy_buf, sizeof(dummy_buf), NULL, &write_handle_read_overlapped);
311 | }
312 | }
313 | else if (table[i] == data->exit_event)
314 | {
315 | /* We should quit as exit_event is set. */
316 | data->process = FALSE;
317 | }
318 | else if (table[i] == connect_overlapped.hEvent)
319 | {
320 | ResetEvent(connect_overlapped.hEvent);
321 | /* Start reading data. */
322 | ReadFile(data->read_handle, (PVOID)buffer, data->bufferlen, &read, &read_overlapped);
323 | }
324 | }
325 | else if (dw == WAIT_FAILED)
326 | {
327 | fprintf(stderr, "WaitForMultipleObjects failed in read_thread(): %d", GetLastError());
328 | break;
329 | }
330 | }
331 |
332 | CancelIo(data->read_handle);
333 | CancelIo(data->write_handle);
334 | CloseHandle(read_overlapped.hEvent);
335 | CloseHandle(connect_overlapped.hEvent);
336 | CloseHandle(write_overlapped.hEvent);
337 | CloseHandle(write_handle_read_overlapped.hEvent);
338 |
339 | finish:
340 | if (buffer != NULL)
341 | {
342 | free(buffer);
343 | }
344 |
345 | /* Notify main thread that we are done.
346 | * If we are exiting due to exit_event being set by another thread,
347 | * setting the exit_event here isn't a problem (it is already set).
348 | */
349 | if (data->exit_event != INVALID_HANDLE_VALUE)
350 | {
351 | SetEvent(data->exit_event);
352 | }
353 |
354 | return 0;
355 | }
356 |
--------------------------------------------------------------------------------
/USBPcapCMD/thread.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 | #ifndef USBPCAP_CMD_THREAD_H
8 | #define USBPCAP_CMD_THREAD_H
9 |
10 | #include
11 | #include "USBPcap.h"
12 |
13 | struct inject_descriptors
14 | {
15 | void *descriptors; /* Packets to inject after pcap header on capture start */
16 | int descriptors_len; /* inject_packets length in bytes */
17 |
18 | /* Buffer to keep track of pcap data read from driver. Once it is filled, the magic
19 | * and DLT is checked and if it matches, the the inject_packets are written after
20 | * the header and then the normal capture continues.
21 | */
22 | unsigned char buf[sizeof(pcap_hdr_t)];
23 | int buf_written;
24 | };
25 |
26 | struct thread_data
27 | {
28 | char *device; /* Filter device object name */
29 | char *filename; /* Output filename */
30 | char *address_list; /* Comma separated list with addresses of device to capture. */
31 | USBPCAP_ADDRESS_FILTER filter; /* Addresses that should be filtered */
32 | BOOLEAN capture_all; /* TRUE if all devices should be captured despite address_list. */
33 | BOOLEAN capture_new; /* TRUE if we should automatically capture from new devices. */
34 | UINT32 snaplen; /* Snapshot length */
35 | UINT32 bufferlen; /* Internal kernel-mode buffer size */
36 | volatile BOOL process; /* FALSE if thread should stop */
37 | HANDLE read_handle; /* Handle to read data from. */
38 | HANDLE write_handle; /* Handle to write data to. */
39 | HANDLE job_handle; /* Handle to job object of worker process. */
40 | HANDLE worker_process_thread; /* Handle to breakaway worker process main thread. */
41 | HANDLE exit_event; /* Handle to event that indicates that main thread should exit. */
42 |
43 | BOOLEAN inject_descriptors; /* TRUE if descriptors should be injected into capture. */
44 | struct inject_descriptors descriptors;
45 | };
46 |
47 | HANDLE create_filter_read_handle(struct thread_data *data);
48 | DWORD WINAPI read_thread(LPVOID param);
49 |
50 | #endif /* USBPCAP_CMD_THREAD_H */
51 |
--------------------------------------------------------------------------------
/USBPcapCMD/version.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 |
8 | #ifndef USBPCAPCMD_VERSION_H
9 | #define USBPCAPCMD_VERSION_H
10 |
11 | #define USBPCAPCMD_VERSION_MAJOR 1
12 | #define USBPCAPCMD_VERSION_MINOR 5
13 | #define USBPCAPCMD_VERSION_REVISION 4
14 | #define USBPCAPCMD_VERSION_BUILD 0
15 |
16 | #define makeStr(x) #x
17 | #define makeString(x) makeStr(x)
18 |
19 | #define USBPCAPCMD_VERSION_STR \
20 | makeString(USBPCAPCMD_VERSION_MAJOR) "." \
21 | makeString(USBPCAPCMD_VERSION_MINOR) "." \
22 | makeString(USBPCAPCMD_VERSION_REVISION) "." \
23 | makeString(USBPCAPCMD_VERSION_BUILD)
24 |
25 | #endif /* USBPCAPCMD_VERSION_H */
26 |
--------------------------------------------------------------------------------
/USBPcapDriver/SOURCES:
--------------------------------------------------------------------------------
1 | TARGETNAME = USBPcap
2 |
3 | TARGETTYPE = DRIVER
4 |
5 | DRIVERTYPE = WDM
6 |
7 | INF_NAME=USBPcap
8 | USBPCAP_VERSION=1.5.4.0
9 | NTTARGETFILE2=$(OBJ_PATH)\$(O)\$(INF_NAME).inf
10 |
11 | TARGETLIBS = $(DDK_LIB_PATH)\Wdm.lib \
12 | $(DDK_LIB_PATH)\Wdmsec.lib \
13 | $(DDK_LIB_PATH)\Ntstrsafe.lib \
14 | $(DDK_LIB_PATH)\Ntoskrnl.lib \
15 | $(DDK_LIB_PATH)\USBd.lib
16 |
17 | C_DEFINES=$(C_DEFINES) -DPOOL_NX_OPTIN=1
18 |
19 | INCLUDES = $(DDK_INC_PATH); \
20 | $(WDM_INC_PATH);
21 |
22 | SOURCES = USBPcap.rc \
23 | USBPcapBuffer.c \
24 | USBPcapDeviceControl.c \
25 | USBPcapFilterManager.c \
26 | USBPcapGenReq.c \
27 | USBPcapHelperFunctions.c \
28 | USBPcapMain.c \
29 | USBPcapPnP.c \
30 | USBPcapPower.c \
31 | USBPcapRootHubControl.c \
32 | USBPcapQueue.c \
33 | USBPcapTables.c \
34 | USBPcapURB.c
35 |
36 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcap.inx:
--------------------------------------------------------------------------------
1 | [Version]
2 | Signature = "$WINDOWS NT$"
3 | Class = USB
4 | ClassGuid = {36FC9E60-C465-11CF-8056-444553540000}
5 | DriverPackageType = ClassFilter
6 | Provider = %PROVIDER%
7 | CatalogFile.NTx86 = USBPcapx86.cat
8 | CatalogFile.NTamd64 = USBPcapamd64.cat
9 |
10 | [DestinationDirs]
11 | DefaultDestDir = 12
12 |
13 | [SourceDisksNames]
14 | 1 = %DiskId1%,,,"."
15 |
16 | [SourceDisksFiles]
17 | USBPcap.sys = 1,,
18 |
19 | [DefaultInstall.NTx86]
20 | CopyFiles = @USBPcap.sys
21 | AddReg = USBPcap.AddReg
22 |
23 | [DefaultUninstall.NTx86]
24 | DelFiles = @USBPcap.sys
25 | DelReg = USBPcap.DelReg
26 |
27 | [DefaultInstall.NTamd64]
28 | CopyFiles = @USBPcap.sys
29 | AddReg = USBPcap.AddReg
30 |
31 | [DefaultUninstall.NTamd64]
32 | DelFiles = @USBPcap.sys
33 | DelReg = USBPcap.DelReg
34 |
35 | [USBPcap.AddReg]
36 | ;Add USBPcap to UpperFilters
37 | HKLM, System\CurrentControlSet\Control\Class\{36FC9E60-C465-11CF-8056-444553540000}, UpperFilters, 0x00010008, USBPcap
38 |
39 | [USBPcap.DelReg]
40 | ;Delete USBPcap from UpperFilters
41 | HKLM, System\CurrentControlSet\Control\Class\{36FC9E60-C465-11CF-8056-444553540000}, UpperFilters, 0x00018002, USBPcap
42 |
43 | [DefaultInstall.NTx86.Services]
44 | AddService = USBPcap,,Service.AddService
45 |
46 | [DefaultUninstall.NTx86.Services]
47 | DelService = USBPcap,0x00000200
48 |
49 | [DefaultInstall.NTamd64.Services]
50 | AddService = USBPcap,,Service.AddService
51 |
52 | [DefaultUninstall.NTamd64.Services]
53 | DelService = USBPcap,0x00000200
54 |
55 | [Service.AddService]
56 | DisplayName = %USBPcap.SvcDesc%
57 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER
58 | StartType = 3 ; SERVICE_DEMAND_START
59 | ErrorControl = 2 ; SERVICE_ERROR_SEVERE
60 | ServiceBinary = %12%\USBPcap.sys
61 |
62 | [Strings]
63 | PROVIDER = "USBPcap"
64 | StdMfg = "USBPcap Developers"
65 | DiskId1 = "USBPcap Installation Disk #1"
66 | USBPcap.DeviceDesc = "USBPcap Filter Driver"
67 | USBPcap.SvcDesc = "USBPcap Capture Service"
68 |
69 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcap.rc:
--------------------------------------------------------------------------------
1 | #include "Windows.h"
2 |
3 | 1 VERSIONINFO
4 | FILEVERSION 1,5,4,0
5 | PRODUCTVERSION 1,5,4,0
6 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
7 | FILEFLAGS (VS_FF_PRIVATEBUILD|VS_FF_PRERELEASE|VS_FF_DEBUG)
8 | FILEOS VOS__WINDOWS32
9 | FILETYPE VFT_APP
10 | FILESUBTYPE VFT2_UNKNOWN
11 | BEGIN
12 | BLOCK "StringFileInfo"
13 | BEGIN
14 | BLOCK "040904E4"
15 | BEGIN
16 | VALUE "CompanyName", "USBPcap"
17 | VALUE "FileDescription", "USBPcap Driver"
18 | VALUE "FileVersion", "1.5.4.0"
19 | VALUE "InternalName", "USBPcap"
20 | VALUE "LegalCopyright", "(c) 2013-2020 Tomasz Mon"
21 | VALUE "OriginalFilename", "USBPcap"
22 | VALUE "ProductName", "USBPcap Sniffer Driver"
23 | VALUE "ProductVersion", "1.5.4.0"
24 | END
25 | END
26 |
27 | BLOCK "VarFileInfo"
28 | BEGIN
29 | VALUE "Translation", 0x409, 1252
30 | END
31 | END
32 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapBuffer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #ifndef USBPCAP_BUFFER_H
8 | #define USBPCAP_BUFFER_H
9 |
10 | #include "USBPcapMain.h"
11 |
12 | typedef struct
13 | {
14 | UINT32 size;
15 | PVOID buffer;
16 | } USBPCAP_PAYLOAD_ENTRY, *PUSBPCAP_PAYLOAD_ENTRY;
17 |
18 | NTSTATUS USBPcapSetUpBuffer(PUSBPCAP_ROOTHUB_DATA pData,
19 | UINT32 bytes);
20 | NTSTATUS USBPcapSetSnaplenSize(PUSBPCAP_ROOTHUB_DATA pData,
21 | UINT32 bytes);
22 |
23 | VOID USBPcapBufferRemoveBuffer(PDEVICE_EXTENSION pDevExt);
24 | VOID USBPcapBufferInitializeBuffer(PDEVICE_EXTENSION pDevExt);
25 | NTSTATUS USBPcapBufferHandleReadIrp(PIRP pIrp,
26 | PDEVICE_EXTENSION pDevExt,
27 | PUINT32 pBytesRead);
28 |
29 | /* Same as USBPcapBufferWriteTimestampedPacket but take {0, NULL} terminated
30 | * array of payload entries instead of single buffer pointer.
31 | */
32 | NTSTATUS USBPcapBufferWriteTimestampedPayload(PUSBPCAP_ROOTHUB_DATA pRootData,
33 | LARGE_INTEGER timestamp,
34 | PUSBPCAP_BUFFER_PACKET_HEADER header,
35 | PUSBPCAP_PAYLOAD_ENTRY payload);
36 | /* Same as USBPcapBufferWritePacket but take {0, NULL} terminated
37 | * array of payload entries instead of single buffer pointer.
38 | */
39 | NTSTATUS USBPcapBufferWritePayload(PUSBPCAP_ROOTHUB_DATA pRootData,
40 | PUSBPCAP_BUFFER_PACKET_HEADER header,
41 | PUSBPCAP_PAYLOAD_ENTRY payload);
42 |
43 | NTSTATUS USBPcapBufferWriteTimestampedPacket(PUSBPCAP_ROOTHUB_DATA pRootData,
44 | LARGE_INTEGER timestamp,
45 | PUSBPCAP_BUFFER_PACKET_HEADER header,
46 | PVOID buffer);
47 | NTSTATUS USBPcapBufferWritePacket(PUSBPCAP_ROOTHUB_DATA pRootData,
48 | PUSBPCAP_BUFFER_PACKET_HEADER header,
49 | PVOID buffer);
50 |
51 | #endif /* USBPCAP_BUFFER_H */
52 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapDeviceControl.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #include "USBPcapMain.h"
8 | #include "include\USBPcap.h"
9 | #include "USBPcapURB.h"
10 | #include "USBPcapRootHubControl.h"
11 | #include "USBPcapBuffer.h"
12 | #include "USBPcapHelperFunctions.h"
13 |
14 | static NTSTATUS
15 | HandleUSBPcapControlIOCTL(PIRP pIrp, PIO_STACK_LOCATION pStack,
16 | PDEVICE_EXTENSION rootExt, PUSBPCAP_ROOTHUB_DATA pRootData,
17 | BOOLEAN allowCapture,
18 | SIZE_T *outLength)
19 | {
20 | NTSTATUS ntStat = STATUS_SUCCESS;
21 | if (pStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USBPCAP_GET_HUB_SYMLINK)
22 | {
23 | PWSTR interfaces;
24 | SIZE_T length;
25 |
26 | DkDbgStr("IOCTL_USBPCAP_GET_HUB_SYMLINK");
27 |
28 | interfaces = USBPcapGetHubInterfaces(rootExt->pNextDevObj);
29 | if (interfaces == NULL)
30 | {
31 | return STATUS_NOT_FOUND;
32 | }
33 |
34 | length = wcslen(interfaces);
35 | length = (length+1)*sizeof(WCHAR);
36 |
37 | if (pStack->Parameters.DeviceIoControl.OutputBufferLength < length)
38 | {
39 | DkDbgVal("Too small buffer", length);
40 | ntStat = STATUS_BUFFER_TOO_SMALL;
41 | }
42 | else
43 | {
44 | RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
45 | (PVOID)interfaces,
46 | length);
47 | *outLength = length;
48 | DkDbgVal("Successfully copied data", length);
49 | }
50 | ExFreePool((PVOID)interfaces);
51 | return ntStat;
52 | }
53 |
54 | /* Other IOCTLs are allowed only for the capture handle (exclusive) */
55 | if (!allowCapture)
56 | {
57 | return STATUS_ACCESS_DENIED;
58 | }
59 |
60 | switch (pStack->Parameters.DeviceIoControl.IoControlCode)
61 | {
62 | case IOCTL_USBPCAP_SETUP_BUFFER:
63 | {
64 | PUSBPCAP_IOCTL_SIZE pBufferSize;
65 |
66 | if (pStack->Parameters.DeviceIoControl.InputBufferLength !=
67 | sizeof(USBPCAP_IOCTL_SIZE))
68 | {
69 | ntStat = STATUS_INVALID_PARAMETER;
70 | break;
71 | }
72 |
73 | pBufferSize = (PUSBPCAP_IOCTL_SIZE)pIrp->AssociatedIrp.SystemBuffer;
74 | DkDbgVal("IOCTL_USBPCAP_SETUP_BUFFER", pBufferSize->size);
75 |
76 | ntStat = USBPcapSetUpBuffer(pRootData, pBufferSize->size);
77 | break;
78 | }
79 |
80 | case IOCTL_USBPCAP_START_FILTERING:
81 | {
82 | PUSBPCAP_ADDRESS_FILTER pAddressFilter;
83 |
84 | if (pStack->Parameters.DeviceIoControl.InputBufferLength !=
85 | sizeof(USBPCAP_ADDRESS_FILTER))
86 | {
87 | ntStat = STATUS_INVALID_PARAMETER;
88 | break;
89 | }
90 |
91 | pAddressFilter = (PUSBPCAP_ADDRESS_FILTER)pIrp->AssociatedIrp.SystemBuffer;
92 | memcpy(&pRootData->filter, pAddressFilter,
93 | sizeof(USBPCAP_ADDRESS_FILTER));
94 |
95 | DkDbgStr("IOCTL_USBPCAP_START_FILTERING");
96 | DkDbgVal("", pAddressFilter->addresses[0]);
97 | DkDbgVal("", pAddressFilter->addresses[1]);
98 | DkDbgVal("", pAddressFilter->addresses[2]);
99 | DkDbgVal("", pAddressFilter->addresses[3]);
100 | DkDbgVal("", pAddressFilter->filterAll);
101 | break;
102 | }
103 |
104 | case IOCTL_USBPCAP_STOP_FILTERING:
105 | DkDbgStr("IOCTL_USBPCAP_STOP_FILTERING");
106 | memset(&pRootData->filter, 0,
107 | sizeof(USBPCAP_ADDRESS_FILTER));
108 | break;
109 |
110 | case IOCTL_USBPCAP_SET_SNAPLEN_SIZE:
111 | {
112 | PUSBPCAP_IOCTL_SIZE pSnaplen;
113 |
114 | if (pStack->Parameters.DeviceIoControl.InputBufferLength !=
115 | sizeof(USBPCAP_IOCTL_SIZE))
116 | {
117 | ntStat = STATUS_INVALID_PARAMETER;
118 | break;
119 | }
120 |
121 | pSnaplen = (PUSBPCAP_IOCTL_SIZE)pIrp->AssociatedIrp.SystemBuffer;
122 | DkDbgVal("IOCTL_USBPCAP_SET_SNAPLEN_SIZE", pSnaplen->size);
123 |
124 | ntStat = USBPcapSetSnaplenSize(pRootData, pSnaplen->size);
125 | break;
126 | }
127 |
128 | default:
129 | {
130 | ULONG ctlCode = IoGetFunctionCodeFromCtlCode(pStack->Parameters.DeviceIoControl.IoControlCode);
131 | DkDbgVal("This: IOCTL_XXXXX", ctlCode);
132 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
133 | break;
134 | }
135 | }
136 | return ntStat;
137 | }
138 |
139 | ///////////////////////////////////////////////////////////////////////
140 | // I/O device control request handlers
141 | //
142 | NTSTATUS DkDevCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
143 | {
144 | NTSTATUS ntStat = STATUS_SUCCESS;
145 | PDEVICE_EXTENSION pDevExt = NULL;
146 | PIO_STACK_LOCATION pStack = NULL;
147 | ULONG ulRes = 0;
148 |
149 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
150 |
151 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
152 | if (!NT_SUCCESS(ntStat))
153 | {
154 | DkDbgVal("Error lock!", ntStat);
155 | DkCompleteRequest(pIrp, ntStat, 0);
156 | return ntStat;
157 | }
158 |
159 | pStack = IoGetCurrentIrpStackLocation(pIrp);
160 |
161 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB ||
162 | pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE)
163 | {
164 | IoSkipCurrentIrpStackLocation(pIrp);
165 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
166 | }
167 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL)
168 | {
169 | PDEVICE_EXTENSION rootExt;
170 | PUSBPCAP_ROOTHUB_DATA pRootData;
171 | BOOLEAN allowCapture = FALSE;
172 | SIZE_T length = 0;
173 | UINT_PTR info;
174 |
175 | rootExt = (PDEVICE_EXTENSION)pDevExt->context.control.pRootHubObject->DeviceExtension;
176 | pRootData = (PUSBPCAP_ROOTHUB_DATA)rootExt->context.usb.pDeviceData->pRootData;
177 | if (InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, NULL, NULL) == pStack->FileObject)
178 | {
179 | allowCapture = TRUE;
180 | }
181 |
182 | ntStat = HandleUSBPcapControlIOCTL(pIrp, pStack, rootExt, pRootData, allowCapture, &length);
183 |
184 | info = (UINT_PTR)length;
185 |
186 | DkCompleteRequest(pIrp, ntStat, info);
187 | }
188 |
189 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
190 |
191 | return ntStat;
192 | }
193 |
194 |
195 | //
196 | //--------------------------------------------------------------------------
197 | //
198 |
199 | ////////////////////////////////////////////////////////////////////////////
200 | // Internal I/O device control request handlers
201 | //
202 | NTSTATUS DkInDevCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
203 | {
204 | NTSTATUS ntStat = STATUS_SUCCESS;
205 | PDEVICE_EXTENSION pDevExt = NULL;
206 | PIO_STACK_LOCATION pStack = NULL;
207 | PDEVICE_OBJECT pNextDevObj = NULL;
208 | ULONG ctlCode = 0;
209 |
210 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
211 |
212 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
213 | if (!NT_SUCCESS(ntStat))
214 | {
215 | DkDbgVal("Error lock!", ntStat);
216 | DkCompleteRequest(pIrp, ntStat, 0);
217 | return ntStat;
218 | }
219 |
220 | pStack = IoGetCurrentIrpStackLocation(pIrp);
221 |
222 | ctlCode = IoGetFunctionCodeFromCtlCode(pStack->Parameters.DeviceIoControl.IoControlCode);
223 |
224 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB)
225 | {
226 | DkDbgVal("Hub Filter: IOCTL_INTERNAL_XXXXX", ctlCode);
227 | pNextDevObj = pDevExt->pNextDevObj;
228 | }
229 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE)
230 | {
231 | ntStat = DkTgtInDevCtl(pDevExt, pStack, pIrp);
232 |
233 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
234 |
235 | return ntStat;
236 | }
237 | else
238 | {
239 | DkDbgVal("This: IOCTL_INTERNAL_XXXXX", ctlCode);
240 | pNextDevObj = pDevExt->pNextDevObj;
241 | }
242 |
243 | if (pNextDevObj == NULL)
244 | {
245 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
246 | DkCompleteRequest(pIrp, ntStat, 0);
247 | }
248 | else
249 | {
250 | IoSkipCurrentIrpStackLocation(pIrp);
251 | ntStat = IoCallDriver(pNextDevObj, pIrp);
252 | }
253 |
254 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
255 |
256 | return ntStat;
257 | }
258 |
259 |
260 | NTSTATUS DkTgtInDevCtl(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp)
261 | {
262 | NTSTATUS ntStat = STATUS_SUCCESS;
263 | PURB pUrb = NULL;
264 | ULONG ctlCode = 0;
265 |
266 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
267 | if (!NT_SUCCESS(ntStat))
268 | {
269 | DkDbgVal("Error lock!", ntStat);
270 | DkCompleteRequest(pIrp, ntStat, 0);
271 | return ntStat;
272 | }
273 |
274 | ctlCode = IoGetFunctionCodeFromCtlCode(pStack->Parameters.DeviceIoControl.IoControlCode);
275 |
276 | // Our interest is IOCTL_INTERNAL_USB_SUBMIT_URB, where USB device driver send URB to
277 | // it's USB bus driver
278 | if (pStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
279 | {
280 | /* code here should cope with DISPATCH_LEVEL */
281 |
282 | // URB is collected BEFORE forward to bus driver or next lower object
283 | pUrb = (PURB) pStack->Parameters.Others.Argument1;
284 | if (pUrb != NULL)
285 | {
286 | USBPcapAnalyzeURB(pIrp, pUrb, FALSE,
287 | pDevExt->context.usb.pDeviceData);
288 | }
289 |
290 | // Forward this request to bus driver or next lower object
291 | // with completion routine
292 | IoCopyCurrentIrpStackLocationToNext(pIrp);
293 | IoSetCompletionRoutine(pIrp,
294 | (PIO_COMPLETION_ROUTINE) DkTgtInDevCtlCompletion,
295 | NULL, TRUE, TRUE, TRUE);
296 |
297 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
298 | }
299 | else
300 | {
301 | DkDbgVal("IOCTL_INTERNAL_USB_XXXX", ctlCode);
302 |
303 | IoSkipCurrentIrpStackLocation(pIrp);
304 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
305 |
306 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
307 | }
308 |
309 | return ntStat;
310 | }
311 |
312 | NTSTATUS DkTgtInDevCtlCompletion(PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pCtx)
313 | {
314 | NTSTATUS status;
315 | PDEVICE_EXTENSION pDevExt = NULL;
316 | PURB pUrb = NULL;
317 | PIO_STACK_LOCATION pStack = NULL;
318 |
319 | if (pIrp->PendingReturned)
320 | IoMarkIrpPending(pIrp);
321 |
322 | status = pIrp->IoStatus.Status;
323 |
324 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
325 |
326 | // URB is collected AFTER forward to bus driver or next lower object
327 | pStack = IoGetCurrentIrpStackLocation(pIrp);
328 | pUrb = (PURB) pStack->Parameters.Others.Argument1;
329 | if (pUrb != NULL)
330 | {
331 | USBPcapAnalyzeURB(pIrp, pUrb, TRUE,
332 | pDevExt->context.usb.pDeviceData);
333 | }
334 |
335 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
336 |
337 | return status;
338 | }
339 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapFilterManager.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #include "USBPcapMain.h"
8 | #include "USBPcapHelperFunctions.h"
9 | #include "USBPcapTables.h"
10 | #include "USBPcapRootHubControl.h"
11 |
12 | /*
13 | * Frees pDevExt.context.usb.pDeviceData
14 | */
15 | static void USBPcapFreeDeviceData(IN PDEVICE_EXTENSION pDevExt)
16 | {
17 | PUSBPCAP_DEVICE_DATA pDeviceData;
18 |
19 | if (pDevExt == NULL)
20 | {
21 | return;
22 | }
23 |
24 | ASSERT((pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB) ||
25 | (pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE));
26 |
27 | pDeviceData = pDevExt->context.usb.pDeviceData;
28 |
29 | if (pDeviceData != NULL)
30 | {
31 | if (pDeviceData->pRootData)
32 | {
33 | LONG count;
34 |
35 | count = InterlockedDecrement(&pDeviceData->pRootData->refCount);
36 | if (count == 0)
37 | {
38 | /*
39 | * RootHub is supposed to hold the last reference.
40 | * So if we enter here, this data can be safely removed.
41 | */
42 | if (pDeviceData->pRootData->buffer != NULL)
43 | {
44 | ExFreePool((PVOID)pDeviceData->pRootData->buffer);
45 | }
46 | ExFreePool((PVOID)pDeviceData->pRootData);
47 | pDeviceData->pRootData = NULL;
48 | }
49 | }
50 |
51 | if (pDeviceData->endpointTable != NULL)
52 | {
53 | USBPcapFreeEndpointTable(pDeviceData->endpointTable);
54 | pDeviceData->endpointTable = NULL;
55 | }
56 |
57 | if (pDeviceData->URBIrpTable != NULL)
58 | {
59 | USBPcapFreeURBIRPInfoTable(pDeviceData->URBIrpTable);
60 | pDeviceData->URBIrpTable = NULL;
61 | }
62 |
63 | if (pDeviceData->previousChildren != NULL)
64 | {
65 | ExFreePool((PVOID)pDeviceData->previousChildren);
66 | pDeviceData->previousChildren = NULL;
67 | }
68 |
69 | if (pDeviceData->descriptor != NULL)
70 | {
71 | ExFreePool((PVOID)pDeviceData->descriptor);
72 | pDeviceData->descriptor = NULL;
73 | }
74 |
75 | ExFreePool((PVOID)pDeviceData);
76 | pDevExt->context.usb.pDeviceData = NULL;
77 | }
78 | }
79 |
80 | /*
81 | * Allocates USBPCAP_DEVICE_DATA.
82 | */
83 | static NTSTATUS USBPcapAllocateDeviceData(IN PDEVICE_EXTENSION pDevExt,
84 | IN PDEVICE_EXTENSION pParentDevExt)
85 | {
86 | PUSBPCAP_DEVICE_DATA pDeviceData;
87 | NTSTATUS status = STATUS_SUCCESS;
88 | BOOLEAN allocRoothubData;
89 |
90 | allocRoothubData = (pParentDevExt == NULL);
91 |
92 | /* Allocate USBPCAP_DEVICE_DATA */
93 | pDeviceData = ExAllocatePoolWithTag(NonPagedPool,
94 | sizeof(USBPCAP_DEVICE_DATA),
95 | DKPORT_MTAG);
96 |
97 | if (pDeviceData != NULL)
98 | {
99 | /* deviceAddress, port and isHub will be properly set up when
100 | * filter driver handles IRP_MN_START_DEVICE
101 | */
102 |
103 | pDeviceData->deviceAddress = 255; /* UNKNOWN */
104 |
105 | /* This will get changed to TRUE once the deviceAddress,
106 | * parentPort and isHub will be correctly set up.
107 | */
108 | pDeviceData->properData = FALSE;
109 |
110 | /* Since 0 is invalid connection index, set that here */
111 | pDeviceData->parentPort = 0;
112 | /* assume that roothub is a hub and all other devices are not. */
113 | pDeviceData->isHub = allocRoothubData;
114 |
115 | pDeviceData->previousChildren = NULL;
116 |
117 | if (allocRoothubData == FALSE)
118 | {
119 | /*
120 | * This is not a roothub, just get the roothub data pointer
121 | * and increment the reference count
122 | */
123 | pDeviceData->pRootData =
124 | pParentDevExt->context.usb.pDeviceData->pRootData;
125 | InterlockedIncrement(&pDeviceData->pRootData->refCount);
126 | }
127 | else
128 | {
129 | /* Allocate USBPCAP_ROOTHUB_DATA */
130 | pDeviceData->pRootData =
131 | ExAllocatePoolWithTag(NonPagedPool,
132 | sizeof(USBPCAP_ROOTHUB_DATA),
133 | DKPORT_MTAG);
134 | if (pDeviceData->pRootData != NULL)
135 | {
136 | /* Initialize empty buffer */
137 | KeInitializeSpinLock(&pDeviceData->pRootData->bufferLock);
138 | pDeviceData->pRootData->buffer = NULL;
139 | pDeviceData->pRootData->readOffset = 0;
140 | pDeviceData->pRootData->writeOffset = 0;
141 | pDeviceData->pRootData->bufferSize = 0;
142 |
143 | /* Initialize default snaplen size */
144 | pDeviceData->pRootData->snaplen = USBPCAP_DEFAULT_SNAP_LEN;
145 |
146 | /* Setup initial filtering state to FALSE */
147 | memset(&pDeviceData->pRootData->filter, 0,
148 | sizeof(USBPCAP_ADDRESS_FILTER));
149 |
150 | /*
151 | * Set the reference count
152 | *
153 | * The reference count will drop down to zero once the
154 | * roothub filter object gets destroyed.
155 | */
156 | pDeviceData->pRootData->refCount = 1L;
157 | }
158 | else
159 | {
160 | status = STATUS_INSUFFICIENT_RESOURCES;
161 | }
162 | }
163 |
164 | KeInitializeSpinLock(&pDeviceData->tablesSpinLock);
165 | pDeviceData->endpointTable = USBPcapInitializeEndpointTable(NULL);
166 | pDeviceData->URBIrpTable = USBPcapInitializeURBIRPInfoTable(NULL);
167 |
168 | pDeviceData->descriptor = NULL;
169 | }
170 | else
171 | {
172 | status = STATUS_INSUFFICIENT_RESOURCES;
173 | }
174 |
175 | pDevExt->context.usb.pDeviceData = pDeviceData;
176 |
177 | if (!NT_SUCCESS(status))
178 | {
179 | USBPcapFreeDeviceData(pDevExt);
180 | }
181 | else if (allocRoothubData == FALSE)
182 | {
183 | /* Set up parent and target objects in USBPCAP_DEVICE_DATA */
184 | pDeviceData->pParentFlt = pParentDevExt->pThisDevObj;
185 | pDeviceData->pNextParentFlt = pParentDevExt->pNextDevObj;
186 | }
187 |
188 | return status;
189 | }
190 |
191 | static ULONG GetDeviceTypeToUse(PDEVICE_OBJECT pdo)
192 | {
193 | PDEVICE_OBJECT ldo = IoGetAttachedDeviceReference(pdo);
194 | ULONG devtype = FILE_DEVICE_UNKNOWN;
195 |
196 | if (ldo != NULL)
197 | {
198 | devtype = ldo->DeviceType;
199 | ObDereferenceObject(ldo);
200 | }
201 |
202 | return devtype;
203 | }
204 |
205 | /////////////////////////////////////////////////////////////////////
206 | // Functions to attach and detach USB Root HUB filter
207 | #pragma prefast(suppress: 28152, "Suppress 28152 for path where filter was not created. Please remove this suppression after doing any changes to AddDevice()!")
208 | NTSTATUS AddDevice(IN PDRIVER_OBJECT pDrvObj,
209 | IN PDEVICE_OBJECT pTgtDevObj)
210 | {
211 | NTSTATUS ntStat = STATUS_SUCCESS;
212 | UNICODE_STRING usTgtName;
213 | PDEVICE_OBJECT pHubFilter = NULL;
214 | PDEVICE_EXTENSION pDevExt = NULL;
215 | BOOLEAN isRootHub;
216 |
217 | // 1. Check if device is Root Hub
218 | isRootHub = USBPcapIsDeviceRootHub(pTgtDevObj);
219 | if (isRootHub == FALSE)
220 | {
221 | /* Do not attach to non-RootHub devices */
222 | return STATUS_SUCCESS;
223 | }
224 |
225 | // 2. Create filter object
226 | ntStat = IoCreateDevice(pDrvObj,
227 | sizeof(DEVICE_EXTENSION), NULL,
228 | GetDeviceTypeToUse(pTgtDevObj), 0,
229 | FALSE, &pHubFilter);
230 | if (!NT_SUCCESS(ntStat))
231 | {
232 | DkDbgVal("Error create Hub Filter!", ntStat);
233 | goto EndFunc;
234 | }
235 |
236 | pDevExt = (PDEVICE_EXTENSION) pHubFilter->DeviceExtension;
237 | pDevExt->deviceMagic = USBPCAP_MAGIC_ROOTHUB;
238 | pDevExt->pThisDevObj = pHubFilter;
239 | pDevExt->pDrvObj = pDrvObj;
240 | pDevExt->parentRemoveLock = NULL;
241 |
242 | IoInitializeRemoveLock(&pDevExt->removeLock, 0, 0, 0);
243 |
244 | ntStat = USBPcapAllocateDeviceData(pDevExt, NULL);
245 | if (!NT_SUCCESS(ntStat))
246 | {
247 | goto EndFunc;
248 | }
249 |
250 | // 3. Attach to bus driver
251 | pDevExt->pNextDevObj = NULL;
252 | pDevExt->pNextDevObj = IoAttachDeviceToDeviceStack(pHubFilter, pTgtDevObj);
253 | if (pDevExt->pNextDevObj == NULL)
254 | {
255 | ntStat = STATUS_NO_SUCH_DEVICE;
256 | DkDbgStr("Error attach device!");
257 | goto EndFunc;
258 | }
259 |
260 | pHubFilter->Flags |=
261 | (pDevExt->pNextDevObj->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE));
262 |
263 | pHubFilter->Flags &= ~DO_DEVICE_INITIALIZING;
264 |
265 | if (NT_SUCCESS(ntStat))
266 | {
267 | PDEVICE_OBJECT control = NULL;
268 | PUSBPCAP_ROOTHUB_DATA pRootData;
269 | USHORT id;
270 |
271 | ntStat = USBPcapCreateRootHubControlDevice(pDevExt,
272 | &control,
273 | &id);
274 |
275 | pRootData = pDevExt->context.usb.pDeviceData->pRootData;
276 | pRootData->controlDevice = control;
277 | pRootData->busId = id;
278 | }
279 |
280 | EndFunc:
281 |
282 | // If something bad happened
283 | if (!NT_SUCCESS(ntStat))
284 | {
285 | USBPcapFreeDeviceData(pDevExt);
286 | if (pHubFilter)
287 | {
288 | IoDeleteDevice(pHubFilter);
289 | pHubFilter = NULL;
290 | }
291 | }
292 |
293 | return ntStat;
294 | }
295 |
296 | VOID DkDetachAndDeleteHubFilt(PDEVICE_EXTENSION pDevExt)
297 | {
298 | NTSTATUS status;
299 | if (pDevExt->parentRemoveLock)
300 | {
301 | IoReleaseRemoveLock(pDevExt->parentRemoveLock, NULL);
302 | }
303 |
304 | if (pDevExt->pNextDevObj)
305 | {
306 | IoDetachDevice(pDevExt->pNextDevObj);
307 | pDevExt->pNextDevObj = NULL;
308 | }
309 | if (pDevExt->pThisDevObj)
310 | {
311 | IoDeleteDevice(pDevExt->pThisDevObj);
312 | pDevExt->pThisDevObj = NULL;
313 | }
314 | USBPcapFreeDeviceData(pDevExt);
315 | }
316 |
317 | ////////////////////////////////////////////////////////////////////////////
318 | // Functions to attach and detach target device object
319 | //
320 | NTSTATUS DkCreateAndAttachTgt(PDEVICE_EXTENSION pParentDevExt, PDEVICE_OBJECT pTgtDevObj)
321 | {
322 | NTSTATUS ntStat = STATUS_SUCCESS;
323 | PDEVICE_OBJECT pDeviceObject = NULL;
324 | PDEVICE_EXTENSION pDevExt = NULL;
325 |
326 | // 1. Create filter object for target device object
327 | ntStat = IoCreateDevice(pParentDevExt->pDrvObj,
328 | sizeof(DEVICE_EXTENSION), NULL,
329 | pTgtDevObj->DeviceType, 0,
330 | FALSE, &pDeviceObject);
331 | if (!NT_SUCCESS(ntStat))
332 | {
333 | DkDbgVal("Error create target device!", ntStat);
334 | return ntStat;
335 | }
336 |
337 | if (pDeviceObject == NULL)
338 | {
339 | DkDbgStr("IoCreateDevice() succeeded but pDeviceObject was not set.");
340 | return ntStat;
341 | }
342 |
343 | pDevExt = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension;
344 | pDevExt->deviceMagic = USBPCAP_MAGIC_DEVICE;
345 | pDevExt->pThisDevObj = pDeviceObject;
346 | pDevExt->parentRemoveLock = &pParentDevExt->removeLock;
347 | pDevExt->pDrvObj = pParentDevExt->pDrvObj;
348 |
349 | ntStat = USBPcapAllocateDeviceData(pDevExt, pParentDevExt);
350 | if (!NT_SUCCESS(ntStat))
351 | {
352 | goto EndAttDev;
353 | }
354 |
355 | // 2. Initilize remove lock for filter object of target device
356 | IoInitializeRemoveLock(&pDevExt->removeLock, 0, 0, 0);
357 |
358 | // 3. Attach to target device
359 | pDevExt->pNextDevObj = NULL;
360 | pDevExt->pNextDevObj = IoAttachDeviceToDeviceStack(pDevExt->pThisDevObj, pTgtDevObj);
361 | if (pDevExt->pNextDevObj == NULL)
362 | {
363 | DkDbgStr("Error attach target device!");
364 | ntStat = STATUS_NO_SUCH_DEVICE;
365 | goto EndAttDev;
366 | }
367 |
368 |
369 | // 4. Set up some filter device object flags
370 | pDevExt->pThisDevObj->Flags |=
371 | (pDevExt->pNextDevObj->Flags & (DO_BUFFERED_IO | DO_POWER_PAGABLE | DO_DIRECT_IO));
372 | pDevExt->pThisDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
373 |
374 | IoAcquireRemoveLock(pDevExt->parentRemoveLock, NULL);
375 |
376 | EndAttDev:
377 | if (!NT_SUCCESS(ntStat))
378 | {
379 | USBPcapFreeDeviceData(pDevExt);
380 | if (pDeviceObject)
381 | {
382 | IoDeleteDevice(pDeviceObject);
383 | pDeviceObject = NULL;
384 | }
385 | }
386 |
387 | return ntStat;
388 | }
389 |
390 | VOID DkDetachAndDeleteTgt(PDEVICE_EXTENSION pDevExt)
391 | {
392 | PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData;
393 |
394 | if (pDevExt->parentRemoveLock)
395 | {
396 | IoReleaseRemoveLock(pDevExt->parentRemoveLock, NULL);
397 | }
398 | if (pDevExt->pNextDevObj)
399 | {
400 | IoDetachDevice(pDevExt->pNextDevObj);
401 | pDevExt->pNextDevObj = NULL;
402 | }
403 | if (pDevExt->pThisDevObj)
404 | {
405 | IoDeleteDevice(pDevExt->pThisDevObj);
406 | pDevExt->pThisDevObj = NULL;
407 | }
408 | USBPcapFreeDeviceData(pDevExt);
409 | }
410 |
411 |
412 | //////////////////////////////////////////////////////////////////////////
413 | // Function to get USB Root Hub device name, e.g., \Device\USBPDO-4
414 | //
415 | NTSTATUS DkGetHubDevName(PIO_STACK_LOCATION pStack, PIRP pIrp, PULONG pUlRes)
416 | {
417 | NTSTATUS ntStat = STATUS_SUCCESS, clStat = STATUS_SUCCESS;
418 | HANDLE hObj;
419 | OBJECT_ATTRIBUTES oa;
420 | UNICODE_STRING usHubPath, usTgtDev;
421 | ULONG ulRet;
422 |
423 | RtlInitUnicodeString(&usHubPath, (PCWSTR) pIrp->AssociatedIrp.SystemBuffer);
424 |
425 | InitializeObjectAttributes(&oa, &usHubPath, OBJ_KERNEL_HANDLE, NULL, NULL);
426 |
427 | ntStat = ZwOpenSymbolicLinkObject(&hObj, GENERIC_ALL, &oa);
428 | if (!NT_SUCCESS(ntStat))
429 | {
430 | DkDbgVal("Error open symbolic link!", ntStat);
431 | return ntStat;
432 | }
433 |
434 | usTgtDev.Length = 0;
435 | usTgtDev.MaximumLength = 512;
436 | usTgtDev.Buffer = (PWSTR) ExAllocatePoolWithTag(NonPagedPool, 512, DKPORT_MTAG);
437 | RtlFillMemory(usTgtDev.Buffer, 512, '\0');
438 |
439 | ntStat = ZwQuerySymbolicLinkObject(hObj, &usTgtDev, &ulRet);
440 | if (!NT_SUCCESS(ntStat))
441 | {
442 | DkDbgVal("Error query symbolic link!", ntStat);
443 | pIrp->IoStatus.Status = ntStat;
444 |
445 | *pUlRes = 0;
446 |
447 | }
448 | else
449 | {
450 | RtlFillMemory(pIrp->AssociatedIrp.SystemBuffer, pStack->Parameters.DeviceIoControl.InputBufferLength, '\0');
451 | RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, usTgtDev.Buffer, 512);
452 |
453 | pIrp->IoStatus.Information = usTgtDev.Length;
454 | pIrp->IoStatus.Status = ntStat;
455 |
456 | *pUlRes = (ULONG) usTgtDev.Length;
457 | }
458 |
459 | ExFreePoolWithTag(usTgtDev.Buffer, DKPORT_MTAG);
460 |
461 | clStat = ZwClose(hObj);
462 | if (!NT_SUCCESS(clStat))
463 | {
464 | DkDbgVal("Error close symbolic link!", clStat);
465 | }
466 |
467 | return ntStat;
468 | }
469 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapGenReq.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #include "USBPcapMain.h"
8 | #include "USBPcapBuffer.h"
9 |
10 | ////////////////////////////////////////////////////////////////////////////
11 | // Create, close and clean up handlers
12 | //
13 | NTSTATUS DkCreateClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
14 | {
15 | NTSTATUS ntStat = STATUS_SUCCESS;
16 | PDEVICE_EXTENSION pDevExt = NULL;
17 | PIO_STACK_LOCATION pStack = NULL;
18 | PDEVICE_OBJECT pNextDevObj = NULL;
19 |
20 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
21 |
22 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
23 | if (!NT_SUCCESS(ntStat))
24 | {
25 | DkDbgVal("Error acquire lock!", ntStat);
26 | DkCompleteRequest(pIrp, ntStat, 0);
27 | return ntStat;
28 | }
29 |
30 | pStack = IoGetCurrentIrpStackLocation(pIrp);
31 |
32 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB ||
33 | pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE)
34 | {
35 | // Handling Create, Close and Cleanup request for Hub Filter and
36 | // target devices
37 | IoSkipCurrentIrpStackLocation(pIrp);
38 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
39 | }
40 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL)
41 | {
42 | // Handling Create, Close and Cleanup request for this object
43 | switch (pStack->MajorFunction)
44 | {
45 | case IRP_MJ_CREATE:
46 | /* When elevated USBPcapCMD worker is opening the USBPcapX device, the DesiredAccess is:
47 | * SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
48 | * FILE_WRITE_EA | FILE_READ_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA
49 | *
50 | * When unpriviledged USBPcapCMD opens USBPcapX to get hub symlink, the DesiredAccess is:
51 | * SYNCHRONIZE | FILE_READ_ATTRIBUTES
52 | *
53 | * Check for Read flags and allow only one such interface.
54 | */
55 | if (pStack->Parameters.Create.SecurityContext->DesiredAccess & (READ_CONTROL | FILE_READ_DATA))
56 | {
57 | PFILE_OBJECT *previous;
58 | previous = InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, pStack->FileObject, NULL);
59 | if (previous)
60 | {
61 | /* There is another handle that has the READ access - fail this one */
62 | ntStat = STATUS_ACCESS_DENIED;
63 | }
64 | }
65 | else
66 | {
67 | /* Handle will be only able to call IOCTL_USBPCAP_GET_HUB_SYMLINK - allow it */
68 | }
69 | break;
70 |
71 |
72 | case IRP_MJ_CLEANUP:
73 | if (InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, NULL, NULL) == pStack->FileObject)
74 | {
75 | PDEVICE_EXTENSION rootExt;
76 | PUSBPCAP_ROOTHUB_DATA pRootData;
77 | DkCsqCleanUpQueue(pDevObj, pIrp);
78 | /* Stop filtering */
79 | rootExt = (PDEVICE_EXTENSION)pDevExt->context.control.pRootHubObject->DeviceExtension;
80 | pRootData = (PUSBPCAP_ROOTHUB_DATA)rootExt->context.usb.pDeviceData->pRootData;
81 | memset(&pRootData->filter, 0, sizeof(USBPCAP_ADDRESS_FILTER));
82 | /* Free the buffer allocated for this device. */
83 | USBPcapBufferRemoveBuffer(pDevExt);
84 | }
85 | break;
86 |
87 |
88 | case IRP_MJ_CLOSE:
89 | /* Clear the pCaptureObject if the priviledged (able to capture) handle is closed. */
90 | InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, NULL, pStack->FileObject);
91 | break;
92 |
93 |
94 | default:
95 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
96 | break;
97 | }
98 |
99 | DkCompleteRequest(pIrp, ntStat, 0);
100 | }
101 |
102 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
103 |
104 | return ntStat;
105 | }
106 |
107 |
108 | //
109 | //--------------------------------------------------------------------------
110 | //
111 |
112 | ////////////////////////////////////////////////////////////////////////////
113 | // Read and write request handlers
114 | //
115 | NTSTATUS DkReadWrite(PDEVICE_OBJECT pDevObj, PIRP pIrp)
116 | {
117 | NTSTATUS ntStat = STATUS_SUCCESS;
118 | PDEVICE_EXTENSION pDevExt = NULL;
119 | PIO_STACK_LOCATION pStack = NULL;
120 |
121 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
122 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
123 | if (!NT_SUCCESS(ntStat)){
124 | DkDbgVal("Error acquire lock!", ntStat);
125 | DkCompleteRequest(pIrp, ntStat, 0);
126 | return ntStat;
127 | }
128 |
129 | pStack = IoGetCurrentIrpStackLocation(pIrp);
130 |
131 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB ||
132 | pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE)
133 | {
134 | // Handling Read/Write request for Hub Filter object and
135 | // target devices
136 | IoSkipCurrentIrpStackLocation(pIrp);
137 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
138 | }
139 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL)
140 | {
141 | UINT32 bytesRead = 0;
142 | /* Handling Read/Write for control object */
143 | switch (pStack->MajorFunction)
144 | {
145 | case IRP_MJ_READ:
146 | {
147 | if (pStack->FileObject == InterlockedCompareExchangePointer(&pDevExt->context.control.pCaptureObject, NULL, NULL))
148 | {
149 | ntStat = USBPcapBufferHandleReadIrp(pIrp, pDevExt,
150 | &bytesRead);
151 | }
152 | else
153 | {
154 | ntStat = STATUS_ACCESS_DENIED;
155 | }
156 | break;
157 | }
158 |
159 | case IRP_MJ_WRITE:
160 | /* Writing to the control device is not supported */
161 | ntStat = STATUS_NOT_SUPPORTED;
162 | break;
163 |
164 |
165 | default:
166 | DkDbgVal("Unknown IRP Major function", pStack->MajorFunction);
167 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
168 | break;
169 | }
170 |
171 | /* If the IRP was pended, do not call complete request */
172 | if (ntStat != STATUS_PENDING)
173 | {
174 | DkCompleteRequest(pIrp, ntStat, (ULONG_PTR)bytesRead);
175 | }
176 | }
177 |
178 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
179 |
180 | return ntStat;
181 | }
182 |
183 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapHelperFunctions.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #ifndef USBPCAP_HELPER_FUNCTIONS_H
8 | #define USBPCAP_HELPER_FUNCTIONS_H
9 |
10 | #include "USBPcapMain.h"
11 |
12 | NTSTATUS USBPcapGetTargetDevicePdo(IN PDEVICE_OBJECT DeviceObject,
13 | OUT PDEVICE_OBJECT *pdo);
14 |
15 | NTSTATUS USBPcapGetNumberOfPorts(PDEVICE_OBJECT parent,
16 | PULONG numberOfPorts);
17 |
18 | #if DBG
19 | NTSTATUS USBPcapPrintUSBPChildrenInformation(PDEVICE_OBJECT hub);
20 | #else
21 | #define USBPcapPrintUSBPChildrenInformation(hub) {}
22 | #endif
23 |
24 | NTSTATUS USBPcapGetDeviceUSBInfo(PDEVICE_EXTENSION pDevExt);
25 |
26 | BOOLEAN USBPcapIsDeviceRootHub(PDEVICE_OBJECT device);
27 |
28 | PWSTR USBPcapGetHubInterfaces(PDEVICE_OBJECT hub);
29 |
30 |
31 | BOOLEAN USBPcapIsDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address);
32 | BOOLEAN USBPcapSetDeviceFiltered(PUSBPCAP_ADDRESS_FILTER filter, int address);
33 |
34 | LARGE_INTEGER USBPcapGetCurrentTimestamp(VOID);
35 |
36 | #ifdef ALLOC_PRAGMA
37 | #pragma alloc_text (PAGE, USBPcapGetTargetDevicePdo)
38 | #pragma alloc_text (PAGE, USBPcapGetNumberOfPorts)
39 | #if DBG
40 | #pragma alloc_text (PAGE, USBPcapPrintUSBPChildrenInformation)
41 | #endif
42 | #pragma alloc_text (PAGE, USBPcapGetDeviceUSBInfo)
43 | #pragma alloc_text (PAGE, USBPcapIsDeviceRootHub)
44 | #pragma alloc_text (PAGE, USBPcapGetHubInterfaces)
45 | #endif
46 |
47 | #endif /* USBPCAP_HELPER_FUNCTIONS_H */
48 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapMain.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #include "USBPcapMain.h"
8 |
9 | /* Control device ID, used when creating roothub control devices
10 | *
11 | * Although this is 32-bit value (ULONG) we use only lower 16 bits
12 | * The reason for that is lack of InterlockedIncrement16 when building
13 | * for x86 processors
14 | */
15 | ULONG volatile g_controlId;
16 |
17 | NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pUsRegPath)
18 | {
19 | UCHAR ucCnt = 0;
20 |
21 | /* Building for Windows 8 or newer. */
22 | #if _MSC_VER >= 1800
23 | ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
24 | #endif
25 |
26 | DkDbgStr("3");
27 |
28 | pDrvObj->DriverUnload = DkUnload;
29 | pDrvObj->DriverExtension->AddDevice = AddDevice;
30 |
31 | for (ucCnt = 0; ucCnt <= IRP_MJ_MAXIMUM_FUNCTION; ucCnt++)
32 | {
33 | pDrvObj->MajorFunction[ucCnt] = DkDefault;
34 | }
35 |
36 | pDrvObj->MajorFunction[IRP_MJ_CREATE] =
37 | pDrvObj->MajorFunction[IRP_MJ_CLEANUP] =
38 | pDrvObj->MajorFunction[IRP_MJ_CLOSE] = DkCreateClose;
39 |
40 | pDrvObj->MajorFunction[IRP_MJ_READ] =
41 | pDrvObj->MajorFunction[IRP_MJ_WRITE] = DkReadWrite;
42 |
43 | pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DkDevCtl;
44 |
45 | pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DkInDevCtl;
46 |
47 | pDrvObj->MajorFunction[IRP_MJ_PNP] = DkPnP;
48 |
49 | pDrvObj->MajorFunction[IRP_MJ_POWER] = DkPower;
50 |
51 | g_controlId = (ULONG)0;
52 |
53 | return STATUS_SUCCESS;
54 | }
55 |
56 | VOID DkUnload(PDRIVER_OBJECT pDrvObj)
57 | {
58 | DkDbgStr("2");
59 | }
60 |
61 | VOID DkCompleteRequest(PIRP pIrp, NTSTATUS resStat, UINT_PTR uiInfo)
62 | {
63 | pIrp->IoStatus.Status = resStat;
64 | pIrp->IoStatus.Information = uiInfo;
65 | IoCompleteRequest(pIrp, IO_NO_INCREMENT);
66 | }
67 |
68 | NTSTATUS DkDefault(PDEVICE_OBJECT pDevObj, PIRP pIrp)
69 | {
70 | NTSTATUS ntStat = STATUS_SUCCESS;
71 | PDEVICE_EXTENSION pDevExt = NULL;
72 | PDEVICE_OBJECT pNextDevObj = NULL;
73 |
74 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
75 |
76 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
77 | if (!NT_SUCCESS(ntStat))
78 | {
79 | DkDbgVal("Error acquire lock!", ntStat);
80 | DkCompleteRequest(pIrp, ntStat, 0);
81 | return ntStat;
82 | }
83 |
84 | #if DBG
85 | {
86 | PIO_STACK_LOCATION pStack;
87 | pStack = IoGetCurrentIrpStackLocation(pIrp);
88 | DkDbgVal("DkDefault", pStack->MajorFunction);
89 | }
90 | #endif
91 |
92 | pNextDevObj = pDevExt->pNextDevObj;
93 |
94 | if (pNextDevObj == NULL)
95 | {
96 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
97 | DkCompleteRequest(pIrp, ntStat, 0);
98 | }
99 | else
100 | {
101 | IoSkipCurrentIrpStackLocation(pIrp);
102 | ntStat = IoCallDriver(pNextDevObj, pIrp);
103 | }
104 |
105 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
106 |
107 | return ntStat;
108 | }
109 |
110 | NTSTATUS DkForwardAndWait(PDEVICE_OBJECT pNextDevObj, PIRP pIrp)
111 | {
112 | KEVENT kEvt;
113 | NTSTATUS ntStat = STATUS_SUCCESS;
114 |
115 | KeInitializeEvent(&kEvt, NotificationEvent, FALSE);
116 |
117 | IoCopyCurrentIrpStackLocationToNext(pIrp);
118 | IoSetCompletionRoutine(pIrp,
119 | (PIO_COMPLETION_ROUTINE) DkGenCompletion,
120 | (PVOID) &kEvt, TRUE, TRUE, TRUE);
121 |
122 | ntStat = IoCallDriver(pNextDevObj, pIrp);
123 |
124 | if (ntStat == STATUS_PENDING)
125 | {
126 | KeWaitForSingleObject(&kEvt, Executive, KernelMode, FALSE, NULL);
127 | ntStat = pIrp->IoStatus.Status;
128 | }
129 |
130 | return ntStat;
131 | }
132 |
133 | NTSTATUS DkGenCompletion(PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pCtx)
134 | {
135 | PKEVENT pEvt = NULL;
136 |
137 | pEvt = (PKEVENT) pCtx;
138 | if (pEvt == NULL)
139 | return STATUS_UNSUCCESSFUL;
140 |
141 | KeSetEvent(pEvt, IO_NO_INCREMENT, FALSE);
142 |
143 | return STATUS_MORE_PROCESSING_REQUIRED;
144 | }
145 |
146 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapMain.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | /**************************************************************************
8 | *
9 | * Define all structures and functions needed by this driver
10 | *
11 | **************************************************************************/
12 |
13 | #ifndef USBPCAP_MAIN_H
14 | #define USBPCAP_MAIN_H
15 |
16 | #ifndef _PREFAST_
17 | #pragma warning(disable:4068)
18 | #endif
19 |
20 | ////////////////////////////////////////////////////////////
21 | // WDK headers defined here
22 | //
23 | #include "Ntddk.h"
24 | #include "Usbdi.h"
25 | #include "Usbdlib.h"
26 | #include "Usbioctl.h"
27 | #include "Wdm.h"
28 |
29 | #define DKPORT_DEVNAME_STR L"\\Device\\DkSysPort" // Device name string
30 | #define DKPORT_DEVLINK_STR L"\\DosDevices\\Global\\DkSysPort" // Link name string
31 | #define DKPORT_MTAG (ULONG)'dk3A' // To tag memory allocation if any
32 |
33 | #include "USBPcapQueue.h"
34 | #include "include\USBPcap.h"
35 |
36 | #define USBPCAP_DEFAULT_SNAP_LEN 65535
37 |
38 | typedef struct _USBPCAP_ROOTHUB_DATA
39 | {
40 | /* Circular-Buffer related variables */
41 | KSPIN_LOCK bufferLock;
42 | PVOID buffer;
43 | UINT32 bufferSize;
44 | UINT32 readOffset;
45 | UINT32 writeOffset;
46 |
47 | /* Snapshot length */
48 | UINT32 snaplen;
49 |
50 | /* Address filter. See include\USBPcap.h for more information. */
51 | USBPCAP_ADDRESS_FILTER filter;
52 |
53 | /* Reference count. To be used only with InterlockedXXX calls. */
54 | volatile LONG refCount;
55 |
56 | USHORT busId; /* bus number */
57 | PDEVICE_OBJECT controlDevice;
58 | } USBPCAP_ROOTHUB_DATA, *PUSBPCAP_ROOTHUB_DATA;
59 |
60 | typedef struct _DEVICE_DATA
61 | {
62 | /* pParentFlt and pNextParentFlt are NULL for RootHub */
63 | PDEVICE_OBJECT pParentFlt; /* Parent filter object */
64 | PDEVICE_OBJECT pNextParentFlt; /* Lower object of Parent filter */
65 |
66 | /* Previous children. Used when receive IRP_MN_QUERY_DEVICE_RELATIONS */
67 | PDEVICE_OBJECT *previousChildren;
68 |
69 | /* TRUE if the parentPort, isHub and deviceAddress are correct */
70 | BOOLEAN properData;
71 |
72 | /* Parent port number the device is attached to */
73 | ULONG parentPort;
74 | BOOLEAN isHub; /* TRUE if device is hub */
75 |
76 | USHORT deviceAddress;
77 |
78 | KSPIN_LOCK tablesSpinLock;
79 | PRTL_GENERIC_TABLE endpointTable;
80 | PRTL_GENERIC_TABLE URBIrpTable;
81 |
82 | PUSBPCAP_ROOTHUB_DATA pRootData;
83 |
84 | /* Active configuration descriptor */
85 | PUSB_CONFIGURATION_DESCRIPTOR descriptor;
86 | } USBPCAP_DEVICE_DATA, *PUSBPCAP_DEVICE_DATA;
87 |
88 | #define USBPCAP_MAGIC_CONTROL 0xBAD51571
89 | #define USBPCAP_MAGIC_ROOTHUB 0xBAD51572
90 | #define USBPCAP_MAGIC_DEVICE 0xBAD51573
91 |
92 | ////////////////////////////////////////////////////////////
93 | // Device extension structure for this object
94 | //
95 | typedef struct DEVICE_EXTENSION_Tag {
96 | UINT32 deviceMagic; /* determines device type */
97 | PDEVICE_OBJECT pThisDevObj; /* This device object pointer */
98 | PDEVICE_OBJECT pNextDevObj; /* Lower object of this object */
99 | PDRIVER_OBJECT pDrvObj; /* Driver object pointer */
100 | IO_REMOVE_LOCK removeLock; /* Remove lock for this object */
101 | PIO_REMOVE_LOCK parentRemoveLock; /* Pointer to parent remove lock */
102 |
103 | union
104 | {
105 | /* For USBPCAP_MAGIC_CONTROL */
106 | struct
107 | {
108 | USHORT id;
109 | PDEVICE_OBJECT pRootHubObject; /* Root Hub object */
110 |
111 | /* Pointer to handle that can control capture and read the data.
112 | * Only one such handle is allowed at a time.
113 | * However, we allow other callers to obtain handle that can be
114 | * used to call IOCTL_USBPCAP_GET_HUB_SYMLINK.
115 | *
116 | * This pointer is NULL if there isn't any open handle with the READ
117 | * permission.
118 | * This can be accessed only via InterlockedCompareExchangePointer().
119 | */
120 | PFILE_OBJECT pCaptureObject;
121 |
122 | LIST_ENTRY lePendIrp; // Used by I/O Cancel-Safe
123 | IO_CSQ ioCsq; // I/O Cancel-Safe object
124 | KSPIN_LOCK csqSpinLock; // Spin lock object for I/O Cancel-Safe
125 | } control;
126 |
127 | /* For USBPCAP_MAGIC_ROOTHUB or USBPCAP_MAGIC_DEVICE */
128 | struct
129 | {
130 | PUSBPCAP_DEVICE_DATA pDeviceData; /* Device data */
131 | } usb;
132 | } context;
133 | } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
134 |
135 |
136 | ////////////////////////////////////////////////////////////
137 | // These are "must have" routines for this driver
138 | //
139 | DRIVER_INITIALIZE DriverEntry;
140 | DRIVER_UNLOAD DkUnload;
141 | DRIVER_ADD_DEVICE AddDevice;
142 |
143 | ////////////////////////////////////////////////////////////
144 | // Some "standard" dispatch routines, used by this driver
145 | //
146 | __drv_dispatchType(IRP_MJ_CREATE)
147 | __drv_dispatchType(IRP_MJ_CLEANUP)
148 | __drv_dispatchType(IRP_MJ_CLOSE) DRIVER_DISPATCH DkCreateClose;
149 |
150 | __drv_dispatchType(IRP_MJ_READ)
151 | __drv_dispatchType(IRP_MJ_WRITE) DRIVER_DISPATCH DkReadWrite;
152 |
153 | __drv_dispatchType(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH DkDevCtl;
154 |
155 | __drv_dispatchType(IRP_MJ_INTERNAL_DEVICE_CONTROL) DRIVER_DISPATCH DkInDevCtl;
156 |
157 | __drv_dispatchType(IRP_MJ_PNP) DRIVER_DISPATCH DkPnP;
158 |
159 | __drv_dispatchType(IRP_MJ_POWER) DRIVER_DISPATCH DkPower;
160 |
161 | __drv_dispatchType_other DRIVER_DISPATCH DkDefault;
162 |
163 |
164 | ///////////////////////////////////////////////////////////////////////////
165 | // Completion routine for internal device control request for target object
166 | //
167 | IO_COMPLETION_ROUTINE DkTgtInDevCtlCompletion;
168 | NTSTATUS DkTgtInDevCtlCompletion(PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pCtx);
169 |
170 |
171 | ///////////////////////////////////////////////////////////////////////////
172 | // General purpose I/O request completion routine
173 | //
174 | VOID DkCompleteRequest(PIRP pIrp, NTSTATUS resStat, UINT_PTR uiInfo);
175 |
176 |
177 | ///////////////////////////////////////////////////////////////////////////
178 | // Macro to show some "debugging messages" to a debugging tool
179 | //
180 | #define DkDbgStr(a) KdPrint(("USBPcap, %s(): %s\n", __FUNCTION__, a))
181 | #define DkDbgVal(a, b) KdPrint(("USBPcap, %s(): %s ("#b" = 0x%X)\n", __FUNCTION__, a, b))
182 |
183 |
184 | ///////////////////////////////////////////////////////////////////////////
185 | // General purpose routine to forward to next or lower driver and then
186 | // wait forever until lower driver finished it's job
187 | //
188 | NTSTATUS DkForwardAndWait(PDEVICE_OBJECT pNextDevObj, PIRP pIrp);
189 |
190 |
191 | ///////////////////////////////////////////////////////////
192 | // Completion routine for general purpose
193 | //
194 | IO_COMPLETION_ROUTINE DkGenCompletion;
195 | NTSTATUS DkGenCompletion(PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pCtx);
196 |
197 |
198 | ///////////////////////////////////////////////////////////////////////////
199 | // "Sub dispatch routines" for Hub filter object
200 | //
201 | NTSTATUS DkHubFltPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp);
202 | NTSTATUS DkHubFltPnpHandleQryDevRels(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp);
203 |
204 |
205 | ///////////////////////////////////////////////////////////////////////////
206 | // "Sub dispatch routines" for target device
207 | //
208 | NTSTATUS DkTgtPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp);
209 | NTSTATUS DkTgtInDevCtl(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp);
210 |
211 |
212 | ///////////////////////////////////////////////////////////////////////////
213 | // Detach and delete hub filter objects routine
214 | //
215 | VOID DkDetachAndDeleteHubFilt(PDEVICE_EXTENSION pDevExt);
216 |
217 |
218 | ///////////////////////////////////////////////////////////////////////////
219 | // Create and attach target device filter routine
220 | //
221 | NTSTATUS DkCreateAndAttachTgt(PDEVICE_EXTENSION pDevExt, PDEVICE_OBJECT pTgtDevObj);
222 |
223 |
224 | ///////////////////////////////////////////////////////////////////////////
225 | // Detach and delete target device fitler routine
226 | //
227 | VOID DkDetachAndDeleteTgt(PDEVICE_EXTENSION pDevExt);
228 |
229 |
230 | ///////////////////////////////////////////////////////////////////////////
231 | // Get USB Hub device name
232 | //
233 | NTSTATUS DkGetHubDevName(PIO_STACK_LOCATION pStack, PIRP pIrp, PULONG pUlRes);
234 |
235 | #endif /* USBPCAP_MAIN_H */
236 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapPnP.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #include "USBPcapMain.h"
8 | #include "USBPcapHelperFunctions.h"
9 | #include "USBPcapRootHubControl.h"
10 |
11 | NTSTATUS DkPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp)
12 | {
13 | NTSTATUS ntStat = STATUS_SUCCESS;
14 | PDEVICE_EXTENSION pDevExt = NULL;
15 | PIO_STACK_LOCATION pStack = NULL;
16 |
17 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
18 |
19 | pStack = IoGetCurrentIrpStackLocation(pIrp);
20 |
21 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB)
22 | {
23 | return DkHubFltPnP(pDevExt, pStack, pIrp);
24 | }
25 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE)
26 | {
27 | return DkTgtPnP(pDevExt, pStack, pIrp);
28 | }
29 | else
30 | {
31 | // Do nothing
32 | }
33 |
34 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
35 | if (!NT_SUCCESS(ntStat))
36 | {
37 | DkDbgVal("Error acquire lock!", ntStat);
38 | DkCompleteRequest(pIrp, ntStat, 0);
39 | return ntStat;
40 | }
41 |
42 | if (pDevExt->pNextDevObj == NULL)
43 | {
44 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
45 | DkCompleteRequest(pIrp, ntStat, 0);
46 | }
47 | else
48 | {
49 | IoSkipCurrentIrpStackLocation(pIrp);
50 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
51 | }
52 |
53 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
54 |
55 | return ntStat;
56 | }
57 |
58 |
59 | NTSTATUS DkHubFltPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp)
60 | {
61 | NTSTATUS ntStat = STATUS_SUCCESS;
62 |
63 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
64 | if (!NT_SUCCESS(ntStat))
65 | {
66 | DkDbgVal("Error lock!", ntStat);
67 | DkCompleteRequest(pIrp, ntStat, 0);
68 | return ntStat;
69 | }
70 |
71 | switch (pStack->MinorFunction)
72 | {
73 | case IRP_MN_START_DEVICE:
74 | DkDbgStr("IRP_MN_START_DEVICE");
75 |
76 | ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp);
77 | IoCompleteRequest(pIrp, IO_NO_INCREMENT);
78 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
79 |
80 | return ntStat;
81 |
82 | case IRP_MN_REMOVE_DEVICE:
83 | {
84 | PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData;
85 | DkDbgStr("IRP_MN_REMOVE_DEVICE");
86 |
87 | IoSkipCurrentIrpStackLocation(pIrp);
88 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
89 |
90 | if (pDeviceData != NULL &&
91 | pDeviceData->pRootData != NULL &&
92 | pDeviceData->pRootData->controlDevice != NULL)
93 | {
94 | USBPcapDeleteRootHubControlDevice(pDeviceData->pRootData->controlDevice);
95 | }
96 |
97 | IoReleaseRemoveLockAndWait(&pDevExt->removeLock, (PVOID) pIrp);
98 |
99 | DkDetachAndDeleteHubFilt(pDevExt);
100 |
101 | return ntStat;
102 | }
103 |
104 | case IRP_MN_QUERY_DEVICE_RELATIONS:
105 | DkDbgStr("IRP_MN_QUERY_DEVICE_RELATIONS");
106 | ntStat = DkHubFltPnpHandleQryDevRels(pDevExt, pStack, pIrp);
107 |
108 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
109 | return ntStat;
110 |
111 | default:
112 | DkDbgVal("", pStack->MinorFunction);
113 | break;
114 |
115 | }
116 |
117 | if (pDevExt->pNextDevObj == NULL)
118 | {
119 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
120 | DkCompleteRequest(pIrp, ntStat, 0);
121 | }
122 | else
123 | {
124 | IoSkipCurrentIrpStackLocation(pIrp);
125 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
126 | }
127 |
128 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
129 |
130 | return ntStat;
131 | }
132 |
133 | NTSTATUS DkTgtPnP(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp)
134 | {
135 | NTSTATUS ntStat = STATUS_SUCCESS;
136 | PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData;
137 |
138 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
139 | if (!NT_SUCCESS(ntStat))
140 | {
141 | DkDbgVal("Error lock!", ntStat);
142 | DkCompleteRequest(pIrp, ntStat, 0);
143 | return ntStat;
144 | }
145 |
146 | switch (pStack->MinorFunction)
147 | {
148 | case IRP_MN_START_DEVICE:
149 | /* IRP_MN_START_DEVICE is sent at PASSIVE_LEVEL */
150 | DkDbgStr("IRP_MN_START_DEVICE");
151 |
152 | ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp);
153 | IoCompleteRequest(pIrp, IO_NO_INCREMENT);
154 |
155 | if (NT_SUCCESS(USBPcapGetDeviceUSBInfo(pDevExt)))
156 | {
157 | DkDbgVal("Started device", pDeviceData->deviceAddress);
158 | }
159 | else
160 | {
161 | DkDbgStr("Failed to get info of started device");
162 | }
163 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
164 | return ntStat;
165 |
166 | case IRP_MN_QUERY_DEVICE_RELATIONS:
167 | /* Keep track of, and create child devices only for hubs.
168 | * Do not create child filters for composite devices.
169 | */
170 | if (pDeviceData->isHub == TRUE)
171 | {
172 | DkDbgStr("IRP_MN_QUERY_DEVICE_RELATIONS");
173 | ntStat = DkHubFltPnpHandleQryDevRels(pDevExt, pStack, pIrp);
174 |
175 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
176 | return ntStat;
177 | }
178 | else
179 | {
180 | break;
181 | }
182 |
183 | case IRP_MN_REMOVE_DEVICE:
184 | DkDbgStr("IRP_MN_REMOVE_DEVICE");
185 |
186 | IoSkipCurrentIrpStackLocation(pIrp);
187 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
188 |
189 | IoReleaseRemoveLockAndWait(&pDevExt->removeLock, (PVOID) pIrp);
190 |
191 | DkDetachAndDeleteTgt(pDevExt);
192 |
193 | return ntStat;
194 |
195 |
196 | default:
197 | DkDbgVal("", pStack->MinorFunction);
198 | break;
199 |
200 | }
201 |
202 | if (pDevExt->pNextDevObj == NULL)
203 | {
204 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
205 | DkCompleteRequest(pIrp, ntStat, 0);
206 | }
207 | else
208 | {
209 | IoSkipCurrentIrpStackLocation(pIrp);
210 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
211 | }
212 |
213 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
214 |
215 | return ntStat;
216 | }
217 |
218 | NTSTATUS DkHubFltPnpHandleQryDevRels(PDEVICE_EXTENSION pDevExt, PIO_STACK_LOCATION pStack, PIRP pIrp)
219 | {
220 | NTSTATUS ntStat = STATUS_SUCCESS;
221 | PDEVICE_RELATIONS pDevRel = NULL;
222 | PUSBPCAP_DEVICE_DATA pDeviceData = pDevExt->context.usb.pDeviceData;
223 | ULONG i;
224 |
225 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
226 | if (!NT_SUCCESS(ntStat))
227 | {
228 | DkDbgVal("Error lock!", ntStat);
229 | DkCompleteRequest(pIrp, ntStat, 0);
230 | return ntStat;
231 | }
232 |
233 | /* PnP manager sends this at PASSIVE_LEVEL */
234 | switch (pStack->Parameters.QueryDeviceRelations.Type)
235 | {
236 | case BusRelations:
237 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: BusRelations");
238 |
239 | ntStat = DkForwardAndWait(pDevExt->pNextDevObj, pIrp);
240 |
241 | // After we forward the request, the bus driver have created or deleted
242 | // a child device object. When bus driver created one (or more), this is the PDO
243 | // of our target device, we create and attach a filter object to it.
244 | // Note that we only attach the last detected USB device on it's Hub.
245 | if (NT_SUCCESS(ntStat))
246 | {
247 | pDevRel = (PDEVICE_RELATIONS) pIrp->IoStatus.Information;
248 | if (pDevRel)
249 | {
250 | USBPcapPrintUSBPChildrenInformation(pDevExt->pNextDevObj);
251 |
252 | DkDbgVal("Child(s) number", pDevRel->Count);
253 |
254 | for (i = 0; i < pDevRel->Count; i++)
255 | {
256 | PDEVICE_OBJECT *child;
257 | BOOLEAN found = FALSE;
258 |
259 | child = pDeviceData->previousChildren;
260 |
261 | /* Search only if there are any children */
262 | if (child != NULL)
263 | {
264 | while (*child != NULL)
265 | {
266 | if (*child == pDevRel->Objects[i])
267 | {
268 | found = TRUE;
269 | break;
270 | }
271 | child++;
272 | }
273 | }
274 |
275 | if (found == FALSE)
276 | {
277 | /* New device attached */
278 | DkCreateAndAttachTgt(pDevExt,
279 | pDevRel->Objects[i]);
280 | }
281 | }
282 |
283 | /* Free old children information */
284 | if (pDeviceData->previousChildren != NULL)
285 | {
286 | ExFreePool(pDeviceData->previousChildren);
287 | pDeviceData->previousChildren = NULL;
288 | }
289 |
290 | if (pDevRel->Count > 0)
291 | {
292 | PDEVICE_OBJECT *children;
293 |
294 | children =
295 | ExAllocatePoolWithTag(NonPagedPool,
296 | sizeof(PDEVICE_OBJECT) *
297 | (pDevRel->Count + 1),
298 | DKPORT_MTAG);
299 |
300 | if (children != NULL)
301 | {
302 | for (i = 0; i < pDevRel->Count; i++)
303 | {
304 | children[i] = pDevRel->Objects[i];
305 | }
306 |
307 | /* NULL-terminate the array */
308 | children[pDevRel->Count] = NULL;
309 |
310 | pDeviceData->previousChildren = children;
311 | }
312 | else
313 | {
314 | /* Failed to allocate memory. Just leave it
315 | * as it. In next pass we won't check for
316 | * new devices (probably will miss some).
317 | * But it's probably the best we can do.
318 | */
319 | DkDbgStr("Failed to allocate previousChildren");
320 | }
321 | }
322 | }
323 | }
324 |
325 | IoCompleteRequest(pIrp, IO_NO_INCREMENT);
326 |
327 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
328 |
329 | return ntStat;
330 |
331 |
332 | case EjectionRelations:
333 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: EjectionRelations");
334 | break;
335 | case RemovalRelations:
336 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: RemovalRelations");
337 | break;
338 | case TargetDeviceRelation:
339 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: TargetDeviceRelation");
340 | break;
341 | case PowerRelations:
342 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: PowerRelations");
343 | break;
344 | case SingleBusRelations:
345 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: SingleBusRelations");
346 | break;
347 | case TransportRelations:
348 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: TransportRelations");
349 | break;
350 |
351 | default:
352 | DkDbgStr("PnP, IRP_MN_QUERY_DEVICE_RELATIONS: Unknown query relation type");
353 | break;
354 | }
355 |
356 | if (pDevExt->pNextDevObj == NULL)
357 | {
358 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
359 | DkCompleteRequest(pIrp, ntStat, 0);
360 | }
361 | else
362 | {
363 | IoSkipCurrentIrpStackLocation(pIrp);
364 | ntStat = IoCallDriver(pDevExt->pNextDevObj, pIrp);
365 | }
366 |
367 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
368 |
369 | return ntStat;
370 | }
371 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapPower.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #include "USBPcapMain.h"
8 |
9 | NTSTATUS DkPower(PDEVICE_OBJECT pDevObj, PIRP pIrp)
10 | {
11 | NTSTATUS ntStat = STATUS_SUCCESS;
12 | PDEVICE_EXTENSION pDevExt = NULL;
13 | PIO_STACK_LOCATION pStack = NULL;
14 | PDEVICE_OBJECT pNextDevObj = NULL;
15 | PCHAR pTmp = NULL;
16 |
17 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
18 | ntStat = IoAcquireRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
19 | if (!NT_SUCCESS(ntStat))
20 | {
21 | DkDbgVal("Error acquire lock!", ntStat);
22 | DkCompleteRequest(pIrp, ntStat, 0);
23 | return ntStat;
24 | }
25 |
26 | pStack = IoGetCurrentIrpStackLocation(pIrp);
27 |
28 | pNextDevObj = pDevExt->pNextDevObj;
29 |
30 | if (pDevExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB)
31 | {
32 | pTmp = "Root Hub Filter";
33 | }
34 | else if (pDevExt->deviceMagic == USBPCAP_MAGIC_DEVICE)
35 | {
36 | pTmp = "Device";
37 | }
38 | else
39 | {
40 | pTmp = "Global";
41 | }
42 |
43 | switch (pStack->MinorFunction)
44 | {
45 | case IRP_MN_POWER_SEQUENCE:
46 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_POWER_SEQUENCE\n", __FUNCTION__, pTmp));
47 | break;
48 |
49 | case IRP_MN_QUERY_POWER:
50 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_QUERY_POWER\n", __FUNCTION__, pTmp));
51 | break;
52 |
53 | case IRP_MN_SET_POWER:
54 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_SET_POWER\n", __FUNCTION__, pTmp));
55 | break;
56 |
57 | case IRP_MN_WAIT_WAKE:
58 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_WAIT_WAKE\n", __FUNCTION__, pTmp));
59 | break;
60 |
61 | default:
62 | KdPrint(("USBPcap, %s(): %s -> IRP_MN_XXX (0x%X)\n", __FUNCTION__, pTmp, pStack->MinorFunction));
63 | break;
64 | }
65 |
66 | if (pDevExt->pNextDevObj == NULL)
67 | {
68 | ntStat = STATUS_INVALID_DEVICE_REQUEST;
69 | DkCompleteRequest(pIrp, ntStat, 0);
70 | return ntStat;
71 | }
72 |
73 | #if (NTDDI_VERSION < NTDDI_VISTA)
74 | PoStartNextPowerIrp(pIrp);
75 | #endif
76 |
77 | IoSkipCurrentIrpStackLocation(pIrp);
78 |
79 | #if (NTDDI_VERSION < NTDDI_VISTA)
80 | ntStat = PoCallDriver(pNextDevObj, pIrp);
81 | #else
82 | ntStat = IoCallDriver(pNextDevObj, pIrp);
83 | #endif
84 |
85 | IoReleaseRemoveLock(&pDevExt->removeLock, (PVOID) pIrp);
86 |
87 | return ntStat;
88 | }
89 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapQueue.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #include "USBPcapMain.h"
8 | #include "USBPcapQueue.h"
9 |
10 | VOID DkCsqInsertIrp(__in PIO_CSQ pCsq, __in PIRP pIrp)
11 | {
12 | PDEVICE_EXTENSION pDevExt = NULL;
13 |
14 | pDevExt = CONTAINING_RECORD(pCsq, DEVICE_EXTENSION,
15 | context.control.ioCsq);
16 |
17 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL);
18 |
19 | InsertTailList(&pDevExt->context.control.lePendIrp,
20 | &pIrp->Tail.Overlay.ListEntry);
21 | }
22 |
23 | VOID DkCsqRemoveIrp(__in PIO_CSQ pCsq, __in PIRP pIrp)
24 | {
25 | BOOLEAN bRes = FALSE;
26 |
27 | UNREFERENCED_PARAMETER(pCsq);
28 |
29 | bRes = RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
30 | }
31 |
32 | PIRP DkCsqPeekNextIrp(__in PIO_CSQ pCsq, __in PIRP pIrp, __in PVOID pCtx)
33 | {
34 | PDEVICE_EXTENSION pDevExt = NULL;
35 | PIRP pNextIrp = NULL;
36 | PLIST_ENTRY pNextList = NULL, pHeadList = NULL;
37 | PIO_STACK_LOCATION pStack = NULL;
38 |
39 | pDevExt = CONTAINING_RECORD(pCsq, DEVICE_EXTENSION,
40 | context.control.ioCsq);
41 |
42 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL);
43 |
44 | pHeadList = &pDevExt->context.control.lePendIrp;
45 |
46 | if (pIrp == NULL)
47 | {
48 | pNextList = pHeadList->Flink;
49 | }
50 | else
51 | {
52 | pNextList = pIrp->Tail.Overlay.ListEntry.Flink;
53 | }
54 |
55 | while (pNextList != pHeadList)
56 | {
57 | pNextIrp = CONTAINING_RECORD(pNextList, IRP, Tail.Overlay.ListEntry);
58 | pStack = IoGetCurrentIrpStackLocation(pNextIrp);
59 | if (pCtx)
60 | {
61 | if (pStack->FileObject == (PFILE_OBJECT)pCtx)
62 | {
63 | break;
64 | }
65 | }
66 | else
67 | {
68 | break;
69 | }
70 | pNextIrp = NULL;
71 | pNextList = pNextList->Flink;
72 | }
73 |
74 | return pNextIrp;
75 | }
76 |
77 | __drv_raisesIRQL(DISPATCH_LEVEL)
78 | __drv_maxIRQL(DISPATCH_LEVEL)
79 | VOID DkCsqAcquireLock(__in PIO_CSQ pCsq, __out __drv_out_deref(__drv_savesIRQL) PKIRQL pKIrql)
80 | {
81 | PDEVICE_EXTENSION pDevExt = NULL;
82 |
83 | pDevExt = CONTAINING_RECORD(pCsq, DEVICE_EXTENSION,
84 | context.control.ioCsq);
85 |
86 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL);
87 |
88 | KeAcquireSpinLock(&pDevExt->context.control.csqSpinLock, pKIrql);
89 | }
90 |
91 | __drv_requiresIRQL(DISPATCH_LEVEL)
92 | VOID DkCsqReleaseLock(__in PIO_CSQ pCsq, __in __drv_in(__drv_restoresIRQL) KIRQL kIrql)
93 | {
94 | PDEVICE_EXTENSION pDevExt = NULL;
95 |
96 | pDevExt = CONTAINING_RECORD(pCsq, DEVICE_EXTENSION,
97 | context.control.ioCsq);
98 |
99 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL);
100 |
101 | KeReleaseSpinLock(&pDevExt->context.control.csqSpinLock, kIrql);
102 | }
103 |
104 | VOID DkCsqCompleteCanceledIrp(__in PIO_CSQ pCsq, __in PIRP pIrp)
105 | {
106 | UNREFERENCED_PARAMETER(pCsq);
107 |
108 | pIrp->IoStatus.Status = STATUS_CANCELLED;
109 | pIrp->IoStatus.Information = 0;
110 | IoCompleteRequest(pIrp, IO_NO_INCREMENT);
111 | }
112 |
113 | VOID DkCsqCleanUpQueue(PDEVICE_OBJECT pDevObj, PIRP pIrp)
114 | {
115 | PIO_STACK_LOCATION pStack = NULL;
116 | PDEVICE_EXTENSION pDevExt = NULL;
117 | PIRP pPendIrp = NULL;
118 |
119 | pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
120 |
121 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL);
122 |
123 | pStack = IoGetCurrentIrpStackLocation(pIrp);
124 |
125 | while (TRUE)
126 | {
127 | pPendIrp = IoCsqRemoveNextIrp(&pDevExt->context.control.ioCsq,
128 | (PVOID)pStack->FileObject);
129 | if (pPendIrp == NULL)
130 | {
131 | break;
132 | }
133 | else
134 | {
135 | DkCsqCompleteCanceledIrp(&pDevExt->context.control.ioCsq,
136 | pPendIrp);
137 | }
138 | }
139 | }
140 |
141 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapQueue.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #ifndef USBPCAP_QUEUE_H
8 | #define USBPCAP_QUEUE_H
9 |
10 | #include "Wdm.h"
11 | #include "include\USBPcap.h"
12 |
13 | __drv_raisesIRQL(DISPATCH_LEVEL)
14 | __drv_maxIRQL(DISPATCH_LEVEL)
15 | VOID DkCsqAcquireLock(__in PIO_CSQ pCsq, __out __drv_out_deref(__drv_savesIRQL) PKIRQL pKIrql);
16 |
17 | __drv_requiresIRQL(DISPATCH_LEVEL)
18 | VOID DkCsqReleaseLock(__in PIO_CSQ pCsq, __in __drv_in(__drv_restoresIRQL) KIRQL kIrql);
19 |
20 | IO_CSQ_INSERT_IRP DkCsqInsertIrp;
21 | IO_CSQ_REMOVE_IRP DkCsqRemoveIrp;
22 | IO_CSQ_PEEK_NEXT_IRP DkCsqPeekNextIrp;
23 | IO_CSQ_COMPLETE_CANCELED_IRP DkCsqCompleteCanceledIrp;
24 |
25 | VOID DkCsqCleanUpQueue(PDEVICE_OBJECT pDevObj, PIRP pIrp);
26 |
27 | #endif /* USBPCAP_QUEUE_H */
28 |
29 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapRootHubControl.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #include "USBPcapMain.h"
8 | #include
9 | #include "USBPcapRootHubControl.h"
10 | #include "Ntstrsafe.h"
11 |
12 | extern ULONG volatile g_controlId;
13 |
14 | #define NTNAME_PREFIX L"\\Device\\USBPcap"
15 | #define SYMBOLIC_PREFIX L"\\DosDevices\\USBPcap"
16 | #define MAX_CONTROL_ID L"65535"
17 |
18 | #define MAX_NTNAME_LEN (sizeof(NTNAME_PREFIX)+sizeof(MAX_CONTROL_ID))
19 | #define MAX_SYMBOLIC_LEN (sizeof(SYMBOLIC_PREFIX)+sizeof(MAX_CONTROL_ID))
20 |
21 | DECLARE_CONST_UNICODE_STRING(
22 | SDDL_DEVOBJ_SYS_ALL_ADM_ALL_EVERYONE_ANY,
23 | L"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GX;;;WD)(A;;GX;;;RC)"
24 | );
25 |
26 | __drv_requiresIRQL(PASSIVE_LEVEL)
27 | NTSTATUS USBPcapCreateRootHubControlDevice(IN PDEVICE_EXTENSION hubExt,
28 | OUT PDEVICE_OBJECT *control,
29 | OUT USHORT *busId)
30 | {
31 | UNICODE_STRING ntDeviceName;
32 | UNICODE_STRING symbolicLinkName;
33 | PDEVICE_OBJECT controlDevice = NULL;
34 | PDEVICE_EXTENSION controlExt = NULL;
35 | NTSTATUS status;
36 | USHORT id;
37 | PWCHAR ntNameBuffer[MAX_NTNAME_LEN];
38 | PWCHAR symbolicNameBuffer[MAX_SYMBOLIC_LEN];
39 |
40 | ASSERT(hubExt->deviceMagic == USBPCAP_MAGIC_ROOTHUB);
41 |
42 | /* Acquire the control device ID */
43 | id = (USHORT) InterlockedIncrement(&g_controlId);
44 |
45 | ntDeviceName.Length = 0;
46 | ntDeviceName.MaximumLength = MAX_NTNAME_LEN;
47 | ntDeviceName.Buffer = (PWSTR)ntNameBuffer;
48 |
49 | symbolicLinkName.Length = 0;
50 | symbolicLinkName.MaximumLength = MAX_SYMBOLIC_LEN;
51 | symbolicLinkName.Buffer = (PWSTR)symbolicNameBuffer;
52 |
53 | status = RtlUnicodeStringPrintf(&ntDeviceName,
54 | NTNAME_PREFIX L"%hu", id);
55 | if (!NT_SUCCESS(status))
56 | {
57 | return status;
58 | }
59 |
60 | status = RtlUnicodeStringPrintf(&symbolicLinkName,
61 | SYMBOLIC_PREFIX L"%hu", id);
62 | if (!NT_SUCCESS(status))
63 | {
64 | return status;
65 | }
66 |
67 | KdPrint(("Creating device %wZ (%wZ)\n",
68 | &ntDeviceName, &symbolicLinkName));
69 |
70 | status = IoCreateDeviceSecure(hubExt->pDrvObj,
71 | sizeof(DEVICE_EXTENSION),
72 | &ntDeviceName,
73 | FILE_DEVICE_UNKNOWN,
74 | FILE_DEVICE_SECURE_OPEN,
75 | FALSE, /* Non-Exclusive device */
76 | &SDDL_DEVOBJ_SYS_ALL_ADM_ALL_EVERYONE_ANY,
77 | NULL,
78 | &controlDevice);
79 |
80 | if (NT_SUCCESS(status))
81 | {
82 | controlDevice->Flags |= DO_DIRECT_IO;
83 |
84 | status = IoCreateSymbolicLink(&symbolicLinkName, &ntDeviceName);
85 |
86 | if (!NT_SUCCESS(status))
87 | {
88 | IoDeleteDevice(controlDevice);
89 | KdPrint(("IoCreateSymbolicLink failed %x\n", status));
90 | return status;
91 | }
92 |
93 | controlExt = (PDEVICE_EXTENSION)controlDevice->DeviceExtension;
94 | controlExt->deviceMagic = USBPCAP_MAGIC_CONTROL;
95 | controlExt->pThisDevObj = controlDevice;
96 | controlExt->pNextDevObj = NULL;
97 | controlExt->pDrvObj = hubExt->pDrvObj;
98 |
99 | IoInitializeRemoveLock(&controlExt->removeLock, 0, 0, 0);
100 | controlExt->parentRemoveLock = &hubExt->removeLock;
101 |
102 | /* Initialize USBPcap control context */
103 | controlExt->context.control.id = id;
104 | controlExt->context.control.pRootHubObject = hubExt->pThisDevObj;
105 | controlExt->context.control.pCaptureObject = NULL;
106 |
107 |
108 | KeInitializeSpinLock(&controlExt->context.control.csqSpinLock);
109 | InitializeListHead(&controlExt->context.control.lePendIrp);
110 | status = IoCsqInitialize(&controlExt->context.control.ioCsq,
111 | DkCsqInsertIrp, DkCsqRemoveIrp,
112 | DkCsqPeekNextIrp, DkCsqAcquireLock,
113 | DkCsqReleaseLock, DkCsqCompleteCanceledIrp);
114 | if (!NT_SUCCESS(status))
115 | {
116 | DkDbgVal("Error initialize Cancel-safe queue!", status);
117 | goto End;
118 | }
119 |
120 | controlDevice->Flags &= ~DO_DEVICE_INITIALIZING;
121 | }
122 | else
123 | {
124 | KdPrint(("IoCreateDevice failed %x\n", status));
125 | }
126 |
127 | End:
128 | if ((!NT_SUCCESS(status)) || (controlExt == NULL))
129 | {
130 | if (controlDevice != NULL)
131 | {
132 | IoDeleteSymbolicLink(&symbolicLinkName);
133 | IoDeleteDevice(controlDevice);
134 | }
135 | }
136 | else
137 | {
138 | IoAcquireRemoveLock(controlExt->parentRemoveLock, NULL);
139 | *control = controlDevice;
140 | *busId = id;
141 | }
142 |
143 | return status;
144 | }
145 |
146 |
147 | VOID USBPcapDeleteRootHubControlDevice(IN PDEVICE_OBJECT controlDevice)
148 | {
149 | UNICODE_STRING symbolicLinkName;
150 | PWCHAR symbolicNameBuffer[MAX_SYMBOLIC_LEN];
151 | USHORT id;
152 | PDEVICE_EXTENSION pDevExt;
153 | NTSTATUS status;
154 |
155 | pDevExt = ((PDEVICE_EXTENSION)controlDevice->DeviceExtension);
156 |
157 | ASSERT(pDevExt->deviceMagic == USBPCAP_MAGIC_CONTROL);
158 |
159 | id = pDevExt->context.control.id;
160 |
161 | symbolicLinkName.Length = 0;
162 | symbolicLinkName.MaximumLength = MAX_SYMBOLIC_LEN;
163 | symbolicLinkName.Buffer = (PWSTR)symbolicNameBuffer;
164 |
165 | status = RtlUnicodeStringPrintf(&symbolicLinkName,
166 | SYMBOLIC_PREFIX L"%hu", id);
167 |
168 | IoAcquireRemoveLock(&pDevExt->removeLock, NULL);
169 | IoReleaseRemoveLockAndWait(&pDevExt->removeLock, NULL);
170 |
171 | IoReleaseRemoveLock(pDevExt->parentRemoveLock, NULL);
172 |
173 | ASSERT(NT_SUCCESS(status));
174 | if (NT_SUCCESS(status))
175 | {
176 | IoDeleteSymbolicLink(&symbolicLinkName);
177 | IoDeleteDevice(controlDevice);
178 | }
179 | else
180 | {
181 | /* Very bad */
182 | KdPrint(("Failed to init symbolic link name\n"));
183 |
184 | pDevExt->context.control.pRootHubObject = NULL;
185 | }
186 | }
187 |
188 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapRootHubControl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #ifndef USBPCAP_ROOTHUB_CONTROL_H
8 | #define USBPCAP_ROOTHUB_CONTROL_H
9 |
10 | #include "USBPcapMain.h"
11 |
12 | NTSTATUS USBPcapCreateRootHubControlDevice(IN PDEVICE_EXTENSION hubExt,
13 | OUT PDEVICE_OBJECT *control,
14 | OUT USHORT *busId);
15 |
16 | VOID USBPcapDeleteRootHubControlDevice(IN PDEVICE_OBJECT controlDevice);
17 |
18 | #endif /* USBPCAP_ROOTHUB_CONTROL_H */
19 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapTables.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #include "USBPcapMain.h"
8 | #include "USBPcapTables.h"
9 |
10 | #define USBPCAP_TABLE_TAG ' BAT'
11 |
12 | typedef struct _USBPCAP_INTERNAL_ENDPOINT_INFO
13 | {
14 | RTL_SPLAY_LINKS links;
15 | LIST_ENTRY entry;
16 | USBPCAP_ENDPOINT_INFO info;
17 | } USBPCAP_INTERNAL_ENDPOINT_INFO, *PUSBPCAP_INTERNAL_ENDPOINT_INFO;
18 |
19 | VOID USBPcapRemoveEndpointInfo(IN PRTL_GENERIC_TABLE table,
20 | IN USBD_PIPE_HANDLE handle)
21 | {
22 | USBPCAP_INTERNAL_ENDPOINT_INFO info;
23 | BOOLEAN deleted;
24 |
25 | info.info.handle = handle;
26 |
27 | deleted = RtlDeleteElementGenericTable(table, &info);
28 |
29 | if (deleted == TRUE)
30 | {
31 | DkDbgVal("Successfully removed", handle);
32 | }
33 | else
34 | {
35 | DkDbgVal("Failed to remove", handle);
36 | }
37 | }
38 |
39 | VOID USBPcapAddEndpointInfo(IN PRTL_GENERIC_TABLE table,
40 | IN PUSBD_PIPE_INFORMATION pipeInfo,
41 | IN USHORT deviceAddress)
42 | {
43 | USBPCAP_INTERNAL_ENDPOINT_INFO info;
44 | BOOLEAN new;
45 | PUSBPCAP_INTERNAL_ENDPOINT_INFO pInfo;
46 |
47 | info.info.handle = pipeInfo->PipeHandle;
48 | info.info.type = pipeInfo->PipeType;
49 | info.info.endpointAddress = pipeInfo->EndpointAddress;
50 | info.info.deviceAddress = deviceAddress;
51 |
52 | pInfo = RtlInsertElementGenericTable(table,
53 | (PVOID)&info,
54 | sizeof(USBPCAP_INTERNAL_ENDPOINT_INFO),
55 | &new);
56 |
57 | if ((new == FALSE) && (pInfo != NULL))
58 | {
59 | DkDbgStr("Element already exists in table, updating entry");
60 | pInfo->info.type = pipeInfo->PipeType;
61 | pInfo->info.endpointAddress = pipeInfo->EndpointAddress;
62 | pInfo->info.deviceAddress = deviceAddress;
63 | }
64 | }
65 |
66 | /*
67 | * Retrieves the USBPCAP_ENDPOINT_INFO information from endpoint table.
68 | *
69 | * Returns NULL when no such endpoint information was found
70 | */
71 | PUSBPCAP_ENDPOINT_INFO USBPcapGetEndpointInfo(IN PRTL_GENERIC_TABLE table,
72 | IN USBD_PIPE_HANDLE handle)
73 | {
74 | PUSBPCAP_INTERNAL_ENDPOINT_INFO pInfo;
75 | USBPCAP_INTERNAL_ENDPOINT_INFO info;
76 |
77 | info.info.handle = handle;
78 |
79 | pInfo = RtlLookupElementGenericTable(table, &info);
80 |
81 | if (pInfo == NULL)
82 | {
83 | return NULL;
84 | }
85 |
86 | return &pInfo->info;
87 | }
88 |
89 | RTL_GENERIC_FREE_ROUTINE USBPcapFreeRoutine;
90 | static VOID
91 | USBPcapFreeRoutine(IN PRTL_GENERIC_TABLE table,
92 | IN PVOID buffer)
93 | {
94 | ExFreePool(buffer);
95 | }
96 |
97 | RTL_GENERIC_ALLOCATE_ROUTINE USBPcapAllocateRoutine;
98 | static PVOID
99 | USBPcapAllocateRoutine(IN PRTL_GENERIC_TABLE table,
100 | IN CLONG size)
101 | {
102 | return ExAllocatePoolWithTag(NonPagedPool,
103 | size,
104 | USBPCAP_TABLE_TAG);
105 | }
106 |
107 | RTL_GENERIC_COMPARE_ROUTINE USBPcapCompareEndpointInfo;
108 | static RTL_GENERIC_COMPARE_RESULTS
109 | USBPcapCompareEndpointInfo(IN PRTL_GENERIC_TABLE table,
110 | IN PVOID first,
111 | IN PVOID second)
112 | {
113 | PUSBPCAP_INTERNAL_ENDPOINT_INFO left = first;
114 | PUSBPCAP_INTERNAL_ENDPOINT_INFO right = second;
115 |
116 | if (left->info.handle < right->info.handle)
117 | {
118 | return GenericLessThan;
119 | }
120 | else if (left->info.handle == right->info.handle)
121 | {
122 | return GenericEqual;
123 | }
124 | else
125 | {
126 | return GenericGreaterThan;
127 | }
128 | }
129 |
130 | VOID USBPcapFreeEndpointTable(IN PRTL_GENERIC_TABLE table)
131 | {
132 | PVOID element;
133 |
134 | DkDbgStr("Free endpoint data");
135 |
136 | /* Delete all the elements from table */
137 | while (NULL != (element = RtlGetElementGenericTable(table, 0)))
138 | {
139 | RtlDeleteElementGenericTable(table, element);
140 | }
141 |
142 | /* Delete table structure */
143 | ExFreePool(table);
144 | }
145 |
146 | /*
147 | * Initializes endpoint table.
148 | * Returns NULL if there are no sufficient resources availble.
149 | *
150 | * Returned table must be freed using USBPcapFreeEndpointTable()
151 | */
152 | PRTL_GENERIC_TABLE USBPcapInitializeEndpointTable(IN PVOID context)
153 | {
154 | PRTL_GENERIC_TABLE table;
155 |
156 | DkDbgStr("Initialize endpoint table");
157 |
158 | table = (PRTL_GENERIC_TABLE)
159 | ExAllocatePoolWithTag(NonPagedPool,
160 | sizeof(RTL_GENERIC_TABLE),
161 | USBPCAP_TABLE_TAG);
162 |
163 | if (table == NULL)
164 | {
165 | DkDbgStr("Unable to allocate endpoint table");
166 | return table;
167 | }
168 |
169 | RtlInitializeGenericTable(table,
170 | USBPcapCompareEndpointInfo,
171 | USBPcapAllocateRoutine,
172 | USBPcapFreeRoutine,
173 | context);
174 |
175 | return table;
176 | }
177 |
178 | BOOLEAN USBPcapRetrieveEndpointInfo(IN PUSBPCAP_DEVICE_DATA pDeviceData,
179 | IN USBD_PIPE_HANDLE handle,
180 | PUSBPCAP_ENDPOINT_INFO pInfo)
181 | {
182 | KIRQL irql;
183 | PUSBPCAP_ENDPOINT_INFO info;
184 | BOOLEAN found = FALSE;
185 |
186 | KeAcquireSpinLock(&pDeviceData->tablesSpinLock, &irql);
187 | info = USBPcapGetEndpointInfo(pDeviceData->endpointTable, handle);
188 | if (info != NULL)
189 | {
190 | found = TRUE;
191 | memcpy(pInfo, info, sizeof(USBPCAP_ENDPOINT_INFO));
192 | }
193 | KeReleaseSpinLock(&pDeviceData->tablesSpinLock, irql);
194 |
195 | if (found == TRUE)
196 | {
197 | DkDbgVal("Found endpoint info", handle);
198 | DkDbgVal("", pInfo->type);
199 | DkDbgVal("", pInfo->endpointAddress);
200 | DkDbgVal("", pInfo->deviceAddress);
201 | }
202 | else
203 | {
204 | DkDbgVal("Unable to find endpoint info", handle);
205 | }
206 |
207 | return found;
208 | }
209 |
210 |
211 | typedef struct _USBPCAP_INTERNAL_URB_IRP_INFO
212 | {
213 | RTL_SPLAY_LINKS links;
214 | LIST_ENTRY entry;
215 | USBPCAP_URB_IRP_INFO info;
216 | } USBPCAP_INTERNAL_URB_IRP_INFO, *PUSBPCAP_INTERNAL_URB_IRP_INFO;
217 |
218 | VOID USBPcapRemoveURBIRPInfo(IN PRTL_GENERIC_TABLE table,
219 | IN PIRP irp)
220 | {
221 | USBPCAP_INTERNAL_URB_IRP_INFO info;
222 | BOOLEAN deleted;
223 |
224 | info.info.irp = irp;
225 |
226 | deleted = RtlDeleteElementGenericTable(table, &info);
227 |
228 | if (deleted == TRUE)
229 | {
230 | DkDbgVal("Successfully removed irp from table", irp);
231 | }
232 | }
233 |
234 | VOID USBPcapAddURBIRPInfo(IN PRTL_GENERIC_TABLE table,
235 | IN PUSBPCAP_URB_IRP_INFO irpinfo)
236 | {
237 | USBPCAP_INTERNAL_URB_IRP_INFO info;
238 | BOOLEAN new;
239 |
240 | info.info = *irpinfo;
241 |
242 | RtlInsertElementGenericTable(table,
243 | (PVOID)&info,
244 | sizeof(USBPCAP_INTERNAL_URB_IRP_INFO),
245 | &new);
246 |
247 | if (new == FALSE)
248 | {
249 | DkDbgVal("Element already exists in table", irpinfo->irp);
250 | }
251 | }
252 |
253 | static PUSBPCAP_URB_IRP_INFO
254 | USBPcapGetURBIRPInfo(IN PRTL_GENERIC_TABLE table,
255 | IN PIRP irp)
256 | {
257 | PUSBPCAP_INTERNAL_URB_IRP_INFO pInfo;
258 | USBPCAP_INTERNAL_URB_IRP_INFO info;
259 |
260 | info.info.irp = irp;
261 |
262 | pInfo = RtlLookupElementGenericTable(table, &info);
263 |
264 | if (pInfo == NULL)
265 | {
266 | return NULL;
267 | }
268 |
269 | return &pInfo->info;
270 | }
271 |
272 | VOID USBPcapFreeURBIRPInfoTable(IN PRTL_GENERIC_TABLE table)
273 | {
274 | PVOID element;
275 |
276 | DkDbgStr("Free URB irp data");
277 |
278 | /* Delete all the elements from table */
279 | while (NULL != (element = RtlGetElementGenericTable(table, 0)))
280 | {
281 | RtlDeleteElementGenericTable(table, element);
282 | }
283 |
284 | /* Delete table structure */
285 | ExFreePool(table);
286 | }
287 |
288 | RTL_GENERIC_COMPARE_ROUTINE USBPcapCompareURBIRPInfo;
289 | static RTL_GENERIC_COMPARE_RESULTS
290 | USBPcapCompareURBIRPInfo(IN PRTL_GENERIC_TABLE table,
291 | IN PVOID first,
292 | IN PVOID second)
293 | {
294 | PUSBPCAP_INTERNAL_URB_IRP_INFO left = first;
295 | PUSBPCAP_INTERNAL_URB_IRP_INFO right = second;
296 |
297 | if (left->info.irp < right->info.irp)
298 | {
299 | return GenericLessThan;
300 | }
301 | else if (left->info.irp == right->info.irp)
302 | {
303 | return GenericEqual;
304 | }
305 | else
306 | {
307 | return GenericGreaterThan;
308 | }
309 | }
310 |
311 | PRTL_GENERIC_TABLE USBPcapInitializeURBIRPInfoTable(IN PVOID context)
312 | {
313 | PRTL_GENERIC_TABLE table;
314 |
315 | DkDbgStr("Initialize URB irp table");
316 |
317 | table = (PRTL_GENERIC_TABLE)
318 | ExAllocatePoolWithTag(NonPagedPool,
319 | sizeof(RTL_GENERIC_TABLE),
320 | USBPCAP_TABLE_TAG);
321 |
322 | if (table == NULL)
323 | {
324 | DkDbgStr("Unable to allocate URB irp table");
325 | return table;
326 | }
327 |
328 | RtlInitializeGenericTable(table,
329 | USBPcapCompareURBIRPInfo,
330 | USBPcapAllocateRoutine,
331 | USBPcapFreeRoutine,
332 | context);
333 |
334 | return table;
335 | }
336 |
337 | /* Obtains the URB IRP info from the URB IRP info table
338 | *
339 | * If the value was present in the table, it will be removed.
340 | *
341 | * Returns TRUE if irp was found in table, FALSE otherwise.
342 | */
343 | BOOLEAN USBPcapObtainURBIRPInfo(IN PUSBPCAP_DEVICE_DATA pDeviceData,
344 | IN PIRP irp,
345 | PUSBPCAP_URB_IRP_INFO pInfo)
346 | {
347 | KIRQL irql;
348 | PUSBPCAP_URB_IRP_INFO info;
349 | BOOLEAN found = FALSE;
350 |
351 | KeAcquireSpinLock(&pDeviceData->tablesSpinLock, &irql);
352 | info = USBPcapGetURBIRPInfo(pDeviceData->URBIrpTable, irp);
353 | if (info != NULL)
354 | {
355 | found = TRUE;
356 | memcpy(pInfo, info, sizeof(USBPCAP_URB_IRP_INFO));
357 | USBPcapRemoveURBIRPInfo(pDeviceData->URBIrpTable, irp);
358 | }
359 | KeReleaseSpinLock(&pDeviceData->tablesSpinLock, irql);
360 |
361 | if (found == TRUE)
362 | {
363 | DkDbgVal("Found URB irp info", irp);
364 | DkDbgVal("", pInfo->function);
365 | }
366 |
367 | return found;
368 | }
369 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapTables.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #ifndef USBPCAP_TABLES_H
8 | #define USBPCAP_TABLES_H
9 |
10 | #include "USBPcapMain.h"
11 |
12 | typedef struct _USBPCAP_ENDPOINT_INFO
13 | {
14 | /* handle is used as a key */
15 | USBD_PIPE_HANDLE handle;
16 | USBD_PIPE_TYPE type;
17 | UCHAR endpointAddress;
18 | USHORT deviceAddress;
19 | } USBPCAP_ENDPOINT_INFO, *PUSBPCAP_ENDPOINT_INFO;
20 |
21 | VOID USBPcapRemoveEndpointInfo(IN PRTL_GENERIC_TABLE table,
22 | IN USBD_PIPE_HANDLE handle);
23 | VOID USBPcapAddEndpointInfo(IN PRTL_GENERIC_TABLE table,
24 | IN PUSBD_PIPE_INFORMATION pipeInfo,
25 | IN USHORT deviceAddress);
26 |
27 | PUSBPCAP_ENDPOINT_INFO USBPcapGetEndpointInfo(IN PRTL_GENERIC_TABLE table,
28 | IN USBD_PIPE_HANDLE handle);
29 |
30 | VOID USBPcapFreeEndpointTable(IN PRTL_GENERIC_TABLE table);
31 | PRTL_GENERIC_TABLE USBPcapInitializeEndpointTable(IN PVOID context);
32 |
33 |
34 | BOOLEAN USBPcapRetrieveEndpointInfo(IN PUSBPCAP_DEVICE_DATA pDeviceData,
35 | IN USBD_PIPE_HANDLE handle,
36 | PUSBPCAP_ENDPOINT_INFO pInfo);
37 |
38 | typedef struct _USBPCAP_URB_IRP_INFO
39 | {
40 | /* IRP pointer is used as a key */
41 | PIRP irp;
42 | /* Data collected when the URB was travelling from FDO to PDO */
43 | LARGE_INTEGER timestamp;
44 | USBD_STATUS status;
45 | USHORT function;
46 | UCHAR info; /* I/O Request info */
47 | USHORT bus; /* bus (RootHub) number */
48 | USHORT device; /* device address */
49 | } USBPCAP_URB_IRP_INFO, *PUSBPCAP_URB_IRP_INFO;
50 |
51 | VOID USBPcapRemoveURBIRPInfo(IN PRTL_GENERIC_TABLE table,
52 | IN PIRP irp);
53 | VOID USBPcapAddURBIRPInfo(IN PRTL_GENERIC_TABLE table,
54 | IN PUSBPCAP_URB_IRP_INFO irpinfo);
55 |
56 | VOID USBPcapFreeURBIRPInfoTable(IN PRTL_GENERIC_TABLE table);
57 | PRTL_GENERIC_TABLE USBPcapInitializeURBIRPInfoTable(IN PVOID context);
58 |
59 | BOOLEAN USBPcapObtainURBIRPInfo(IN PUSBPCAP_DEVICE_DATA pDeviceData,
60 | IN PIRP irp,
61 | PUSBPCAP_URB_IRP_INFO pInfo);
62 |
63 | #endif /* USBPCAP_TABLES_H */
64 |
--------------------------------------------------------------------------------
/USBPcapDriver/USBPcapURB.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: GPL-2.0
5 | */
6 |
7 | #ifndef USBPCAP_URB_H
8 | #define USBPCAP_URB_H
9 |
10 | #include "USBPcapMain.h"
11 |
12 | VOID USBPcapAnalyzeURB(PIRP pIrp, PURB pUrb, BOOLEAN post,
13 | PUSBPCAP_DEVICE_DATA pDeviceData);
14 |
15 | #endif /* USBPCAP_URB_H */
16 |
--------------------------------------------------------------------------------
/USBPcapDriver/include/USBPcap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2019 Tomasz Moń
3 | *
4 | * SPDX-License-Identifier: BSD-2-Clause
5 | */
6 |
7 | #ifndef USBPCAP_H
8 | #define USBPCAP_H
9 |
10 | #ifdef __cplusplus
11 | extern "C" {
12 | #endif
13 |
14 | #include
15 |
16 | typedef struct
17 | {
18 | UINT32 size;
19 | } USBPCAP_IOCTL_SIZE, *PUSBPCAP_IOCTL_SIZE;
20 |
21 | #pragma pack(push)
22 | #pragma pack(1)
23 | /* USBPCAP_ADDRESS_FILTER is parameter structure to IOCTL_USBPCAP_START_FILTERING. */
24 | typedef struct _USBPCAP_ADDRESS_FILTER
25 | {
26 | /* Individual device filter bit array. USB standard assigns device
27 | * numbers 1 to 127 (0 is reserved for initial configuration).
28 | *
29 | * If address 0 bit is set, then we will automatically capture from
30 | * newly connected devices.
31 | *
32 | * addresses[0] - 0 - 31
33 | * addresses[1] - 32 - 63
34 | * addresses[2] - 64 - 95
35 | * addresses[3] - 96 - 127
36 | */
37 | UINT32 addresses[4];
38 |
39 | /* Filter all devices */
40 | BOOLEAN filterAll;
41 | } USBPCAP_ADDRESS_FILTER, *PUSBPCAP_ADDRESS_FILTER;
42 | #pragma pack(pop)
43 |
44 | #define IOCTL_USBPCAP_SETUP_BUFFER \
45 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
46 |
47 | #define IOCTL_USBPCAP_START_FILTERING \
48 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
49 |
50 | #define IOCTL_USBPCAP_STOP_FILTERING \
51 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
52 |
53 | #define IOCTL_USBPCAP_GET_HUB_SYMLINK \
54 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
55 |
56 | #define IOCTL_USBPCAP_SET_SNAPLEN_SIZE \
57 | CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_READ_ACCESS)
58 |
59 | /* USB packets, beginning with a USBPcap header */
60 | #define DLT_USBPCAP 249
61 |
62 | #pragma pack(push, 1)
63 | typedef struct pcap_hdr_s {
64 | UINT32 magic_number; /* magic number */
65 | UINT16 version_major; /* major version number */
66 | UINT16 version_minor; /* minor version number */
67 | INT32 thiszone; /* GMT to local correction */
68 | UINT32 sigfigs; /* accuracy of timestamps */
69 | UINT32 snaplen; /* max length of captured packets, in octets */
70 | UINT32 network; /* data link type */
71 | } pcap_hdr_t;
72 | #pragma pack(pop)
73 |
74 | #pragma pack(push, 1)
75 | typedef struct pcaprec_hdr_s {
76 | UINT32 ts_sec; /* timestamp seconds */
77 | UINT32 ts_usec; /* timestamp microseconds */
78 | UINT32 incl_len; /* number of octets of packet saved in file */
79 | UINT32 orig_len; /* actual length of packet */
80 | } pcaprec_hdr_t;
81 | #pragma pack(pop)
82 |
83 | /* All multi-byte fields are stored in .pcap file in little endian */
84 |
85 | #define USBPCAP_TRANSFER_ISOCHRONOUS 0
86 | #define USBPCAP_TRANSFER_INTERRUPT 1
87 | #define USBPCAP_TRANSFER_CONTROL 2
88 | #define USBPCAP_TRANSFER_BULK 3
89 | #define USBPCAP_TRANSFER_IRP_INFO 0xFE
90 | #define USBPCAP_TRANSFER_UNKNOWN 0xFF
91 |
92 | /* info byte fields:
93 | * bit 0 (LSB) - when 1: PDO -> FDO
94 | * bits 1-7: Reserved
95 | */
96 | #define USBPCAP_INFO_PDO_TO_FDO (1 << 0)
97 |
98 | #pragma pack(push, 1)
99 | typedef struct
100 | {
101 | USHORT headerLen; /* This header length */
102 | UINT64 irpId; /* I/O Request packet ID */
103 | USBD_STATUS status; /* USB status code (on return from host controller) */
104 | USHORT function; /* URB Function */
105 | UCHAR info; /* I/O Request info */
106 |
107 | USHORT bus; /* bus (RootHub) number */
108 | USHORT device; /* device address */
109 | UCHAR endpoint; /* endpoint number and transfer direction */
110 | UCHAR transfer; /* transfer type */
111 |
112 | UINT32 dataLength;/* Data length */
113 | } USBPCAP_BUFFER_PACKET_HEADER, *PUSBPCAP_BUFFER_PACKET_HEADER;
114 | #pragma pack(pop)
115 |
116 | /* USBPcap versions before 1.5.0.0 recorded control transactions as two
117 | * or three pcap packets:
118 | * * USBPCAP_CONTROL_STAGE_SETUP with 8 bytes USB SETUP data
119 | * * Optional USBPCAP_CONTROL_STAGE_DATA with either DATA OUT or IN
120 | * * USBPCAP_CONTROL_STAGE_STATUS without data on IRP completion
121 | *
122 | * Such capture was considered unnecessary complex. Due to that, since
123 | * USBPcap 1.5.0.0, the control transactions are recorded as two packets:
124 | * * USBPCAP_CONTROL_STAGE_SETUP with 8 bytes USB SETUP data and
125 | * optional DATA OUT
126 | * * USBPCAP_CONTROL_STAGE_COMPLETE without payload or with the DATA IN
127 | *
128 | * The merit behind this change was that Wireshark dissector, since the
129 | * very first time when Wireshark understood USBPcap format, was really
130 | * expecting the USBPCAP_CONTROL_STAGE_SETUP to contain SETUP + DATA OUT.
131 | * Even when they Wireshark doesn't recognize USBPCAP_CONTROL_STAGE_COMPLETE
132 | * it will still process the payload correctly.
133 | */
134 | #define USBPCAP_CONTROL_STAGE_SETUP 0
135 | #define USBPCAP_CONTROL_STAGE_DATA 1
136 | #define USBPCAP_CONTROL_STAGE_STATUS 2
137 | #define USBPCAP_CONTROL_STAGE_COMPLETE 3
138 |
139 | #pragma pack(push, 1)
140 | typedef struct
141 | {
142 | USBPCAP_BUFFER_PACKET_HEADER header;
143 | UCHAR stage;
144 | } USBPCAP_BUFFER_CONTROL_HEADER, *PUSBPCAP_BUFFER_CONTROL_HEADER;
145 | #pragma pack(pop)
146 |
147 | /* Note about isochronous packets:
148 | * packet[x].length, packet[x].status and errorCount are only relevant
149 | * when USBPCAP_INFO_PDO_TO_FDO is set
150 | *
151 | * packet[x].length is not used for isochronous OUT transfers.
152 | *
153 | * Buffer data is attached to:
154 | * * for isochronous OUT transactions (write to device)
155 | * Requests (USBPCAP_INFO_PDO_TO_FDO is not set)
156 | * * for isochronous IN transactions (read from device)
157 | * Responses (USBPCAP_INFO_PDO_TO_FDO is set)
158 | */
159 | #pragma pack(push, 1)
160 | typedef struct
161 | {
162 | ULONG offset;
163 | ULONG length;
164 | USBD_STATUS status;
165 | } USBPCAP_BUFFER_ISO_PACKET, *PUSBPCAP_BUFFER_ISO_PACKET;
166 | #pragma pack(pop)
167 |
168 | #pragma pack(push, 1)
169 | typedef struct
170 | {
171 | USBPCAP_BUFFER_PACKET_HEADER header;
172 | ULONG startFrame;
173 | ULONG numberOfPackets;
174 | ULONG errorCount;
175 | USBPCAP_BUFFER_ISO_PACKET packet[1];
176 | } USBPCAP_BUFFER_ISOCH_HEADER, *PUSBPCAP_BUFFER_ISOCH_HEADER;
177 | #pragma pack(pop)
178 |
179 | #ifdef __cplusplus
180 | }
181 | #endif
182 |
183 | #endif /* USBPCAP_H */
184 |
--------------------------------------------------------------------------------
/USBPcapDriver/makefile.inc:
--------------------------------------------------------------------------------
1 | _LNG=$(LANGUAGE)
2 | _INX=.
3 | STAMP=stampinf -f $@ -a $(_BUILDARCH) -v $(USBPCAP_VERSION)
4 |
5 | $(OBJ_PATH)\$(O)\$(INF_NAME).inf: $(_INX)\$(INF_NAME).inx
6 | copy $(_INX)\$(@B).inx $@
7 | $(STAMP)
8 |
--------------------------------------------------------------------------------
/appveyor_build.bat:
--------------------------------------------------------------------------------
1 | call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64
2 |
3 | set USBPcap_catalog=USBPcapamd64.cat
4 | set USBPcap_OS=8_X64
5 | set USBPcap_builddir=x64\Win8Release\dirs-Package
6 |
7 | cd %~dp0
8 | CALL config.bat
9 |
10 | ::Delete the release directory if it already exists
11 | if exist %USBPcap_builddir% RMDIR /S /Q %USBPcap_builddir%
12 |
13 | Nmake2MsBuild dirs
14 | MSBuild dirs.sln /p:Configuration="Win8 Release"
15 |
16 | if errorlevel 1 goto error
17 |
18 | ::Consider the build a success even if test signing fails
19 | ::Actual signing that matter is release one which for obvious reasons
20 | ::is done using non-public keys
21 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %USBPcap_builddir%\USBPcap.sys
22 | Inf2cat.exe /driver:%USBPcap_builddir%\ /os:%USBPcap_OS%
23 |
24 | copy %USBPcap_builddir%\USBPcap.sys %2
25 | copy %USBPcap_builddir%\USBPcap.inf %2
26 | copy %USBPcap_builddir%\%USBPcap_catalog% %2
27 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %2\%USBPcap_catalog%
28 |
29 | exit /B 0
30 |
31 | :error
32 | echo ===== BUILD FAILED! =====
33 | exit /B 1
34 |
--------------------------------------------------------------------------------
/build_release.bat:
--------------------------------------------------------------------------------
1 | cd %~dp0
2 |
3 | ::Remove the Release directory if it exists
4 | if exist Release RMDIR /S /Q Release
5 |
6 | ::build for Windows 7
7 | mkdir Release\Windows7\x86
8 | mkdir Release\Windows7\x64
9 |
10 | call cmd.exe /c driver_build.bat x86 WIN7 Release\Windows7\x86
11 | call cmd.exe /c driver_build.bat x64 WIN7 Release\Windows7\x64
12 |
13 | ::Copy the USBPcapCMD.exe
14 | copy USBPcapCMD\objfre_win7_x86\i386\USBPcapCMD.exe Release\USBPcapCMD_x86.exe
15 | copy USBPcapCMD\objfre_win7_amd64\amd64\USBPcapCMD.exe Release\USBPcapCMD_x64.exe
16 |
17 | ::Build for Windows 8
18 | mkdir Release\Windows8\x86
19 | mkdir Release\Windows8\x64
20 |
21 | call cmd.exe /c driver_build_win8.bat x86 Release\Windows8\x86
22 | call cmd.exe /c driver_build_win8.bat x86_amd64 Release\Windows8\x64
23 |
24 | ::Create Attestation signing cabinet files
25 | call cmd.exe /c driver_attestation_signing.bat
26 | @echo off
27 | echo Attestation signing packages should be available in disk1 directory
28 | echo Sign these files with EV Code Signing certificate and upload them
29 | echo to Hardware Dev Center Dashboard
30 | echo After you are ready, unzip signed files to Release directory
31 | @echo on
32 | pause
33 |
34 | ::Build finished
35 |
36 | @echo off
37 | echo Build finished. Please check if Release directory contains all required
38 | echo files. Now you can build the installer using nsis\USBPcap.nsi
39 | @echo on
40 |
41 | pause
42 |
--------------------------------------------------------------------------------
/certificates/Certum Trusted Network CA.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFTTCCAzWgAwIBAgIKYTvHkQAAAAAANDANBgkqhkiG9w0BAQUFADB/MQswCQYD
3 | VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
4 | MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv
5 | ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0xMTA0MTUyMDE1MzRaFw0yMTA0
6 | MTUyMDI1MzRaMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hu
7 | b2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo
8 | b3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwggEiMA0G
9 | CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDj+32jcrrC8MkUh/VrAU7hbkAHum0n
10 | XX/3Wy2zWsdRX6ukMqZhh7ZuD4bSMAKX+NdpV6EYOV1qZHnGAVmsPDFKOHzSBNJL
11 | KOggXzsHosxNc9vzrk/HVtVap5aJ+vOraNQjhlknzwknvKxucoMcMHLf4KLp0uF0
12 | dRm9Kp57FVQEG9dDOa1VKMXiGrv0wOSuOEkzzHaFnzlF0qSe8hKMUfh85C1/9axf
13 | 6xafsS3RusyRQndMJcmQOG/b8Mz7jh6XWT7VYE7mBSjtSXkTS7pI2y/5ctM5yv4f
14 | 2DRy9bRAzzEBw+zeES0XXR+4UNFeGadp3gczKMpQlfmnVMtUhlBFqflJAgMBAAGj
15 | gcswgcgwEQYDVR0gBAowCDAGBgRVHSAAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
16 | BBYEFAh2zcsH/yT2xc3tu5C84oQ3RnX3MAsGA1UdDwQEAwIBhjAfBgNVHSMEGDAW
17 | gBRi+wohW39DbhHaCVRQa/XSlnHxnjBVBgNVHR8ETjBMMEqgSKBGhkRodHRwOi8v
18 | Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNyb3NvZnRDb2Rl
19 | VmVyaWZSb290LmNybDANBgkqhkiG9w0BAQUFAAOCAgEAQZ8SFg7t7iSR/l1fEKCX
20 | qHSeDczzEVFjEipbuV3Hr6xaolwAAstyjg2SJbZSJlO+PHeiwoyAidhBGFcauNBQ
21 | V8Mo5/rQRIBOfokzKG86R+9eIx7yev46KhnerWsaKEd4bpu/63NnWJonGdjrXD0I
22 | WGBinVkUz552s8/ZYq97cqyA+eAVq5x6XEsccIPbcJQRe9IqTHc03DbMzUbUCxmM
23 | CfZhCt5IHJs//wtD1/EBgGGr2nDPp4RErLMcziYw9cpfaWc1g26jiIwPuJOb1lsG
24 | FeZLfblQqwngeyvrTBpruhzKeRvFn4G95EPwLeGV1aFmB2zm5UVuBgvb9bxDlbiK
25 | pQVV5ZZorB0x2zgEvBw9thl10bWAKoIeOFxGdiVsTYt0g1RDded7s5W/7hNgng7N
26 | +8r3OipSoKYlSXoXGTrolB8sggQDXqlRPO9Sb3tDztorgbR/2hosYmXR7Cg3gjAU
27 | MZ0Vvf+syIslbkG9HyN0G+P8+Uvi60bmgVFTDslKhHiN7Ki4D41Mf+D2sNLFOLJP
28 | gsQQ/oe4jsa2sPh8Eqe0g038HotqW/nVZHk+0eN+GvbIHlnbTcpgXFd+olh37PoF
29 | JgAyp/b/E06Y2G9bQ0yzNuQlvNk7nzjgDum+gebJHw8CL406Eoiojhux53aRPhje
30 | NhIo/vdmVXxb1GRIdFLDIYk=
31 | -----END CERTIFICATE-----
32 |
--------------------------------------------------------------------------------
/certificates/Readme.txt:
--------------------------------------------------------------------------------
1 | Following certificates were created with following commands:
2 | MakeCert -r -pe -ss PrivateCertStore -n "CN=USBPcapTest" -sv USBPcapTestCert.pvk USBPcapTestCert.cer
3 | pvk2pfx -pvk USBPcapTestCert.pvk -spc USBPcapTestCert.cer -pfx USBPcapTestCert.pfx
4 |
5 | Password: USBPcap
6 |
7 |
8 | WARNING: Prior to installing the test-signed driver you need to run:
9 | CertMgr /add USBPcapTestCert.cer /s /r localMachine root
10 | CertMgr /add USBPcapTestCert.cer /s /r localMachine trustedpublisher
11 | Bcdedit.exe -set TESTSIGNING ON
12 |
--------------------------------------------------------------------------------
/certificates/USBPcapTestCert.cer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/certificates/USBPcapTestCert.cer
--------------------------------------------------------------------------------
/certificates/USBPcapTestCert.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/certificates/USBPcapTestCert.pfx
--------------------------------------------------------------------------------
/certificates/USBPcapTestCert.pvk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/certificates/USBPcapTestCert.pvk
--------------------------------------------------------------------------------
/certificates/VeriSign Class 3 Public Primary Certification Authority - G5.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFmjCCA4KgAwIBAgIKYRmT5AAAAAAAHDANBgkqhkiG9w0BAQUFADB/MQswCQYD
3 | VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
4 | MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv
5 | ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0xMTAyMjIxOTI1MTdaFw0yMTAy
6 | MjIxOTM1MTdaMIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIElu
7 | Yy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShj
8 | KSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkx
9 | RTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlm
10 | aWNhdGlvbiBBdXRob3JpdHkgLSBHNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
11 | AQoCggEBAK8kCAgpejWeYAyq50s7Ttx8vDxFHLsr4P4pAvlXCKNkhRUn9fGtyDGJ
12 | XSLoKqqmQrOP+LlVt7G3S7P+j34HV+zvQ9tmYhVhz2ANpNje+ODDYgg9VBPrScpZ
13 | VIUm5SuPG5/r9aGRwjNJ2ENjalJL0o/ocFFN0Ylpe8dw9rPcEnTbe11LVtOWvxV3
14 | obD0oiXyrxySZxjl9AYE75C55ADk3Tq1Gf8CuvQ87uCL6zeL7PTXrPL28D2v3XWR
15 | MxkdHEDLdCQZIZPZFP6sKlLHj9UESeSNY0eIPGmDy/5HvSt+T8WVrg6d1NFDwGdz
16 | 4xQIfuU/n3O4MwrPXT80h5aK7lPoJRUCAwEAAaOByzCByDARBgNVHSAECjAIMAYG
17 | BFUdIAAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAYYwHQYDVR0OBBYEFH/T
18 | ZafC3ey78DAJ80M5+gKvMzEzMB8GA1UdIwQYMBaAFGL7CiFbf0NuEdoJVFBr9dKW
19 | cfGeMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9w
20 | a2kvY3JsL3Byb2R1Y3RzL01pY3Jvc29mdENvZGVWZXJpZlJvb3QuY3JsMA0GCSqG
21 | SIb3DQEBBQUAA4ICAQCBKoIWjDRnK+UD6zR7jKKjUIr0VYbxHoyOrn3uAxnOcpUY
22 | SK1iEf0g/T9HBgFa4uBvjBUsTjxqUGwLNqPPeg2cQrxc+BnVYONp5uIjQWeMaIN2
23 | K4+Toyq1f75Z+6nJsiaPyqLzghuYPpGVJ5eGYe5bXQdrzYao4mWAqOIV4rK+IwVq
24 | ugzzR5NNrKSMB3k5wGESOgUNiaPsn1eJhPvsynxHZhSR2LYPGV3muEqsvEfIcUOW
25 | 5jIgpdx3hv0844tx23ubA/y3HTJk6xZSoEOj+i6tWZJOfMfyM0JIOFE6fDjHGyQi
26 | KEAeGkYfF9sY9/AnNWy4Y9nNuWRdK6Ve78YptPLH+CHMBLpX/QG2q8Zn+efTmX/0
27 | 9SL6cvX9/zocQjqh+YAYpe6NHNRmnkUB/qru//sXjzD38c0pxZ3stdVJAD2FuMu7
28 | kzonaknAMK5myfcjKDJ2+aSDVshIzlqWqqDMDMR/tI6Xr23jVCfDn4bA1uRzCJcF
29 | 29BUYl4DSMLVn3+nZozQnbBP1NOYX0t6yX+yKVLQEoDHD1S2HmfNxqBsEQOE00h1
30 | 5yr+sDtuCjqma3aZBaPxd2hhMxRHBvxTf1K9khRcSiRqZ4yvjZCq0PZ5IRuTJnzD
31 | zh69iDiSrkXGGWpJULMF+K5ZN4pqJQOUsVmBUOi6g4C3IzX0drlnHVkYrSCNlA==
32 | -----END CERTIFICATE-----
33 |
--------------------------------------------------------------------------------
/config.bat:
--------------------------------------------------------------------------------
1 | ::Change code page to UTF-8 when building official release and your cerificate
2 | ::has non-ASCII characters in name
3 | ::Do not change it by default as this seems to cause problems with AppVeyor
4 | ::chcp 65001
5 |
6 | ::Use SignTool from Windows Driver Kit
7 | set _USBPCAP_SIGNTOOL="C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe"
8 |
9 | ::Development build - on x64 you have to use TESTSIGNING to load driver
10 | set _USBPCAP_SIGN_OPTS_SHA256=sign /as /v /fd sha256 /f %~dp0certificates\USBPcapTestCert.pfx /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td sha256
11 | ::Release build. Keep in mind you would have to replace the certificate
12 | ::name with your personal/company certificate.
13 | ::Also, you might want to use different cross-certificate depending on the
14 | ::certificate authority that you got the certificate from
15 | ::
16 | ::For more information check out the Kernel-Mode Code Signing Walkthrough
17 | ::http://msdn.microsoft.com/en-us/library/windows/hardware/gg487328.aspx
18 | ::set _USBPCAP_SIGN_OPTS_SHA256=sign /as /v /fd sha256 /ac "%~dp0certificates\Certum Trusted Network CA.crt" /n "Tomasz" /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td sha256
19 |
20 | ::_USBPCAP_VERSION specifies version of the installer.
21 | ::To update driver version edit USBPcapDriver\USBPcap.rc and
22 | ::USBPcapDriver\SOURCES
23 | set _USBPCAP_VERSION="1.5.4.0"
24 |
--------------------------------------------------------------------------------
/dirs:
--------------------------------------------------------------------------------
1 | dirs = USBPcapCMD USBPcapDriver
2 |
--------------------------------------------------------------------------------
/driver_attestation_signing.bat:
--------------------------------------------------------------------------------
1 | cd %~dp0
2 | CALL config.bat
3 |
4 | CALL :dequote _USBPCAP_VERSION
5 |
6 | ::Prepare driver package for Windows 10 Attestation signing
7 | ::According to documentation Attestation signed driver works
8 | ::only on Windows 10, hence we cannot use exactly the same
9 | ::driver file for Windows 8 and Windows 10
10 | ::However, we use the same source, only the signing differ
11 | CALL :CreateCab x86
12 | CALL :CreateCab x64
13 | Goto :eof
14 |
15 | :DeQuote
16 | for /f "delims=" %%A in ('echo %%%1%%') do set %1=%%~A
17 | Goto :eof
18 |
19 | :CreateCab
20 | (
21 | echo .OPTION EXPLICIT ; Generate errors
22 | echo .Set CabinetFileCountThreshold=0
23 | echo .Set FolderFileCountThreshold=0
24 | echo .Set FolderSizeThreshold=0
25 | echo .Set MaxCabinetSize=0
26 | echo .Set MaxDiskFileCount=0
27 | echo .Set MaxDiskSize=0
28 | echo .Set CompressionType=MSZIP
29 | echo .Set Cabinet=on
30 | echo .Set Compress=on
31 | echo .Set CabinetNameTemplate=USBPcap-%_USBPCAP_VERSION%-%1.cab
32 | echo .Set DestinationDir=Windows10%1
33 | echo %~dp0Release\Windows8\%1\USBPcap.inf
34 | echo %~dp0Release\Windows8\%1\USBPcap.sys
35 | echo %~dp0Release\Windows8\%1\USBPcap.pdb
36 | ) > Windows10-%1.ddf
37 | MakeCab /f Windows10-%1.ddf
38 | Goto :eof
39 |
--------------------------------------------------------------------------------
/driver_build.bat:
--------------------------------------------------------------------------------
1 | ::Parameters:
2 | :: %1 - x86 or x64
3 | :: %2 - WIN7
4 | :: %3 - target directory
5 |
6 | call C:\WinDDK\7600.16385.1\bin\setenv.bat C:\WinDDK\7600.16385.1\ fre %1 %2
7 |
8 | cd %~dp0
9 | CALL config.bat
10 |
11 | if "%_BUILDARCH%"=="x86" (
12 | set USBPcap_arch=i386
13 | set USBPcap_catalog=USBPcapx86.cat
14 | if "%DDK_TARGET_OS%"=="WinLH" (
15 | set USBPcap_OS=Vista_X86
16 | ) else if "%DDK_TARGET_OS%"=="WinXP" (
17 | set USBPcap_OS=XP_X86
18 | ) else if "%DDK_TARGET_OS%"=="Win7" (
19 | set USBPcap_OS=7_X86
20 | )
21 | ) else (
22 | set USBPcap_arch=amd64
23 | set USBPcap_catalog=USBPcapamd64.cat
24 | if "%DDK_TARGET_OS%"=="WinLH" (
25 | set USBPcap_OS=Vista_X64
26 | ) else if "%DDK_TARGET_OS%"=="WinNET" (
27 | set USBPcap_OS=XP_X64
28 | ) else if "%DDK_TARGET_OS%"=="Win7" (
29 | set USBPcap_OS=7_X64
30 | )
31 | )
32 |
33 | cd %~dp0
34 | CALL config.bat
35 |
36 | build -ceZg
37 | if exist build%BUILD_ALT_DIR%.err goto error
38 |
39 | ::Sign the USBPcapCMD.exe, it is not critical so do not fail on error
40 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcapCMD\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcapCMD.exe
41 |
42 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.sys
43 | if errorlevel 1 goto error
44 |
45 | Inf2cat.exe /driver:USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\ /os:%USBPcap_OS%
46 |
47 | goto end
48 |
49 | :error
50 | echo ===== BUILD FAILED! =====
51 | pause
52 | exit /B 1
53 |
54 | :end
55 |
56 | copy USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.sys %3
57 | copy USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.pdb %3
58 | copy USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.inf %3
59 | copy USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\%USBPcap_catalog% %3
60 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %3\%USBPcap_catalog%
61 | if errorlevel 1 goto error
62 |
63 | exit /B 0
64 |
--------------------------------------------------------------------------------
/driver_build_win7_64bit.bat:
--------------------------------------------------------------------------------
1 | call C:\WinDDK\7600.16385.1\bin\setenv.bat C:\WinDDK\7600.16385.1\ fre x64 WIN7
2 |
3 | if "%_BUILDARCH%"=="x86" (
4 | set USBPcap_arch=i386
5 | if "%DDK_TARGET_OS%"=="WinLH" (
6 | set USBPcap_OS=Vista_X86
7 | ) else if "%DDK_TARGET_OS%"=="WinXP" (
8 | set USBPcap_OS=XP_X86
9 | ) else if "%DDK_TARGET_OS%"=="Win7" (
10 | set USBPcap_OS=7_X86
11 | )
12 | ) else (
13 | set USBPcap_arch=amd64
14 | if "%DDK_TARGET_OS%"=="WinLH" (
15 | set USBPcap_OS=Vista_X64
16 | ) else if "%DDK_TARGET_OS%"=="WinXP" (
17 | set USBPcap_OS=XP_X64
18 | ) else if "%DDK_TARGET_OS%"=="Win7" (
19 | set USBPcap_OS=7_X64
20 | )
21 | )
22 |
23 | cd %~dp0
24 | CALL config.bat
25 |
26 | build -ceZg
27 | if exist build%BUILD_ALT_DIR%.err goto error
28 |
29 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\USBPcap.sys
30 | if errorlevel 1 goto error
31 |
32 | Inf2cat.exe /driver:USBPcapDriver\obj%BUILD_ALT_DIR%\%USBPcap_arch%\ /os:%USBPcap_OS%
33 |
34 | goto end
35 |
36 | :error
37 | echo ===== BUILD FAILED! =====
38 | cd %~dp0
39 | pause
40 | exit /B 1
41 |
42 | :end
43 | cd %~dp0
44 | pause
45 | exit /B 0
46 |
--------------------------------------------------------------------------------
/driver_build_win8.bat:
--------------------------------------------------------------------------------
1 | ::Parameters:
2 | :: %1 - x86 or x86_amd64
3 |
4 | call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" %1
5 |
6 | if "%1"=="x86" (
7 | set USBPcap_catalog=USBPcapx86.cat
8 | set USBPcap_OS=8_X86
9 | set USBPcap_builddir=USBPcapDriver\Win8Release\x86
10 | ) else (
11 | set USBPcap_catalog=USBPcapamd64.cat
12 | set USBPcap_OS=8_X64
13 | set USBPcap_builddir=USBPcapDriver\Win8Release\x64
14 | )
15 |
16 | cd %~dp0
17 | CALL config.bat
18 |
19 | ::Delete the release directory if it already exists
20 | if exist %USBPcap_builddir% RMDIR /S /Q %USBPcap_builddir%
21 |
22 | Nmake2MsBuild dirs
23 | MSBuild dirs.sln /p:Configuration="Win8 Release"
24 |
25 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %USBPcap_builddir%\USBPcap.sys
26 | if errorlevel 1 goto error
27 |
28 | Inf2cat.exe /driver:%USBPcap_builddir%\ /os:%USBPcap_OS%
29 |
30 | goto end
31 |
32 | :error
33 | echo ===== BUILD FAILED! =====
34 | pause
35 | exit /B 1
36 |
37 | :end
38 | copy %USBPcap_builddir%\USBPcap.sys %2
39 | copy %USBPcap_builddir%\USBPcap.pdb %2
40 | copy %USBPcap_builddir%\USBPcap.inf %2
41 | copy %USBPcap_builddir%\%USBPcap_catalog% %2
42 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% %2\%USBPcap_catalog%
43 | if errorlevel 1 goto error
44 |
45 | exit /B 0
46 |
--------------------------------------------------------------------------------
/nsis/SysRestore.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/desowin/usbpcap/477b6edcbd7e99a47f77afc0c4168a9ebee603bb/nsis/SysRestore.dll
--------------------------------------------------------------------------------
/nsis/USBPcap.nsi:
--------------------------------------------------------------------------------
1 | !include "LogicLib.nsh"
2 | !include "x64.nsh"
3 | !include "WinVer.nsh"
4 | !include "FileFunc.nsh"
5 | !include "WordFunc.nsh"
6 |
7 | !addplugindir .
8 |
9 | !macro __MOZ__WinVer_DefineOSTests WinVer
10 | !insertmacro __WinVer_DefineOSTest AtLeast ${WinVer} ""
11 | !insertmacro __WinVer_DefineOSTest AtMost ${WinVer} ""
12 | !insertmacro __WinVer_DefineOSTest Is ${WinVer} ""
13 | !macroend
14 |
15 | !ifndef WINVER_8
16 | !define WINVER_8 0x06020000 ;6.02.????
17 | !insertmacro __MOZ__WinVer_DefineOSTests 8
18 | !endif
19 |
20 | !define VERSION $%_USBPCAP_VERSION%
21 |
22 | Name "USBPcap ${VERSION}"
23 |
24 | RequestExecutionLevel admin
25 |
26 | !ifdef INNER
27 | !echo "Inner invocation" ; just to see what's going on
28 | OutFile "$%TEMP%\tempinstaller.exe" ; not really important where this is
29 | SetCompress off ; for speed
30 | !else
31 | !echo "Outer invocation"
32 |
33 | ; Call makensis again, defining INNER. This writes an installer for us
34 | ; which, when it is invoked, will just write the uninstaller to some
35 | ; location, and then exit.
36 | ; Be sure to substitute the name of this script here.
37 |
38 | !system "$\"${NSISDIR}\makensis$\" /DINNER USBPcap.nsi" = 0
39 |
40 | ; So now run that installer we just created as %TEMP%\tempinstaller.exe.
41 | ; Since it calls quit the return value isn't zero.
42 |
43 | !system "$%TEMP%\tempinstaller.exe" = 2
44 |
45 | ; That will have written an uninstaller binary for us. Now we sign it
46 | ; with your favourite code signing tool.
47 | !system '$%_USBPCAP_SIGNTOOL% $%_USBPCAP_SIGN_OPTS_SHA256% $%TEMP%\Uninstall.exe' = 0
48 |
49 | ; Good. Now we can carry on writing the real installer.
50 |
51 | outFile "USBPcapSetup-${VERSION}.exe"
52 | SetCompressor /SOLID lzma
53 |
54 | VIAddVersionKey "ProductName" "USBPcap"
55 | VIAddVersionKey "ProductVersion" "${VERSION}"
56 | VIAddVersionKey "LegalCopyright" "(c) 2013-2020 Tomasz Mon"
57 | VIAddVersionKey "FileDescription" "USBPcap installer"
58 | VIAddVersionKey "FileVersion" "${VERSION}"
59 | VIProductVersion "${VERSION}"
60 | !endif
61 |
62 | PageEx license
63 | LicenseText "USBPcap Driver license"
64 | LicenseData gpl-2.0.txt
65 | LicenseForceSelection checkbox
66 | PageExEnd
67 |
68 | PageEx license
69 | LicenseText "USBPcapCMD license"
70 | LicenseData bsd-2clause.txt
71 | LicenseForceSelection checkbox
72 | PageExEnd
73 |
74 | Page components
75 | Page directory
76 | Page instfiles
77 | UninstPage uninstConfirm
78 | UninstPage instfiles
79 |
80 | Function EnsureSHA2IsSupported
81 | push $0
82 | push $1
83 | push $2
84 |
85 | StrCpy $2 0
86 |
87 | System::Call "kernel32::LoadLibrary(t 'wintrust.dll') p .r1"
88 | ${If} $1 != 0
89 | System::Call "kernel32::GetProcAddress(p r1, t 'CryptCATAdminAcquireContext2') p .r2"
90 | System::Call "kernel32::FreeLibrary(p r1)"
91 | ${EndIf}
92 |
93 | ${If} $2 == 0
94 | MessageBox MB_OK|MB_ICONEXCLAMATION "Windows 7 without updates does not support SHA-2.$\nInstall KB3033929 or KB4474419 before installing USBPcap."
95 | Quit
96 | ${EndIf}
97 |
98 | pop $2
99 | pop $1
100 | pop $0
101 | FunctionEnd
102 |
103 | Function .onInit
104 | !ifdef INNER
105 | ; If INNER is defined, then we aren't supposed to do anything except write
106 | ; out the installer. This is better than processing a command line option
107 | ; as it means this entire code path is not present in the final (real)
108 | ; installer.
109 |
110 | WriteUninstaller "$%TEMP%\Uninstall.exe"
111 | Quit ; just bail out quickly when running the "inner" installer
112 | !endif
113 |
114 | ; It is no longer possible to get SHA-1 Kernel Mode Code Signing certificate
115 | ; Windows 8 and later contain SHA-2 support built-in.
116 | ; Windows 7 supports SHA-2 when KB3033929 or KB4474419 is installed.
117 | ; Older Windows versions do not support SHA-2.
118 | ${IfNot} ${AtLeastWin7}
119 | MessageBox MB_OK "Unsupported Windows version. Only Windows 7, 8 and 10 are supported.$\nThe last USBPcap release supporting Windows XP and Vista was 1.5.3.0."
120 | Quit
121 | ${EndIf}
122 |
123 | ${IfNot} ${AtLeastWin8}
124 | Call EnsureSHA2IsSupported
125 | ${EndIf}
126 |
127 | ${If} ${RunningX64}
128 | ${DisableX64FSRedirection}
129 | SetRegView 64
130 | ${EndIf}
131 | ReadRegStr $R0 HKLM \
132 | "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \
133 | "UninstallString"
134 | ${If} ${RunningX64}
135 | ${EnableX64FSRedirection}
136 | ${EndIf}
137 | StrCmp $R0 "" not_installed
138 |
139 | MessageBox MB_OK|MB_ICONEXCLAMATION \
140 | "USBPcap is already installed. Please uninstall it first.$\r$\nMake sure to reboot after uninstall."
141 | Abort
142 |
143 | not_installed:
144 | ; Check if USBPcap driver service is pending removal
145 | ClearErrors
146 | ReadRegDWORD $0 HKLM "SYSTEM\CurrentControlSet\services\USBPcap" "DeleteFlag"
147 | IfErrors no_removal_pending
148 | ; DeleteFlag exists. On Windows 7 it seems that it will result in USBPcap
149 | ; service getting removed after reboot no matter what DeleteFlag value is
150 | MessageBox MB_OK|MB_ICONEXCLAMATION \
151 | "USBPcap driver service is pending removal.$\r$\nReboot is required before installation."
152 | Abort
153 |
154 | no_removal_pending:
155 | ${If} ${RunningX64}
156 | StrCpy $INSTDIR "$PROGRAMFILES64\USBPcap"
157 | ${Else}
158 | StrCpy $INSTDIR "$PROGRAMFILES\USBPcap"
159 | ${EndIf}
160 |
161 | ; Windows To Go is not supported
162 | ClearErrors
163 | ReadRegDWORD $0 HKLM "SYSTEM\CurrentControlSet\Control" "PortableOperatingSystem"
164 | ${If} $0 <> 0
165 | MessageBox MB_OK "USBPcap cannot be installed on Windows To Go."
166 | Quit
167 | ${EndIf}
168 |
169 | Pop $R0
170 | FunctionEnd
171 |
172 | InstType "Full"
173 | InstType "Minimal"
174 |
175 | Section "USBPcap Driver" SEC_USBPCAPDRIVER
176 | SectionIn RO
177 | SetOutPath "$INSTDIR"
178 |
179 | Var /GLOBAL restore_point_success
180 | !define RESTORE_POINT_NAME_INSTALL "USBPcap ${VERSION} installation"
181 |
182 | DetailPrint "Start setting system restore point: ${RESTORE_POINT_NAME_INSTALL}"
183 | SysRestore::StartRestorePoint /NOUNLOAD "${RESTORE_POINT_NAME_INSTALL}"
184 | Pop $0
185 | ${If} $0 != 0
186 | DetailPrint "Error occurred when starting setting system restore point, return value=|$0|"
187 | ${Else}
188 | StrCpy $restore_point_success "yes"
189 | ${Endif}
190 |
191 | ${If} ${RunningX64}
192 | ${DisableX64FSRedirection}
193 | SetRegView 64
194 | ${EndIf}
195 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \
196 | "DisplayName" "USBPcap ${VERSION}"
197 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \
198 | "DisplayVersion" "${VERSION}"
199 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \
200 | "UninstallString" "$\"$INSTDIR\Uninstall.exe$\""
201 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \
202 | "QuietUninstallString" "$\"$INSTDIR\Uninstall.exe$\" /S"
203 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \
204 | "URLInfoAbout" "http://desowin.org/usbpcap"
205 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \
206 | "Publisher" "Tomasz Mon"
207 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \
208 | "NoModify" 1
209 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap" \
210 | "NoRepair" 1
211 |
212 | ${If} ${RunningX64}
213 | ${If} ${AtLeastWin10}
214 | File "..\Release\Windows10\x64\USBPcap.inf"
215 | File "..\Release\Windows10\x64\USBPcap.sys"
216 | File "..\Release\Windows10\x64\USBPcapamd64.cat"
217 | ${ElseIf} ${AtLeastWin8}
218 | File "..\Release\Windows8\x64\USBPcap.inf"
219 | File "..\Release\Windows8\x64\USBPcap.sys"
220 | File "..\Release\Windows8\x64\USBPcapamd64.cat"
221 | ${Else}
222 | ; Assume 64-bit Windows 7
223 | File "..\Release\Windows7\x64\USBPcap.inf"
224 | File "..\Release\Windows7\x64\USBPcap.sys"
225 | File "..\Release\Windows7\x64\USBPcapamd64.cat"
226 | ${EndIf}
227 | ${Else}
228 | ${If} ${AtLeastWin10}
229 | File "..\Release\Windows10\x86\USBPcap.inf"
230 | File "..\Release\Windows10\x86\USBPcap.sys"
231 | File "..\Release\Windows10\x86\USBPcapx86.cat"
232 | ${ElseIf} ${AtLeastWin8}
233 | File "..\Release\Windows8\x86\USBPcap.inf"
234 | File "..\Release\Windows8\x86\USBPcap.sys"
235 | File "..\Release\Windows8\x86\USBPcapx86.cat"
236 | ${Else}
237 | ; Assume 32-bit Windows 7
238 | File "..\Release\Windows7\x86\USBPcap.inf"
239 | File "..\Release\Windows7\x86\USBPcap.sys"
240 | File "..\Release\Windows7\x86\USBPcapx86.cat"
241 | ${EndIf}
242 | ${EndIf}
243 |
244 | ExecWait '$SYSDIR\RUNDLL32.EXE SETUPAPI.DLL,InstallHinfSection DefaultInstall 132 .\USBPcap.inf'
245 |
246 | ${If} ${RunningX64}
247 | ${EnableX64FSRedirection}
248 | ${EndIf}
249 |
250 | !ifndef INNER
251 | ; this packages the signed uninstaller
252 | File $%TEMP%\Uninstall.exe
253 | !endif
254 | SectionEnd
255 |
256 | Section "USBPcapCMD" SEC_USBPCAPCMD
257 | SectionIn 1 RO
258 | SetOutPath "$INSTDIR"
259 |
260 | ${If} ${RunningX64}
261 | File /oname=USBPcapCMD.exe "..\Release\USBPcapCMD_x64.exe"
262 | ${Else}
263 | File /oname=USBPcapCMD.exe "..\Release\USBPcapCMD_x86.exe"
264 | ${EndIf}
265 |
266 | ${If} $restore_point_success == "yes"
267 | DetailPrint "Finish setting system restore point: ${RESTORE_POINT_NAME_INSTALL}"
268 | SysRestore::FinishRestorePoint /NOUNLOAD
269 | Pop $0
270 | ${If} $0 != 0
271 | DetailPrint "Error occurred when finishing setting system restore point, return value=|$0|"
272 | ${EndIf}
273 | ${EndIf}
274 | SectionEnd
275 |
276 | Section "Detect USB 3.0" SEC_USB3
277 | SectionIn 1
278 |
279 | Exec '"$INSTDIR\USBPcapCMD.exe" -I'
280 | SectionEnd
281 |
282 | Function .onSelChange
283 | ${If} ${SectionIsSelected} ${SEC_USB3}
284 | !insertmacro SetSectionFlag ${SEC_USBPCAPCMD} ${SF_RO}
285 | !insertmacro SelectSection ${SEC_USBPCAPCMD}
286 | ${Else}
287 | !insertmacro ClearSectionFlag ${SEC_USBPCAPCMD} ${SF_RO}
288 | ${EndIf}
289 | FunctionEnd
290 |
291 | !ifdef INNER
292 | Section "Uninstall"
293 | ${If} ${RunningX64}
294 | ${DisableX64FSRedirection}
295 | SetRegView 64
296 | ${EndIf}
297 | SetOutPath "$INSTDIR"
298 | ExecWait '$SYSDIR\RUNDLL32.EXE SETUPAPI.DLL,InstallHinfSection DefaultUninstall 132 .\USBPcap.inf'
299 |
300 | Delete $INSTDIR\Uninstall.exe
301 | Delete $INSTDIR\USBPcap.inf
302 | Delete $INSTDIR\USBPcap.sys
303 | ${If} ${RunningX64}
304 | Delete $INSTDIR\USBPcapamd64.cat
305 | ${Else}
306 | Delete $INSTDIR\USBPcapx86.cat
307 | ${EndIf}
308 |
309 | IfFileExists $INSTDIR\USBPcapCMD.exe CMDExists PastCMDCheck
310 | CMDExists:
311 | Delete $INSTDIR\USBPcapCMD.exe
312 | PastCMDCheck:
313 | RMDir /REBOOTOK $INSTDIR
314 |
315 | DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\USBPcap"
316 | ${If} ${RunningX64}
317 | ${EnableX64FSRedirection}
318 | ${EndIf}
319 | SectionEnd
320 | !endif
321 |
322 |
--------------------------------------------------------------------------------
/nsis/bsd-2clause.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013-2020, Tomasz Mon
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 |
6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9 |
10 |
--------------------------------------------------------------------------------
/nsis/build_installer.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | CALL ..\config.bat
4 |
5 | set nsis_compiler=
6 |
7 | if defined NSIS_HOME (
8 | if exist "%NSIS_HOME%\makensis.exe" (
9 | set "nsis_compiler=%NSIS_HOME%"
10 | )
11 | )
12 |
13 | if %PROCESSOR_ARCHITECTURE%==x86 (
14 | Set RegQry=HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NSIS
15 | ) else (
16 | Set RegQry=HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\NSIS
17 | )
18 |
19 | if not defined nsis_compiler (
20 | for /F "tokens=2*" %%a in ('reg query %RegQry% /v InstallLocation ^|findstr InstallLocation') do set nsis_compiler=%%b
21 | )
22 |
23 | if not defined nsis_compiler (
24 | for %%X in (makensis.exe) do (set nsis_compiler=%%~dp$PATH:X)
25 | )
26 |
27 | if defined nsis_compiler (
28 | "%nsis_compiler%\makensis.exe" %~dp0USBPcap.nsi
29 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcapSetup-%_USBPCAP_VERSION%.exe
30 | pause
31 | ) else (
32 | echo "Error, build system cannot find NSIS! Please reinstall it, add makensis.exe to your PATH, or defined the NSIS_HOME environment variable."
33 | )
34 |
--------------------------------------------------------------------------------
/nsis/gpl-2.0.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
--------------------------------------------------------------------------------
/wix/USBPcap.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | NOT USBPCAP_NSIS
29 |
30 | %PROCESSOR_ARCHITECTURE ~= "x86" AND %PROCESSOR_ARCHITEW6432 <> "amd64"
31 |
32 | NOT VersionNT < 501
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | VersionNT >= 501 AND VersionNT < 600
45 |
46 |
47 |
48 |
49 |
50 | VersionNT = 600
51 |
52 |
53 |
54 |
55 |
56 | VersionNT = 601
57 |
58 |
59 |
60 |
61 |
62 | VersionNT >= 602
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | NOT Installed AND
93 | NOT Installed
94 | REMOVE="ALL"
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/wix/build.bat:
--------------------------------------------------------------------------------
1 | set _WIX_PATH="C:\Program Files (x86)\WiX Toolset v3.9\bin"
2 |
3 | cd %~dp0
4 |
5 | %_WIX_PATH%\candle.exe -nologo USBPcap.wxs -out USBPcap-x86.wixobj -ext WixUIExtension -arch x86 -dPlatform="x86"
6 | if errorlevel 1 goto error
7 | %_WIX_PATH%\light.exe -nologo USBPcap-x86.wixobj -out USBPcap-x86.msi -ext WixUIExtension
8 | if errorlevel 1 goto error
9 | pause
10 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcap-x86.msi
11 |
12 | %_WIX_PATH%\candle.exe -nologo USBPcap.wxs -out USBPcap-x64.wixobj -ext WixUIExtension -arch x64 -dPlatform="x64"
13 | if errorlevel 1 goto error
14 | %_WIX_PATH%\light.exe -nologo USBPcap-x64.wixobj -out USBPcap-x64.msi -ext WixUIExtension
15 | if errorlevel 1 goto error
16 | %_USBPCAP_SIGNTOOL% %_USBPCAP_SIGN_OPTS_SHA256% USBPcap-x64.msi
17 |
18 | :error
19 | echo ===== Failed to build installer! =====
20 | pause
21 | exit /B 1
22 |
23 | :end
24 | echo ==== Success! ====
25 | pause
26 | exit /B 0
27 |
--------------------------------------------------------------------------------