mirror of
https://github.com/ventoy/Ventoy.git
synced 2025-08-28 00:11:15 +00:00
update
This commit is contained in:
@@ -57,6 +57,10 @@ typedef enum STR_ID
|
||||
STR_PRESERVE_SPACE,//24
|
||||
STR_SPACE_VAL_INVALID,//25
|
||||
|
||||
STR_MENU_CLEAR, //26
|
||||
STR_CLEAR_SUCCESS, //27
|
||||
STR_CLEAR_FAILED, //28
|
||||
|
||||
STR_ID_MAX
|
||||
}STR_ID;
|
||||
|
||||
@@ -64,6 +68,7 @@ extern BOOL g_SecureBoot;
|
||||
|
||||
#define VTOY_MENU_SECURE_BOOT 0xA000
|
||||
#define VTOY_MENU_PART_CFG 0xA001
|
||||
#define VTOY_MENU_CLEAN 0xA002
|
||||
#define VTOY_MENU_LANGUAGE_BEGIN 0xB000
|
||||
|
||||
|
||||
|
@@ -1232,9 +1232,13 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
|
||||
|
||||
Ret = f_mount(0, TEXT("0:"), 1);
|
||||
Log("umount part %d", Ret);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("mount exfat failed %d", Ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1244,6 +1248,201 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter)
|
||||
{
|
||||
int i;
|
||||
int rc = 0;
|
||||
int state = 0;
|
||||
HANDLE hDrive;
|
||||
DWORD dwSize;
|
||||
BOOL bRet;
|
||||
CHAR MountDrive;
|
||||
CHAR DriveName[] = "?:\\";
|
||||
CHAR DriveLetters[MAX_PATH] = { 0 };
|
||||
LARGE_INTEGER liCurrentPosition;
|
||||
char *pTmpBuf = NULL;
|
||||
MBR_HEAD MBR;
|
||||
|
||||
*pDrvLetter = 0;
|
||||
|
||||
Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
|
||||
pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
|
||||
GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
|
||||
|
||||
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
|
||||
|
||||
Log("Lock disk for clean ............................. ");
|
||||
|
||||
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
|
||||
if (hDrive == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Log("Failed to open physical disk");
|
||||
return 1;
|
||||
}
|
||||
|
||||
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
|
||||
|
||||
if (DriveLetters[0] == 0)
|
||||
{
|
||||
Log("No drive letter was assigned...");
|
||||
DriveName[0] = GetFirstUnusedDriveLetter();
|
||||
Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unmount all mounted volumes that belong to this drive
|
||||
// Do it in reverse so that we always end on the first volume letter
|
||||
for (i = (int)strlen(DriveLetters); i > 0; i--)
|
||||
{
|
||||
DriveName[0] = DriveLetters[i - 1];
|
||||
bRet = DeleteVolumeMountPointA(DriveName);
|
||||
Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
MountDrive = DriveName[0];
|
||||
Log("Will use '%C:' as volume mountpoint", DriveName[0]);
|
||||
|
||||
// It kind of blows, but we have to relinquish access to the physical drive
|
||||
// for VDS to be able to delete the partitions that reside on it...
|
||||
DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
|
||||
PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
|
||||
|
||||
if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE))
|
||||
{
|
||||
Log("Notice: Could not delete partitions: %u", GetLastError());
|
||||
}
|
||||
|
||||
Log("Deleting all partitions ......................... OK");
|
||||
|
||||
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
|
||||
|
||||
Log("Lock disk for write ............................. ");
|
||||
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
|
||||
if (hDrive == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Log("Failed to GetPhysicalHandle for write.");
|
||||
rc = 1;
|
||||
goto End;
|
||||
}
|
||||
|
||||
// clear first and last 1MB space
|
||||
pTmpBuf = malloc(SIZE_1MB);
|
||||
if (!pTmpBuf)
|
||||
{
|
||||
Log("Failed to alloc memory.");
|
||||
rc = 1;
|
||||
goto End;
|
||||
}
|
||||
memset(pTmpBuf, 0, SIZE_1MB);
|
||||
|
||||
SET_FILE_POS(512);
|
||||
bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB - 512, &dwSize, NULL);
|
||||
Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
|
||||
if (!bRet)
|
||||
{
|
||||
rc = 1;
|
||||
goto End;
|
||||
}
|
||||
|
||||
SET_FILE_POS(SIZE_1MB);
|
||||
bRet = WriteFile(hDrive, pTmpBuf, SIZE_1MB, &dwSize, NULL);
|
||||
Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
|
||||
if (!bRet)
|
||||
{
|
||||
rc = 1;
|
||||
goto End;
|
||||
}
|
||||
|
||||
SET_FILE_POS(0);
|
||||
bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
|
||||
Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
|
||||
if (!bRet)
|
||||
{
|
||||
rc = 1;
|
||||
goto End;
|
||||
}
|
||||
|
||||
//clear boot code and partition table (reserved disk signature)
|
||||
memset(MBR.BootCode, 0, 440);
|
||||
memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl));
|
||||
|
||||
VentoyFillLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);
|
||||
|
||||
MBR.PartTbl[0].Active = 0x80; // bootable
|
||||
MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS
|
||||
|
||||
SET_FILE_POS(0);
|
||||
bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
|
||||
Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
|
||||
if (!bRet)
|
||||
{
|
||||
rc = 1;
|
||||
goto End;
|
||||
}
|
||||
|
||||
Log("Clear Ventoy successfully finished");
|
||||
|
||||
End:
|
||||
|
||||
PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
|
||||
|
||||
if (pTmpBuf)
|
||||
{
|
||||
free(pTmpBuf);
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
Log("Mounting Ventoy Partition ....................... ");
|
||||
Sleep(1000);
|
||||
|
||||
state = 0;
|
||||
memset(DriveLetters, 0, sizeof(DriveLetters));
|
||||
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
|
||||
Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
|
||||
|
||||
for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
|
||||
{
|
||||
DriveName[0] = DriveLetters[i];
|
||||
Log("%s is ventoy part1, already mounted", DriveName);
|
||||
state = 1;
|
||||
}
|
||||
|
||||
if (state != 1)
|
||||
{
|
||||
Log("need to mount ventoy part1...");
|
||||
if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE))
|
||||
{
|
||||
DriveName[0] = MountDrive;
|
||||
bRet = SetVolumeMountPointA(DriveName, DriveLetters);
|
||||
Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
|
||||
|
||||
*pDrvLetter = MountDrive;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Failed to find ventoy volume");
|
||||
}
|
||||
}
|
||||
|
||||
Log("OK\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
FindProcessOccupyDisk(hDrive, pPhyDrive);
|
||||
}
|
||||
|
||||
//Refresh Drive Layout
|
||||
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
|
||||
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
|
||||
{
|
||||
int i;
|
||||
@@ -1332,6 +1531,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
|
||||
Log("Formatting part1 exFAT ...");
|
||||
if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
|
||||
{
|
||||
log("FormatPart1exFAT failed.");
|
||||
rc = 1;
|
||||
goto End;
|
||||
}
|
||||
@@ -1340,6 +1540,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
|
||||
Log("Writing part2 FAT img ...");
|
||||
if (0 != FormatPart2Fat(hDrive, MBR.PartTbl[1].StartSectorId))
|
||||
{
|
||||
log("FormatPart2Fat failed.");
|
||||
rc = 1;
|
||||
goto End;
|
||||
}
|
||||
@@ -1348,11 +1549,11 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
|
||||
Log("Writting Boot Image ............................. ");
|
||||
if (WriteGrubStage1ToPhyDrive(hDrive) != 0)
|
||||
{
|
||||
log("WriteGrubStage1ToPhyDrive failed.");
|
||||
rc = 1;
|
||||
goto End;
|
||||
}
|
||||
|
||||
|
||||
PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
|
||||
Log("Writting Partition Table ........................ ");
|
||||
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
|
||||
@@ -1369,49 +1570,56 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
|
||||
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
|
||||
|
||||
End:
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
|
||||
PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
|
||||
Log("Mounting Ventoy Partition ....................... ");
|
||||
Sleep(1000);
|
||||
|
||||
state = 0;
|
||||
memset(DriveLetters, 0, sizeof(DriveLetters));
|
||||
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
|
||||
Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
|
||||
|
||||
for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
|
||||
if (rc == 0)
|
||||
{
|
||||
DriveName[0] = DriveLetters[i];
|
||||
if (IsVentoyLogicalDrive(DriveName[0]))
|
||||
Log("Mounting Ventoy Partition ....................... ");
|
||||
Sleep(1000);
|
||||
|
||||
state = 0;
|
||||
memset(DriveLetters, 0, sizeof(DriveLetters));
|
||||
GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
|
||||
Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
|
||||
|
||||
for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
|
||||
{
|
||||
Log("%s is ventoy part2, delete mountpoint", DriveName);
|
||||
DeleteVolumeMountPointA(DriveName);
|
||||
DriveName[0] = DriveLetters[i];
|
||||
if (IsVentoyLogicalDrive(DriveName[0]))
|
||||
{
|
||||
Log("%s is ventoy part2, delete mountpoint", DriveName);
|
||||
DeleteVolumeMountPointA(DriveName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("%s is ventoy part1, already mounted", DriveName);
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (state != 1)
|
||||
{
|
||||
Log("%s is ventoy part1, already mounted", DriveName);
|
||||
state = 1;
|
||||
Log("need to mount ventoy part1...");
|
||||
if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE))
|
||||
{
|
||||
DriveName[0] = MountDrive;
|
||||
bRet = SetVolumeMountPointA(DriveName, DriveLetters);
|
||||
Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Failed to find ventoy volume");
|
||||
}
|
||||
}
|
||||
Log("OK\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
FindProcessOccupyDisk(hDrive, pPhyDrive);
|
||||
}
|
||||
|
||||
if (state != 1)
|
||||
{
|
||||
Log("need to mount ventoy part1...");
|
||||
if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, MBR.PartTbl[0].StartSectorId, DriveLetters, sizeof(DriveLetters), FALSE))
|
||||
{
|
||||
DriveName[0] = MountDrive;
|
||||
bRet = SetVolumeMountPointA(DriveName, DriveLetters);
|
||||
Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Failed to find ventoy volume");
|
||||
}
|
||||
}
|
||||
|
||||
Log("OK\n");
|
||||
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1616,8 +1824,19 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
|
||||
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
|
||||
|
||||
End:
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
Log("OK");
|
||||
}
|
||||
else
|
||||
{
|
||||
FindProcessOccupyDisk(hDrive, pPhyDrive);
|
||||
}
|
||||
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -382,7 +382,7 @@ BOOL IsVentoyLogicalDrive(CHAR DriveLetter)
|
||||
}
|
||||
|
||||
|
||||
static int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table)
|
||||
int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table)
|
||||
{
|
||||
BYTE Head;
|
||||
BYTE Sector;
|
||||
|
@@ -276,6 +276,7 @@ int SortPhysicalDrive(PHY_DRIVE_INFO *pDriveList, DWORD DriveCount)
|
||||
|
||||
int Ventoy2DiskInit(void)
|
||||
{
|
||||
Log("\n===================== Enum All PhyDrives =====================");
|
||||
g_PhyDriveList = (PHY_DRIVE_INFO *)malloc(sizeof(PHY_DRIVE_INFO)* VENTOY_MAX_PHY_DRIVE);
|
||||
if (NULL == g_PhyDriveList)
|
||||
{
|
||||
|
@@ -161,5 +161,13 @@ int INIT unxz(unsigned char *in, int in_size,
|
||||
void disk_io_set_param(HANDLE Handle, UINT64 SectorCount);
|
||||
INT_PTR CALLBACK PartDialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
|
||||
int GetReservedSpaceInMB(void);
|
||||
int FindProcessOccupyDisk(HANDLE hDrive, PHY_DRIVE_INFO *pPhyDrive);
|
||||
int VentoyFillLocation(UINT64 DiskSizeInBytes, UINT32 StartSectorId, UINT32 SectorCount, PART_TABLE *Table);
|
||||
int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter);
|
||||
|
||||
#define SET_FILE_POS(pos) \
|
||||
liCurrentPosition.QuadPart = pos; \
|
||||
SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN)\
|
||||
|
||||
|
||||
#endif
|
||||
|
Binary file not shown.
@@ -106,6 +106,7 @@
|
||||
<ClCompile Include="Language.c" />
|
||||
<ClCompile Include="PartDialog.c" />
|
||||
<ClCompile Include="PhyDrive.c" />
|
||||
<ClCompile Include="process.c" />
|
||||
<ClCompile Include="Utility.c" />
|
||||
<ClCompile Include="Ventoy2Disk.c" />
|
||||
<ClCompile Include="WinDialog.c" />
|
||||
@@ -128,6 +129,7 @@
|
||||
<ClInclude Include="ff14\source\ff.h" />
|
||||
<ClInclude Include="ff14\source\ffconf.h" />
|
||||
<ClInclude Include="Language.h" />
|
||||
<ClInclude Include="process.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="Ventoy2Disk.h" />
|
||||
</ItemGroup>
|
||||
@@ -135,6 +137,8 @@
|
||||
<ResourceCompile Include="Ventoy2Disk.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="res\icon2.ico" />
|
||||
<Image Include="Res\refresh.ico" />
|
||||
<Image Include="Res\ventoy.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@@ -72,6 +72,9 @@
|
||||
<ClCompile Include="PartDialog.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="process.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Ventoy2Disk.h">
|
||||
@@ -128,6 +131,9 @@
|
||||
<ClInclude Include="ff14\source\ffconf.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="process.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Ventoy2Disk.rc">
|
||||
@@ -138,5 +144,11 @@
|
||||
<Image Include="Res\ventoy.ico">
|
||||
<Filter>资源文件</Filter>
|
||||
</Image>
|
||||
<Image Include="res\icon2.ico">
|
||||
<Filter>资源文件</Filter>
|
||||
</Image>
|
||||
<Image Include="Res\refresh.ico">
|
||||
<Filter>资源文件</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
</Project>
|
Binary file not shown.
672
Ventoy2Disk/Ventoy2Disk/process.c
Normal file
672
Ventoy2Disk/Ventoy2Disk/process.c
Normal file
@@ -0,0 +1,672 @@
|
||||
/*
|
||||
* Rufus: The Reliable USB Formatting Utility
|
||||
* Process search functionality
|
||||
*
|
||||
* Modified from Process Hacker:
|
||||
* https://github.com/processhacker2/processhacker2/
|
||||
* Copyright © 2017-2019 Pete Batard <pete@akeo.ie>
|
||||
* Copyright © 2017 dmex
|
||||
* Copyright © 2009-2016 wj32
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* 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 <winternl.h>
|
||||
#include <commctrl.h>
|
||||
#include <initguid.h>
|
||||
#include <vds.h>
|
||||
#include "resource.h"
|
||||
#include "Language.h"
|
||||
#include "Ventoy2Disk.h"
|
||||
#include "fat_filelib.h"
|
||||
#include "ff.h"
|
||||
#include "process.h"
|
||||
#include <Psapi.h>
|
||||
|
||||
|
||||
OPENED_LIBRARIES_VARS;
|
||||
|
||||
STATIC WCHAR *_wHandleName = NULL;
|
||||
static PVOID PhHeapHandle = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Convert an NT Status to an error message
|
||||
*
|
||||
* \param Status An operattonal status.
|
||||
*
|
||||
* \return An error message string.
|
||||
*
|
||||
*/
|
||||
char* NtStatusError(NTSTATUS Status) {
|
||||
static char unknown[32];
|
||||
|
||||
switch (Status) {
|
||||
case STATUS_SUCCESS:
|
||||
return "Operation Successful";
|
||||
case STATUS_UNSUCCESSFUL:
|
||||
return "Operation Failed";
|
||||
case STATUS_BUFFER_OVERFLOW:
|
||||
return "Buffer Overflow";
|
||||
case STATUS_NOT_IMPLEMENTED:
|
||||
return "Not Implemented";
|
||||
case STATUS_INFO_LENGTH_MISMATCH:
|
||||
return "Info Length Mismatch";
|
||||
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_OBJECT_PATH_INVALID:
|
||||
return "Object Path Invalid";
|
||||
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, "Unknown error 0x%08lx", Status);
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS PhCreateHeap(VOID)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
if (PhHeapHandle != NULL)
|
||||
return STATUS_ALREADY_COMPLETE;
|
||||
|
||||
PF_INIT_OR_SET_STATUS(RtlCreateHeap, Ntdll);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
PhHeapHandle = pfRtlCreateHeap(HEAP_NO_SERIALIZE | HEAP_GROWABLE, NULL, 2 * MB, 1 * MB, NULL, NULL);
|
||||
if (PhHeapHandle == NULL)
|
||||
status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS PhDestroyHeap(VOID)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
if (PhHeapHandle == NULL)
|
||||
return STATUS_ALREADY_COMPLETE;
|
||||
|
||||
PF_INIT_OR_SET_STATUS(RtlDestroyHeap, Ntdll);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (pfRtlDestroyHeap(PhHeapHandle) == NULL) {
|
||||
PhHeapHandle = NULL;
|
||||
}
|
||||
else {
|
||||
status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(RtlAllocateHeap, Ntdll);
|
||||
if (pfRtlAllocateHeap == NULL)
|
||||
return NULL;
|
||||
|
||||
return pfRtlAllocateHeap(PhHeapHandle, 0, Size);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = STATUS_SUCCESS;
|
||||
PVOID buffer;
|
||||
ULONG bufferSize;
|
||||
|
||||
PF_INIT_OR_SET_STATUS(NtQuerySystemInformation, Ntdll);
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
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_SUCCESS;
|
||||
OBJECT_ATTRIBUTES objectAttributes;
|
||||
CLIENT_ID clientId;
|
||||
|
||||
if ((LONG_PTR)ProcessId == (LONG_PTR)GetCurrentProcessId()) {
|
||||
*ProcessHandle = NtCurrentProcess();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PF_INIT_OR_SET_STATUS(NtOpenProcess, Ntdll);
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
clientId.UniqueProcess = ProcessId;
|
||||
clientId.UniqueThread = NULL;
|
||||
|
||||
InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL);
|
||||
status = pfNtOpenProcess(ProcessHandle, DesiredAccess, &objectAttributes, &clientId);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the full commandline that was used to create a process.
|
||||
* This can be helpful to differentiate between service instances (svchost.exe).
|
||||
* Taken from: https://stackoverflow.com/a/14012919/1069307
|
||||
*
|
||||
* \param hProcess A handle to a process.
|
||||
*
|
||||
* \return A Unicode commandline string, or NULL on error.
|
||||
* The returned string must be freed by the caller.
|
||||
*/
|
||||
static PWSTR GetProcessCommandLine(HANDLE hProcess)
|
||||
{
|
||||
PWSTR wcmdline = NULL;
|
||||
BOOL wow;
|
||||
DWORD pp_offset, cmd_offset;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
SYSTEM_INFO si;
|
||||
PBYTE peb = NULL, pp = NULL;
|
||||
|
||||
// Determine if 64 or 32-bit processor
|
||||
GetNativeSystemInfo(&si);
|
||||
if ((si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) || (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64)) {
|
||||
pp_offset = 0x20;
|
||||
cmd_offset = 0x70;
|
||||
}
|
||||
else {
|
||||
pp_offset = 0x10;
|
||||
cmd_offset = 0x40;
|
||||
}
|
||||
|
||||
// PEB and Process Parameters (we only need the beginning of these structs)
|
||||
peb = (PBYTE)calloc(pp_offset + 8, 1);
|
||||
if (peb == NULL)
|
||||
goto out;
|
||||
pp = (PBYTE)calloc(cmd_offset + 16, 1);
|
||||
if (pp == NULL)
|
||||
goto out;
|
||||
|
||||
IsWow64Process(GetCurrentProcess(), &wow);
|
||||
if (wow) {
|
||||
// 32-bit process running on a 64-bit OS
|
||||
PROCESS_BASIC_INFORMATION_WOW64 pbi = { 0 };
|
||||
ULONGLONG params;
|
||||
UNICODE_STRING_WOW64* ucmdline;
|
||||
|
||||
PF_INIT_OR_OUT(NtWow64QueryInformationProcess64, NtDll);
|
||||
PF_INIT_OR_OUT(NtWow64ReadVirtualMemory64, NtDll);
|
||||
|
||||
status = pfNtWow64QueryInformationProcess64(hProcess, 0, &pbi, sizeof(pbi), NULL);
|
||||
if (!NT_SUCCESS(status))
|
||||
goto out;
|
||||
|
||||
status = pfNtWow64ReadVirtualMemory64(hProcess, pbi.PebBaseAddress, peb, pp_offset + 8, NULL);
|
||||
if (!NT_SUCCESS(status))
|
||||
goto out;
|
||||
|
||||
// Read Process Parameters from the 64-bit address space
|
||||
params = (ULONGLONG)*((ULONGLONG*)(peb + pp_offset));
|
||||
status = pfNtWow64ReadVirtualMemory64(hProcess, params, pp, cmd_offset + 16, NULL);
|
||||
if (!NT_SUCCESS(status))
|
||||
goto out;
|
||||
|
||||
ucmdline = (UNICODE_STRING_WOW64*)(pp + cmd_offset);
|
||||
wcmdline = (PWSTR)calloc(ucmdline->Length + 1, sizeof(WCHAR));
|
||||
if (wcmdline == NULL)
|
||||
goto out;
|
||||
status = pfNtWow64ReadVirtualMemory64(hProcess, ucmdline->Buffer, wcmdline, ucmdline->Length, NULL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
safe_free(wcmdline);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 32-bit process on a 32-bit OS, or 64-bit process on a 64-bit OS
|
||||
PROCESS_BASIC_INFORMATION pbi = { 0 };
|
||||
PBYTE* params;
|
||||
UNICODE_STRING* ucmdline;
|
||||
|
||||
PF_INIT_OR_OUT(NtQueryInformationProcess, NtDll);
|
||||
|
||||
status = pfNtQueryInformationProcess(hProcess, 0, &pbi, sizeof(pbi), NULL);
|
||||
if (!NT_SUCCESS(status))
|
||||
goto out;
|
||||
|
||||
// Read PEB
|
||||
if (!ReadProcessMemory(hProcess, pbi.PebBaseAddress, peb, pp_offset + 8, NULL))
|
||||
goto out;
|
||||
|
||||
// Read Process Parameters
|
||||
params = (PBYTE*)*(LPVOID*)(peb + pp_offset);
|
||||
if (!ReadProcessMemory(hProcess, params, pp, cmd_offset + 16, NULL))
|
||||
goto out;
|
||||
|
||||
ucmdline = (UNICODE_STRING*)(pp + cmd_offset);
|
||||
// In the absolute, someone could craft a process with dodgy attributes to try to cause an overflow
|
||||
ucmdline->Length = min(ucmdline->Length, 512);
|
||||
wcmdline = (PWSTR)calloc(ucmdline->Length + 1, sizeof(WCHAR));
|
||||
if (!ReadProcessMemory(hProcess, ucmdline->Buffer, wcmdline, ucmdline->Length, NULL)) {
|
||||
safe_free(wcmdline);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
free(peb);
|
||||
free(pp);
|
||||
return wcmdline;
|
||||
}
|
||||
|
||||
|
||||
static int GetDevicePathName(PHY_DRIVE_INFO *pPhyDrive, WCHAR *wDevPath)
|
||||
{
|
||||
int i;
|
||||
CHAR PhyDrive[128];
|
||||
CHAR DevPath[MAX_PATH] = { 0 };
|
||||
|
||||
safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", pPhyDrive->PhyDrive);
|
||||
|
||||
if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath)))
|
||||
{
|
||||
Log("QueryDosDeviceA failed error:%u", GetLastError());
|
||||
strcpy_s(DevPath, sizeof(DevPath), "???");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("QueryDosDeviceA success %s", DevPath);
|
||||
}
|
||||
|
||||
for (i = 0; DevPath[i] && i < MAX_PATH; i++)
|
||||
{
|
||||
wDevPath[i] = DevPath[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int FindProcessOccupyDisk(HANDLE hDrive, PHY_DRIVE_INFO *pPhyDrive)
|
||||
{
|
||||
WCHAR wDevPath[MAX_PATH] = { 0 };
|
||||
const char *access_rights_str[8] = { "n", "r", "w", "rw", "x", "rx", "wx", "rwx" };
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
PSYSTEM_HANDLE_INFORMATION_EX handles = NULL;
|
||||
POBJECT_NAME_INFORMATION buffer = NULL;
|
||||
ULONG_PTR i;
|
||||
ULONG_PTR pid[2];
|
||||
ULONG_PTR last_access_denied_pid = 0;
|
||||
ULONG bufferSize;
|
||||
USHORT wHandleNameLen;
|
||||
HANDLE dupHandle = NULL;
|
||||
HANDLE processHandle = NULL;
|
||||
BOOLEAN bFound = FALSE, bGotCmdLine, verbose = TRUE;
|
||||
ULONG access_rights = 0;
|
||||
DWORD size;
|
||||
char cmdline[MAX_PATH] = { 0 };
|
||||
wchar_t wexe_path[MAX_PATH], *wcmdline;
|
||||
int cur_pid;
|
||||
|
||||
|
||||
Log("FindProcessOccupyDisk for PhyDrive %d", pPhyDrive->PhyDrive);
|
||||
|
||||
GetDevicePathName(pPhyDrive, wDevPath);
|
||||
_wHandleName = wDevPath;
|
||||
|
||||
|
||||
PF_INIT_OR_SET_STATUS(NtQueryObject, Ntdll);
|
||||
PF_INIT_OR_SET_STATUS(NtDuplicateObject, NtDll);
|
||||
PF_INIT_OR_SET_STATUS(NtClose, NtDll);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
status = PhCreateHeap();
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
status = PhEnumHandlesEx(&handles);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Log("Warning: Could not enumerate process handles: %s", NtStatusError(status));
|
||||
goto out;
|
||||
}
|
||||
|
||||
pid[0] = (ULONG_PTR)0;
|
||||
cur_pid = 1;
|
||||
|
||||
wHandleNameLen = (USHORT)wcslen(_wHandleName);
|
||||
|
||||
bufferSize = 0x200;
|
||||
buffer = PhAllocate(bufferSize);
|
||||
if (buffer == NULL)
|
||||
goto out;
|
||||
|
||||
for (i = 0;; i++) {
|
||||
ULONG attempts = 8;
|
||||
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo =
|
||||
(i < handles->NumberOfHandles) ? &handles->Handles[i] : NULL;
|
||||
|
||||
if ((dupHandle != NULL) && (processHandle != NtCurrentProcess())) {
|
||||
pfNtClose(dupHandle);
|
||||
dupHandle = NULL;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if (pid[0] != pid[1]) {
|
||||
cur_pid = (cur_pid + 1) % 2;
|
||||
|
||||
// If we're switching process and found a match, print it
|
||||
if (bFound) {
|
||||
Log("* [%06u] %s (%s)", (UINT32)pid[cur_pid], cmdline, access_rights_str[access_rights & 0x7]);
|
||||
bFound = FALSE;
|
||||
access_rights = 0;
|
||||
}
|
||||
|
||||
// Close the previous handle
|
||||
if (processHandle != NULL) {
|
||||
if (processHandle != NtCurrentProcess())
|
||||
pfNtClose(processHandle);
|
||||
processHandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Exit loop condition
|
||||
if (i >= handles->NumberOfHandles)
|
||||
break;
|
||||
|
||||
// Don't bother with processes we can't access
|
||||
if (handleInfo->UniqueProcessId == last_access_denied_pid)
|
||||
continue;
|
||||
|
||||
// Filter out handles that aren't opened with Read (bit 0), Write (bit 1) or Execute (bit 5) access
|
||||
if ((handleInfo->GrantedAccess & 0x23) == 0)
|
||||
continue;
|
||||
|
||||
// Open the process to which the handle we are after belongs, if not already opened
|
||||
if (pid[0] != pid[1]) {
|
||||
status = PhOpenProcess(&processHandle, PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
||||
(HANDLE)handleInfo->UniqueProcessId);
|
||||
// There exists some processes we can't access
|
||||
if (!NT_SUCCESS(status)) {
|
||||
//Log("SearchProcess: Could not open process %ld: %s",
|
||||
// handleInfo->UniqueProcessId, NtStatusError(status));
|
||||
processHandle = NULL;
|
||||
if (status == STATUS_ACCESS_DENIED) {
|
||||
last_access_denied_pid = handleInfo->UniqueProcessId;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Now duplicate this handle onto our own process, so that we can access its properties
|
||||
if (processHandle == NtCurrentProcess()) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
status = pfNtDuplicateObject(processHandle, (HANDLE)handleInfo->HandleValue,
|
||||
NtCurrentProcess(), &dupHandle, 0, 0, 0);
|
||||
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 {
|
||||
ULONG returnSize;
|
||||
// TODO: We might potentially still need a timeout on ObjectName queries, as PH does...
|
||||
status = pfNtQueryObject(dupHandle, ObjectNameInformation, buffer, bufferSize, &returnSize);
|
||||
if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH ||
|
||||
status == STATUS_BUFFER_TOO_SMALL) {
|
||||
Log("SearchProcess: Realloc from %d to %d", bufferSize, returnSize);
|
||||
bufferSize = returnSize;
|
||||
PhFree(buffer);
|
||||
buffer = PhAllocate(bufferSize);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
} while (--attempts);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
Log("SearchProcess: NtQueryObject failed for handle %X of process %ld: %s",
|
||||
handleInfo->HandleValue, handleInfo->UniqueProcessId, NtStatusError(status));
|
||||
continue;
|
||||
}
|
||||
|
||||
// we are looking for a partial match and the current length is smaller
|
||||
if (wHandleNameLen > buffer->Name.Length)
|
||||
continue;
|
||||
|
||||
// Match against our target string
|
||||
if (wcsncmp(_wHandleName, buffer->Name.Buffer, wHandleNameLen) != 0)
|
||||
continue;
|
||||
|
||||
// If we are here, we have a process accessing our target!
|
||||
bFound = TRUE;
|
||||
|
||||
// Keep a mask of all the access rights being used
|
||||
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 & 0x03) | 0x04;
|
||||
|
||||
// If this is the very first process we find, print a header
|
||||
if (cmdline[0] == 0)
|
||||
Log("WARNING: The following process(es) or service(s) are accessing %S:", _wHandleName);
|
||||
|
||||
// Where possible, try to get the full command line
|
||||
bGotCmdLine = FALSE;
|
||||
size = MAX_PATH;
|
||||
wcmdline = GetProcessCommandLine(processHandle);
|
||||
if (wcmdline != NULL) {
|
||||
bGotCmdLine = TRUE;
|
||||
wchar_to_utf8_no_alloc(wcmdline, cmdline, sizeof(cmdline));
|
||||
free(wcmdline);
|
||||
}
|
||||
|
||||
// If we couldn't get the full commandline, try to get the executable path
|
||||
if (!bGotCmdLine)
|
||||
bGotCmdLine = (GetModuleFileNameExU(processHandle, 0, cmdline, MAX_PATH - 1) != 0);
|
||||
|
||||
// The above may not work on Windows 7, so try QueryFullProcessImageName (Vista or later)
|
||||
if (!bGotCmdLine) {
|
||||
bGotCmdLine = QueryFullProcessImageNameW(processHandle, 0, wexe_path, &size);
|
||||
if (bGotCmdLine)
|
||||
wchar_to_utf8_no_alloc(wexe_path, cmdline, sizeof(cmdline));
|
||||
}
|
||||
|
||||
// Still nothing? Try GetProcessImageFileName. Note that GetProcessImageFileName uses
|
||||
// '\Device\Harddisk#\Partition#\' instead drive letters
|
||||
if (!bGotCmdLine) {
|
||||
bGotCmdLine = (GetProcessImageFileNameW(processHandle, wexe_path, MAX_PATH) != 0);
|
||||
if (bGotCmdLine)
|
||||
wchar_to_utf8_no_alloc(wexe_path, cmdline, sizeof(cmdline));
|
||||
}
|
||||
|
||||
// Complete failure => Just craft a default process name that includes the PID
|
||||
if (!bGotCmdLine) {
|
||||
safe_sprintf(cmdline, "Unknown_Process_0x%llx", (ULONGLONG)handleInfo->UniqueProcessId);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (cmdline[0] != 0)
|
||||
Log("You should close these applications before attempting to reformat the drive.");
|
||||
else
|
||||
Log("NOTE: Could not identify the process(es) or service(s) accessing %S", _wHandleName);
|
||||
|
||||
PhFree(buffer);
|
||||
PhFree(handles);
|
||||
PhDestroyHeap();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
405
Ventoy2Disk/Ventoy2Disk/process.h
Normal file
405
Ventoy2Disk/Ventoy2Disk/process.h
Normal file
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Rufus: The Reliable USB Formatting Utility
|
||||
* Process search functionality
|
||||
*
|
||||
* Modified from Process Hacker:
|
||||
* https://github.com/processhacker2/processhacker2/
|
||||
* Copyright © 2017-2019 Pete Batard <pete@akeo.ie>
|
||||
* Copyright © 2017 dmex
|
||||
* Copyright © 2009-2016 wj32
|
||||
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
||||
*
|
||||
* 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_SUCCESS ((NTSTATUS)0x00000000L)
|
||||
#define STATUS_ALREADY_COMPLETE ((NTSTATUS)0x000000FFL)
|
||||
#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_OBJECT_PATH_INVALID ((NTSTATUS)0xC0000039L)
|
||||
#define STATUS_SHARING_VIOLATION ((NTSTATUS)0xC0000043L)
|
||||
#define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS)0xC000009AL)
|
||||
#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BBL)
|
||||
|
||||
#define SystemExtendedHandleInformation 64
|
||||
#define FileProcessIdsUsingFileInformation 47
|
||||
|
||||
// MinGW doesn't know this one yet
|
||||
#if !defined(PROCESSOR_ARCHITECTURE_ARM64)
|
||||
#define PROCESSOR_ARCHITECTURE_ARM64 12
|
||||
#endif
|
||||
|
||||
#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 _OBJECT_TYPE_INFORMATION
|
||||
{
|
||||
UNICODE_STRING TypeName;
|
||||
ULONG TotalNumberOfObjects;
|
||||
ULONG TotalNumberOfHandles;
|
||||
ULONG TotalPagedPoolUsage;
|
||||
ULONG TotalNonPagedPoolUsage;
|
||||
ULONG TotalNamePoolUsage;
|
||||
ULONG TotalHandleTableUsage;
|
||||
ULONG HighWaterNumberOfObjects;
|
||||
ULONG HighWaterNumberOfHandles;
|
||||
ULONG HighWaterPagedPoolUsage;
|
||||
ULONG HighWaterNonPagedPoolUsage;
|
||||
ULONG HighWaterNamePoolUsage;
|
||||
ULONG HighWaterHandleTableUsage;
|
||||
ULONG InvalidAttributes;
|
||||
GENERIC_MAPPING GenericMapping;
|
||||
ULONG ValidAccessMask;
|
||||
BOOLEAN SecurityRequired;
|
||||
BOOLEAN MaintainHandleCount;
|
||||
UCHAR TypeIndex; // since WINBLUE
|
||||
CHAR ReservedByte;
|
||||
ULONG PoolType;
|
||||
ULONG DefaultPagedPoolCharge;
|
||||
ULONG DefaultNonPagedPoolCharge;
|
||||
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
|
||||
|
||||
#define ObjectNameInformation 1
|
||||
#endif
|
||||
#define ObjectTypesInformation 3
|
||||
|
||||
typedef struct _OBJECT_TYPES_INFORMATION
|
||||
{
|
||||
ULONG NumberOfTypes;
|
||||
} OBJECT_TYPES_INFORMATION, *POBJECT_TYPES_INFORMATION;
|
||||
|
||||
typedef struct _PROCESS_BASIC_INFORMATION_WOW64
|
||||
{
|
||||
PVOID Reserved1[2];
|
||||
// MinGW32 screws us with a sizeof(PVOID64) of 4 instead of 8 => Use ULONGLONG instead
|
||||
ULONGLONG PebBaseAddress;
|
||||
PVOID Reserved2[4];
|
||||
ULONG_PTR UniqueProcessId[2];
|
||||
PVOID Reserved3[2];
|
||||
} PROCESS_BASIC_INFORMATION_WOW64;
|
||||
|
||||
typedef struct _UNICODE_STRING_WOW64
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
ULONGLONG Buffer;
|
||||
} UNICODE_STRING_WOW64;
|
||||
|
||||
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))
|
||||
|
||||
#define PH_FIRST_OBJECT_TYPE(ObjectTypes) \
|
||||
(POBJECT_TYPE_INFORMATION)((PCHAR)(ObjectTypes)+ALIGN_UP(sizeof(OBJECT_TYPES_INFORMATION), ULONG_PTR))
|
||||
|
||||
#define PH_NEXT_OBJECT_TYPE(ObjectType) \
|
||||
(POBJECT_TYPE_INFORMATION)((PCHAR)(ObjectType)+sizeof(OBJECT_TYPE_INFORMATION)+\
|
||||
ALIGN_UP(ObjectType->TypeName.MaximumLength, ULONG_PTR))
|
||||
|
||||
// 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
|
||||
|
||||
// Privileges
|
||||
|
||||
#define SE_MIN_WELL_KNOWN_PRIVILEGE (2L)
|
||||
#define SE_CREATE_TOKEN_PRIVILEGE (2L)
|
||||
#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE (3L)
|
||||
#define SE_LOCK_MEMORY_PRIVILEGE (4L)
|
||||
#define SE_INCREASE_QUOTA_PRIVILEGE (5L)
|
||||
#define SE_MACHINE_ACCOUNT_PRIVILEGE (6L)
|
||||
#define SE_TCB_PRIVILEGE (7L)
|
||||
#define SE_SECURITY_PRIVILEGE (8L)
|
||||
#define SE_TAKE_OWNERSHIP_PRIVILEGE (9L)
|
||||
#define SE_LOAD_DRIVER_PRIVILEGE (10L)
|
||||
#define SE_SYSTEM_PROFILE_PRIVILEGE (11L)
|
||||
#define SE_SYSTEMTIME_PRIVILEGE (12L)
|
||||
#define SE_PROF_SINGLE_PROCESS_PRIVILEGE (13L)
|
||||
#define SE_INC_BASE_PRIORITY_PRIVILEGE (14L)
|
||||
#define SE_CREATE_PAGEFILE_PRIVILEGE (15L)
|
||||
#define SE_CREATE_PERMANENT_PRIVILEGE (16L)
|
||||
#define SE_BACKUP_PRIVILEGE (17L)
|
||||
#define SE_RESTORE_PRIVILEGE (18L)
|
||||
#define SE_SHUTDOWN_PRIVILEGE (19L)
|
||||
#define SE_DEBUG_PRIVILEGE (20L)
|
||||
#define SE_AUDIT_PRIVILEGE (21L)
|
||||
#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L)
|
||||
#define SE_CHANGE_NOTIFY_PRIVILEGE (23L)
|
||||
#define SE_REMOTE_SHUTDOWN_PRIVILEGE (24L)
|
||||
#define SE_UNDOCK_PRIVILEGE (25L)
|
||||
#define SE_SYNC_AGENT_PRIVILEGE (26L)
|
||||
#define SE_ENABLE_DELEGATION_PRIVILEGE (27L)
|
||||
#define SE_MANAGE_VOLUME_PRIVILEGE (28L)
|
||||
#define SE_IMPERSONATE_PRIVILEGE (29L)
|
||||
#define SE_CREATE_GLOBAL_PRIVILEGE (30L)
|
||||
#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE (31L)
|
||||
#define SE_RELABEL_PRIVILEGE (32L)
|
||||
#define SE_INC_WORKING_SET_PRIVILEGE (33L)
|
||||
#define SE_TIME_ZONE_PRIVILEGE (34L)
|
||||
#define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE (35L)
|
||||
#define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_SYMBOLIC_LINK_PRIVILEGE
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* typedefs for the function prototypes. Use the something like:
|
||||
* PF_DECL(FormatEx);
|
||||
* which translates to:
|
||||
* FormatEx_t pfFormatEx = NULL;
|
||||
* in your code, to declare the entrypoint and then use:
|
||||
* PF_INIT(FormatEx, Fmifs);
|
||||
* which translates to:
|
||||
* pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx");
|
||||
* to make it accessible.
|
||||
*/
|
||||
#define MAX_LIBRARY_HANDLES 32
|
||||
extern HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES];
|
||||
extern UINT16 OpenedLibrariesHandleSize;
|
||||
#define OPENED_LIBRARIES_VARS HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES]; UINT16 OpenedLibrariesHandleSize = 0
|
||||
#define CLOSE_OPENED_LIBRARIES while(OpenedLibrariesHandleSize > 0) FreeLibrary(OpenedLibrariesHandle[--OpenedLibrariesHandleSize])
|
||||
static __inline HMODULE GetLibraryHandle(char* szLibraryName) {
|
||||
HMODULE h = NULL;
|
||||
if ((h = GetModuleHandleA(szLibraryName)) == NULL) {
|
||||
if (OpenedLibrariesHandleSize >= MAX_LIBRARY_HANDLES) {
|
||||
Log("Error: MAX_LIBRARY_HANDLES is too small\n");
|
||||
}
|
||||
else {
|
||||
h = LoadLibraryA(szLibraryName);
|
||||
if (h != NULL)
|
||||
OpenedLibrariesHandle[OpenedLibrariesHandleSize++] = h;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
#define PF_TYPE(api, ret, proc, args) typedef ret (api *proc##_t)args
|
||||
#define PF_DECL(proc) static proc##_t pf##proc = NULL
|
||||
#define PF_TYPE_DECL(api, ret, proc, args) PF_TYPE(api, ret, proc, args); PF_DECL(proc)
|
||||
#define PF_INIT(proc, name) if (pf##proc == NULL) pf##proc = \
|
||||
(proc##_t) GetProcAddress(GetLibraryHandle(#name), #proc)
|
||||
#define PF_INIT_OR_OUT(proc, name) do {PF_INIT(proc, name); \
|
||||
if (pf##proc == NULL) { Log("Unable to locate %s() in %s.dll: %d\n", \
|
||||
#proc, #name, GetLastError()); goto out;} } while (0)
|
||||
|
||||
#define PF_INIT_OR_SET_STATUS(proc, name) do {PF_INIT(proc, name); \
|
||||
if ((pf##proc == NULL) && (NT_SUCCESS(status))) status = STATUS_NOT_IMPLEMENTED; \
|
||||
} while (0)
|
||||
|
||||
/* Custom application errors */
|
||||
#define FAC(f) ((f)<<16)
|
||||
#define APPERR(err) (APPLICATION_ERROR_MASK|(err))
|
||||
#define ERROR_INCOMPATIBLE_FS 0x1201
|
||||
#define ERROR_CANT_QUICK_FORMAT 0x1202
|
||||
#define ERROR_INVALID_CLUSTER_SIZE 0x1203
|
||||
#define ERROR_INVALID_VOLUME_SIZE 0x1204
|
||||
#define ERROR_CANT_START_THREAD 0x1205
|
||||
#define ERROR_BADBLOCKS_FAILURE 0x1206
|
||||
#define ERROR_ISO_SCAN 0x1207
|
||||
#define ERROR_ISO_EXTRACT 0x1208
|
||||
#define ERROR_CANT_REMOUNT_VOLUME 0x1209
|
||||
#define ERROR_CANT_PATCH 0x120A
|
||||
#define ERROR_CANT_ASSIGN_LETTER 0x120B
|
||||
#define ERROR_CANT_MOUNT_VOLUME 0x120C
|
||||
#define ERROR_BAD_SIGNATURE 0x120D
|
||||
#define ERROR_CANT_DOWNLOAD 0x120E
|
||||
|
||||
|
||||
#define KB 1024LL
|
||||
#define MB 1048576LL
|
||||
#define GB 1073741824LL
|
||||
#define TB 1099511627776LL
|
||||
|
||||
typedef struct _CLIENT_ID {
|
||||
HANDLE UniqueProcess;
|
||||
HANDLE UniqueThread;
|
||||
} CLIENT_ID;
|
||||
|
||||
|
||||
|
||||
|
||||
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));
|
||||
|
||||
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, NtQueryInformationProcess, (HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG));
|
||||
PF_TYPE_DECL(NTAPI, NTSTATUS, NtWow64QueryInformationProcess64, (HANDLE, ULONG, PVOID, ULONG, PULONG));
|
||||
PF_TYPE_DECL(NTAPI, NTSTATUS, NtWow64ReadVirtualMemory64, (HANDLE, ULONGLONG, PVOID, ULONG64, PULONG64));
|
||||
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, CLIENT_ID*));
|
||||
PF_TYPE_DECL(NTAPI, NTSTATUS, NtOpenProcessToken, (HANDLE, ACCESS_MASK, PHANDLE));
|
||||
PF_TYPE_DECL(NTAPI, NTSTATUS, NtAdjustPrivilegesToken, (HANDLE, BOOLEAN, PTOKEN_PRIVILEGES, ULONG, PTOKEN_PRIVILEGES, PULONG));
|
||||
PF_TYPE_DECL(NTAPI, NTSTATUS, NtClose, (HANDLE));
|
||||
|
||||
|
||||
#define safe_free(p) do {free((void*)p); p = NULL;} while(0)
|
||||
|
||||
#define wchar_to_utf8_no_alloc(wsrc, dest, dest_size) \
|
||||
WideCharToMultiByte(CP_UTF8, 0, wsrc, -1, dest, dest_size, NULL, NULL)
|
||||
#define utf8_to_wchar_no_alloc(src, wdest, wdest_size) \
|
||||
MultiByteToWideChar(CP_UTF8, 0, src, -1, wdest, wdest_size)
|
||||
|
||||
#define sfree(p) do {if (p != NULL) {free((void*)(p)); p = NULL;}} while(0)
|
||||
#define wconvert(p) wchar_t* w ## p = utf8_to_wchar(p)
|
||||
#define walloc(p, size) wchar_t* w ## p = (p == NULL)?NULL:(wchar_t*)calloc(size, sizeof(wchar_t))
|
||||
#define wfree(p) sfree(w ## p)
|
||||
|
Binary file not shown.
Reference in New Issue
Block a user