mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[process] add a more efficient method to search for processes
* As suggested in #773 * Don't switch to using this method though, as it requires a handle to the disk or volume to be obtained, and we use the process search in case there is an issue doing so.
This commit is contained in:
parent
867177c5cd
commit
302f108d79
3 changed files with 107 additions and 6 deletions
|
@ -48,6 +48,7 @@ PF_TYPE_DECL(NTAPI, BOOLEAN, RtlEqualUnicodeString, (PCUNICODE_STRING, PCUNICODE
|
|||
#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));
|
||||
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));
|
||||
|
@ -338,6 +339,54 @@ ULONG PhGetObjectTypeNumber(PUNICODE_STRING TypeName)
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Query processes with open handles to a file, volume or disk.
|
||||
*
|
||||
* \param VolumeOrFileHandle The handle to the target.
|
||||
* \param Information The returned list of processes.
|
||||
*
|
||||
* \return An NTStatus indicating success or the error code.
|
||||
*/
|
||||
NTSTATUS PhQueryProcessesUsingVolumeOrFile(HANDLE VolumeOrFileHandle,
|
||||
PFILE_PROCESS_IDS_USING_FILE_INFORMATION *Information)
|
||||
{
|
||||
static ULONG initialBufferSize = 16 * KB;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
PVOID buffer;
|
||||
ULONG bufferSize;
|
||||
IO_STATUS_BLOCK isb;
|
||||
|
||||
PF_INIT_OR_SET_STATUS(NtQueryInformationFile, NtDll);
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
bufferSize = initialBufferSize;
|
||||
buffer = PhAllocate(bufferSize);
|
||||
if (buffer == NULL)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
while ((status = pfNtQueryInformationFile(VolumeOrFileHandle, &isb, buffer, bufferSize,
|
||||
FileProcessIdsUsingFileInformation)) == STATUS_INFO_LENGTH_MISMATCH) {
|
||||
PhFree(buffer);
|
||||
bufferSize *= 2;
|
||||
// Fail if we're resizing the buffer to something very large.
|
||||
if (bufferSize > 64 * MB)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
buffer = PhAllocate(bufferSize);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
PhFree(buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (bufferSize <= 64 * MB)
|
||||
initialBufferSize = bufferSize;
|
||||
*Information = (PFILE_PROCESS_IDS_USING_FILE_INFORMATION)buffer;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search all the processes and list the ones that have a specific handle open.
|
||||
*
|
||||
|
@ -553,6 +602,51 @@ out:
|
|||
return bFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative search for processes keeping a handle on a specific disk or volume
|
||||
* Note that this search requires opening the disk or volume, which may not always
|
||||
* be convenient for our usage (since we might be looking for processes preventing
|
||||
* us to open said target in exclusive mode).
|
||||
*
|
||||
* \param HandleName The name of the handle to look for.
|
||||
*
|
||||
* \return TRUE if processes were found, FALSE otherwise.
|
||||
*/
|
||||
BOOL SearchProcessAlt(char* HandleName)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
ULONG i;
|
||||
HANDLE searchHandle = NULL;
|
||||
BOOLEAN bFound = FALSE;
|
||||
PFILE_PROCESS_IDS_USING_FILE_INFORMATION info = NULL;
|
||||
|
||||
status = PhCreateHeap();
|
||||
if (!NT_SUCCESS(status))
|
||||
goto out;
|
||||
|
||||
// Note that the access rights being used with CreateFile() might matter...
|
||||
searchHandle = CreateFileA(HandleName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
status = PhQueryProcessesUsingVolumeOrFile(searchHandle, &info);
|
||||
|
||||
if (NT_SUCCESS(status) && (info->NumberOfProcessIdsInList > 0)) {
|
||||
bFound = TRUE;
|
||||
uprintf("NOTE: The following process(es) or service(s) are accessing %s:", HandleName);
|
||||
for (i = 0; i < info->NumberOfProcessIdsInList; i++) {
|
||||
uprintf("o Process with PID %ld", info->ProcessIdList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
safe_closehandle(searchHandle);
|
||||
PhFree(info);
|
||||
PhDestroyHeap();
|
||||
if (!NT_SUCCESS(status))
|
||||
uprintf("SearchProcessAlt('%s') failed: %s", HandleName, NtStatusError(status));
|
||||
return bFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the privileges of the current application.
|
||||
*
|
||||
|
|
|
@ -47,7 +47,8 @@
|
|||
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL)
|
||||
#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL)
|
||||
|
||||
#define SystemExtendedHandleInformation 64
|
||||
#define SystemExtendedHandleInformation 64
|
||||
#define FileProcessIdsUsingFileInformation 47
|
||||
|
||||
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
|
||||
|
||||
|
@ -118,6 +119,12 @@ typedef struct _OBJECT_TYPES_INFORMATION
|
|||
ULONG NumberOfTypes;
|
||||
} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION;
|
||||
|
||||
|
||||
typedef struct _FILE_PROCESS_IDS_USING_FILE_INFORMATION {
|
||||
ULONG NumberOfProcessIdsInList;
|
||||
ULONG_PTR ProcessIdList[1];
|
||||
} FILE_PROCESS_IDS_USING_FILE_INFORMATION, *PFILE_PROCESS_IDS_USING_FILE_INFORMATION;
|
||||
|
||||
#define ALIGN_UP_BY(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1))
|
||||
#define ALIGN_UP(Address, Type) ALIGN_UP_BY(Address, sizeof(Type))
|
||||
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 242, 376
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 2.15.1106"
|
||||
CAPTION "Rufus 2.15.1107"
|
||||
FONT 8, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
|
||||
|
@ -334,8 +334,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,15,1106,0
|
||||
PRODUCTVERSION 2,15,1106,0
|
||||
FILEVERSION 2,15,1107,0
|
||||
PRODUCTVERSION 2,15,1107,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -352,13 +352,13 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "2.15.1106"
|
||||
VALUE "FileVersion", "2.15.1107"
|
||||
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.1106"
|
||||
VALUE "ProductVersion", "2.15.1107"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
Loading…
Reference in a new issue