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…
Reference in a new issue