mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[core] list potentially blocking processes on disk access error
* Using functionality from Process Hacker: https://github.com/processhacker2/processhacker2/ * Part of the #773 enhancement * Also fix minor MinGW and WDK warnings
This commit is contained in:
		
							parent
							
								
									27bc4cb02b
								
							
						
					
					
						commit
						d5f6ddb653
					
				
					 16 changed files with 654 additions and 26 deletions
				
			
		|  | @ -210,6 +210,7 @@ | |||
|     <ClCompile Include="..\pki.c" /> | ||||
|     <ClCompile Include="..\rufus.c" /> | ||||
|     <ClCompile Include="..\checksum.c" /> | ||||
|     <ClCompile Include="..\search.c" /> | ||||
|     <ClCompile Include="..\smart.c" /> | ||||
|     <ClCompile Include="..\stdfn.c" /> | ||||
|     <ClCompile Include="..\stdio.c" /> | ||||
|  | @ -225,6 +226,7 @@ | |||
|     <ClInclude Include="..\format.h" /> | ||||
|     <ClInclude Include="..\hdd_vs_ufd.h" /> | ||||
|     <ClInclude Include="..\missing.h" /> | ||||
|     <ClInclude Include="..\search.h" /> | ||||
|     <ClInclude Include="..\settings.h" /> | ||||
|     <ClInclude Include="..\libcdio\cdio\cdio.h" /> | ||||
|     <ClInclude Include="..\libcdio\cdio\iso9660.h" /> | ||||
|  |  | |||
|  | @ -75,6 +75,9 @@ | |||
|     <ClCompile Include="..\dev.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\search.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="..\rufus.h"> | ||||
|  | @ -143,6 +146,9 @@ | |||
|     <ClInclude Include="..\db.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\search.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="..\..\res\rufus.ico"> | ||||
|  |  | |||
|  | @ -193,6 +193,7 @@ | |||
|     <ClCompile Include="..\pki.c" /> | ||||
|     <ClCompile Include="..\rufus.c" /> | ||||
|     <ClCompile Include="..\checksum.c" /> | ||||
|     <ClCompile Include="..\search.c" /> | ||||
|     <ClCompile Include="..\smart.c" /> | ||||
|     <ClCompile Include="..\stdfn.c" /> | ||||
|     <ClCompile Include="..\stdio.c" /> | ||||
|  | @ -208,6 +209,7 @@ | |||
|     <ClInclude Include="..\format.h" /> | ||||
|     <ClInclude Include="..\hdd_vs_ufd.h" /> | ||||
|     <ClInclude Include="..\missing.h" /> | ||||
|     <ClInclude Include="..\search.h" /> | ||||
|     <ClInclude Include="..\settings.h" /> | ||||
|     <ClInclude Include="..\libcdio\cdio\cdio.h" /> | ||||
|     <ClInclude Include="..\libcdio\cdio\iso9660.h" /> | ||||
|  |  | |||
|  | @ -75,6 +75,9 @@ | |||
|     <ClCompile Include="..\dev.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\search.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="..\rufus.h"> | ||||
|  | @ -143,6 +146,9 @@ | |||
|     <ClInclude Include="..\db.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\search.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="..\..\res\rufus.ico"> | ||||
|  |  | |||
|  | @ -11,8 +11,8 @@ AM_V_WINDRES   = $(AM_V_WINDRES_$(V)) | |||
| 	$(AM_V_WINDRES) $(AM_RCFLAGS) -i $< -o $@ | ||||
| 
 | ||||
| rufus_SOURCES = badblocks.c checksum.c dev.c dos.c dos_locale.c drive.c format.c icon.c iso.c localization.c \ | ||||
| 	net.c parser.c pki.c rufus.c smart.c stdfn.c stdio.c stdlg.c syslinux.c vhd.c | ||||
| 	net.c parser.c pki.c rufus.c search.c smart.c stdfn.c stdio.c stdlg.c syslinux.c vhd.c | ||||
| rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS) | ||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | ||||
| rufus_LDADD = rufus_rc.o bled/libbled.a ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a syslinux/win/libwin.a \ | ||||
| 	libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 -lwininet -lshlwapi -lcrypt32 -lwintrust -lcomdlg32 -luuid | ||||
| 	libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 -lwininet -lshlwapi -lcrypt32 -lwintrust -lcomdlg32 -luuid -lpsapi | ||||
|  |  | |||
|  | @ -93,10 +93,10 @@ am_rufus_OBJECTS = rufus-badblocks.$(OBJEXT) rufus-checksum.$(OBJEXT) \ | |||
| 	rufus-format.$(OBJEXT) rufus-icon.$(OBJEXT) \
 | ||||
| 	rufus-iso.$(OBJEXT) rufus-localization.$(OBJEXT) \
 | ||||
| 	rufus-net.$(OBJEXT) rufus-parser.$(OBJEXT) rufus-pki.$(OBJEXT) \
 | ||||
| 	rufus-rufus.$(OBJEXT) rufus-smart.$(OBJEXT) \
 | ||||
| 	rufus-stdfn.$(OBJEXT) rufus-stdio.$(OBJEXT) \
 | ||||
| 	rufus-stdlg.$(OBJEXT) rufus-syslinux.$(OBJEXT) \
 | ||||
| 	rufus-vhd.$(OBJEXT) | ||||
| 	rufus-rufus.$(OBJEXT) rufus-search.$(OBJEXT) \
 | ||||
| 	rufus-smart.$(OBJEXT) rufus-stdfn.$(OBJEXT) \
 | ||||
| 	rufus-stdio.$(OBJEXT) rufus-stdlg.$(OBJEXT) \
 | ||||
| 	rufus-syslinux.$(OBJEXT) rufus-vhd.$(OBJEXT) | ||||
| rufus_OBJECTS = $(am_rufus_OBJECTS) | ||||
| rufus_DEPENDENCIES = rufus_rc.o bled/libbled.a ms-sys/libmssys.a \
 | ||||
| 	syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
 | ||||
|  | @ -271,12 +271,12 @@ AM_V_WINDRES_1 = $(WINDRES) | |||
| AM_V_WINDRES_ = $(AM_V_WINDRES_$(AM_DEFAULT_VERBOSITY)) | ||||
| AM_V_WINDRES = $(AM_V_WINDRES_$(V)) | ||||
| rufus_SOURCES = badblocks.c checksum.c dev.c dos.c dos_locale.c drive.c format.c icon.c iso.c localization.c \
 | ||||
| 	net.c parser.c pki.c rufus.c smart.c stdfn.c stdio.c stdlg.c syslinux.c vhd.c | ||||
| 	net.c parser.c pki.c rufus.c search.c smart.c stdfn.c stdio.c stdlg.c syslinux.c vhd.c | ||||
| 
 | ||||
| rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS) | ||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | ||||
| rufus_LDADD = rufus_rc.o bled/libbled.a ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a syslinux/win/libwin.a \
 | ||||
| 	libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 -lwininet -lshlwapi -lcrypt32 -lwintrust -lcomdlg32 -luuid | ||||
| 	libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 -lwininet -lshlwapi -lcrypt32 -lwintrust -lcomdlg32 -luuid -lpsapi | ||||
| 
 | ||||
| all: all-recursive | ||||
| 
 | ||||
|  | @ -416,6 +416,12 @@ rufus-rufus.o: rufus.c | |||
| rufus-rufus.obj: rufus.c | ||||
| 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-rufus.obj `if test -f 'rufus.c'; then $(CYGPATH_W) 'rufus.c'; else $(CYGPATH_W) '$(srcdir)/rufus.c'; fi` | ||||
| 
 | ||||
| rufus-search.o: search.c | ||||
| 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-search.o `test -f 'search.c' || echo '$(srcdir)/'`search.c | ||||
| 
 | ||||
| rufus-search.obj: search.c | ||||
| 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-search.obj `if test -f 'search.c'; then $(CYGPATH_W) 'search.c'; else $(CYGPATH_W) '$(srcdir)/search.c'; fi` | ||||
| 
 | ||||
| rufus-smart.o: smart.c | ||||
| 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-smart.o `test -f 'smart.c' || echo '$(srcdir)/'`smart.c | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										11
									
								
								src/drive.c
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								src/drive.c
									
										
									
									
									
								
							|  | @ -127,8 +127,7 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr | |||
| 	if ((safe_strlen(Path) < 5) || (Path[0] != '\\') || (Path[1] != '\\') || (Path[3] != '\\')) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	// Resolve a device path, so that users can seek for it in Process Explorer
 | ||||
| 	// in case of access issues.
 | ||||
| 	// Resolve a device path, so that we can look for that handle in case of access issues.
 | ||||
| 	if (QueryDosDeviceA(&Path[4], DevPath, sizeof(DevPath)) == 0) | ||||
| 		strcpy(DevPath, "???"); | ||||
| 
 | ||||
|  | @ -151,6 +150,7 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr | |||
| 			// If we can't seem to get a hold of the drive for some time,
 | ||||
| 			// try to enable FILE_SHARE_WRITE...
 | ||||
| 			uprintf("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled..."); | ||||
| 			SearchProcess(DevPath, TRUE, TRUE); | ||||
| 			bWriteShare = TRUE; | ||||
| 		} | ||||
| 		Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES); | ||||
|  | @ -161,7 +161,7 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr | |||
| 	} | ||||
| 
 | ||||
| 	if (bWriteAccess) { | ||||
| 		uprintf("Opened %s [%s] for write access\n", Path, DevPath); | ||||
| 		uprintf("Opened %s [%s] for write access", Path, DevPath); | ||||
| 	} | ||||
| 
 | ||||
| 	if (bLockDrive) { | ||||
|  | @ -177,7 +177,10 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr | |||
| 			Sleep(DRIVE_ACCESS_TIMEOUT/DRIVE_ACCESS_RETRIES); | ||||
| 		} | ||||
| 		// If we reached this section, either we didn't manage to get a lock or the user cancelled
 | ||||
| 		uprintf("Could not get exclusive access to %s [%s]: %s\n", Path, DevPath, WindowsErrorString()); | ||||
| 		uprintf("Could not get exclusive access to %s: %s", Path, WindowsErrorString()); | ||||
| 		// See if we can tell the user what processes are accessing the drive
 | ||||
| 		if (!IS_ERROR(FormatStatus)) | ||||
| 			SearchProcess(DevPath, TRUE, TRUE); | ||||
| 		safe_closehandle(hDrive); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -84,6 +84,10 @@ const char* additional_copyrights = | |||
| "http://www.codeguru.com/forum/showthread.php?p=1951973\\line\n" | ||||
| "Public Domain\\line\n" | ||||
| "\\line\n" | ||||
| "Handle search & process enumeration from Process Hacker by wj32 & dmex:\\line\n" | ||||
| "http://processhacker.sourceforge.net/\\line\n" | ||||
| "GNU General Public License (GPL) v3 or later\\line\n" | ||||
| "\\line\n" | ||||
| "Decompression support from BusyBox/Bled:\\line\n" | ||||
| "http://www.busybox.net/\\line\n" | ||||
| "https://github.com/pbatard/bled\\line\n" | ||||
|  |  | |||
|  | @ -31,6 +31,9 @@ | |||
| #include <share.h> | ||||
| #include <fcntl.h> | ||||
| #include <io.h> | ||||
| #if !defined(DDKBUILD) | ||||
| #include <psapi.h> | ||||
| #endif | ||||
| 
 | ||||
| #pragma once | ||||
| #if defined(_MSC_VER) | ||||
|  | @ -125,6 +128,31 @@ static __inline wchar_t* utf8_to_wchar(const char* str) | |||
| 	return wstr; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| * Converts an non NUL-terminated UTF-16 string of length len to UTF8 (allocate returned string) | ||||
| * Returns NULL on error | ||||
| */ | ||||
| static __inline char* wchar_len_to_utf8(const wchar_t* wstr, int wlen) | ||||
| { | ||||
| 	int size = 0; | ||||
| 	char* str = NULL; | ||||
| 
 | ||||
| 	// Find out the size we need to allocate for our converted string
 | ||||
| 	size = WideCharToMultiByte(CP_UTF8, 0, wstr, wlen, NULL, 0, NULL, NULL); | ||||
| 	if (size <= 1)	// An empty string would be size 1
 | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	if ((str = (char*)calloc(size, 1)) == NULL) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	if (WideCharToMultiByte(CP_UTF8, 0, wstr, wlen, str, size, NULL, NULL) != size) { | ||||
| 		sfree(str); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return str; | ||||
| } | ||||
| 
 | ||||
| static __inline DWORD FormatMessageU(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, | ||||
| 									 DWORD dwLanguageId, char* lpBuffer, DWORD nSize, va_list *Arguments) | ||||
| { | ||||
|  | @ -554,6 +582,24 @@ static __inline DWORD GetModuleFileNameU(HMODULE hModule, char* lpFilename, DWOR | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| #if !defined(DDKBUILD) | ||||
| static __inline DWORD GetModuleFileNameExU(HANDLE hProcess, HMODULE hModule, char* lpFilename, DWORD nSize) | ||||
| { | ||||
| 	DWORD ret = 0, err = ERROR_INVALID_DATA; | ||||
| 	// coverity[returned_null]
 | ||||
| 	walloc(lpFilename, nSize); | ||||
| 	ret = GetModuleFileNameExW(hProcess, hModule, wlpFilename, nSize); | ||||
| 	err = GetLastError(); | ||||
| 	if ((ret != 0) | ||||
| 		&& ((ret = wchar_to_utf8_no_alloc(wlpFilename, lpFilename, nSize)) == 0)) { | ||||
| 		err = GetLastError(); | ||||
| 	} | ||||
| 	wfree(lpFilename); | ||||
| 	SetLastError(err); | ||||
| 	return ret; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static __inline DWORD GetFullPathNameU(const char* lpFileName, DWORD nBufferLength, char* lpBuffer, char** lpFilePart) | ||||
| { | ||||
| 	DWORD ret = 0, err = ERROR_INVALID_DATA; | ||||
|  |  | |||
|  | @ -3469,3 +3469,11 @@ out: | |||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| // The old WDK is showing its age and becoming a pain to support
 | ||||
| #if defined(DDKBUILD) | ||||
| BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) { | ||||
| 	uprintf("NOTE: Process search is not implemented on this platform"); | ||||
| 	return FALSE; | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -498,6 +498,7 @@ extern BOOL IsCurrentProcessElevated(void); | |||
| extern char* GetCurrentMUI(void); | ||||
| extern BOOL SetFormatPromptHook(void); | ||||
| extern void ClrFormatPromptHook(void); | ||||
| extern BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf); | ||||
| 
 | ||||
| DWORD WINAPI FormatThread(void* param); | ||||
| DWORD WINAPI SaveImageThread(void* param); | ||||
|  |  | |||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | |||
| IDD_DIALOG DIALOGEX 12, 12, 242, 376 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_ACCEPTFILES | ||||
| CAPTION "Rufus 2.15.1094" | ||||
| CAPTION "Rufus 2.15.1095" | ||||
| FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | ||||
| BEGIN | ||||
|     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 | ||||
|  | @ -334,8 +334,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 2,15,1094,0 | ||||
|  PRODUCTVERSION 2,15,1094,0 | ||||
|  FILEVERSION 2,15,1095,0 | ||||
|  PRODUCTVERSION 2,15,1095,0 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -352,13 +352,13 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "2.15.1094" | ||||
|             VALUE "FileVersion", "2.15.1095" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2017 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||
|             VALUE "OriginalFilename", "rufus.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "2.15.1094" | ||||
|             VALUE "ProductVersion", "2.15.1095" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
							
								
								
									
										358
									
								
								src/search.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										358
									
								
								src/search.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,358 @@ | |||
| /*
 | ||||
|  * Rufus: The Reliable USB Formatting Utility | ||||
|  * Search functionality for handles | ||||
|  * | ||||
|  * Modified from Process Hacker: | ||||
|  *   https://github.com/processhacker2/processhacker2/
 | ||||
|  * Copyright © 2009-2016 wj32 | ||||
|  * Copyright © 2017 dmex | ||||
|  * Copyright © 2017 Pete Batard <pete@akeo.ie> | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #ifdef _CRTDBG_MAP_ALLOC | ||||
| #include <stdlib.h> | ||||
| #include <crtdbg.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <windows.h> | ||||
| 
 | ||||
| #include "rufus.h" | ||||
| #include "search.h" | ||||
| #include "missing.h" | ||||
| #include "msapi_utf8.h" | ||||
| 
 | ||||
| PF_TYPE_DECL(NTAPI, PVOID, RtlCreateHeap, (ULONG, PVOID, SIZE_T, SIZE_T, PVOID, PRTL_HEAP_PARAMETERS)); | ||||
| PF_TYPE_DECL(NTAPI, PVOID, RtlAllocateHeap, (PVOID, ULONG, SIZE_T)); | ||||
| PF_TYPE_DECL(NTAPI, BOOLEAN, RtlFreeHeap, (PVOID, ULONG, PVOID)); | ||||
| 
 | ||||
| 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, NtDuplicateObject, (HANDLE, HANDLE, HANDLE, PHANDLE, ACCESS_MASK, ULONG, ULONG)); | ||||
| PF_TYPE_DECL(NTAPI, NTSTATUS, NtOpenProcess, (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID)); | ||||
| PF_TYPE_DECL(NTAPI, NTSTATUS, NtClose, (HANDLE)); | ||||
| 
 | ||||
| PVOID PhHeapHandle = NULL; | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert an NT Status to an error message | ||||
|  * | ||||
|  * \param Status An operattonal status. | ||||
|  * | ||||
|  * \return An error message string. | ||||
|  * | ||||
|  */ | ||||
| static char* NtStatusError(NTSTATUS Status) { | ||||
| 	static char unknown[32]; | ||||
| 
 | ||||
| 	switch (Status) { | ||||
| 	case STATUS_UNSUCCESSFUL: | ||||
| 		return "Operation Failed"; | ||||
| 	case STATUS_NOT_IMPLEMENTED: | ||||
| 		return "Not Implemented"; | ||||
| 	case STATUS_BUFFER_OVERFLOW: | ||||
| 		return "Buffer Overflow"; | ||||
| 	case STATUS_INVALID_HANDLE: | ||||
| 		return "Invalid Handle."; | ||||
| 	case STATUS_INVALID_PARAMETER: | ||||
| 		return "Invalid Parameter"; | ||||
| 	case STATUS_NO_MEMORY: | ||||
| 		return "Not Enough Quota"; | ||||
| 	case STATUS_ACCESS_DENIED: | ||||
| 		return "Access Denied"; | ||||
| 	case STATUS_BUFFER_TOO_SMALL: | ||||
| 		return "Buffer Too Small"; | ||||
| 	case STATUS_OBJECT_TYPE_MISMATCH: | ||||
| 		return "Wrong Type"; | ||||
| 	case STATUS_OBJECT_NAME_INVALID: | ||||
| 		return "Object Name invalid"; | ||||
| 	case STATUS_OBJECT_NAME_NOT_FOUND: | ||||
| 		return "Object Name not found"; | ||||
| 	case STATUS_SHARING_VIOLATION: | ||||
| 		return "Sharing Violation"; | ||||
| 	case STATUS_INSUFFICIENT_RESOURCES: | ||||
| 		return "Insufficient resources"; | ||||
| 	case STATUS_NOT_SUPPORTED: | ||||
| 		return "Operation is not supported"; | ||||
| 	default: | ||||
| 		safe_sprintf(unknown, sizeof(unknown), "Unknown error 0x%08lx", Status); | ||||
| 		return unknown; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Allocates a block of memory. | ||||
|  * | ||||
|  * \param Size The number of bytes to allocate. | ||||
|  * | ||||
|  * \return A pointer to the allocated block of memory. | ||||
|  * | ||||
|  */ | ||||
| static PVOID PhAllocate(SIZE_T Size) | ||||
| { | ||||
| 	PF_INIT_OR_OUT(RtlCreateHeap, Ntdll); | ||||
| 	PF_INIT_OR_OUT(RtlAllocateHeap, Ntdll); | ||||
| 
 | ||||
| 	if (PhHeapHandle == NULL) { | ||||
| 		PhHeapHandle = pfRtlCreateHeap(HEAP_GROWABLE, NULL, 2 * MB, 1 * MB, NULL, NULL); | ||||
| 	} | ||||
| 	return pfRtlAllocateHeap(PhHeapHandle, 0, Size); | ||||
| out: | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Frees a block of memory allocated with PhAllocate(). | ||||
|  * | ||||
|  * \param Memory A pointer to a block of memory. | ||||
|  * | ||||
|  */ | ||||
| static VOID PhFree(PVOID Memory) | ||||
| { | ||||
| 	PF_INIT(RtlFreeHeap, Ntdll); | ||||
| 	if (pfRtlFreeHeap != NULL) | ||||
| 		pfRtlFreeHeap(PhHeapHandle, 0, Memory); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Enumerates all open handles. | ||||
|  * | ||||
|  * \param Handles A variable which receives a pointer to a structure containing information about | ||||
|  * all opened handles. You must free the structure using PhFree() when you no longer need it. | ||||
|  * | ||||
|  * \return An NTStatus indicating success or the error code. | ||||
|  */ | ||||
| NTSTATUS PhEnumHandlesEx(PSYSTEM_HANDLE_INFORMATION_EX *Handles) | ||||
| { | ||||
| 	static ULONG initialBufferSize = 0x10000; | ||||
| 	NTSTATUS status; | ||||
| 	PVOID buffer; | ||||
| 	ULONG bufferSize; | ||||
| 
 | ||||
| 	PF_INIT(NtQuerySystemInformation, Ntdll); | ||||
| 	if (pfNtQuerySystemInformation == NULL) | ||||
| 		return STATUS_NOT_IMPLEMENTED; | ||||
| 
 | ||||
| 	bufferSize = initialBufferSize; | ||||
| 	buffer = PhAllocate(bufferSize); | ||||
| 	if (buffer == NULL) | ||||
| 		return STATUS_NO_MEMORY; | ||||
| 
 | ||||
| 	while ((status = pfNtQuerySystemInformation(SystemExtendedHandleInformation, | ||||
| 		buffer, bufferSize, NULL)) == 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 (buffer == NULL) | ||||
| 			return STATUS_NO_MEMORY; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!NT_SUCCESS(status)) { | ||||
| 		PhFree(buffer); | ||||
| 		return status; | ||||
| 	} | ||||
| 
 | ||||
| 	if (bufferSize <= 0x200000) | ||||
| 		initialBufferSize = bufferSize; | ||||
| 	*Handles = (PSYSTEM_HANDLE_INFORMATION_EX)buffer; | ||||
| 
 | ||||
| 	return status; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Opens a process. | ||||
|  * | ||||
|  * \param ProcessHandle A variable which receives a handle to the process. | ||||
|  * \param DesiredAccess The desired access to the process. | ||||
|  * \param ProcessId The ID of the process. | ||||
|  * | ||||
|  * \return An NTStatus indicating success or the error code. | ||||
|  */ | ||||
| NTSTATUS PhOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, HANDLE ProcessId) | ||||
| { | ||||
| 	NTSTATUS status = STATUS_NOT_IMPLEMENTED; | ||||
| 	OBJECT_ATTRIBUTES objectAttributes; | ||||
| 	CLIENT_ID clientId; | ||||
| 
 | ||||
| 	if ((LONG_PTR)ProcessId == (LONG_PTR)GetCurrentProcessId()) { | ||||
| 		*ProcessHandle = NtCurrentProcess(); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	PF_INIT_OR_OUT(NtOpenProcess, Ntdll); | ||||
| 
 | ||||
| 	clientId.UniqueProcess = ProcessId; | ||||
| 	clientId.UniqueThread = NULL; | ||||
| 
 | ||||
| 	InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL); | ||||
| 	status = pfNtOpenProcess(ProcessHandle, DesiredAccess, &objectAttributes, &clientId); | ||||
| 
 | ||||
| out: | ||||
| 	return status; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Search all the processes and list the ones that have a specific handle open. | ||||
|  * | ||||
|  * \param HandleName The name of the handle to look for. | ||||
|  * \param bPartialMatch Whether partial matches should be allowed. | ||||
|  * \param bIgnoreSelf Whether the current process should be listed. | ||||
|  * | ||||
|  * \return TRUE if matching processes were found, FALSE otherwise. | ||||
|  */ | ||||
| BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf) | ||||
| { | ||||
| 	NTSTATUS status; | ||||
| 	PSYSTEM_HANDLE_INFORMATION_EX handles; | ||||
| 	POBJECT_NAME_INFORMATION buffer; | ||||
| 	ULONG_PTR i; | ||||
| 	ULONG bufferSize; | ||||
| 	USHORT wHandleNameLen; | ||||
| 	WCHAR *wHandleName; | ||||
| 	HANDLE dupHandle = NULL; | ||||
| 	HANDLE processHandle = NULL; | ||||
| 	BOOLEAN bFound = FALSE; | ||||
| 	char exe_path[2][MAX_PATH]; | ||||
| 	int cur; | ||||
| 
 | ||||
| 	status = STATUS_NOT_IMPLEMENTED; | ||||
| 	PF_INIT(NtQueryObject, Ntdll); | ||||
| 	PF_INIT(NtDuplicateObject, NtDll); | ||||
| 	PF_INIT(NtClose, NtDll); | ||||
| 	if ((pfNtQueryObject != NULL) && (pfNtClose != NULL) && (pfNtDuplicateObject != NULL)) | ||||
| 		status = 0; | ||||
| 
 | ||||
| 	if (NT_SUCCESS(status)) | ||||
| 		status = PhEnumHandlesEx(&handles); | ||||
| 	if (!NT_SUCCESS(status)) { | ||||
| 		uprintf("Could not enumerate handles: %s", NtStatusError(status)); | ||||
| 		return FALSE; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	exe_path[0][0] = 0; | ||||
| 	cur = 1; | ||||
| 
 | ||||
| 	wHandleName = utf8_to_wchar(HandleName); | ||||
| 	wHandleNameLen = (USHORT) wcslen(wHandleName); | ||||
| 
 | ||||
| 	bufferSize = 0x200; | ||||
| 	buffer = PhAllocate(bufferSize); | ||||
| 
 | ||||
| 	for (i = 0; ; i++) { | ||||
| 		ULONG attempts = 8; | ||||
| 		PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo = &handles->Handles[i]; | ||||
| 
 | ||||
| 		if ((dupHandle != NULL) && (processHandle != NtCurrentProcess())) { | ||||
| 			pfNtClose(dupHandle); | ||||
| 			dupHandle = NULL; | ||||
| 		} | ||||
| 		if (processHandle != NULL) { | ||||
| 			if (processHandle != NtCurrentProcess()) | ||||
| 				pfNtClose(processHandle); | ||||
| 			processHandle = NULL; | ||||
| 		} | ||||
| 
 | ||||
| 		CHECK_FOR_USER_CANCEL; | ||||
| 
 | ||||
| 		// Exit loop condition
 | ||||
| 		if (i >= handles->NumberOfHandles) | ||||
| 			break; | ||||
| 
 | ||||
| 		// Get the process that created the handle we are after
 | ||||
| 		// TODO: We probably should keep a list of the most recent processes and perform a lookup
 | ||||
| 		// instead of Opening the process every time
 | ||||
| 		status = PhOpenProcess(&processHandle, PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, | ||||
| 			(HANDLE)handleInfo->UniqueProcessId); | ||||
| 		// There exists some processes we can't access
 | ||||
| 		if (!NT_SUCCESS(status)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		// Must duplicate the handle onto our own process, before we can access its properties
 | ||||
| 		if (processHandle == NtCurrentProcess()) { | ||||
| 			if (bIgnoreSelf) | ||||
| 				continue; | ||||
| 			dupHandle = (HANDLE)handleInfo->HandleValue; | ||||
| 		} else { | ||||
| 			status = pfNtDuplicateObject(processHandle, (HANDLE)handleInfo->HandleValue, | ||||
| 				NtCurrentProcess(), &dupHandle, 0, 0, 0); | ||||
| 			// Why does it always work for Process Hacker and not me???
 | ||||
| 			if (!NT_SUCCESS(status)) | ||||
| 				continue; | ||||
| 		} | ||||
| 
 | ||||
| 		// Filter non-storage handles. We're not interested in them and they make NtQueryObject() freeze
 | ||||
| 		if (GetFileType(dupHandle) != FILE_TYPE_DISK) | ||||
| 			continue; | ||||
| 
 | ||||
| 		// A loop is needed because the I/O subsystem likes to give us the wrong return lengths...
 | ||||
| 		do { | ||||
| 			status = pfNtQueryObject(dupHandle, ObjectBasicInformation + 1, | ||||
| 				buffer, bufferSize, &bufferSize); | ||||
| 			if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH || | ||||
| 				status == STATUS_BUFFER_TOO_SMALL) { | ||||
| 				PhFree(buffer); | ||||
| 				buffer = PhAllocate(bufferSize); | ||||
| 			} else { | ||||
| 				break; | ||||
| 			} | ||||
| 		} while (--attempts); | ||||
| 		if (!NT_SUCCESS(status)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		// Don't bother comparing if we are looking for full match and the length is different
 | ||||
| 		if ((!bPartialMatch) && (wHandleNameLen != buffer->Name.Length)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		// Likewise, if we are looking for a partial match and the current length is smaller
 | ||||
| 		if ((bPartialMatch) && (wHandleNameLen > buffer->Name.Length)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		// Match against our target string
 | ||||
| 		if (wcsncmp(wHandleName, buffer->Name.Buffer, wHandleNameLen) != 0) | ||||
| 			continue; | ||||
| 
 | ||||
| 		if (!bFound) { | ||||
| 			uprintf("\r\nNOTE: The following process(es) are accessing %s:", HandleName); | ||||
| 			bFound = TRUE; | ||||
| 		} | ||||
| 
 | ||||
| 		// TODO: only list processes with conflicting access rights (ignore "Read attributes" or "Synchronize")
 | ||||
| 		if (GetModuleFileNameExU(processHandle, 0, exe_path[cur], MAX_PATH - 1)) { | ||||
| 			// Avoid printing the same path repeatedly
 | ||||
| 			if (strcmp(exe_path[0], exe_path[1]) != 0) { | ||||
| 				uprintf("o %s", exe_path[cur]); | ||||
| 				cur = (cur + 1) % 2; | ||||
| 			} | ||||
| 		} else { | ||||
| 			uprintf("o Unknown (Process ID %d)", GetProcessId(processHandle)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	if (bFound) | ||||
| 		uprintf("You should try to close these applications before attempting to reformat the drive."); | ||||
| 	else | ||||
| 		uprintf("NOTE: " APPLICATION_NAME " was not able to identify the process(es) preventing access to %s", HandleName); | ||||
| 
 | ||||
| 	free(wHandleName); | ||||
| 	PhFree(buffer); | ||||
| 	return bFound; | ||||
| } | ||||
							
								
								
									
										186
									
								
								src/search.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								src/search.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,186 @@ | |||
| /*
 | ||||
|  * Rufus: The Reliable USB Formatting Utility | ||||
|  * Search functionality for handles | ||||
|  * | ||||
|  * Modified from Process Hacker: | ||||
|  *   https://github.com/processhacker2/processhacker2/
 | ||||
|  * Copyright © 2009-2016 wj32 | ||||
|  * Copyright © 2017 dmex | ||||
|  * Copyright © 2017 Pete Batard <pete@akeo.ie> | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include <windows.h> | ||||
| #include <winnt.h> | ||||
| #include <winternl.h> | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #define PH_LARGE_BUFFER_SIZE			(256 * 1024 * 1024) | ||||
| 
 | ||||
| #define STATUS_UNSUCCESSFUL				((NTSTATUS)0x80000001L) | ||||
| #define STATUS_BUFFER_OVERFLOW			((NTSTATUS)0x80000005L) | ||||
| #define STATUS_NOT_IMPLEMENTED			((NTSTATUS)0xC0000002L) | ||||
| #define STATUS_INFO_LENGTH_MISMATCH		((NTSTATUS)0xC0000004L) | ||||
| //#define STATUS_INVALID_HANDLE			((NTSTATUS)0xC0000008L)
 | ||||
| #define STATUS_ACCESS_DENIED			((NTSTATUS)0xC0000022L) | ||||
| #define STATUS_BUFFER_TOO_SMALL			((NTSTATUS)0xC0000023L) | ||||
| #define STATUS_OBJECT_TYPE_MISMATCH		((NTSTATUS)0xC0000024L) | ||||
| #define STATUS_OBJECT_NAME_INVALID		((NTSTATUS)0xC0000033L) | ||||
| #define STATUS_OBJECT_NAME_NOT_FOUND	((NTSTATUS)0xC0000034L) | ||||
| #define STATUS_SHARING_VIOLATION		((NTSTATUS)0xC0000043L) | ||||
| #define STATUS_INSUFFICIENT_RESOURCES	((NTSTATUS)0xC000009AL) | ||||
| #define STATUS_NOT_SUPPORTED			((NTSTATUS)0xC00000BBL) | ||||
| 
 | ||||
| #define SystemExtendedHandleInformation	64 | ||||
| 
 | ||||
| #define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1) | ||||
| 
 | ||||
| typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX | ||||
| { | ||||
| 	PVOID Object; | ||||
| 	ULONG_PTR UniqueProcessId; | ||||
| 	ULONG_PTR HandleValue; | ||||
| 	ULONG GrantedAccess; | ||||
| 	USHORT CreatorBackTraceIndex; | ||||
| 	USHORT ObjectTypeIndex; | ||||
| 	ULONG HandleAttributes; | ||||
| 	ULONG Reserved; | ||||
| } SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; | ||||
| 
 | ||||
| typedef struct _SYSTEM_HANDLE_INFORMATION_EX | ||||
| { | ||||
| 	ULONG_PTR NumberOfHandles; | ||||
| 	ULONG_PTR Reserved; | ||||
| 	SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; | ||||
| } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; | ||||
| 
 | ||||
| #if defined(_MSC_VER) | ||||
| typedef struct _OBJECT_NAME_INFORMATION | ||||
| { | ||||
| 	UNICODE_STRING Name; | ||||
| } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; | ||||
| 
 | ||||
| typedef struct _CLIENT_ID | ||||
| { | ||||
| 	HANDLE UniqueProcess; | ||||
| 	HANDLE UniqueThread; | ||||
| } CLIENT_ID, *PCLIENT_ID; | ||||
| #endif | ||||
| 
 | ||||
| // Heaps
 | ||||
| 
 | ||||
| typedef struct _RTL_HEAP_ENTRY | ||||
| { | ||||
| 	SIZE_T Size; | ||||
| 	USHORT Flags; | ||||
| 	USHORT AllocatorBackTraceIndex; | ||||
| 	union | ||||
| 	{ | ||||
| 		struct | ||||
| 		{ | ||||
| 			SIZE_T Settable; | ||||
| 			ULONG Tag; | ||||
| 		} s1; | ||||
| 		struct | ||||
| 		{ | ||||
| 			SIZE_T CommittedSize; | ||||
| 			PVOID FirstBlock; | ||||
| 		} s2; | ||||
| 	} u; | ||||
| } RTL_HEAP_ENTRY, *PRTL_HEAP_ENTRY; | ||||
| 
 | ||||
| #define RTL_HEAP_BUSY (USHORT)0x0001 | ||||
| #define RTL_HEAP_SEGMENT (USHORT)0x0002 | ||||
| #define RTL_HEAP_SETTABLE_VALUE (USHORT)0x0010 | ||||
| #define RTL_HEAP_SETTABLE_FLAG1 (USHORT)0x0020 | ||||
| #define RTL_HEAP_SETTABLE_FLAG2 (USHORT)0x0040 | ||||
| #define RTL_HEAP_SETTABLE_FLAG3 (USHORT)0x0080 | ||||
| #define RTL_HEAP_SETTABLE_FLAGS (USHORT)0x00e0 | ||||
| #define RTL_HEAP_UNCOMMITTED_RANGE (USHORT)0x0100 | ||||
| #define RTL_HEAP_PROTECTED_ENTRY (USHORT)0x0200 | ||||
| 
 | ||||
| typedef struct _RTL_HEAP_TAG | ||||
| { | ||||
| 	ULONG NumberOfAllocations; | ||||
| 	ULONG NumberOfFrees; | ||||
| 	SIZE_T BytesAllocated; | ||||
| 	USHORT TagIndex; | ||||
| 	USHORT CreatorBackTraceIndex; | ||||
| 	WCHAR TagName[24]; | ||||
| } RTL_HEAP_TAG, *PRTL_HEAP_TAG; | ||||
| 
 | ||||
| typedef struct _RTL_HEAP_INFORMATION | ||||
| { | ||||
| 	PVOID BaseAddress; | ||||
| 	ULONG Flags; | ||||
| 	USHORT EntryOverhead; | ||||
| 	USHORT CreatorBackTraceIndex; | ||||
| 	SIZE_T BytesAllocated; | ||||
| 	SIZE_T BytesCommitted; | ||||
| 	ULONG NumberOfTags; | ||||
| 	ULONG NumberOfEntries; | ||||
| 	ULONG NumberOfPseudoTags; | ||||
| 	ULONG PseudoTagGranularity; | ||||
| 	ULONG Reserved[5]; | ||||
| 	PRTL_HEAP_TAG Tags; | ||||
| 	PRTL_HEAP_ENTRY Entries; | ||||
| } RTL_HEAP_INFORMATION, *PRTL_HEAP_INFORMATION; | ||||
| 
 | ||||
| typedef struct _RTL_PROCESS_HEAPS | ||||
| { | ||||
| 	ULONG NumberOfHeaps; | ||||
| 	RTL_HEAP_INFORMATION Heaps[1]; | ||||
| } RTL_PROCESS_HEAPS, *PRTL_PROCESS_HEAPS; | ||||
| 
 | ||||
| typedef NTSTATUS(NTAPI *PRTL_HEAP_COMMIT_ROUTINE)( | ||||
| 	_In_ PVOID Base, | ||||
| 	_Inout_ PVOID *CommitAddress, | ||||
| 	_Inout_ PSIZE_T CommitSize | ||||
| 	); | ||||
| 
 | ||||
| #if defined(_MSC_VER) | ||||
| typedef struct _RTL_HEAP_PARAMETERS | ||||
| { | ||||
| 	ULONG Length; | ||||
| 	SIZE_T SegmentReserve; | ||||
| 	SIZE_T SegmentCommit; | ||||
| 	SIZE_T DeCommitFreeBlockThreshold; | ||||
| 	SIZE_T DeCommitTotalFreeThreshold; | ||||
| 	SIZE_T MaximumAllocationSize; | ||||
| 	SIZE_T VirtualMemoryThreshold; | ||||
| 	SIZE_T InitialCommit; | ||||
| 	SIZE_T InitialReserve; | ||||
| 	PRTL_HEAP_COMMIT_ROUTINE CommitRoutine; | ||||
| 	SIZE_T Reserved[2]; | ||||
| } RTL_HEAP_PARAMETERS, *PRTL_HEAP_PARAMETERS; | ||||
| #endif | ||||
| 
 | ||||
| #define HEAP_SETTABLE_USER_VALUE 0x00000100 | ||||
| #define HEAP_SETTABLE_USER_FLAG1 0x00000200 | ||||
| #define HEAP_SETTABLE_USER_FLAG2 0x00000400 | ||||
| #define HEAP_SETTABLE_USER_FLAG3 0x00000800 | ||||
| #define HEAP_SETTABLE_USER_FLAGS 0x00000e00 | ||||
| 
 | ||||
| #define HEAP_CLASS_0 0x00000000 // Process heap
 | ||||
| #define HEAP_CLASS_1 0x00001000 // Private heap
 | ||||
| #define HEAP_CLASS_2 0x00002000 // Kernel heap
 | ||||
| #define HEAP_CLASS_3 0x00003000 // GDI heap
 | ||||
| #define HEAP_CLASS_4 0x00004000 // User heap
 | ||||
| #define HEAP_CLASS_5 0x00005000 // Console heap
 | ||||
| #define HEAP_CLASS_6 0x00006000 // User desktop heap
 | ||||
| #define HEAP_CLASS_7 0x00007000 // CSR shared heap
 | ||||
| #define HEAP_CLASS_8 0x00008000 // CSR port heap
 | ||||
| #define HEAP_CLASS_MASK 0x0000f000 | ||||
							
								
								
									
										16
									
								
								src/stdfn.c
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								src/stdfn.c
									
										
									
									
									
								
							|  | @ -717,19 +717,19 @@ DWORD WINAPI SetLGPThread(LPVOID param) | |||
| 	// We need an IGroupPolicyObject instance to set a Local Group Policy
 | ||||
| 	hr = CoCreateInstance(&my_CLSID_GroupPolicyObject, NULL, CLSCTX_INPROC_SERVER, &my_IID_IGroupPolicyObject, (LPVOID*)&pLGPO); | ||||
| 	if (FAILED(hr)) { | ||||
| 		ubprintf("SetLGP: CoCreateInstance failed; hr = %x", hr); | ||||
| 		ubprintf("SetLGP: CoCreateInstance failed; hr = %lx", hr); | ||||
| 		goto error; | ||||
| 	} | ||||
| 
 | ||||
| 	hr = pLGPO->lpVtbl->OpenLocalMachineGPO(pLGPO, GPO_OPEN_LOAD_REGISTRY); | ||||
| 	if (FAILED(hr)) { | ||||
| 		ubprintf("SetLGP: OpenLocalMachineGPO failed - error %x", hr); | ||||
| 		ubprintf("SetLGP: OpenLocalMachineGPO failed - error %lx", hr); | ||||
| 		goto error; | ||||
| 	} | ||||
| 
 | ||||
| 	hr = pLGPO->lpVtbl->GetRegistryKey(pLGPO, GPO_SECTION_MACHINE, &path_key); | ||||
| 	if (FAILED(hr)) { | ||||
| 		ubprintf("SetLGP: GetRegistryKey failed - error %x", hr); | ||||
| 		ubprintf("SetLGP: GetRegistryKey failed - error %lx", hr); | ||||
| 		goto error; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -737,7 +737,7 @@ DWORD WINAPI SetLGPThread(LPVOID param) | |||
| 	r = RegCreateKeyExA(path_key, p->szPath, 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, | ||||
| 		NULL, &policy_key, &disp); | ||||
| 	if (r != ERROR_SUCCESS) { | ||||
| 		ubprintf("SetLGP: Failed to open LGPO path %s - error %x", p->szPath, hr); | ||||
| 		ubprintf("SetLGP: Failed to open LGPO path %s - error %lx", p->szPath, hr); | ||||
| 		policy_key = NULL; | ||||
| 		goto error; | ||||
| 	} | ||||
|  | @ -751,7 +751,7 @@ DWORD WINAPI SetLGPThread(LPVOID param) | |||
| 			// The Key exists but not its value, which is OK
 | ||||
| 			*(p->bExistingKey) = FALSE; | ||||
| 		} else if (r != ERROR_SUCCESS) { | ||||
| 			ubprintf("SetLGP: Failed to read original %s policy value - error %x", p->szPolicy, r); | ||||
| 			ubprintf("SetLGP: Failed to read original %s policy value - error %lx", p->szPolicy, r); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -762,7 +762,7 @@ DWORD WINAPI SetLGPThread(LPVOID param) | |||
| 		r = RegDeleteValueA(policy_key, p->szPolicy); | ||||
| 	} | ||||
| 	if (r != ERROR_SUCCESS) { | ||||
| 		ubprintf("SetLGP: RegSetValueEx / RegDeleteValue failed - error %x", r); | ||||
| 		ubprintf("SetLGP: RegSetValueEx / RegDeleteValue failed - error %lx", r); | ||||
| 	} | ||||
| 	RegCloseKey(policy_key); | ||||
| 	policy_key = NULL; | ||||
|  | @ -770,11 +770,11 @@ DWORD WINAPI SetLGPThread(LPVOID param) | |||
| 	// Apply policy
 | ||||
| 	hr = pLGPO->lpVtbl->Save(pLGPO, TRUE, (p->bRestore)?FALSE:TRUE, &ext_guid, &snap_guid); | ||||
| 	if (hr != S_OK) { | ||||
| 		ubprintf("SetLGP: Unable to apply %s policy - error %x", p->szPolicy, hr); | ||||
| 		ubprintf("SetLGP: Unable to apply %s policy - error %lx", p->szPolicy, hr); | ||||
| 		goto error; | ||||
| 	} else { | ||||
| 		if ((!p->bRestore) || (*(p->bExistingKey))) { | ||||
| 			ubprintf("SetLGP: Successfully %s %s policy to 0x%08X", (p->bRestore)?"restored":"set", p->szPolicy, val); | ||||
| 			ubprintf("SetLGP: Successfully %s %s policy to 0x%08lX", (p->bRestore)?"restored":"set", p->szPolicy, val); | ||||
| 		} else { | ||||
| 			ubprintf("SetLGP: Successfully removed %s policy key", p->szPolicy); | ||||
| 		} | ||||
|  |  | |||
|  | @ -1855,7 +1855,7 @@ void ClrFormatPromptHook(void) { | |||
| } | ||||
| 
 | ||||
| #ifdef RUFUS_TEST | ||||
| static inline LPWORD lpwAlign(LPWORD addr) | ||||
| static __inline LPWORD lpwAlign(LPWORD addr) | ||||
| { | ||||
| 	return (LPWORD)((((uintptr_t)addr) + 3) & (~3)); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue