Skip to content

Commit

Permalink
[core] attempt to continue if the only conflicting handles we found a…
Browse files Browse the repository at this point in the history
…re for read-only

* Also clean-up the process code and update for rufus-next
  • Loading branch information
pbatard committed Jul 13, 2017
1 parent a528bb3 commit bed8897
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 140 deletions.
20 changes: 10 additions & 10 deletions configure
Original file line number Diff line number Diff line change
@@ -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>.
#
Expand Down Expand Up @@ -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'

Expand Down Expand Up @@ -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]...
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 $@
Expand Down Expand Up @@ -2303,7 +2303,7 @@ fi
# Define the identity of the package.
PACKAGE='rufus'
VERSION='2.15'
VERSION='2.16'
cat >>confdefs.h <<_ACEOF
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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\\"
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -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])
Expand Down
2 changes: 1 addition & 1 deletion res/appstore/AppxManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion res/appstore/packme.cmd
Original file line number Diff line number Diff line change
@@ -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...
Expand Down
16 changes: 9 additions & 7 deletions src/drive.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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:
Expand Down
127 changes: 13 additions & 114 deletions src/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -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 =
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/rufus.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Loading

0 comments on commit bed8897

Please sign in to comment.