mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[core] handle search improvements
* Fix memory leaks due to not releasing the heap * Also speed up lookups by not reopening the same process twice in a row * Also make the usb_debug variable global so we can use uuprintf everywhere
This commit is contained in:
		
							parent
							
								
									fec0813073
								
							
						
					
					
						commit
						d1927ac1ef
					
				
					 7 changed files with 304 additions and 66 deletions
				
			
		|  | @ -61,7 +61,7 @@ static int task_number = 0; | ||||||
| extern const int nb_steps[FS_MAX]; | extern const int nb_steps[FS_MAX]; | ||||||
| extern uint32_t dur_mins, dur_secs; | extern uint32_t dur_mins, dur_secs; | ||||||
| static int fs_index = 0, wintogo_index = -1; | static int fs_index = 0, wintogo_index = -1; | ||||||
| extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, disable_file_indexing, usb_debug; | extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, disable_file_indexing; | ||||||
| uint8_t *grub2_buf = NULL; | uint8_t *grub2_buf = NULL; | ||||||
| long grub2_len; | long grub2_len; | ||||||
| static BOOL WritePBR(HANDLE hLogicalDrive); | static BOOL WritePBR(HANDLE hLogicalDrive); | ||||||
|  |  | ||||||
|  | @ -2170,8 +2170,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 	case WM_COMMAND: | 	case WM_COMMAND: | ||||||
| #ifdef RUFUS_TEST | #ifdef RUFUS_TEST | ||||||
| 		if (LOWORD(wParam) == IDC_TEST) { | 		if (LOWORD(wParam) == IDC_TEST) { | ||||||
| 			char* choices[] = { "Choice 1", "Choice 2", "Choice 3" }; | 			SearchProcess("\\Device\\Harddisk5\\DR5", TRUE, TRUE); | ||||||
| 			SelectionDyn("Test Choice", "Unused", choices, ARRAYSIZE(choices)); | //			char* choices[] = { "Choice 1", "Choice 2", "Choice 3" };
 | ||||||
|  | //			SelectionDyn("Test Choice", "Unused", choices, ARRAYSIZE(choices));
 | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -392,7 +392,7 @@ extern BOOL PromptOnError; | ||||||
| extern unsigned long syslinux_ldlinux_len[2]; | extern unsigned long syslinux_ldlinux_len[2]; | ||||||
| extern const int nb_steps[FS_MAX]; | extern const int nb_steps[FS_MAX]; | ||||||
| extern BOOL use_own_c32[NB_OLD_C32], detect_fakes, iso_op_in_progress, format_op_in_progress, right_to_left_mode; | extern BOOL use_own_c32[NB_OLD_C32], detect_fakes, iso_op_in_progress, format_op_in_progress, right_to_left_mode; | ||||||
| extern BOOL allow_dual_uefi_bios, togo_mode, large_drive; | extern BOOL allow_dual_uefi_bios, togo_mode, large_drive, usb_debug; | ||||||
| extern RUFUS_IMG_REPORT img_report; | extern RUFUS_IMG_REPORT img_report; | ||||||
| extern int64_t iso_blocking_status; | extern int64_t iso_blocking_status; | ||||||
| extern uint16_t rufus_version[3], embedded_sl_version[2]; | extern uint16_t rufus_version[3], embedded_sl_version[2]; | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | ||||||
| IDD_DIALOG DIALOGEX 12, 12, 242, 376 | IDD_DIALOG DIALOGEX 12, 12, 242, 376 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_ACCEPTFILES | EXSTYLE WS_EX_ACCEPTFILES | ||||||
| CAPTION "Rufus 2.15.1096" | CAPTION "Rufus 2.15.1097" | ||||||
| FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | ||||||
| BEGIN | BEGIN | ||||||
|     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 |     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 | ||||||
|  | @ -334,8 +334,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 2,15,1096,0 |  FILEVERSION 2,15,1097,0 | ||||||
|  PRODUCTVERSION 2,15,1096,0 |  PRODUCTVERSION 2,15,1097,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -352,13 +352,13 @@ BEGIN | ||||||
|         BEGIN |         BEGIN | ||||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" |             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "2.15.1096" |             VALUE "FileVersion", "2.15.1097" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2017 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2017 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" |             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||||
|             VALUE "OriginalFilename", "rufus.exe" |             VALUE "OriginalFilename", "rufus.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "2.15.1096" |             VALUE "ProductVersion", "2.15.1097" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
							
								
								
									
										290
									
								
								src/search.c
									
										
									
									
									
								
							
							
						
						
									
										290
									
								
								src/search.c
									
										
									
									
									
								
							|  | @ -34,9 +34,18 @@ | ||||||
| #include "missing.h" | #include "missing.h" | ||||||
| #include "msapi_utf8.h" | #include "msapi_utf8.h" | ||||||
| 
 | 
 | ||||||
|  | // Process Hacker does some filtering using Object Types, but this doesn't help us.
 | ||||||
|  | // Keep this option, just in case.
 | ||||||
|  | // #define USE_OBJECT_TYPES
 | ||||||
|  | 
 | ||||||
| PF_TYPE_DECL(NTAPI, PVOID, RtlCreateHeap, (ULONG, PVOID, SIZE_T, SIZE_T, PVOID, PRTL_HEAP_PARAMETERS)); | PF_TYPE_DECL(NTAPI, PVOID, RtlCreateHeap, (ULONG, PVOID, SIZE_T, SIZE_T, PVOID, PRTL_HEAP_PARAMETERS)); | ||||||
|  | PF_TYPE_DECL(NTAPI, PVOID, RtlDestroyHeap, (PVOID)); | ||||||
| PF_TYPE_DECL(NTAPI, PVOID, RtlAllocateHeap, (PVOID, ULONG, SIZE_T)); | PF_TYPE_DECL(NTAPI, PVOID, RtlAllocateHeap, (PVOID, ULONG, SIZE_T)); | ||||||
| PF_TYPE_DECL(NTAPI, BOOLEAN, RtlFreeHeap, (PVOID, ULONG, PVOID)); | PF_TYPE_DECL(NTAPI, BOOLEAN, RtlFreeHeap, (PVOID, ULONG, PVOID)); | ||||||
|  | #ifdef USE_OBJECT_TYPES | ||||||
|  | PF_TYPE_DECL(NTAPI, VOID, RtlInitUnicodeString, (PUNICODE_STRING, PCWSTR)); | ||||||
|  | PF_TYPE_DECL(NTAPI, BOOLEAN, RtlEqualUnicodeString, (PCUNICODE_STRING, PCUNICODE_STRING, BOOLEAN)); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| PF_TYPE_DECL(NTAPI, NTSTATUS, NtQuerySystemInformation, (SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG)); | PF_TYPE_DECL(NTAPI, NTSTATUS, NtQuerySystemInformation, (SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG)); | ||||||
| PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryObject, (HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG)); | PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryObject, (HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG)); | ||||||
|  | @ -60,10 +69,12 @@ static char* NtStatusError(NTSTATUS Status) { | ||||||
| 	switch (Status) { | 	switch (Status) { | ||||||
| 	case STATUS_UNSUCCESSFUL: | 	case STATUS_UNSUCCESSFUL: | ||||||
| 		return "Operation Failed"; | 		return "Operation Failed"; | ||||||
| 	case STATUS_NOT_IMPLEMENTED: |  | ||||||
| 		return "Not Implemented"; |  | ||||||
| 	case STATUS_BUFFER_OVERFLOW: | 	case STATUS_BUFFER_OVERFLOW: | ||||||
| 		return "Buffer Overflow"; | 		return "Buffer Overflow"; | ||||||
|  | 	case STATUS_NOT_IMPLEMENTED: | ||||||
|  | 		return "Not Implemented"; | ||||||
|  | 	case STATUS_INFO_LENGTH_MISMATCH: | ||||||
|  | 		return "Info Length Mismatch"; | ||||||
| 	case STATUS_INVALID_HANDLE: | 	case STATUS_INVALID_HANDLE: | ||||||
| 		return "Invalid Handle."; | 		return "Invalid Handle."; | ||||||
| 	case STATUS_INVALID_PARAMETER: | 	case STATUS_INVALID_PARAMETER: | ||||||
|  | @ -77,9 +88,11 @@ static char* NtStatusError(NTSTATUS Status) { | ||||||
| 	case STATUS_OBJECT_TYPE_MISMATCH: | 	case STATUS_OBJECT_TYPE_MISMATCH: | ||||||
| 		return "Wrong Type"; | 		return "Wrong Type"; | ||||||
| 	case STATUS_OBJECT_NAME_INVALID: | 	case STATUS_OBJECT_NAME_INVALID: | ||||||
| 		return "Object Name invalid"; | 		return "Object Name Invalid"; | ||||||
| 	case STATUS_OBJECT_NAME_NOT_FOUND: | 	case STATUS_OBJECT_NAME_NOT_FOUND: | ||||||
| 		return "Object Name not found"; | 		return "Object Name not found"; | ||||||
|  | 	case STATUS_OBJECT_PATH_INVALID: | ||||||
|  | 		return "Object Path Invalid"; | ||||||
| 	case STATUS_SHARING_VIOLATION: | 	case STATUS_SHARING_VIOLATION: | ||||||
| 		return "Sharing Violation"; | 		return "Sharing Violation"; | ||||||
| 	case STATUS_INSUFFICIENT_RESOURCES: | 	case STATUS_INSUFFICIENT_RESOURCES: | ||||||
|  | @ -92,6 +105,45 @@ static char* NtStatusError(NTSTATUS Status) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | static NTSTATUS PhCreateHeap(VOID) | ||||||
|  | { | ||||||
|  | 	NTSTATUS status = STATUS_SUCCESS; | ||||||
|  | 
 | ||||||
|  | 	if (PhHeapHandle != NULL) | ||||||
|  | 		return STATUS_ALREADY_COMPLETE; | ||||||
|  | 
 | ||||||
|  | 	PF_INIT_OR_SET_STATUS(RtlCreateHeap, Ntdll); | ||||||
|  | 	 | ||||||
|  | 	if (NT_SUCCESS(status)) { | ||||||
|  | 		PhHeapHandle = pfRtlCreateHeap(HEAP_NO_SERIALIZE | HEAP_GROWABLE, NULL, 2 * MB, 1 * MB, NULL, NULL); | ||||||
|  | 		if (PhHeapHandle == NULL) | ||||||
|  | 			status = STATUS_UNSUCCESSFUL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static NTSTATUS PhDestroyHeap(VOID) | ||||||
|  | { | ||||||
|  | 	NTSTATUS status = STATUS_SUCCESS; | ||||||
|  | 
 | ||||||
|  | 	if (PhHeapHandle == NULL) | ||||||
|  | 		return STATUS_ALREADY_COMPLETE; | ||||||
|  | 
 | ||||||
|  | 	PF_INIT_OR_SET_STATUS(RtlDestroyHeap, Ntdll); | ||||||
|  | 
 | ||||||
|  | 	if (NT_SUCCESS(status)) { | ||||||
|  | 		if (pfRtlDestroyHeap(PhHeapHandle) == NULL) { | ||||||
|  | 			PhHeapHandle = NULL; | ||||||
|  | 		} else { | ||||||
|  | 			status = STATUS_UNSUCCESSFUL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Allocates a block of memory. |  * Allocates a block of memory. | ||||||
|  * |  * | ||||||
|  | @ -102,15 +154,11 @@ static char* NtStatusError(NTSTATUS Status) { | ||||||
|  */ |  */ | ||||||
| static PVOID PhAllocate(SIZE_T Size) | static PVOID PhAllocate(SIZE_T Size) | ||||||
| { | { | ||||||
| 	PF_INIT_OR_OUT(RtlCreateHeap, Ntdll); | 	PF_INIT(RtlAllocateHeap, Ntdll); | ||||||
| 	PF_INIT_OR_OUT(RtlAllocateHeap, Ntdll); | 	if (pfRtlAllocateHeap == NULL) | ||||||
|  | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (PhHeapHandle == NULL) { |  | ||||||
| 		PhHeapHandle = pfRtlCreateHeap(HEAP_GROWABLE, NULL, 2 * MB, 1 * MB, NULL, NULL); |  | ||||||
| 	} |  | ||||||
| 	return pfRtlAllocateHeap(PhHeapHandle, 0, Size); | 	return pfRtlAllocateHeap(PhHeapHandle, 0, Size); | ||||||
| out: |  | ||||||
| 	return NULL; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -122,6 +170,7 @@ out: | ||||||
| static VOID PhFree(PVOID Memory) | static VOID PhFree(PVOID Memory) | ||||||
| { | { | ||||||
| 	PF_INIT(RtlFreeHeap, Ntdll); | 	PF_INIT(RtlFreeHeap, Ntdll); | ||||||
|  | 
 | ||||||
| 	if (pfRtlFreeHeap != NULL) | 	if (pfRtlFreeHeap != NULL) | ||||||
| 		pfRtlFreeHeap(PhHeapHandle, 0, Memory); | 		pfRtlFreeHeap(PhHeapHandle, 0, Memory); | ||||||
| } | } | ||||||
|  | @ -137,13 +186,13 @@ static VOID PhFree(PVOID Memory) | ||||||
| NTSTATUS PhEnumHandlesEx(PSYSTEM_HANDLE_INFORMATION_EX *Handles) | NTSTATUS PhEnumHandlesEx(PSYSTEM_HANDLE_INFORMATION_EX *Handles) | ||||||
| { | { | ||||||
| 	static ULONG initialBufferSize = 0x10000; | 	static ULONG initialBufferSize = 0x10000; | ||||||
| 	NTSTATUS status; | 	NTSTATUS status = STATUS_SUCCESS; | ||||||
| 	PVOID buffer; | 	PVOID buffer; | ||||||
| 	ULONG bufferSize; | 	ULONG bufferSize; | ||||||
| 
 | 
 | ||||||
| 	PF_INIT(NtQuerySystemInformation, Ntdll); | 	PF_INIT_OR_SET_STATUS(NtQuerySystemInformation, Ntdll); | ||||||
| 	if (pfNtQuerySystemInformation == NULL) | 	if (!NT_SUCCESS(status)) | ||||||
| 		return STATUS_NOT_IMPLEMENTED; | 		return status; | ||||||
| 
 | 
 | ||||||
| 	bufferSize = initialBufferSize; | 	bufferSize = initialBufferSize; | ||||||
| 	buffer = PhAllocate(bufferSize); | 	buffer = PhAllocate(bufferSize); | ||||||
|  | @ -187,7 +236,7 @@ NTSTATUS PhEnumHandlesEx(PSYSTEM_HANDLE_INFORMATION_EX *Handles) | ||||||
|  */ |  */ | ||||||
| NTSTATUS PhOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, HANDLE ProcessId) | NTSTATUS PhOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, HANDLE ProcessId) | ||||||
| { | { | ||||||
| 	NTSTATUS status = STATUS_NOT_IMPLEMENTED; | 	NTSTATUS status = STATUS_SUCCESS; | ||||||
| 	OBJECT_ATTRIBUTES objectAttributes; | 	OBJECT_ATTRIBUTES objectAttributes; | ||||||
| 	CLIENT_ID clientId; | 	CLIENT_ID clientId; | ||||||
| 
 | 
 | ||||||
|  | @ -196,7 +245,9 @@ NTSTATUS PhOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, HANDLE | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	PF_INIT_OR_OUT(NtOpenProcess, Ntdll); | 	PF_INIT_OR_SET_STATUS(NtOpenProcess, Ntdll); | ||||||
|  | 	if (!NT_SUCCESS(status)) | ||||||
|  | 		return status; | ||||||
| 
 | 
 | ||||||
| 	clientId.UniqueProcess = ProcessId; | 	clientId.UniqueProcess = ProcessId; | ||||||
| 	clientId.UniqueThread = NULL; | 	clientId.UniqueThread = NULL; | ||||||
|  | @ -204,10 +255,85 @@ NTSTATUS PhOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, HANDLE | ||||||
| 	InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL); | 	InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL); | ||||||
| 	status = pfNtOpenProcess(ProcessHandle, DesiredAccess, &objectAttributes, &clientId); | 	status = pfNtOpenProcess(ProcessHandle, DesiredAccess, &objectAttributes, &clientId); | ||||||
| 
 | 
 | ||||||
| out: |  | ||||||
| 	return status; | 	return status; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef USE_OBJECT_TYPES | ||||||
|  | NTSTATUS PhEnumObjectTypes(POBJECT_TYPES_INFORMATION *ObjectTypes) | ||||||
|  | { | ||||||
|  | 	NTSTATUS status = STATUS_SUCCESS; | ||||||
|  | 	PVOID buffer; | ||||||
|  | 	ULONG bufferSize; | ||||||
|  | 	ULONG returnLength; | ||||||
|  | 
 | ||||||
|  | 	PF_INIT_OR_SET_STATUS(NtQueryObject, Ntdll); | ||||||
|  | 	if (!NT_SUCCESS(status)) | ||||||
|  | 		return status; | ||||||
|  | 
 | ||||||
|  | 	bufferSize = 0x1000; | ||||||
|  | 	buffer = PhAllocate(bufferSize); | ||||||
|  | 
 | ||||||
|  | 	while ((status = pfNtQueryObject(NULL, ObjectTypesInformation, buffer, bufferSize, &returnLength)) == STATUS_INFO_LENGTH_MISMATCH) { | ||||||
|  | 		PhFree(buffer); | ||||||
|  | 		bufferSize *= 2; | ||||||
|  | 
 | ||||||
|  | 		// Fail if we're resizing the buffer to something very large.
 | ||||||
|  | 		if (bufferSize > PH_LARGE_BUFFER_SIZE) | ||||||
|  | 			return STATUS_INSUFFICIENT_RESOURCES; | ||||||
|  | 
 | ||||||
|  | 		buffer = PhAllocate(bufferSize); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!NT_SUCCESS(status)) { | ||||||
|  | 		PhFree(buffer); | ||||||
|  | 		return status; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	*ObjectTypes = (POBJECT_TYPES_INFORMATION)buffer; | ||||||
|  | 
 | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ULONG PhGetObjectTypeNumber(PUNICODE_STRING TypeName) | ||||||
|  | { | ||||||
|  | 	NTSTATUS status = STATUS_SUCCESS; | ||||||
|  | 	POBJECT_TYPES_INFORMATION objectTypes; | ||||||
|  | 	POBJECT_TYPE_INFORMATION objectType; | ||||||
|  | 	ULONG objectIndex = -1; | ||||||
|  | 	ULONG i; | ||||||
|  | 
 | ||||||
|  | 	PF_INIT_OR_SET_STATUS(RtlEqualUnicodeString, NtDll); | ||||||
|  | 	if (!NT_SUCCESS(status)) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	status = PhEnumObjectTypes(&objectTypes); | ||||||
|  | 	if (NT_SUCCESS(status)) { | ||||||
|  | 		objectType = PH_FIRST_OBJECT_TYPE(objectTypes); | ||||||
|  | 
 | ||||||
|  | 		for (i = 0; i < objectTypes->NumberOfTypes; i++) { | ||||||
|  | 			if (pfRtlEqualUnicodeString(&objectType->TypeName, TypeName, TRUE)) { | ||||||
|  | 				if (nWindowsVersion >= WINDOWS_8_1) { | ||||||
|  | 					objectIndex = objectType->TypeIndex; | ||||||
|  | 					break; | ||||||
|  | 				} else if (nWindowsVersion >= WINDOWS_7) { | ||||||
|  | 					objectIndex = i + 2; | ||||||
|  | 					break; | ||||||
|  | 				} else { | ||||||
|  | 					objectIndex = i + 1; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			objectType = PH_NEXT_OBJECT_TYPE(objectType); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		PhFree(objectTypes); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return objectIndex; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Search all the processes and list the ones that have a specific handle open. |  * Search all the processes and list the ones that have a specific handle open. | ||||||
|  * |  * | ||||||
|  | @ -219,42 +345,63 @@ out: | ||||||
|  */ |  */ | ||||||
| BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) | BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) | ||||||
| { | { | ||||||
| 	NTSTATUS status; | 	NTSTATUS status = STATUS_SUCCESS; | ||||||
| 	PSYSTEM_HANDLE_INFORMATION_EX handles; | 	PSYSTEM_HANDLE_INFORMATION_EX handles = NULL; | ||||||
| 	POBJECT_NAME_INFORMATION buffer; | 	POBJECT_NAME_INFORMATION buffer = NULL; | ||||||
|  | #ifdef USE_OBJECT_TYPES | ||||||
|  | 	UNICODE_STRING fileTypeName; | ||||||
|  | 	ULONG fileObjectTypeIndex = -1; | ||||||
|  | #endif | ||||||
| 	ULONG_PTR i; | 	ULONG_PTR i; | ||||||
|  | 	ULONG_PTR pid[2]; | ||||||
|  | 	ULONG_PTR last_access_denied_pid = 0; | ||||||
| 	ULONG bufferSize; | 	ULONG bufferSize; | ||||||
| 	USHORT wHandleNameLen; | 	USHORT wHandleNameLen; | ||||||
| 	WCHAR *wHandleName; | 	WCHAR *wHandleName = NULL; | ||||||
| 	HANDLE dupHandle = NULL; | 	HANDLE dupHandle = NULL; | ||||||
| 	HANDLE processHandle = NULL; | 	HANDLE processHandle = NULL; | ||||||
| 	BOOLEAN bFound = FALSE; | 	BOOLEAN bFound = FALSE; | ||||||
| 	char exe_path[2][MAX_PATH]; | 	char exe[2][MAX_PATH]; | ||||||
| 	int cur; | 	int cur_exe, cur_pid; | ||||||
| 
 | 
 | ||||||
| 	status = STATUS_NOT_IMPLEMENTED; | 	PF_INIT_OR_SET_STATUS(NtQueryObject, Ntdll); | ||||||
| 	PF_INIT(NtQueryObject, Ntdll); | 	PF_INIT_OR_SET_STATUS(NtDuplicateObject, NtDll); | ||||||
| 	PF_INIT(NtDuplicateObject, NtDll); | 	PF_INIT_OR_SET_STATUS(NtClose, NtDll); | ||||||
| 	PF_INIT(NtClose, NtDll); | #ifdef USE_OBJECT_TYPES | ||||||
| 	if ((pfNtQueryObject != NULL) && (pfNtClose != NULL) && (pfNtDuplicateObject != NULL)) | 	PF_INIT(RtlInitUnicodeString, NtDll); | ||||||
| 		status = 0; | #endif | ||||||
|  | 
 | ||||||
|  | 	if (NT_SUCCESS(status)) | ||||||
|  | 		status = PhCreateHeap(); | ||||||
| 
 | 
 | ||||||
| 	if (NT_SUCCESS(status)) | 	if (NT_SUCCESS(status)) | ||||||
| 		status = PhEnumHandlesEx(&handles); | 		status = PhEnumHandlesEx(&handles); | ||||||
|  | 
 | ||||||
| 	if (!NT_SUCCESS(status)) { | 	if (!NT_SUCCESS(status)) { | ||||||
| 		uprintf("Could not enumerate handles: %s", NtStatusError(status)); | 		uprintf("Warning: Could not enumerate process handles: %s", NtStatusError(status)); | ||||||
| 		return FALSE; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	pid[0] = (ULONG_PTR)NULL; | ||||||
| 	exe_path[0][0] = 0; | 	cur_pid = 1; | ||||||
| 	cur = 1; | 	exe[0][0] = 0; | ||||||
|  | 	cur_exe = 1; | ||||||
| 
 | 
 | ||||||
| 	wHandleName = utf8_to_wchar(HandleName); | 	wHandleName = utf8_to_wchar(HandleName); | ||||||
| 	wHandleNameLen = (USHORT) wcslen(wHandleName); | 	wHandleNameLen = (USHORT)wcslen(wHandleName); | ||||||
| 
 | 
 | ||||||
| 	bufferSize = 0x200; | 	bufferSize = 0x200; | ||||||
| 	buffer = PhAllocate(bufferSize); | 	buffer = PhAllocate(bufferSize); | ||||||
|  | 	if (buffer == NULL) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | #ifdef USE_OBJECT_TYPES | ||||||
|  | 	pfRtlInitUnicodeString(&fileTypeName, L"File"); | ||||||
|  | 	fileObjectTypeIndex = PhGetObjectTypeNumber(&fileTypeName); | ||||||
|  | 	if (fileObjectTypeIndex < 0) | ||||||
|  | 		uprintf("Warning: Could not get Object Index for file types"); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; ; i++) { | 	for (i = 0; ; i++) { | ||||||
| 		ULONG attempts = 8; | 		ULONG attempts = 8; | ||||||
|  | @ -264,28 +411,53 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) | ||||||
| 			pfNtClose(dupHandle); | 			pfNtClose(dupHandle); | ||||||
| 			dupHandle = NULL; | 			dupHandle = NULL; | ||||||
| 		} | 		} | ||||||
| 		if (processHandle != NULL) { | 
 | ||||||
| 			if (processHandle != NtCurrentProcess()) | #ifdef USE_OBJECT_TYPES | ||||||
| 				pfNtClose(processHandle); | 		// Only look for File objects type
 | ||||||
| 			processHandle = NULL; | 		if ((fileObjectTypeIndex >= 0 ) && (handleInfo->ObjectTypeIndex != (USHORT)fileObjectTypeIndex)) | ||||||
|  | 			continue; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 		// Update the current handle's process PID and compare against last
 | ||||||
|  | 		pid[cur_pid] = handleInfo->UniqueProcessId; | ||||||
|  | 
 | ||||||
|  | 		if (pid[0] != pid[1]) { | ||||||
|  | 			cur_pid = (cur_pid + 1) % 2; | ||||||
|  | 			// Close the previous handle
 | ||||||
|  | 			if (processHandle != NULL) { | ||||||
|  | 				if (processHandle != NtCurrentProcess()) | ||||||
|  | 					pfNtClose(processHandle); | ||||||
|  | 				processHandle = NULL; | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		CHECK_FOR_USER_CANCEL; | 		CHECK_FOR_USER_CANCEL; | ||||||
| 
 | 
 | ||||||
|  | 		// Don't bother with processes we can't access
 | ||||||
|  | 		if (handleInfo->UniqueProcessId == last_access_denied_pid) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
| 		// Exit loop condition
 | 		// Exit loop condition
 | ||||||
| 		if (i >= handles->NumberOfHandles) | 		if (i >= handles->NumberOfHandles) | ||||||
| 			break; | 			break; | ||||||
| 
 | 
 | ||||||
| 		// Get the process that created the handle we are after
 | 		// Open the process to which the handle we are after belongs, if not already opened
 | ||||||
| 		// TODO: We probably should keep a list of the most recent processes and perform a lookup
 | 		if (pid[0] != pid[1]) { | ||||||
| 		// instead of Opening the process every time
 | 			status = PhOpenProcess(&processHandle, PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, | ||||||
| 		status = PhOpenProcess(&processHandle, PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, | 				(HANDLE)handleInfo->UniqueProcessId); | ||||||
| 			(HANDLE)handleInfo->UniqueProcessId); | 			// There exists some processes we can't access
 | ||||||
| 		// There exists some processes we can't access
 | 			if (!NT_SUCCESS(status)) { | ||||||
| 		if (!NT_SUCCESS(status)) | 				uuprintf("SearchProcess: Could not open process %ld: %s", | ||||||
| 			continue; | 					handleInfo->UniqueProcessId, NtStatusError(status)); | ||||||
|  | 				processHandle = NULL; | ||||||
|  | 				if (status == STATUS_ACCESS_DENIED) { | ||||||
|  | 					last_access_denied_pid = handleInfo->UniqueProcessId; | ||||||
|  | 				} | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		// Must duplicate the handle onto our own process, before we can access its properties
 | 		// Now duplicate this handle onto our own process, so that we can access its properties
 | ||||||
| 		if (processHandle == NtCurrentProcess()) { | 		if (processHandle == NtCurrentProcess()) { | ||||||
| 			if (bIgnoreSelf) | 			if (bIgnoreSelf) | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -293,7 +465,6 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) | ||||||
| 		} else { | 		} else { | ||||||
| 			status = pfNtDuplicateObject(processHandle, (HANDLE)handleInfo->HandleValue, | 			status = pfNtDuplicateObject(processHandle, (HANDLE)handleInfo->HandleValue, | ||||||
| 				NtCurrentProcess(), &dupHandle, 0, 0, 0); | 				NtCurrentProcess(), &dupHandle, 0, 0, 0); | ||||||
| 			// Why does it always work for Process Hacker and not me???
 |  | ||||||
| 			if (!NT_SUCCESS(status)) | 			if (!NT_SUCCESS(status)) | ||||||
| 				continue; | 				continue; | ||||||
| 		} | 		} | ||||||
|  | @ -304,18 +475,23 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) | ||||||
| 
 | 
 | ||||||
| 		// A loop is needed because the I/O subsystem likes to give us the wrong return lengths...
 | 		// A loop is needed because the I/O subsystem likes to give us the wrong return lengths...
 | ||||||
| 		do { | 		do { | ||||||
| 			status = pfNtQueryObject(dupHandle, ObjectBasicInformation + 1, | 			ULONG returnSize; | ||||||
| 				buffer, bufferSize, &bufferSize); | 			status = pfNtQueryObject(dupHandle, ObjectNameInformation, buffer, bufferSize, &returnSize); | ||||||
| 			if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH || | 			if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH || | ||||||
| 				status == STATUS_BUFFER_TOO_SMALL) { | 				status == STATUS_BUFFER_TOO_SMALL) { | ||||||
|  | 				uuprintf("SearchProcess: Realloc from %d to %d", bufferSize, returnSize); | ||||||
|  | 				bufferSize = returnSize; | ||||||
| 				PhFree(buffer); | 				PhFree(buffer); | ||||||
| 				buffer = PhAllocate(bufferSize); | 				buffer = PhAllocate(bufferSize); | ||||||
| 			} else { | 			} else { | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 		} while (--attempts); | 		} while (--attempts); | ||||||
| 		if (!NT_SUCCESS(status)) | 		if (!NT_SUCCESS(status)) { | ||||||
|  | 			uuprintf("SearchProcess: NtQueryObject failed for handle %X of process %ld: %s", | ||||||
|  | 				handleInfo->HandleValue, handleInfo->UniqueProcessId, NtStatusError(status)); | ||||||
| 			continue; | 			continue; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		// Don't bother comparing if we are looking for full match and the length is different
 | 		// Don't bother comparing if we are looking for full match and the length is different
 | ||||||
| 		if ((!bPartialMatch) && (wHandleNameLen != buffer->Name.Length)) | 		if ((!bPartialMatch) && (wHandleNameLen != buffer->Name.Length)) | ||||||
|  | @ -335,11 +511,11 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// TODO: only list processes with conflicting access rights (ignore "Read attributes" or "Synchronize")
 | 		// TODO: only list processes with conflicting access rights (ignore "Read attributes" or "Synchronize")
 | ||||||
| 		if (GetModuleFileNameExU(processHandle, 0, exe_path[cur], MAX_PATH - 1)) { | 		if (GetModuleFileNameExU(processHandle, 0, exe[cur_exe], MAX_PATH - 1)) { | ||||||
| 			// Avoid printing the same path repeatedly
 | 			// Avoid printing the same path repeatedly
 | ||||||
| 			if (strcmp(exe_path[0], exe_path[1]) != 0) { | 			if (strcmp(exe[0], exe[1]) != 0) { | ||||||
| 				uprintf("o %s", exe_path[cur]); | 				uprintf("o %s", exe[cur_exe]); | ||||||
| 				cur = (cur + 1) % 2; | 				cur_exe = (cur_exe + 1) % 2; | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			uprintf("o Unknown (Process ID %d)", GetProcessId(processHandle)); | 			uprintf("o Unknown (Process ID %d)", GetProcessId(processHandle)); | ||||||
|  | @ -354,5 +530,7 @@ out: | ||||||
| 
 | 
 | ||||||
| 	free(wHandleName); | 	free(wHandleName); | ||||||
| 	PhFree(buffer); | 	PhFree(buffer); | ||||||
|  | 	PhFree(handles); | ||||||
|  | 	PhDestroyHeap(); | ||||||
| 	return bFound; | 	return bFound; | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										60
									
								
								src/search.h
									
										
									
									
									
								
							
							
						
						
									
										60
									
								
								src/search.h
									
										
									
									
									
								
							|  | @ -30,6 +30,8 @@ | ||||||
| 
 | 
 | ||||||
| #define PH_LARGE_BUFFER_SIZE			(256 * 1024 * 1024) | #define PH_LARGE_BUFFER_SIZE			(256 * 1024 * 1024) | ||||||
| 
 | 
 | ||||||
|  | #define STATUS_SUCCESS					((NTSTATUS)0x00000000L) | ||||||
|  | #define STATUS_ALREADY_COMPLETE			((NTSTATUS)0x000000FFL) | ||||||
| #define STATUS_UNSUCCESSFUL				((NTSTATUS)0x80000001L) | #define STATUS_UNSUCCESSFUL				((NTSTATUS)0x80000001L) | ||||||
| #define STATUS_BUFFER_OVERFLOW			((NTSTATUS)0x80000005L) | #define STATUS_BUFFER_OVERFLOW			((NTSTATUS)0x80000005L) | ||||||
| #define STATUS_NOT_IMPLEMENTED			((NTSTATUS)0xC0000002L) | #define STATUS_NOT_IMPLEMENTED			((NTSTATUS)0xC0000002L) | ||||||
|  | @ -40,6 +42,7 @@ | ||||||
| #define STATUS_OBJECT_TYPE_MISMATCH		((NTSTATUS)0xC0000024L) | #define STATUS_OBJECT_TYPE_MISMATCH		((NTSTATUS)0xC0000024L) | ||||||
| #define STATUS_OBJECT_NAME_INVALID		((NTSTATUS)0xC0000033L) | #define STATUS_OBJECT_NAME_INVALID		((NTSTATUS)0xC0000033L) | ||||||
| #define STATUS_OBJECT_NAME_NOT_FOUND	((NTSTATUS)0xC0000034L) | #define STATUS_OBJECT_NAME_NOT_FOUND	((NTSTATUS)0xC0000034L) | ||||||
|  | #define STATUS_OBJECT_PATH_INVALID		((NTSTATUS)0xC0000039L) | ||||||
| #define STATUS_SHARING_VIOLATION		((NTSTATUS)0xC0000043L) | #define STATUS_SHARING_VIOLATION		((NTSTATUS)0xC0000043L) | ||||||
| #define STATUS_INSUFFICIENT_RESOURCES	((NTSTATUS)0xC000009AL) | #define STATUS_INSUFFICIENT_RESOURCES	((NTSTATUS)0xC000009AL) | ||||||
| #define STATUS_NOT_SUPPORTED			((NTSTATUS)0xC00000BBL) | #define STATUS_NOT_SUPPORTED			((NTSTATUS)0xC00000BBL) | ||||||
|  | @ -78,8 +81,62 @@ typedef struct _CLIENT_ID | ||||||
| 	HANDLE UniqueProcess; | 	HANDLE UniqueProcess; | ||||||
| 	HANDLE UniqueThread; | 	HANDLE UniqueThread; | ||||||
| } CLIENT_ID, *PCLIENT_ID; | } CLIENT_ID, *PCLIENT_ID; | ||||||
|  | 
 | ||||||
|  | typedef struct _OBJECT_TYPE_INFORMATION | ||||||
|  | { | ||||||
|  | 	UNICODE_STRING TypeName; | ||||||
|  | 	ULONG TotalNumberOfObjects; | ||||||
|  | 	ULONG TotalNumberOfHandles; | ||||||
|  | 	ULONG TotalPagedPoolUsage; | ||||||
|  | 	ULONG TotalNonPagedPoolUsage; | ||||||
|  | 	ULONG TotalNamePoolUsage; | ||||||
|  | 	ULONG TotalHandleTableUsage; | ||||||
|  | 	ULONG HighWaterNumberOfObjects; | ||||||
|  | 	ULONG HighWaterNumberOfHandles; | ||||||
|  | 	ULONG HighWaterPagedPoolUsage; | ||||||
|  | 	ULONG HighWaterNonPagedPoolUsage; | ||||||
|  | 	ULONG HighWaterNamePoolUsage; | ||||||
|  | 	ULONG HighWaterHandleTableUsage; | ||||||
|  | 	ULONG InvalidAttributes; | ||||||
|  | 	GENERIC_MAPPING GenericMapping; | ||||||
|  | 	ULONG ValidAccessMask; | ||||||
|  | 	BOOLEAN SecurityRequired; | ||||||
|  | 	BOOLEAN MaintainHandleCount; | ||||||
|  | 	UCHAR TypeIndex; // since WINBLUE
 | ||||||
|  | 	CHAR ReservedByte; | ||||||
|  | 	ULONG PoolType; | ||||||
|  | 	ULONG DefaultPagedPoolCharge; | ||||||
|  | 	ULONG DefaultNonPagedPoolCharge; | ||||||
|  | } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; | ||||||
|  | 
 | ||||||
|  | typedef enum _MY_OBJECT_INFORMATION_CLASS | ||||||
|  | { | ||||||
|  | 	_ObjectBasicInformation, // OBJECT_BASIC_INFORMATION
 | ||||||
|  | 	ObjectNameInformation, // OBJECT_NAME_INFORMATION
 | ||||||
|  | 	_ObjectTypeInformation, // OBJECT_TYPE_INFORMATION
 | ||||||
|  | 	ObjectTypesInformation, // OBJECT_TYPES_INFORMATION
 | ||||||
|  | 	ObjectHandleFlagInformation, // OBJECT_HANDLE_FLAG_INFORMATION
 | ||||||
|  | 	ObjectSessionInformation, | ||||||
|  | 	ObjectSessionObjectInformation, | ||||||
|  | 	MaxObjectInfoClass | ||||||
|  | } MY_OBJECT_INFORMATION_CLASS; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | typedef struct _OBJECT_TYPES_INFORMATION | ||||||
|  | { | ||||||
|  | 	ULONG NumberOfTypes; | ||||||
|  | } OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION; | ||||||
|  | 
 | ||||||
|  | #define ALIGN_UP_BY(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1)) | ||||||
|  | #define ALIGN_UP(Address, Type) ALIGN_UP_BY(Address, sizeof(Type)) | ||||||
|  | 
 | ||||||
|  | #define PH_FIRST_OBJECT_TYPE(ObjectTypes) \ | ||||||
|  |     (POBJECT_TYPE_INFORMATION)((PCHAR)(ObjectTypes) + ALIGN_UP(sizeof(OBJECT_TYPES_INFORMATION), ULONG_PTR)) | ||||||
|  | 
 | ||||||
|  | #define PH_NEXT_OBJECT_TYPE(ObjectType) \ | ||||||
|  |     (POBJECT_TYPE_INFORMATION)((PCHAR)(ObjectType) + sizeof(OBJECT_TYPE_INFORMATION) + \ | ||||||
|  |     ALIGN_UP(ObjectType->TypeName.MaximumLength, ULONG_PTR)) | ||||||
|  | 
 | ||||||
| // Heaps
 | // Heaps
 | ||||||
| 
 | 
 | ||||||
| typedef struct _RTL_HEAP_ENTRY | typedef struct _RTL_HEAP_ENTRY | ||||||
|  | @ -184,3 +241,6 @@ typedef struct _RTL_HEAP_PARAMETERS | ||||||
| #define HEAP_CLASS_7 0x00007000 // CSR shared heap
 | #define HEAP_CLASS_7 0x00007000 // CSR shared heap
 | ||||||
| #define HEAP_CLASS_8 0x00008000 // CSR port heap
 | #define HEAP_CLASS_8 0x00008000 // CSR port heap
 | ||||||
| #define HEAP_CLASS_MASK 0x0000f000 | #define HEAP_CLASS_MASK 0x0000f000 | ||||||
|  | 
 | ||||||
|  | #define PF_INIT_OR_SET_STATUS(proc, name)  do {PF_INIT(proc, name);   \ | ||||||
|  | 	if (pf##proc == NULL) status = STATUS_NOT_IMPLEMENTED; } while(0) | ||||||
|  |  | ||||||
|  | @ -32,7 +32,6 @@ | ||||||
| 
 | 
 | ||||||
| #include "settings.h" | #include "settings.h" | ||||||
| 
 | 
 | ||||||
| extern BOOL usb_debug;	// For uuprintf
 |  | ||||||
| int  nWindowsVersion = WINDOWS_UNDEFINED; | int  nWindowsVersion = WINDOWS_UNDEFINED; | ||||||
| int  nWindowsBuildNumber = -1; | int  nWindowsBuildNumber = -1; | ||||||
| char WindowsVersionStr[128] = "Windows "; | char WindowsVersionStr[128] = "Windows "; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue