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="..\pki.c" /> | ||||||
|     <ClCompile Include="..\rufus.c" /> |     <ClCompile Include="..\rufus.c" /> | ||||||
|     <ClCompile Include="..\checksum.c" /> |     <ClCompile Include="..\checksum.c" /> | ||||||
|  |     <ClCompile Include="..\search.c" /> | ||||||
|     <ClCompile Include="..\smart.c" /> |     <ClCompile Include="..\smart.c" /> | ||||||
|     <ClCompile Include="..\stdfn.c" /> |     <ClCompile Include="..\stdfn.c" /> | ||||||
|     <ClCompile Include="..\stdio.c" /> |     <ClCompile Include="..\stdio.c" /> | ||||||
|  | @ -225,6 +226,7 @@ | ||||||
|     <ClInclude Include="..\format.h" /> |     <ClInclude Include="..\format.h" /> | ||||||
|     <ClInclude Include="..\hdd_vs_ufd.h" /> |     <ClInclude Include="..\hdd_vs_ufd.h" /> | ||||||
|     <ClInclude Include="..\missing.h" /> |     <ClInclude Include="..\missing.h" /> | ||||||
|  |     <ClInclude Include="..\search.h" /> | ||||||
|     <ClInclude Include="..\settings.h" /> |     <ClInclude Include="..\settings.h" /> | ||||||
|     <ClInclude Include="..\libcdio\cdio\cdio.h" /> |     <ClInclude Include="..\libcdio\cdio\cdio.h" /> | ||||||
|     <ClInclude Include="..\libcdio\cdio\iso9660.h" /> |     <ClInclude Include="..\libcdio\cdio\iso9660.h" /> | ||||||
|  |  | ||||||
|  | @ -75,6 +75,9 @@ | ||||||
|     <ClCompile Include="..\dev.c"> |     <ClCompile Include="..\dev.c"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\search.c"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="..\rufus.h"> |     <ClInclude Include="..\rufus.h"> | ||||||
|  | @ -143,6 +146,9 @@ | ||||||
|     <ClInclude Include="..\db.h"> |     <ClInclude Include="..\db.h"> | ||||||
|       <Filter>Header Files</Filter> |       <Filter>Header Files</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\search.h"> | ||||||
|  |       <Filter>Header Files</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="..\..\res\rufus.ico"> |     <None Include="..\..\res\rufus.ico"> | ||||||
|  |  | ||||||
|  | @ -193,6 +193,7 @@ | ||||||
|     <ClCompile Include="..\pki.c" /> |     <ClCompile Include="..\pki.c" /> | ||||||
|     <ClCompile Include="..\rufus.c" /> |     <ClCompile Include="..\rufus.c" /> | ||||||
|     <ClCompile Include="..\checksum.c" /> |     <ClCompile Include="..\checksum.c" /> | ||||||
|  |     <ClCompile Include="..\search.c" /> | ||||||
|     <ClCompile Include="..\smart.c" /> |     <ClCompile Include="..\smart.c" /> | ||||||
|     <ClCompile Include="..\stdfn.c" /> |     <ClCompile Include="..\stdfn.c" /> | ||||||
|     <ClCompile Include="..\stdio.c" /> |     <ClCompile Include="..\stdio.c" /> | ||||||
|  | @ -208,6 +209,7 @@ | ||||||
|     <ClInclude Include="..\format.h" /> |     <ClInclude Include="..\format.h" /> | ||||||
|     <ClInclude Include="..\hdd_vs_ufd.h" /> |     <ClInclude Include="..\hdd_vs_ufd.h" /> | ||||||
|     <ClInclude Include="..\missing.h" /> |     <ClInclude Include="..\missing.h" /> | ||||||
|  |     <ClInclude Include="..\search.h" /> | ||||||
|     <ClInclude Include="..\settings.h" /> |     <ClInclude Include="..\settings.h" /> | ||||||
|     <ClInclude Include="..\libcdio\cdio\cdio.h" /> |     <ClInclude Include="..\libcdio\cdio\cdio.h" /> | ||||||
|     <ClInclude Include="..\libcdio\cdio\iso9660.h" /> |     <ClInclude Include="..\libcdio\cdio\iso9660.h" /> | ||||||
|  |  | ||||||
|  | @ -75,6 +75,9 @@ | ||||||
|     <ClCompile Include="..\dev.c"> |     <ClCompile Include="..\dev.c"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\search.c"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="..\rufus.h"> |     <ClInclude Include="..\rufus.h"> | ||||||
|  | @ -143,6 +146,9 @@ | ||||||
|     <ClInclude Include="..\db.h"> |     <ClInclude Include="..\db.h"> | ||||||
|       <Filter>Header Files</Filter> |       <Filter>Header Files</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\search.h"> | ||||||
|  |       <Filter>Header Files</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="..\..\res\rufus.ico"> |     <None Include="..\..\res\rufus.ico"> | ||||||
|  |  | ||||||
|  | @ -11,8 +11,8 @@ AM_V_WINDRES   = $(AM_V_WINDRES_$(V)) | ||||||
| 	$(AM_V_WINDRES) $(AM_RCFLAGS) -i $< -o $@ | 	$(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 \ | 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_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS) | ||||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | 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 \ | 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-format.$(OBJEXT) rufus-icon.$(OBJEXT) \
 | ||||||
| 	rufus-iso.$(OBJEXT) rufus-localization.$(OBJEXT) \
 | 	rufus-iso.$(OBJEXT) rufus-localization.$(OBJEXT) \
 | ||||||
| 	rufus-net.$(OBJEXT) rufus-parser.$(OBJEXT) rufus-pki.$(OBJEXT) \
 | 	rufus-net.$(OBJEXT) rufus-parser.$(OBJEXT) rufus-pki.$(OBJEXT) \
 | ||||||
| 	rufus-rufus.$(OBJEXT) rufus-smart.$(OBJEXT) \
 | 	rufus-rufus.$(OBJEXT) rufus-search.$(OBJEXT) \
 | ||||||
| 	rufus-stdfn.$(OBJEXT) rufus-stdio.$(OBJEXT) \
 | 	rufus-smart.$(OBJEXT) rufus-stdfn.$(OBJEXT) \
 | ||||||
| 	rufus-stdlg.$(OBJEXT) rufus-syslinux.$(OBJEXT) \
 | 	rufus-stdio.$(OBJEXT) rufus-stdlg.$(OBJEXT) \
 | ||||||
| 	rufus-vhd.$(OBJEXT) | 	rufus-syslinux.$(OBJEXT) rufus-vhd.$(OBJEXT) | ||||||
| rufus_OBJECTS = $(am_rufus_OBJECTS) | rufus_OBJECTS = $(am_rufus_OBJECTS) | ||||||
| rufus_DEPENDENCIES = rufus_rc.o bled/libbled.a ms-sys/libmssys.a \
 | rufus_DEPENDENCIES = rufus_rc.o bled/libbled.a ms-sys/libmssys.a \
 | ||||||
| 	syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.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_$(AM_DEFAULT_VERBOSITY)) | ||||||
| AM_V_WINDRES = $(AM_V_WINDRES_$(V)) | 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 \
 | 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_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS) | ||||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | 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 \
 | 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 | all: all-recursive | ||||||
| 
 | 
 | ||||||
|  | @ -416,6 +416,12 @@ rufus-rufus.o: rufus.c | ||||||
| rufus-rufus.obj: 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` | 	$(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 | 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 | 	$(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] != '\\')) | 	if ((safe_strlen(Path) < 5) || (Path[0] != '\\') || (Path[1] != '\\') || (Path[3] != '\\')) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	// Resolve a device path, so that users can seek for it in Process Explorer
 | 	// Resolve a device path, so that we can look for that handle in case of access issues.
 | ||||||
| 	// in case of access issues.
 |  | ||||||
| 	if (QueryDosDeviceA(&Path[4], DevPath, sizeof(DevPath)) == 0) | 	if (QueryDosDeviceA(&Path[4], DevPath, sizeof(DevPath)) == 0) | ||||||
| 		strcpy(DevPath, "???"); | 		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,
 | 			// If we can't seem to get a hold of the drive for some time,
 | ||||||
| 			// try to enable FILE_SHARE_WRITE...
 | 			// try to enable FILE_SHARE_WRITE...
 | ||||||
| 			uprintf("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled..."); | 			uprintf("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled..."); | ||||||
|  | 			SearchProcess(DevPath, TRUE, TRUE); | ||||||
| 			bWriteShare = TRUE; | 			bWriteShare = TRUE; | ||||||
| 		} | 		} | ||||||
| 		Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES); | 		Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES); | ||||||
|  | @ -161,7 +161,7 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (bWriteAccess) { | 	if (bWriteAccess) { | ||||||
| 		uprintf("Opened %s [%s] for write access\n", Path, DevPath); | 		uprintf("Opened %s [%s] for write access", Path, DevPath); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (bLockDrive) { | 	if (bLockDrive) { | ||||||
|  | @ -177,7 +177,10 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr | ||||||
| 			Sleep(DRIVE_ACCESS_TIMEOUT/DRIVE_ACCESS_RETRIES); | 			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
 | 		// 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); | 		safe_closehandle(hDrive); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -84,6 +84,10 @@ const char* additional_copyrights = | ||||||
| "http://www.codeguru.com/forum/showthread.php?p=1951973\\line\n" | "http://www.codeguru.com/forum/showthread.php?p=1951973\\line\n" | ||||||
| "Public Domain\\line\n" | "Public Domain\\line\n" | ||||||
| "\\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" | "Decompression support from BusyBox/Bled:\\line\n" | ||||||
| "http://www.busybox.net/\\line\n" | "http://www.busybox.net/\\line\n" | ||||||
| "https://github.com/pbatard/bled\\line\n" | "https://github.com/pbatard/bled\\line\n" | ||||||
|  |  | ||||||
|  | @ -31,6 +31,9 @@ | ||||||
| #include <share.h> | #include <share.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <io.h> | #include <io.h> | ||||||
|  | #if !defined(DDKBUILD) | ||||||
|  | #include <psapi.h> | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #if defined(_MSC_VER) | #if defined(_MSC_VER) | ||||||
|  | @ -125,6 +128,31 @@ static __inline wchar_t* utf8_to_wchar(const char* str) | ||||||
| 	return wstr; | 	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, | static __inline DWORD FormatMessageU(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, | ||||||
| 									 DWORD dwLanguageId, char* lpBuffer, DWORD nSize, va_list *Arguments) | 									 DWORD dwLanguageId, char* lpBuffer, DWORD nSize, va_list *Arguments) | ||||||
| { | { | ||||||
|  | @ -554,6 +582,24 @@ static __inline DWORD GetModuleFileNameU(HMODULE hModule, char* lpFilename, DWOR | ||||||
| 	return ret; | 	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) | static __inline DWORD GetFullPathNameU(const char* lpFileName, DWORD nBufferLength, char* lpBuffer, char** lpFilePart) | ||||||
| { | { | ||||||
| 	DWORD ret = 0, err = ERROR_INVALID_DATA; | 	DWORD ret = 0, err = ERROR_INVALID_DATA; | ||||||
|  |  | ||||||
|  | @ -3469,3 +3469,11 @@ out: | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	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 char* GetCurrentMUI(void); | ||||||
| extern BOOL SetFormatPromptHook(void); | extern BOOL SetFormatPromptHook(void); | ||||||
| extern void ClrFormatPromptHook(void); | extern void ClrFormatPromptHook(void); | ||||||
|  | extern BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf); | ||||||
| 
 | 
 | ||||||
| DWORD WINAPI FormatThread(void* param); | DWORD WINAPI FormatThread(void* param); | ||||||
| DWORD WINAPI SaveImageThread(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 | 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.1094" | CAPTION "Rufus 2.15.1095" | ||||||
| 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,1094,0 |  FILEVERSION 2,15,1095,0 | ||||||
|  PRODUCTVERSION 2,15,1094,0 |  PRODUCTVERSION 2,15,1095,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.1094" |             VALUE "FileVersion", "2.15.1095" | ||||||
|             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.1094" |             VALUE "ProductVersion", "2.15.1095" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     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
 | 	// 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); | 	hr = CoCreateInstance(&my_CLSID_GroupPolicyObject, NULL, CLSCTX_INPROC_SERVER, &my_IID_IGroupPolicyObject, (LPVOID*)&pLGPO); | ||||||
| 	if (FAILED(hr)) { | 	if (FAILED(hr)) { | ||||||
| 		ubprintf("SetLGP: CoCreateInstance failed; hr = %x", hr); | 		ubprintf("SetLGP: CoCreateInstance failed; hr = %lx", hr); | ||||||
| 		goto error; | 		goto error; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	hr = pLGPO->lpVtbl->OpenLocalMachineGPO(pLGPO, GPO_OPEN_LOAD_REGISTRY); | 	hr = pLGPO->lpVtbl->OpenLocalMachineGPO(pLGPO, GPO_OPEN_LOAD_REGISTRY); | ||||||
| 	if (FAILED(hr)) { | 	if (FAILED(hr)) { | ||||||
| 		ubprintf("SetLGP: OpenLocalMachineGPO failed - error %x", hr); | 		ubprintf("SetLGP: OpenLocalMachineGPO failed - error %lx", hr); | ||||||
| 		goto error; | 		goto error; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	hr = pLGPO->lpVtbl->GetRegistryKey(pLGPO, GPO_SECTION_MACHINE, &path_key); | 	hr = pLGPO->lpVtbl->GetRegistryKey(pLGPO, GPO_SECTION_MACHINE, &path_key); | ||||||
| 	if (FAILED(hr)) { | 	if (FAILED(hr)) { | ||||||
| 		ubprintf("SetLGP: GetRegistryKey failed - error %x", hr); | 		ubprintf("SetLGP: GetRegistryKey failed - error %lx", hr); | ||||||
| 		goto error; | 		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, | 	r = RegCreateKeyExA(path_key, p->szPath, 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, | ||||||
| 		NULL, &policy_key, &disp); | 		NULL, &policy_key, &disp); | ||||||
| 	if (r != ERROR_SUCCESS) { | 	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; | 		policy_key = NULL; | ||||||
| 		goto error; | 		goto error; | ||||||
| 	} | 	} | ||||||
|  | @ -751,7 +751,7 @@ DWORD WINAPI SetLGPThread(LPVOID param) | ||||||
| 			// The Key exists but not its value, which is OK
 | 			// The Key exists but not its value, which is OK
 | ||||||
| 			*(p->bExistingKey) = FALSE; | 			*(p->bExistingKey) = FALSE; | ||||||
| 		} else if (r != ERROR_SUCCESS) { | 		} 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); | 		r = RegDeleteValueA(policy_key, p->szPolicy); | ||||||
| 	} | 	} | ||||||
| 	if (r != ERROR_SUCCESS) { | 	if (r != ERROR_SUCCESS) { | ||||||
| 		ubprintf("SetLGP: RegSetValueEx / RegDeleteValue failed - error %x", r); | 		ubprintf("SetLGP: RegSetValueEx / RegDeleteValue failed - error %lx", r); | ||||||
| 	} | 	} | ||||||
| 	RegCloseKey(policy_key); | 	RegCloseKey(policy_key); | ||||||
| 	policy_key = NULL; | 	policy_key = NULL; | ||||||
|  | @ -770,11 +770,11 @@ DWORD WINAPI SetLGPThread(LPVOID param) | ||||||
| 	// Apply policy
 | 	// Apply policy
 | ||||||
| 	hr = pLGPO->lpVtbl->Save(pLGPO, TRUE, (p->bRestore)?FALSE:TRUE, &ext_guid, &snap_guid); | 	hr = pLGPO->lpVtbl->Save(pLGPO, TRUE, (p->bRestore)?FALSE:TRUE, &ext_guid, &snap_guid); | ||||||
| 	if (hr != S_OK) { | 	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; | 		goto error; | ||||||
| 	} else { | 	} else { | ||||||
| 		if ((!p->bRestore) || (*(p->bExistingKey))) { | 		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 { | 		} else { | ||||||
| 			ubprintf("SetLGP: Successfully removed %s policy key", p->szPolicy); | 			ubprintf("SetLGP: Successfully removed %s policy key", p->szPolicy); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -1855,7 +1855,7 @@ void ClrFormatPromptHook(void) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #ifdef RUFUS_TEST | #ifdef RUFUS_TEST | ||||||
| static inline LPWORD lpwAlign(LPWORD addr) | static __inline LPWORD lpwAlign(LPWORD addr) | ||||||
| { | { | ||||||
| 	return (LPWORD)((((uintptr_t)addr) + 3) & (~3)); | 	return (LPWORD)((((uintptr_t)addr) + 3) & (~3)); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue