[core] attempt to continue if the only conflicting handles we found are for read-only

* Also clean-up the process code and update for rufus-next
This commit is contained in:
Pete Batard 2017-07-13 21:53:44 +01:00
parent a528bb3d83
commit bed889718e
8 changed files with 41 additions and 140 deletions

20
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for rufus 2.15.
# Generated by GNU Autoconf 2.69 for rufus 2.16.
#
# Report bugs to <https://github.com/pbatard/rufus/issues>.
#
@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='rufus'
PACKAGE_TARNAME='rufus'
PACKAGE_VERSION='2.15'
PACKAGE_STRING='rufus 2.15'
PACKAGE_VERSION='2.16'
PACKAGE_STRING='rufus 2.16'
PACKAGE_BUGREPORT='https://github.com/pbatard/rufus/issues'
PACKAGE_URL='https://rufus.akeo.ie'
@ -1228,7 +1228,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures rufus 2.15 to adapt to many kinds of systems.
\`configure' configures rufus 2.16 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1294,7 +1294,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of rufus 2.15:";;
short | recursive ) echo "Configuration of rufus 2.16:";;
esac
cat <<\_ACEOF
@ -1385,7 +1385,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
rufus configure 2.15
rufus configure 2.16
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1440,7 +1440,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by rufus $as_me 2.15, which was
It was created by rufus $as_me 2.16, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2303,7 +2303,7 @@ fi
# Define the identity of the package.
PACKAGE='rufus'
VERSION='2.15'
VERSION='2.16'
cat >>confdefs.h <<_ACEOF
@ -4483,7 +4483,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by rufus $as_me 2.15, which was
This file was extended by rufus $as_me 2.16, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -4537,7 +4537,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
rufus config.status 2.15
rufus config.status 2.16
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -1,4 +1,4 @@
AC_INIT([rufus], [2.15], [https://github.com/pbatard/rufus/issues], [rufus], [https://rufus.akeo.ie])
AC_INIT([rufus], [2.16], [https://github.com/pbatard/rufus/issues], [rufus], [https://rufus.akeo.ie])
AM_INIT_AUTOMAKE([-Wno-portability foreign no-dist no-dependencies])
AC_CONFIG_SRCDIR([src/rufus.c])
AC_CONFIG_MACRO_DIR([m4])

View File

@ -8,7 +8,7 @@
for an interesting struggle, when you also happen to have a comma in one of the fields... -->
<Identity
Name="Rufus"
Version="2.15.1117.0"
Version="2.16.1117.0"
ProcessorArchitecture="x86"
Publisher='CN=Akeo Consulting, O=Akeo Consulting, STREET="24, Grey Rock", L=Milford, S=Co Donegal, PostalCode=Co Donegal, C=IE' />
<Properties>

View File

@ -1,5 +1,5 @@
@echo off
set VERSION=2.15
set VERSION=2.16
rem Make sure you don't have anything you don't want included in the package, as anything residing in the
rem current directory will be included, including any previous .appx, which makes for nice recursion...

View File

@ -120,7 +120,7 @@ BOOL GetAutoMount(BOOL* enabled)
static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare)
{
int i;
BOOL bSearchProcess = FALSE;
BYTE access_mask = 0;
DWORD size, EndTime;
HANDLE hDrive = INVALID_HANDLE_VALUE;
char DevPath[MAX_PATH];
@ -152,8 +152,8 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr
uprintf("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
bWriteShare = TRUE;
// Try to report the process that is locking the drive
SearchProcess(DevPath, TRUE, TRUE);
bSearchProcess = TRUE;
// We also use bit 6 as a flag to indicate that SearchProcess was called.
access_mask = SearchProcess(DevPath, TRUE, TRUE, FALSE) | 0x40;
}
Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
}
@ -182,10 +182,12 @@ static HANDLE GetHandle(char* Path, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWr
} while (GetTickCount() < EndTime);
// If we reached this section, either we didn't manage to get a lock or the user cancelled
uprintf("Could not lock access to %s: %s", Path, WindowsErrorString());
// See if we can tell the user what processes are accessing the drive
if (!IS_ERROR(FormatStatus) && !bSearchProcess)
SearchProcess(DevPath, TRUE, TRUE);
safe_closehandle(hDrive);
// See if we can report the processes are accessing the drive
if (!IS_ERROR(FormatStatus) && (access_mask == 0))
access_mask = SearchProcess(DevPath, TRUE, TRUE, FALSE);
// Try to continue if the only access rights we saw were for read-only
if ((access_mask & 0x07) != 0x01)
safe_closehandle(hDrive);
}
out:

View File

@ -34,18 +34,10 @@
#include "missing.h"
#include "msapi_utf8.h"
// Process Hacker does some filtering using Object Types, but this doesn't help us.
// Keep this option, just in case.
// #define USE_OBJECT_TYPES
PF_TYPE_DECL(NTAPI, PVOID, RtlCreateHeap, (ULONG, PVOID, SIZE_T, SIZE_T, PVOID, PRTL_HEAP_PARAMETERS));
PF_TYPE_DECL(NTAPI, PVOID, RtlDestroyHeap, (PVOID));
PF_TYPE_DECL(NTAPI, PVOID, RtlAllocateHeap, (PVOID, ULONG, SIZE_T));
PF_TYPE_DECL(NTAPI, BOOLEAN, RtlFreeHeap, (PVOID, ULONG, PVOID));
#ifdef USE_OBJECT_TYPES
PF_TYPE_DECL(NTAPI, VOID, RtlInitUnicodeString, (PUNICODE_STRING, PCWSTR));
PF_TYPE_DECL(NTAPI, BOOLEAN, RtlEqualUnicodeString, (PCUNICODE_STRING, PCUNICODE_STRING, BOOLEAN));
#endif
PF_TYPE_DECL(NTAPI, NTSTATUS, NtQuerySystemInformation, (SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryInformationFile, (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS));
@ -264,82 +256,6 @@ NTSTATUS PhOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, HANDLE
return status;
}
#ifdef USE_OBJECT_TYPES
NTSTATUS PhEnumObjectTypes(POBJECT_TYPES_INFORMATION *ObjectTypes)
{
NTSTATUS status = STATUS_SUCCESS;
PVOID buffer;
ULONG bufferSize;
ULONG returnLength;
PF_INIT_OR_SET_STATUS(NtQueryObject, Ntdll);
if (!NT_SUCCESS(status))
return status;
bufferSize = 0x1000;
buffer = PhAllocate(bufferSize);
while ((status = pfNtQueryObject(NULL, ObjectTypesInformation, buffer, bufferSize, &returnLength)) == STATUS_INFO_LENGTH_MISMATCH) {
PhFree(buffer);
bufferSize *= 2;
// Fail if we're resizing the buffer to something very large.
if (bufferSize > PH_LARGE_BUFFER_SIZE)
return STATUS_INSUFFICIENT_RESOURCES;
buffer = PhAllocate(bufferSize);
}
if (!NT_SUCCESS(status)) {
PhFree(buffer);
return status;
}
*ObjectTypes = (POBJECT_TYPES_INFORMATION)buffer;
return status;
}
ULONG PhGetObjectTypeNumber(PUNICODE_STRING TypeName)
{
NTSTATUS status = STATUS_SUCCESS;
POBJECT_TYPES_INFORMATION objectTypes;
POBJECT_TYPE_INFORMATION objectType;
ULONG objectIndex = -1;
ULONG i;
PF_INIT_OR_SET_STATUS(RtlEqualUnicodeString, NtDll);
if (!NT_SUCCESS(status))
return -1;
status = PhEnumObjectTypes(&objectTypes);
if (NT_SUCCESS(status)) {
objectType = PH_FIRST_OBJECT_TYPE(objectTypes);
for (i = 0; i < objectTypes->NumberOfTypes; i++) {
if (pfRtlEqualUnicodeString(&objectType->TypeName, TypeName, TRUE)) {
if (nWindowsVersion >= WINDOWS_8_1) {
objectIndex = objectType->TypeIndex;
break;
} else if (nWindowsVersion >= WINDOWS_7) {
objectIndex = i + 2;
break;
} else {
objectIndex = i + 1;
break;
}
}
objectType = PH_NEXT_OBJECT_TYPE(objectType);
}
PhFree(objectTypes);
}
return objectIndex;
}
#endif
/**
* Query processes with open handles to a file, volume or disk.
*
@ -394,20 +310,18 @@ NTSTATUS PhQueryProcessesUsingVolumeOrFile(HANDLE VolumeOrFileHandle,
* \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.
* \param bQuiet Prints minimal output.
*
* \return TRUE if matching processes were found, FALSE otherwise.
* \return a byte containing the cummulated access rights (f----xwr) from all the handles found
* with bit 7 ('f') also set if at least one process was found.
*/
BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf)
BYTE SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf, BOOL bQuiet)
{
const char *access_rights_str[8] = { "n", "r", "w", "rw", "x", "rx", "wx", "rwx" };
char tmp[MAX_PATH];
NTSTATUS status = STATUS_SUCCESS;
PSYSTEM_HANDLE_INFORMATION_EX handles = NULL;
POBJECT_NAME_INFORMATION buffer = NULL;
#ifdef USE_OBJECT_TYPES
UNICODE_STRING fileTypeName;
ULONG fileObjectTypeIndex = -1;
#endif
ULONG_PTR i;
ULONG_PTR pid[2];
ULONG_PTR last_access_denied_pid = 0;
@ -416,17 +330,15 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf)
WCHAR *wHandleName = NULL;
HANDLE dupHandle = NULL;
HANDLE processHandle = NULL;
BOOLEAN bFound = FALSE;
BOOLEAN bFound = FALSE, verbose = !bQuiet;
ULONG access_rights = 0;
BYTE access_mask = 0;
char exe_path[MAX_PATH] = { 0 };
int cur_pid;
PF_INIT_OR_SET_STATUS(NtQueryObject, Ntdll);
PF_INIT_OR_SET_STATUS(NtDuplicateObject, NtDll);
PF_INIT_OR_SET_STATUS(NtClose, NtDll);
#ifdef USE_OBJECT_TYPES
PF_INIT_OR_SET_STATUS(RtlInitUnicodeString, NtDll);
#endif
StrArrayClear(&BlockingProcess);
@ -452,13 +364,6 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf)
if (buffer == NULL)
goto out;
#ifdef USE_OBJECT_TYPES
pfRtlInitUnicodeString(&fileTypeName, L"File");
fileObjectTypeIndex = PhGetObjectTypeNumber(&fileTypeName);
if (fileObjectTypeIndex < 0)
uprintf("Warning: Could not get Object Index for file types");
#endif
for (i = 0; ; i++) {
ULONG attempts = 8;
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo =
@ -469,13 +374,6 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf)
dupHandle = NULL;
}
#ifdef USE_OBJECT_TYPES
// Only look for File objects type
if ((fileObjectTypeIndex >= 0 ) && (handleInfo != NULL) &&
(handleInfo->ObjectTypeIndex != (USHORT)fileObjectTypeIndex))
continue;
#endif
// Update the current handle's process PID and compare against last
// Note: Be careful about not trying to overflow our list!
pid[cur_pid] = (handleInfo != NULL) ? handleInfo->UniqueProcessId : -1;
@ -485,7 +383,7 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf)
// If we're switching process and found a match, print it
if (bFound) {
uprintf("● '%s' (pid: %ld, access: %s)", exe_path, pid[cur_pid], access_rights_str[access_rights & 0x7]);
vuprintf("● '%s' (pid: %ld, access: %s)", exe_path, pid[cur_pid], access_rights_str[access_rights & 0x7]);
static_sprintf(tmp, "● %s (pid %ld)", exe_path, pid[cur_pid]);
StrArrayAdd(&BlockingProcess, tmp, TRUE);
bFound = FALSE;
@ -586,11 +484,12 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf)
access_rights |= handleInfo->GrantedAccess;
// The Executable bit is in a place we don't like => reposition it
if (access_rights & 0x20)
access_rights = (access_rights & 0x3) | 0x4;
access_rights = (access_rights & 0x03) | 0x04;
access_mask |= (BYTE) (access_rights & 0x7) + 0x80; // Bit 7 is always set if a process was found
// If this is the very first process we find, print a header
if (exe_path[0] == 0)
uprintf("WARNING: The following process(es) or service(s) are accessing %s:", HandleName);
vuprintf("WARNING: The following process(es) or service(s) are accessing %s:", HandleName);
if (!GetModuleFileNameExU(processHandle, 0, exe_path, MAX_PATH - 1))
safe_sprintf(exe_path, MAX_PATH, "Unknown_Process_%" PRIu64,
@ -599,15 +498,15 @@ BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf)
out:
if (exe_path[0] != 0)
uprintf("You should try to close these applications before attempting to reformat the drive.");
vuprintf("You should close these applications before attempting to reformat the drive.");
else
uprintf("NOTE: Could not identify the process(es) or service(s) accessing %s", HandleName);
vuprintf("NOTE: Could not identify the process(es) or service(s) accessing %s", HandleName);
free(wHandleName);
PhFree(buffer);
PhFree(handles);
PhDestroyHeap();
return bFound;
return access_mask;
}
/**

View File

@ -495,7 +495,7 @@ extern BOOL IsCurrentProcessElevated(void);
extern char* GetCurrentMUI(void);
extern BOOL SetFormatPromptHook(void);
extern void ClrFormatPromptHook(void);
extern BOOL SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf);
extern BYTE SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf, BOOL bQuiet);
extern BOOL EnablePrivileges(void);
extern void FlashTaskbar(HANDLE handle);

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 2.15.1125"
CAPTION "Rufus 2.16.1126"
FONT 8, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
@ -366,8 +366,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,15,1125,0
PRODUCTVERSION 2,15,1125,0
FILEVERSION 2,16,1126,0
PRODUCTVERSION 2,16,1126,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -384,13 +384,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "2.15.1125"
VALUE "FileVersion", "2.16.1126"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2017 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "2.15.1125"
VALUE "ProductVersion", "2.16.1126"
END
END
BLOCK "VarFileInfo"