go my file uploader
This commit is contained in:
68
phlib/apiimport.c
Normal file
68
phlib/apiimport.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* procedure import module
|
||||
*
|
||||
* Copyright (C) 2015 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <apiimport.h>
|
||||
|
||||
PVOID PhpImportProcedure(
|
||||
_Inout_ PVOID *Cache,
|
||||
_Inout_ PBOOLEAN CacheValid,
|
||||
_In_ PWSTR ModuleName,
|
||||
_In_ PSTR ProcedureName
|
||||
)
|
||||
{
|
||||
HMODULE module;
|
||||
PVOID procedure;
|
||||
|
||||
if (*CacheValid)
|
||||
return *Cache;
|
||||
|
||||
module = GetModuleHandle(ModuleName);
|
||||
|
||||
if (!module)
|
||||
return NULL;
|
||||
|
||||
procedure = GetProcAddress(module, ProcedureName);
|
||||
*Cache = procedure;
|
||||
MemoryBarrier();
|
||||
*CacheValid = TRUE;
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
#define PH_DEFINE_IMPORT(Module, Name) \
|
||||
_##Name Name##_Import(VOID) \
|
||||
{ \
|
||||
static PVOID cache = NULL; \
|
||||
static BOOLEAN cacheValid = FALSE; \
|
||||
\
|
||||
return (_##Name)PhpImportProcedure(&cache, &cacheValid, Module, #Name); \
|
||||
}
|
||||
|
||||
PH_DEFINE_IMPORT(L"comctl32.dll", TaskDialogIndirect);
|
||||
PH_DEFINE_IMPORT(L"ntdll.dll", NtQueryInformationEnlistment);
|
||||
PH_DEFINE_IMPORT(L"ntdll.dll", NtQueryInformationResourceManager);
|
||||
PH_DEFINE_IMPORT(L"ntdll.dll", NtQueryInformationTransaction);
|
||||
PH_DEFINE_IMPORT(L"ntdll.dll", NtQueryInformationTransactionManager);
|
||||
PH_DEFINE_IMPORT(L"shell32.dll", SHCreateShellItem);
|
||||
PH_DEFINE_IMPORT(L"shell32.dll", SHOpenFolderAndSelectItems);
|
||||
PH_DEFINE_IMPORT(L"shell32.dll", SHParseDisplayName);
|
||||
1081
phlib/avltree.c
Normal file
1081
phlib/avltree.c
Normal file
File diff suppressed because it is too large
Load Diff
5983
phlib/basesup.c
Normal file
5983
phlib/basesup.c
Normal file
File diff suppressed because it is too large
Load Diff
22
phlib/circbuf.c
Normal file
22
phlib/circbuf.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <phbase.h>
|
||||
#include <circbuf.h>
|
||||
|
||||
#undef T
|
||||
#define T ULONG
|
||||
#include "circbuf_i.h"
|
||||
|
||||
#undef T
|
||||
#define T ULONG64
|
||||
#include "circbuf_i.h"
|
||||
|
||||
#undef T
|
||||
#define T PVOID
|
||||
#include "circbuf_i.h"
|
||||
|
||||
#undef T
|
||||
#define T SIZE_T
|
||||
#include "circbuf_i.h"
|
||||
|
||||
#undef T
|
||||
#define T FLOAT
|
||||
#include "circbuf_i.h"
|
||||
121
phlib/circbuf_i.h
Normal file
121
phlib/circbuf_i.h
Normal file
@@ -0,0 +1,121 @@
|
||||
#ifdef T
|
||||
|
||||
#include <templ.h>
|
||||
|
||||
VOID T___(PhInitializeCircularBuffer, T)(
|
||||
_Out_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_In_ ULONG Size
|
||||
)
|
||||
{
|
||||
#ifdef PH_CIRCULAR_BUFFER_POWER_OF_TWO_SIZE
|
||||
Buffer->Size = PhRoundUpToPowerOfTwo(Size);
|
||||
Buffer->SizeMinusOne = Buffer->Size - 1;
|
||||
#else
|
||||
Buffer->Size = Size;
|
||||
#endif
|
||||
|
||||
Buffer->Count = 0;
|
||||
Buffer->Index = 0;
|
||||
Buffer->Data = PhAllocate(sizeof(T) * Buffer->Size);
|
||||
}
|
||||
|
||||
VOID T___(PhDeleteCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer
|
||||
)
|
||||
{
|
||||
PhFree(Buffer->Data);
|
||||
}
|
||||
|
||||
VOID T___(PhResizeCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_In_ ULONG NewSize
|
||||
)
|
||||
{
|
||||
T *newData;
|
||||
ULONG tailSize;
|
||||
ULONG headSize;
|
||||
|
||||
#ifdef PH_CIRCULAR_BUFFER_POWER_OF_TWO_SIZE
|
||||
NewSize = PhRoundUpToPowerOfTwo(NewSize);
|
||||
#endif
|
||||
|
||||
// If we're not actually resizing it, return.
|
||||
if (NewSize == Buffer->Size)
|
||||
return;
|
||||
|
||||
newData = PhAllocate(sizeof(T) * NewSize);
|
||||
tailSize = (ULONG)(Buffer->Size - Buffer->Index);
|
||||
headSize = Buffer->Count - tailSize;
|
||||
|
||||
if (NewSize > Buffer->Size)
|
||||
{
|
||||
// Copy the tail, then the head.
|
||||
memcpy(newData, &Buffer->Data[Buffer->Index], sizeof(T) * tailSize);
|
||||
memcpy(&newData[tailSize], Buffer->Data, sizeof(T) * headSize);
|
||||
Buffer->Index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tailSize >= NewSize)
|
||||
{
|
||||
// Copy only a part of the tail.
|
||||
memcpy(newData, &Buffer->Data[Buffer->Index], sizeof(T) * NewSize);
|
||||
Buffer->Index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy the tail, then only part of the head.
|
||||
memcpy(newData, &Buffer->Data[Buffer->Index], sizeof(T) * tailSize);
|
||||
memcpy(&newData[tailSize], Buffer->Data, sizeof(T) * (NewSize - tailSize));
|
||||
Buffer->Index = 0;
|
||||
}
|
||||
|
||||
// Since we're making the circular buffer smaller, limit the count.
|
||||
if (Buffer->Count > NewSize)
|
||||
Buffer->Count = NewSize;
|
||||
}
|
||||
|
||||
Buffer->Data = newData;
|
||||
Buffer->Size = NewSize;
|
||||
#ifdef PH_CIRCULAR_BUFFER_POWER_OF_TWO_SIZE
|
||||
Buffer->SizeMinusOne = NewSize - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID T___(PhClearCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer
|
||||
)
|
||||
{
|
||||
Buffer->Count = 0;
|
||||
Buffer->Index = 0;
|
||||
}
|
||||
|
||||
VOID T___(PhCopyCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_Out_writes_(Count) T *Destination,
|
||||
_In_ ULONG Count
|
||||
)
|
||||
{
|
||||
ULONG tailSize;
|
||||
ULONG headSize;
|
||||
|
||||
tailSize = (ULONG)(Buffer->Size - Buffer->Index);
|
||||
headSize = Buffer->Count - tailSize;
|
||||
|
||||
if (Count > Buffer->Count)
|
||||
Count = Buffer->Count;
|
||||
|
||||
if (tailSize >= Count)
|
||||
{
|
||||
// Copy only a part of the tail.
|
||||
memcpy(Destination, &Buffer->Data[Buffer->Index], sizeof(T) * Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy the tail, then only part of the head.
|
||||
memcpy(Destination, &Buffer->Data[Buffer->Index], sizeof(T) * tailSize);
|
||||
memcpy(&Destination[tailSize], Buffer->Data, sizeof(T) * (Count - tailSize));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
228
phlib/colorbox.c
Normal file
228
phlib/colorbox.c
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* color picker
|
||||
*
|
||||
* Copyright (C) 2010 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <guisup.h>
|
||||
#include <colorbox.h>
|
||||
#include <commdlg.h>
|
||||
|
||||
typedef struct _PHP_COLORBOX_CONTEXT
|
||||
{
|
||||
COLORREF SelectedColor;
|
||||
BOOLEAN Hot;
|
||||
BOOLEAN HasFocus;
|
||||
} PHP_COLORBOX_CONTEXT, *PPHP_COLORBOX_CONTEXT;
|
||||
|
||||
LRESULT CALLBACK PhpColorBoxWndProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
);
|
||||
|
||||
BOOLEAN PhColorBoxInitialization(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
WNDCLASSEX c = { sizeof(c) };
|
||||
|
||||
c.style = CS_GLOBALCLASS;
|
||||
c.lpfnWndProc = PhpColorBoxWndProc;
|
||||
c.cbClsExtra = 0;
|
||||
c.cbWndExtra = sizeof(PVOID);
|
||||
c.hInstance = PhLibImageBase;
|
||||
c.hIcon = NULL;
|
||||
c.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
c.hbrBackground = NULL;
|
||||
c.lpszMenuName = NULL;
|
||||
c.lpszClassName = PH_COLORBOX_CLASSNAME;
|
||||
c.hIconSm = NULL;
|
||||
|
||||
if (!RegisterClassEx(&c))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID PhpCreateColorBoxContext(
|
||||
_Out_ PPHP_COLORBOX_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
PPHP_COLORBOX_CONTEXT context;
|
||||
|
||||
context = PhAllocate(sizeof(PHP_COLORBOX_CONTEXT));
|
||||
memset(context, 0, sizeof(PHP_COLORBOX_CONTEXT));
|
||||
*Context = context;
|
||||
}
|
||||
|
||||
VOID PhpFreeColorBoxContext(
|
||||
_In_ _Post_invalid_ PPHP_COLORBOX_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PhFree(Context);
|
||||
}
|
||||
|
||||
VOID PhpChooseColor(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_COLORBOX_CONTEXT Context
|
||||
)
|
||||
{
|
||||
CHOOSECOLOR chooseColor = { sizeof(chooseColor) };
|
||||
COLORREF customColors[16] = { 0 };
|
||||
|
||||
chooseColor.hwndOwner = hwnd;
|
||||
chooseColor.rgbResult = Context->SelectedColor;
|
||||
chooseColor.lpCustColors = customColors;
|
||||
chooseColor.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
|
||||
|
||||
if (ChooseColor(&chooseColor))
|
||||
{
|
||||
Context->SelectedColor = chooseColor.rgbResult;
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK PhpColorBoxWndProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
{
|
||||
PPHP_COLORBOX_CONTEXT context;
|
||||
|
||||
context = (PPHP_COLORBOX_CONTEXT)GetWindowLongPtr(hwnd, 0);
|
||||
|
||||
if (uMsg == WM_CREATE)
|
||||
{
|
||||
PhpCreateColorBoxContext(&context);
|
||||
SetWindowLongPtr(hwnd, 0, (LONG_PTR)context);
|
||||
}
|
||||
|
||||
if (!context)
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
{
|
||||
// Nothing
|
||||
}
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
{
|
||||
PhpFreeColorBoxContext(context);
|
||||
SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL);
|
||||
}
|
||||
break;
|
||||
case WM_PAINT:
|
||||
{
|
||||
PAINTSTRUCT paintStruct;
|
||||
RECT clientRect;
|
||||
HDC hdc;
|
||||
|
||||
if (hdc = BeginPaint(hwnd, &paintStruct))
|
||||
{
|
||||
GetClientRect(hwnd, &clientRect);
|
||||
|
||||
// Border color
|
||||
SetDCPenColor(hdc, RGB(0x44, 0x44, 0x44));
|
||||
|
||||
// Fill color
|
||||
if (!context->Hot && !context->HasFocus)
|
||||
SetDCBrushColor(hdc, context->SelectedColor);
|
||||
else
|
||||
SetDCBrushColor(hdc, PhMakeColorBrighter(context->SelectedColor, 64));
|
||||
|
||||
// Draw the rectangle.
|
||||
SelectObject(hdc, GetStockObject(DC_PEN));
|
||||
SelectObject(hdc, GetStockObject(DC_BRUSH));
|
||||
Rectangle(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom);
|
||||
|
||||
EndPaint(hwnd, &paintStruct);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case WM_ERASEBKGND:
|
||||
return 1;
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
if (!context->Hot)
|
||||
{
|
||||
TRACKMOUSEEVENT trackMouseEvent = { sizeof(trackMouseEvent) };
|
||||
|
||||
context->Hot = TRUE;
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
|
||||
trackMouseEvent.dwFlags = TME_LEAVE;
|
||||
trackMouseEvent.hwndTrack = hwnd;
|
||||
TrackMouseEvent(&trackMouseEvent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_MOUSELEAVE:
|
||||
{
|
||||
context->Hot = FALSE;
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONDOWN:
|
||||
{
|
||||
PhpChooseColor(hwnd, context);
|
||||
}
|
||||
break;
|
||||
case WM_SETFOCUS:
|
||||
{
|
||||
context->HasFocus = TRUE;
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
}
|
||||
return 0;
|
||||
case WM_KILLFOCUS:
|
||||
{
|
||||
context->HasFocus = FALSE;
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
}
|
||||
return 0;
|
||||
case WM_GETDLGCODE:
|
||||
if (wParam == VK_RETURN)
|
||||
return DLGC_WANTMESSAGE;
|
||||
return 0;
|
||||
case WM_KEYDOWN:
|
||||
{
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_SPACE:
|
||||
case VK_RETURN:
|
||||
PhpChooseColor(hwnd, context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CBCM_SETCOLOR:
|
||||
context->SelectedColor = (COLORREF)wParam;
|
||||
return TRUE;
|
||||
case CBCM_GETCOLOR:
|
||||
return (LRESULT)context->SelectedColor;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
573
phlib/cpysave.c
Normal file
573
phlib/cpysave.c
Normal file
@@ -0,0 +1,573 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* copy/save code for listviews and treelists
|
||||
*
|
||||
* Copyright (C) 2010-2012 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <guisup.h>
|
||||
#include <treenew.h>
|
||||
#include <cpysave.h>
|
||||
|
||||
#define TAB_SIZE 8
|
||||
|
||||
VOID PhpEscapeStringForCsv(
|
||||
_Inout_ PPH_STRING_BUILDER StringBuilder,
|
||||
_In_ PPH_STRING String
|
||||
)
|
||||
{
|
||||
SIZE_T i;
|
||||
SIZE_T length;
|
||||
PWCHAR runStart;
|
||||
SIZE_T runLength;
|
||||
|
||||
length = String->Length / sizeof(WCHAR);
|
||||
runStart = NULL;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
switch (String->Buffer[i])
|
||||
{
|
||||
case '\"':
|
||||
if (runStart)
|
||||
{
|
||||
PhAppendStringBuilderEx(StringBuilder, runStart, runLength * sizeof(WCHAR));
|
||||
runStart = NULL;
|
||||
}
|
||||
|
||||
PhAppendStringBuilder2(StringBuilder, L"\"\"");
|
||||
|
||||
break;
|
||||
default:
|
||||
if (runStart)
|
||||
{
|
||||
runLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
runStart = &String->Buffer[i];
|
||||
runLength = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (runStart)
|
||||
PhAppendStringBuilderEx(StringBuilder, runStart, runLength * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a text table.
|
||||
*
|
||||
* \param Table A variable which receives a pointer to the text table.
|
||||
* \param Rows The number of rows in the table.
|
||||
* \param Columns The number of columns in the table.
|
||||
*/
|
||||
VOID PhaCreateTextTable(
|
||||
_Out_ PPH_STRING ***Table,
|
||||
_In_ ULONG Rows,
|
||||
_In_ ULONG Columns
|
||||
)
|
||||
{
|
||||
PPH_STRING **table;
|
||||
ULONG i;
|
||||
|
||||
table = PH_AUTO(PhCreateAlloc(sizeof(PPH_STRING *) * Rows));
|
||||
|
||||
for (i = 0; i < Rows; i++)
|
||||
{
|
||||
table[i] = PH_AUTO(PhCreateAlloc(sizeof(PPH_STRING) * Columns));
|
||||
memset(table[i], 0, sizeof(PPH_STRING) * Columns);
|
||||
}
|
||||
|
||||
*Table = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a text table to a list of lines.
|
||||
*
|
||||
* \param Table A pointer to the text table.
|
||||
* \param Rows The number of rows in the table.
|
||||
* \param Columns The number of columns in the table.
|
||||
* \param Mode The export formatting mode.
|
||||
*
|
||||
* \return A list of strings for each line in the output. The list object and
|
||||
* string objects are not auto-dereferenced.
|
||||
*/
|
||||
PPH_LIST PhaFormatTextTable(
|
||||
_In_ PPH_STRING **Table,
|
||||
_In_ ULONG Rows,
|
||||
_In_ ULONG Columns,
|
||||
_In_ ULONG Mode
|
||||
)
|
||||
{
|
||||
PPH_LIST lines;
|
||||
// The tab count array contains the number of tabs need to fill the biggest
|
||||
// row cell in each column.
|
||||
PULONG tabCount;
|
||||
ULONG i;
|
||||
ULONG j;
|
||||
|
||||
if (Mode == PH_EXPORT_MODE_TABS || Mode == PH_EXPORT_MODE_SPACES)
|
||||
{
|
||||
// Create the tab count array.
|
||||
|
||||
tabCount = PH_AUTO(PhCreateAlloc(sizeof(ULONG) * Columns));
|
||||
memset(tabCount, 0, sizeof(ULONG) * Columns); // zero all values
|
||||
|
||||
for (i = 0; i < Rows; i++)
|
||||
{
|
||||
for (j = 0; j < Columns; j++)
|
||||
{
|
||||
ULONG newCount;
|
||||
|
||||
if (Table[i][j])
|
||||
newCount = (ULONG)(Table[i][j]->Length / sizeof(WCHAR) / TAB_SIZE);
|
||||
else
|
||||
newCount = 0;
|
||||
|
||||
// Replace the existing count if this tab count is bigger.
|
||||
if (tabCount[j] < newCount)
|
||||
tabCount[j] = newCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the final list of lines by going through each cell and appending
|
||||
// the proper tab count (if we are using tabs). This will make sure each column
|
||||
// is properly aligned.
|
||||
|
||||
lines = PhCreateList(Rows);
|
||||
|
||||
for (i = 0; i < Rows; i++)
|
||||
{
|
||||
PH_STRING_BUILDER stringBuilder;
|
||||
|
||||
PhInitializeStringBuilder(&stringBuilder, 100);
|
||||
|
||||
switch (Mode)
|
||||
{
|
||||
case PH_EXPORT_MODE_TABS:
|
||||
{
|
||||
for (j = 0; j < Columns; j++)
|
||||
{
|
||||
ULONG k;
|
||||
|
||||
if (Table[i][j])
|
||||
{
|
||||
// Calculate the number of tabs needed.
|
||||
k = (ULONG)(tabCount[j] + 1 - Table[i][j]->Length / sizeof(WCHAR) / TAB_SIZE);
|
||||
|
||||
PhAppendStringBuilder(&stringBuilder, &Table[i][j]->sr);
|
||||
}
|
||||
else
|
||||
{
|
||||
k = tabCount[j] + 1;
|
||||
}
|
||||
|
||||
PhAppendCharStringBuilder2(&stringBuilder, '\t', k);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PH_EXPORT_MODE_SPACES:
|
||||
{
|
||||
for (j = 0; j < Columns; j++)
|
||||
{
|
||||
ULONG k;
|
||||
|
||||
if (Table[i][j])
|
||||
{
|
||||
// Calculate the number of spaces needed.
|
||||
k = (ULONG)((tabCount[j] + 1) * TAB_SIZE - Table[i][j]->Length / sizeof(WCHAR));
|
||||
|
||||
PhAppendStringBuilder(&stringBuilder, &Table[i][j]->sr);
|
||||
}
|
||||
else
|
||||
{
|
||||
k = (tabCount[j] + 1) * TAB_SIZE;
|
||||
}
|
||||
|
||||
PhAppendCharStringBuilder2(&stringBuilder, ' ', k);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PH_EXPORT_MODE_CSV:
|
||||
{
|
||||
for (j = 0; j < Columns; j++)
|
||||
{
|
||||
PhAppendCharStringBuilder(&stringBuilder, '\"');
|
||||
|
||||
if (Table[i][j])
|
||||
{
|
||||
PhpEscapeStringForCsv(&stringBuilder, Table[i][j]);
|
||||
}
|
||||
|
||||
PhAppendCharStringBuilder(&stringBuilder, '\"');
|
||||
|
||||
if (j != Columns - 1)
|
||||
PhAppendCharStringBuilder(&stringBuilder, ',');
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
PhAddItemList(lines, PhFinalStringBuilderString(&stringBuilder));
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
VOID PhMapDisplayIndexTreeNew(
|
||||
_In_ HWND TreeNewHandle,
|
||||
_Out_opt_ PULONG *DisplayToId,
|
||||
_Out_opt_ PWSTR **DisplayToText,
|
||||
_Out_ PULONG NumberOfColumns
|
||||
)
|
||||
{
|
||||
PPH_TREENEW_COLUMN fixedColumn;
|
||||
ULONG numberOfColumns;
|
||||
PULONG displayToId;
|
||||
PWSTR *displayToText;
|
||||
ULONG i;
|
||||
PH_TREENEW_COLUMN column;
|
||||
|
||||
fixedColumn = TreeNew_GetFixedColumn(TreeNewHandle);
|
||||
numberOfColumns = TreeNew_GetVisibleColumnCount(TreeNewHandle);
|
||||
|
||||
displayToId = PhAllocate(numberOfColumns * sizeof(ULONG));
|
||||
|
||||
if (fixedColumn)
|
||||
{
|
||||
TreeNew_GetColumnOrderArray(TreeNewHandle, numberOfColumns - 1, displayToId + 1);
|
||||
displayToId[0] = fixedColumn->Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
TreeNew_GetColumnOrderArray(TreeNewHandle, numberOfColumns, displayToId);
|
||||
}
|
||||
|
||||
if (DisplayToText)
|
||||
{
|
||||
displayToText = PhAllocate(numberOfColumns * sizeof(PWSTR));
|
||||
|
||||
for (i = 0; i < numberOfColumns; i++)
|
||||
{
|
||||
if (TreeNew_GetColumn(TreeNewHandle, displayToId[i], &column))
|
||||
{
|
||||
displayToText[i] = column.Text;
|
||||
}
|
||||
}
|
||||
|
||||
*DisplayToText = displayToText;
|
||||
}
|
||||
|
||||
if (DisplayToId)
|
||||
*DisplayToId = displayToId;
|
||||
else
|
||||
PhFree(displayToId);
|
||||
|
||||
*NumberOfColumns = numberOfColumns;
|
||||
}
|
||||
|
||||
PPH_STRING PhGetTreeNewText(
|
||||
_In_ HWND TreeNewHandle,
|
||||
_Reserved_ ULONG Reserved
|
||||
)
|
||||
{
|
||||
PH_STRING_BUILDER stringBuilder;
|
||||
PULONG displayToId;
|
||||
ULONG rows;
|
||||
ULONG columns;
|
||||
ULONG i;
|
||||
ULONG j;
|
||||
|
||||
PhMapDisplayIndexTreeNew(TreeNewHandle, &displayToId, NULL, &columns);
|
||||
rows = TreeNew_GetFlatNodeCount(TreeNewHandle);
|
||||
|
||||
PhInitializeStringBuilder(&stringBuilder, 0x100);
|
||||
|
||||
for (i = 0; i < rows; i++)
|
||||
{
|
||||
PH_TREENEW_GET_CELL_TEXT getCellText;
|
||||
|
||||
getCellText.Node = TreeNew_GetFlatNode(TreeNewHandle, i);
|
||||
assert(getCellText.Node);
|
||||
|
||||
if (!getCellText.Node->Selected)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < columns; j++)
|
||||
{
|
||||
getCellText.Id = displayToId[j];
|
||||
PhInitializeEmptyStringRef(&getCellText.Text);
|
||||
TreeNew_GetCellText(TreeNewHandle, &getCellText);
|
||||
|
||||
PhAppendStringBuilder(&stringBuilder, &getCellText.Text);
|
||||
PhAppendStringBuilder2(&stringBuilder, L", ");
|
||||
}
|
||||
|
||||
// Remove the trailing comma and space.
|
||||
if (stringBuilder.String->Length != 0)
|
||||
PhRemoveEndStringBuilder(&stringBuilder, 2);
|
||||
|
||||
PhAppendStringBuilder2(&stringBuilder, L"\r\n");
|
||||
}
|
||||
|
||||
PhFree(displayToId);
|
||||
|
||||
return PhFinalStringBuilderString(&stringBuilder);
|
||||
}
|
||||
|
||||
PPH_LIST PhGetGenericTreeNewLines(
|
||||
_In_ HWND TreeNewHandle,
|
||||
_In_ ULONG Mode
|
||||
)
|
||||
{
|
||||
PH_AUTO_POOL autoPool;
|
||||
PPH_LIST lines;
|
||||
ULONG rows;
|
||||
ULONG columns;
|
||||
ULONG numberOfNodes;
|
||||
PULONG displayToId;
|
||||
PWSTR *displayToText;
|
||||
PPH_STRING **table;
|
||||
ULONG i;
|
||||
ULONG j;
|
||||
|
||||
PhInitializeAutoPool(&autoPool);
|
||||
|
||||
numberOfNodes = TreeNew_GetFlatNodeCount(TreeNewHandle);
|
||||
|
||||
rows = numberOfNodes + 1;
|
||||
PhMapDisplayIndexTreeNew(TreeNewHandle, &displayToId, &displayToText, &columns);
|
||||
|
||||
PhaCreateTextTable(&table, rows, columns);
|
||||
|
||||
for (i = 0; i < columns; i++)
|
||||
table[0][i] = PhaCreateString(displayToText[i]);
|
||||
|
||||
for (i = 0; i < numberOfNodes; i++)
|
||||
{
|
||||
PPH_TREENEW_NODE node;
|
||||
|
||||
node = TreeNew_GetFlatNode(TreeNewHandle, i);
|
||||
|
||||
if (node)
|
||||
{
|
||||
for (j = 0; j < columns; j++)
|
||||
{
|
||||
PH_TREENEW_GET_CELL_TEXT getCellText;
|
||||
|
||||
getCellText.Node = node;
|
||||
getCellText.Id = displayToId[j];
|
||||
PhInitializeEmptyStringRef(&getCellText.Text);
|
||||
TreeNew_GetCellText(TreeNewHandle, &getCellText);
|
||||
|
||||
table[i + 1][j] = PhaCreateStringEx(getCellText.Text.Buffer, getCellText.Text.Length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < columns; j++)
|
||||
{
|
||||
table[i + 1][j] = PH_AUTO(PhReferenceEmptyString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PhFree(displayToText);
|
||||
PhFree(displayToId);
|
||||
|
||||
lines = PhaFormatTextTable(table, rows, columns, Mode);
|
||||
|
||||
PhDeleteAutoPool(&autoPool);
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
VOID PhaMapDisplayIndexListView(
|
||||
_In_ HWND ListViewHandle,
|
||||
_Out_writes_(Count) PULONG DisplayToId,
|
||||
_Out_writes_opt_(Count) PPH_STRING *DisplayToText,
|
||||
_In_ ULONG Count,
|
||||
_Out_ PULONG NumberOfColumns
|
||||
)
|
||||
{
|
||||
LVCOLUMN lvColumn;
|
||||
ULONG i;
|
||||
ULONG count;
|
||||
WCHAR buffer[128];
|
||||
|
||||
count = 0;
|
||||
lvColumn.mask = LVCF_ORDER | LVCF_TEXT;
|
||||
lvColumn.pszText = buffer;
|
||||
lvColumn.cchTextMax = sizeof(buffer) / sizeof(WCHAR);
|
||||
|
||||
for (i = 0; i < Count; i++)
|
||||
{
|
||||
if (ListView_GetColumn(ListViewHandle, i, &lvColumn))
|
||||
{
|
||||
ULONG displayIndex;
|
||||
|
||||
displayIndex = (ULONG)lvColumn.iOrder;
|
||||
assert(displayIndex < Count);
|
||||
DisplayToId[displayIndex] = i;
|
||||
|
||||
if (DisplayToText)
|
||||
DisplayToText[displayIndex] = PhaCreateString(buffer);
|
||||
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*NumberOfColumns = count;
|
||||
}
|
||||
|
||||
PPH_STRING PhaGetListViewItemText(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT Index,
|
||||
_In_ INT SubItemIndex
|
||||
)
|
||||
{
|
||||
PPH_STRING buffer;
|
||||
SIZE_T allocatedCount;
|
||||
SIZE_T count;
|
||||
LVITEM lvItem;
|
||||
|
||||
// Unfortunately LVM_GETITEMTEXT doesn't want to return the actual length of the text.
|
||||
// Keep doubling the buffer size until we get a return count that is strictly less than
|
||||
// the amount we allocated.
|
||||
|
||||
buffer = NULL;
|
||||
allocatedCount = 256;
|
||||
count = allocatedCount;
|
||||
|
||||
while (count >= allocatedCount)
|
||||
{
|
||||
if (buffer)
|
||||
PhDereferenceObject(buffer);
|
||||
|
||||
allocatedCount *= 2;
|
||||
buffer = PhCreateStringEx(NULL, allocatedCount * sizeof(WCHAR));
|
||||
buffer->Buffer[0] = 0;
|
||||
|
||||
lvItem.iSubItem = SubItemIndex;
|
||||
lvItem.cchTextMax = (INT)allocatedCount + 1;
|
||||
lvItem.pszText = buffer->Buffer;
|
||||
count = SendMessage(ListViewHandle, LVM_GETITEMTEXT, Index, (LPARAM)&lvItem);
|
||||
}
|
||||
|
||||
PhTrimToNullTerminatorString(buffer);
|
||||
PH_AUTO(buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
PPH_STRING PhGetListViewText(
|
||||
_In_ HWND ListViewHandle
|
||||
)
|
||||
{
|
||||
PH_AUTO_POOL autoPool;
|
||||
PH_STRING_BUILDER stringBuilder;
|
||||
ULONG displayToId[100];
|
||||
ULONG rows;
|
||||
ULONG columns;
|
||||
ULONG i;
|
||||
ULONG j;
|
||||
|
||||
PhInitializeAutoPool(&autoPool);
|
||||
|
||||
PhaMapDisplayIndexListView(ListViewHandle, displayToId, NULL, 100, &columns);
|
||||
rows = ListView_GetItemCount(ListViewHandle);
|
||||
|
||||
PhInitializeStringBuilder(&stringBuilder, 0x100);
|
||||
|
||||
for (i = 0; i < rows; i++)
|
||||
{
|
||||
if (!(ListView_GetItemState(ListViewHandle, i, LVIS_SELECTED) & LVIS_SELECTED))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < columns; j++)
|
||||
{
|
||||
PhAppendStringBuilder(&stringBuilder, &PhaGetListViewItemText(ListViewHandle, i, j)->sr);
|
||||
PhAppendStringBuilder2(&stringBuilder, L", ");
|
||||
}
|
||||
|
||||
// Remove the trailing comma and space.
|
||||
if (stringBuilder.String->Length != 0)
|
||||
PhRemoveEndStringBuilder(&stringBuilder, 2);
|
||||
|
||||
PhAppendStringBuilder2(&stringBuilder, L"\r\n");
|
||||
}
|
||||
|
||||
PhDeleteAutoPool(&autoPool);
|
||||
|
||||
return PhFinalStringBuilderString(&stringBuilder);
|
||||
}
|
||||
|
||||
PPH_LIST PhGetListViewLines(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ ULONG Mode
|
||||
)
|
||||
{
|
||||
PH_AUTO_POOL autoPool;
|
||||
PPH_LIST lines;
|
||||
ULONG rows;
|
||||
ULONG columns;
|
||||
ULONG displayToId[100];
|
||||
PPH_STRING displayToText[100];
|
||||
PPH_STRING **table;
|
||||
ULONG i;
|
||||
ULONG j;
|
||||
|
||||
PhInitializeAutoPool(&autoPool);
|
||||
|
||||
rows = ListView_GetItemCount(ListViewHandle) + 1; // +1 for column headers
|
||||
|
||||
// Create the display index/text to ID map.
|
||||
PhaMapDisplayIndexListView(ListViewHandle, displayToId, displayToText, 100, &columns);
|
||||
|
||||
PhaCreateTextTable(&table, rows, columns);
|
||||
|
||||
// Populate the first row with the column headers.
|
||||
for (i = 0; i < columns; i++)
|
||||
table[0][i] = displayToText[i];
|
||||
|
||||
// Populate the other rows with text.
|
||||
for (i = 1; i < rows; i++)
|
||||
{
|
||||
for (j = 0; j < columns; j++)
|
||||
{
|
||||
// Important: use this to bypass extlv's hooking.
|
||||
// extlv only hooks LVM_GETITEM, not LVM_GETITEMTEXT.
|
||||
table[i][j] = PhaGetListViewItemText(ListViewHandle, i - 1, j);
|
||||
}
|
||||
}
|
||||
|
||||
lines = PhaFormatTextTable(table, rows, columns, Mode);
|
||||
|
||||
PhDeleteAutoPool(&autoPool);
|
||||
|
||||
return lines;
|
||||
}
|
||||
219
phlib/data.c
Normal file
219
phlib/data.c
Normal file
@@ -0,0 +1,219 @@
|
||||
#include <ph.h>
|
||||
#include <phdata.h>
|
||||
|
||||
// SIDs
|
||||
|
||||
SID PhSeNobodySid = { SID_REVISION, 1, SECURITY_NULL_SID_AUTHORITY, { SECURITY_NULL_RID } };
|
||||
|
||||
SID PhSeEveryoneSid = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, { SECURITY_WORLD_RID } };
|
||||
|
||||
SID PhSeLocalSid = { SID_REVISION, 1, SECURITY_LOCAL_SID_AUTHORITY, { SECURITY_LOCAL_RID } };
|
||||
|
||||
SID PhSeCreatorOwnerSid = { SID_REVISION, 1, SECURITY_CREATOR_SID_AUTHORITY, { SECURITY_CREATOR_OWNER_RID } };
|
||||
SID PhSeCreatorGroupSid = { SID_REVISION, 1, SECURITY_CREATOR_SID_AUTHORITY, { SECURITY_CREATOR_GROUP_RID } };
|
||||
|
||||
SID PhSeDialupSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_DIALUP_RID } };
|
||||
SID PhSeNetworkSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_NETWORK_RID } };
|
||||
SID PhSeBatchSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_BATCH_RID } };
|
||||
SID PhSeInteractiveSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_INTERACTIVE_RID } };
|
||||
SID PhSeServiceSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_SERVICE_RID } };
|
||||
SID PhSeAnonymousLogonSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_ANONYMOUS_LOGON_RID } };
|
||||
SID PhSeProxySid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_PROXY_RID } };
|
||||
SID PhSeAuthenticatedUserSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_AUTHENTICATED_USER_RID } };
|
||||
SID PhSeRestrictedCodeSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_RESTRICTED_CODE_RID } };
|
||||
SID PhSeTerminalServerUserSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_TERMINAL_SERVER_RID } };
|
||||
SID PhSeRemoteInteractiveLogonSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_REMOTE_LOGON_RID } };
|
||||
SID PhSeLocalSystemSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_LOCAL_SYSTEM_RID } };
|
||||
SID PhSeLocalServiceSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_LOCAL_SERVICE_RID } };
|
||||
SID PhSeNetworkServiceSid = { SID_REVISION, 1, SECURITY_NT_AUTHORITY, { SECURITY_NETWORK_SERVICE_RID } };
|
||||
|
||||
// Unicode
|
||||
|
||||
PH_STRINGREF PhUnicodeByteOrderMark = PH_STRINGREF_INIT(L"\ufeff");
|
||||
|
||||
// Characters
|
||||
|
||||
DECLSPEC_SELECTANY
|
||||
BOOLEAN PhCharIsPrintable[256] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, /* 0 - 15 */ // TAB, LF and CR are printable
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 31 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ' ' - '/' */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* '0' - '9' */
|
||||
1, 1, 1, 1, 1, 1, 1, /* ':' - '@' */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 'A' - 'Z' */
|
||||
1, 1, 1, 1, 1, 1, /* '[' - '`' */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 'a' - 'z' */
|
||||
1, 1, 1, 1, 0, /* '{' - 127 */ // DEL is not printable
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128 - 143 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144 - 159 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 160 - 175 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 176 - 191 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192 - 207 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 208 - 223 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 224 - 239 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 240 - 255 */
|
||||
};
|
||||
|
||||
DECLSPEC_SELECTANY
|
||||
ULONG PhCharToInteger[256] =
|
||||
{
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0 - 15 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 16 - 31 */
|
||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, /* ' ' - '/' */
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* '0' - '9' */
|
||||
52, 53, 54, 55, 56, 57, 58, /* ':' - '@' */
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, /* 'A' - 'Z' */
|
||||
59, 60, 61, 62, 63, 64, /* '[' - '`' */
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, /* 'a' - 'z' */
|
||||
65, 66, 67, 68, -1, /* '{' - 127 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 128 - 143 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144 - 159 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160 - 175 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176 - 191 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192 - 207 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 208 - 223 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224 - 239 */
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 240 - 255 */
|
||||
};
|
||||
|
||||
DECLSPEC_SELECTANY
|
||||
CHAR PhIntegerToChar[69] =
|
||||
"0123456789" /* 0 - 9 */
|
||||
"abcdefghijklmnopqrstuvwxyz" /* 10 - 35 */
|
||||
" !\"#$%&'()*+,-./" /* 36 - 51 */
|
||||
":;<=>?@" /* 52 - 58 */
|
||||
"[\\]^_`" /* 59 - 64 */
|
||||
"{|}~" /* 65 - 68 */
|
||||
;
|
||||
|
||||
DECLSPEC_SELECTANY
|
||||
CHAR PhIntegerToCharUpper[69] =
|
||||
"0123456789" /* 0 - 9 */
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 10 - 35 */
|
||||
" !\"#$%&'()*+,-./" /* 36 - 51 */
|
||||
":;<=>?@" /* 52 - 58 */
|
||||
"[\\]^_`" /* 59 - 64 */
|
||||
"{|}~" /* 65 - 68 */
|
||||
;
|
||||
|
||||
// CRC32 (IEEE 802.3)
|
||||
|
||||
DECLSPEC_SELECTANY
|
||||
ULONG PhCrc32Table[256] =
|
||||
{
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
// Enums
|
||||
|
||||
DECLSPEC_SELECTANY
|
||||
WCHAR *PhIoPriorityHintNames[MaxIoPriorityTypes] =
|
||||
{
|
||||
L"Very low",
|
||||
L"Low",
|
||||
L"Normal",
|
||||
L"High",
|
||||
L"Critical"
|
||||
};
|
||||
|
||||
DECLSPEC_SELECTANY
|
||||
WCHAR *PhPagePriorityNames[MEMORY_PRIORITY_NORMAL + 1] =
|
||||
{
|
||||
L"Lowest",
|
||||
L"Very low",
|
||||
L"Low",
|
||||
L"Medium",
|
||||
L"Below normal",
|
||||
L"Normal"
|
||||
};
|
||||
|
||||
DECLSPEC_SELECTANY
|
||||
WCHAR *PhKThreadStateNames[MaximumThreadState] =
|
||||
{
|
||||
L"Initialized",
|
||||
L"Ready",
|
||||
L"Running",
|
||||
L"Standby",
|
||||
L"Terminated",
|
||||
L"Waiting",
|
||||
L"Transition",
|
||||
L"DeferredReady",
|
||||
L"GateWait",
|
||||
L"WaitingForProcessInSwap"
|
||||
};
|
||||
|
||||
DECLSPEC_SELECTANY
|
||||
WCHAR *PhKWaitReasonNames[MaximumWaitReason] =
|
||||
{
|
||||
L"Executive",
|
||||
L"FreePage",
|
||||
L"PageIn",
|
||||
L"PoolAllocation",
|
||||
L"DelayExecution",
|
||||
L"Suspended",
|
||||
L"UserRequest",
|
||||
L"WrExecutive",
|
||||
L"WrFreePage",
|
||||
L"WrPageIn",
|
||||
L"WrPoolAllocation",
|
||||
L"WrDelayExecution",
|
||||
L"WrSuspended",
|
||||
L"WrUserRequest",
|
||||
L"WrEventPair",
|
||||
L"WrQueue",
|
||||
L"WrLpcReceive",
|
||||
L"WrLpcReply",
|
||||
L"WrVirtualMemory",
|
||||
L"WrPageOut",
|
||||
L"WrRendezvous",
|
||||
L"WrKeyedEvent",
|
||||
L"WrTerminated",
|
||||
L"WrProcessInSwap",
|
||||
L"WrCpuRateControl",
|
||||
L"WrCalloutStack",
|
||||
L"WrKernel",
|
||||
L"WrResource",
|
||||
L"WrPushLock",
|
||||
L"WrMutex",
|
||||
L"WrQuantumEnd",
|
||||
L"WrDispatchInt",
|
||||
L"WrPreempted",
|
||||
L"WrYieldExecution",
|
||||
L"WrFastMutex",
|
||||
L"WrGuardedMutex",
|
||||
L"WrRundown",
|
||||
L"WrAlertByThreadId",
|
||||
L"WrDeferredPreempt"
|
||||
};
|
||||
249
phlib/dspick.c
Normal file
249
phlib/dspick.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* DS object picker wrapper
|
||||
*
|
||||
* Copyright (C) 2010 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <guisup.h>
|
||||
#include <lsasup.h>
|
||||
#include <dspick.h>
|
||||
#include <ole2.h>
|
||||
#define CINTERFACE
|
||||
#define COBJMACROS
|
||||
#include <objsel.h>
|
||||
|
||||
#define IDataObject_AddRef(This) ((This)->lpVtbl->AddRef(This))
|
||||
#define IDataObject_Release(This) ((This)->lpVtbl->Release(This))
|
||||
#define IDataObject_GetData(This, pformatetcIn, pmedium) ((This)->lpVtbl->GetData(This, pformatetcIn, pmedium))
|
||||
|
||||
#define IDsObjectPicker_QueryInterface(This, riid, ppvObject) ((This)->lpVtbl->QueryInterface(This, riid, ppvObject))
|
||||
#define IDsObjectPicker_AddRef(This) ((This)->lpVtbl->AddRef(This))
|
||||
#define IDsObjectPicker_Release(This) ((This)->lpVtbl->Release(This))
|
||||
#define IDsObjectPicker_Initialize(This, pInitInfo) ((This)->lpVtbl->Initialize(This, pInitInfo))
|
||||
#define IDsObjectPicker_InvokeDialog(This, hwndParent, ppdoSelections) ((This)->lpVtbl->InvokeDialog(This, hwndParent, ppdoSelections))
|
||||
|
||||
IDsObjectPicker *PhpCreateDsObjectPicker(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
static CLSID CLSID_DsObjectPicker_I = { 0x17d6ccd8, 0x3b7b, 0x11d2, { 0xb9, 0xe0, 0x00, 0xc0, 0x4f, 0xd8, 0xdb, 0xf7 } };
|
||||
static IID IID_IDsObjectPicker_I = { 0x0c87e64e, 0x3b7a, 0x11d2, { 0xb9, 0xe0, 0x00, 0xc0, 0x4f, 0xd8, 0xdb, 0xf7 } };
|
||||
|
||||
IDsObjectPicker *picker;
|
||||
|
||||
if (SUCCEEDED(CoCreateInstance(
|
||||
&CLSID_DsObjectPicker_I,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
&IID_IDsObjectPicker_I,
|
||||
&picker
|
||||
)))
|
||||
{
|
||||
return picker;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
VOID PhFreeDsObjectPickerDialog(
|
||||
_In_ PVOID PickerDialog
|
||||
)
|
||||
{
|
||||
IDsObjectPicker_Release((IDsObjectPicker *)PickerDialog);
|
||||
}
|
||||
|
||||
PVOID PhCreateDsObjectPickerDialog(
|
||||
_In_ ULONG Flags
|
||||
)
|
||||
{
|
||||
IDsObjectPicker *picker;
|
||||
DSOP_INIT_INFO initInfo;
|
||||
DSOP_SCOPE_INIT_INFO scopeInit[1];
|
||||
|
||||
picker = PhpCreateDsObjectPicker();
|
||||
|
||||
if (!picker)
|
||||
return NULL;
|
||||
|
||||
memset(scopeInit, 0, sizeof(scopeInit));
|
||||
|
||||
scopeInit[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
|
||||
scopeInit[0].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER;
|
||||
scopeInit[0].flScope =
|
||||
DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT |
|
||||
DSOP_SCOPE_FLAG_WANT_SID_PATH |
|
||||
DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS |
|
||||
DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS;
|
||||
scopeInit[0].FilterFlags.Uplevel.flBothModes =
|
||||
DSOP_FILTER_INCLUDE_ADVANCED_VIEW |
|
||||
DSOP_FILTER_USERS |
|
||||
DSOP_FILTER_BUILTIN_GROUPS |
|
||||
DSOP_FILTER_WELL_KNOWN_PRINCIPALS;
|
||||
scopeInit[0].FilterFlags.flDownlevel =
|
||||
DSOP_DOWNLEVEL_FILTER_USERS |
|
||||
DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS |
|
||||
DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS |
|
||||
DSOP_DOWNLEVEL_FILTER_ALL_WELLKNOWN_SIDS;
|
||||
|
||||
memset(&initInfo, 0, sizeof(DSOP_INIT_INFO));
|
||||
initInfo.cbSize = sizeof(DSOP_INIT_INFO);
|
||||
initInfo.pwzTargetComputer = NULL;
|
||||
initInfo.cDsScopeInfos = 1;
|
||||
initInfo.aDsScopeInfos = scopeInit;
|
||||
initInfo.flOptions = DSOP_FLAG_SKIP_TARGET_COMPUTER_DC_CHECK;
|
||||
|
||||
if (Flags & PH_DSPICK_MULTISELECT)
|
||||
initInfo.flOptions |= DSOP_FLAG_MULTISELECT;
|
||||
|
||||
if (!SUCCEEDED(IDsObjectPicker_Initialize(picker, &initInfo)))
|
||||
{
|
||||
IDsObjectPicker_Release(picker);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return picker;
|
||||
}
|
||||
|
||||
PDS_SELECTION_LIST PhpGetDsSelectionList(
|
||||
_In_ IDataObject *Selections
|
||||
)
|
||||
{
|
||||
FORMATETC format;
|
||||
STGMEDIUM medium;
|
||||
|
||||
format.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(L"CFSTR_DSOP_DS_SELECTION_LIST");
|
||||
format.ptd = NULL;
|
||||
format.dwAspect = -1;
|
||||
format.lindex = -1;
|
||||
format.tymed = TYMED_HGLOBAL;
|
||||
|
||||
if (SUCCEEDED(IDataObject_GetData(Selections, &format, &medium)))
|
||||
{
|
||||
if (medium.tymed != TYMED_HGLOBAL)
|
||||
return NULL;
|
||||
|
||||
return (PDS_SELECTION_LIST)GlobalLock(medium.hGlobal);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN PhShowDsObjectPickerDialog(
|
||||
_In_ HWND hWnd,
|
||||
_In_ PVOID PickerDialog,
|
||||
_Out_ PPH_DSPICK_OBJECTS *Objects
|
||||
)
|
||||
{
|
||||
IDsObjectPicker *picker;
|
||||
IDataObject *dataObject;
|
||||
PDS_SELECTION_LIST selections;
|
||||
PPH_DSPICK_OBJECTS objects;
|
||||
ULONG i;
|
||||
|
||||
picker = (IDsObjectPicker *)PickerDialog;
|
||||
|
||||
if (!SUCCEEDED(IDsObjectPicker_InvokeDialog(picker, hWnd, &dataObject)))
|
||||
return FALSE;
|
||||
|
||||
if (!dataObject)
|
||||
return FALSE;
|
||||
|
||||
selections = PhpGetDsSelectionList(dataObject);
|
||||
IDataObject_Release(dataObject);
|
||||
|
||||
if (!selections)
|
||||
return FALSE;
|
||||
|
||||
objects = PhAllocate(
|
||||
FIELD_OFFSET(PH_DSPICK_OBJECTS, Objects) +
|
||||
selections->cItems * sizeof(PH_DSPICK_OBJECT)
|
||||
);
|
||||
|
||||
objects->NumberOfObjects = selections->cItems;
|
||||
|
||||
for (i = 0; i < selections->cItems; i++)
|
||||
{
|
||||
PDS_SELECTION selection;
|
||||
PSID sid;
|
||||
PH_STRINGREF path;
|
||||
PH_STRINGREF prefix;
|
||||
|
||||
selection = &selections->aDsSelection[i];
|
||||
|
||||
objects->Objects[i].Name = PhCreateString(selection->pwzName);
|
||||
objects->Objects[i].Sid = NULL;
|
||||
|
||||
if (selection->pwzADsPath && selection->pwzADsPath[0] != 0)
|
||||
{
|
||||
PhInitializeStringRef(&path, selection->pwzADsPath);
|
||||
PhInitializeStringRef(&prefix, L"LDAP://<SID=");
|
||||
|
||||
if (PhStartsWithStringRef(&path, &prefix, TRUE))
|
||||
{
|
||||
PhSkipStringRef(&path, prefix.Length);
|
||||
path.Length -= sizeof(WCHAR); // Ignore ">" at end
|
||||
|
||||
sid = PhAllocate(path.Length / sizeof(WCHAR) / 2);
|
||||
|
||||
if (PhHexStringToBuffer(&path, (PUCHAR)sid))
|
||||
{
|
||||
if (RtlValidSid(sid))
|
||||
objects->Objects[i].Sid = sid;
|
||||
else
|
||||
PhFree(sid);
|
||||
}
|
||||
else
|
||||
{
|
||||
PhFree(sid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to get the SID.
|
||||
PhLookupName(&objects->Objects[i].Name->sr, &objects->Objects[i].Sid, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
*Objects = objects;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID PhFreeDsObjectPickerObjects(
|
||||
_In_ PPH_DSPICK_OBJECTS Objects
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < Objects->NumberOfObjects; i++)
|
||||
{
|
||||
PhDereferenceObject(Objects->Objects[i].Name);
|
||||
|
||||
if (Objects->Objects[i].Sid)
|
||||
PhFree(Objects->Objects[i].Sid);
|
||||
}
|
||||
|
||||
PhFree(Objects);
|
||||
}
|
||||
856
phlib/emenu.c
Normal file
856
phlib/emenu.c
Normal file
@@ -0,0 +1,856 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* extended menus
|
||||
*
|
||||
* Copyright (C) 2010-2011 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <guisup.h>
|
||||
#include <emenu.h>
|
||||
|
||||
static const PH_FLAG_MAPPING EMenuTypeMappings[] =
|
||||
{
|
||||
{ PH_EMENU_MENUBARBREAK, MFT_MENUBARBREAK },
|
||||
{ PH_EMENU_MENUBREAK, MFT_MENUBREAK },
|
||||
{ PH_EMENU_RADIOCHECK, MFT_RADIOCHECK }
|
||||
};
|
||||
|
||||
static const PH_FLAG_MAPPING EMenuStateMappings[] =
|
||||
{
|
||||
{ PH_EMENU_CHECKED, MFS_CHECKED },
|
||||
{ PH_EMENU_DEFAULT, MFS_DEFAULT },
|
||||
{ PH_EMENU_DISABLED, MFS_DISABLED },
|
||||
{ PH_EMENU_HIGHLIGHT, MFS_HILITE }
|
||||
};
|
||||
|
||||
PPH_EMENU_ITEM PhAllocateEMenuItem(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PPH_EMENU_ITEM item;
|
||||
|
||||
item = PhAllocate(sizeof(PH_EMENU_ITEM));
|
||||
memset(item, 0, sizeof(PH_EMENU_ITEM));
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a menu item.
|
||||
*
|
||||
* \param Flags A combination of the following:
|
||||
* \li \c PH_EMENU_DISABLED The menu item is greyed and cannot be selected.
|
||||
* \li \c PH_EMENU_CHECKED A check mark is displayed.
|
||||
* \li \c PH_EMENU_HIGHLIGHT The menu item is highlighted.
|
||||
* \li \c PH_EMENU_MENUBARBREAK Places the menu item in a new column, separated by a vertical line.
|
||||
* \li \c PH_EMENU_MENUBREAK Places the menu item in a new column, with no vertical line.
|
||||
* \li \c PH_EMENU_DEFAULT The menu item is displayed as the default item. This causes the text to
|
||||
* be bolded.
|
||||
* \li \c PH_EMENU_RADIOCHECK Uses a radio-button mark instead of a check mark.
|
||||
* \param Id A unique identifier for the menu item.
|
||||
* \param Text The text displayed for the menu item.
|
||||
* \param Bitmap A bitmap image for the menu item.
|
||||
* \param Context A user-defined value.
|
||||
*/
|
||||
PPH_EMENU_ITEM PhCreateEMenuItem(
|
||||
_In_ ULONG Flags,
|
||||
_In_ ULONG Id,
|
||||
_In_ PWSTR Text,
|
||||
_In_opt_ HBITMAP Bitmap,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PPH_EMENU_ITEM item;
|
||||
|
||||
item = PhAllocateEMenuItem();
|
||||
|
||||
item->Flags = Flags;
|
||||
item->Id = Id;
|
||||
item->Text = Text;
|
||||
item->Bitmap = Bitmap;
|
||||
|
||||
item->Context = Context;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees resources used by a menu item and its children.
|
||||
*
|
||||
* \param Item The menu item.
|
||||
*
|
||||
* \remarks The menu item is NOT automatically removed from its parent. It is safe to call this
|
||||
* function while enumerating menu items.
|
||||
*/
|
||||
VOID PhpDestroyEMenuItem(
|
||||
_In_ PPH_EMENU_ITEM Item
|
||||
)
|
||||
{
|
||||
if (Item->DeleteFunction)
|
||||
Item->DeleteFunction(Item);
|
||||
|
||||
if ((Item->Flags & PH_EMENU_TEXT_OWNED) && Item->Text)
|
||||
PhFree(Item->Text);
|
||||
if ((Item->Flags & PH_EMENU_BITMAP_OWNED) && Item->Bitmap)
|
||||
DeleteObject(Item->Bitmap);
|
||||
|
||||
if (Item->Items)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < Item->Items->Count; i++)
|
||||
{
|
||||
PhpDestroyEMenuItem(Item->Items->Items[i]);
|
||||
}
|
||||
|
||||
PhDereferenceObject(Item->Items);
|
||||
}
|
||||
|
||||
PhFree(Item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees resources used by a menu item and its children.
|
||||
*
|
||||
* \param Item The menu item.
|
||||
*
|
||||
* \remarks The menu item is automatically removed from its parent.
|
||||
*/
|
||||
VOID PhDestroyEMenuItem(
|
||||
_In_ PPH_EMENU_ITEM Item
|
||||
)
|
||||
{
|
||||
// Remove the item from its parent, if it has one.
|
||||
if (Item->Parent)
|
||||
PhRemoveEMenuItem(NULL, Item, -1);
|
||||
|
||||
PhpDestroyEMenuItem(Item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a child menu item.
|
||||
*
|
||||
* \param Item The parent menu item.
|
||||
* \param Flags A combination of the following:
|
||||
* \li \c PH_EMENU_FIND_DESCEND Searches recursively within child menu items.
|
||||
* \li \c PH_EMENU_FIND_STARTSWITH Performs a partial text search instead of an exact search.
|
||||
* \li \c PH_EMENU_FIND_LITERAL Performs a literal search instead of ignoring prefix characters
|
||||
* (ampersands).
|
||||
* \param Text The text of the menu item to find. If NULL, the text is ignored.
|
||||
* \param Id The identifier of the menu item to find. If 0, the identifier is ignored.
|
||||
*
|
||||
* \return The found menu item, or NULL if the menu item could not be found.
|
||||
*/
|
||||
PPH_EMENU_ITEM PhFindEMenuItem(
|
||||
_In_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ PWSTR Text,
|
||||
_In_opt_ ULONG Id
|
||||
)
|
||||
{
|
||||
return PhFindEMenuItemEx(Item, Flags, Text, Id, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a child menu item.
|
||||
*
|
||||
* \param Item The parent menu item.
|
||||
* \param Flags A combination of the following:
|
||||
* \li \c PH_EMENU_FIND_DESCEND Searches recursively within child menu items.
|
||||
* \li \c PH_EMENU_FIND_STARTSWITH Performs a partial text search instead of an exact search.
|
||||
* \li \c PH_EMENU_FIND_LITERAL Performs a literal search instead of ignoring prefix characters
|
||||
* (ampersands).
|
||||
* \param Text The text of the menu item to find. If NULL, the text is ignored.
|
||||
* \param Id The identifier of the menu item to find. If 0, the identifier is ignored.
|
||||
* \param FoundParent A variable which receives the parent of the found menu item.
|
||||
* \param FoundIndex A variable which receives the index of the found menu item.
|
||||
*
|
||||
* \return The found menu item, or NULL if the menu item could not be found.
|
||||
*/
|
||||
PPH_EMENU_ITEM PhFindEMenuItemEx(
|
||||
_In_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ PWSTR Text,
|
||||
_In_opt_ ULONG Id,
|
||||
_Out_opt_ PPH_EMENU_ITEM *FoundParent,
|
||||
_Out_opt_ PULONG FoundIndex
|
||||
)
|
||||
{
|
||||
PH_STRINGREF searchText;
|
||||
ULONG i;
|
||||
PPH_EMENU_ITEM item;
|
||||
|
||||
if (!Item->Items)
|
||||
return NULL;
|
||||
|
||||
if (Text && (Flags & PH_EMENU_FIND_LITERAL))
|
||||
PhInitializeStringRef(&searchText, Text);
|
||||
|
||||
for (i = 0; i < Item->Items->Count; i++)
|
||||
{
|
||||
item = Item->Items->Items[i];
|
||||
|
||||
if (Text)
|
||||
{
|
||||
if (Flags & PH_EMENU_FIND_LITERAL)
|
||||
{
|
||||
PH_STRINGREF text;
|
||||
|
||||
PhInitializeStringRef(&text, item->Text);
|
||||
|
||||
if (Flags & PH_EMENU_FIND_STARTSWITH)
|
||||
{
|
||||
if (PhStartsWithStringRef(&text, &searchText, TRUE))
|
||||
goto FoundItemHere;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PhEqualStringRef(&text, &searchText, TRUE))
|
||||
goto FoundItemHere;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PhCompareUnicodeStringZIgnoreMenuPrefix(Text, item->Text,
|
||||
TRUE, !!(Flags & PH_EMENU_FIND_STARTSWITH)) == 0)
|
||||
goto FoundItemHere;
|
||||
}
|
||||
}
|
||||
|
||||
if (Id && item->Id == Id)
|
||||
goto FoundItemHere;
|
||||
|
||||
if (Flags & PH_EMENU_FIND_DESCEND)
|
||||
{
|
||||
PPH_EMENU_ITEM foundItem;
|
||||
PPH_EMENU_ITEM foundParent;
|
||||
ULONG foundIndex;
|
||||
|
||||
foundItem = PhFindEMenuItemEx(item, Flags, Text, Id, &foundParent, &foundIndex);
|
||||
|
||||
if (foundItem)
|
||||
{
|
||||
if (FoundParent)
|
||||
*FoundParent = foundParent;
|
||||
if (FoundIndex)
|
||||
*FoundIndex = foundIndex;
|
||||
|
||||
return foundItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
FoundItemHere:
|
||||
if (FoundParent)
|
||||
*FoundParent = Item;
|
||||
if (FoundIndex)
|
||||
*FoundIndex = i;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the index of a menu item.
|
||||
*
|
||||
* \param Parent The parent menu item.
|
||||
* \param Item The child menu item.
|
||||
*
|
||||
* \return The index of the menu item, or -1 if the menu item was not found in the parent menu item.
|
||||
*/
|
||||
ULONG PhIndexOfEMenuItem(
|
||||
_In_ PPH_EMENU_ITEM Parent,
|
||||
_In_ PPH_EMENU_ITEM Item
|
||||
)
|
||||
{
|
||||
if (!Parent->Items)
|
||||
return -1;
|
||||
|
||||
return PhFindItemList(Parent->Items, Item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a menu item into a parent menu item.
|
||||
*
|
||||
* \param Parent The parent menu item.
|
||||
* \param Item The menu item to insert.
|
||||
* \param Index The index at which to insert the menu item. If the index is too large, the menu item
|
||||
* is inserted at the last position.
|
||||
*/
|
||||
VOID PhInsertEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM Parent,
|
||||
_Inout_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Index
|
||||
)
|
||||
{
|
||||
// Remove the item from its old parent if it has one.
|
||||
if (Item->Parent)
|
||||
PhRemoveEMenuItem(Item->Parent, Item, 0);
|
||||
|
||||
if (!Parent->Items)
|
||||
Parent->Items = PhCreateList(16);
|
||||
|
||||
if (Index > Parent->Items->Count)
|
||||
Index = Parent->Items->Count;
|
||||
|
||||
if (Index == -1)
|
||||
PhAddItemList(Parent->Items, Item);
|
||||
else
|
||||
PhInsertItemList(Parent->Items, Index, Item);
|
||||
|
||||
Item->Parent = Parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a menu item from its parent.
|
||||
*
|
||||
* \param Parent The parent menu item. If \a Item is NULL, this parameter must be specified.
|
||||
* \param Item The child menu item. This may be NULL if \a Index is specified.
|
||||
* \param Index The index of the menu item to remove. If \a Item is specified, this parameter is
|
||||
* ignored.
|
||||
*/
|
||||
BOOLEAN PhRemoveEMenuItem(
|
||||
_Inout_opt_ PPH_EMENU_ITEM Parent,
|
||||
_In_opt_ PPH_EMENU_ITEM Item,
|
||||
_In_opt_ ULONG Index
|
||||
)
|
||||
{
|
||||
if (Item)
|
||||
{
|
||||
if (!Parent)
|
||||
Parent = Item->Parent;
|
||||
if (!Parent->Items)
|
||||
return FALSE;
|
||||
|
||||
Index = PhFindItemList(Parent->Items, Item);
|
||||
|
||||
if (Index == -1)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Parent)
|
||||
return FALSE;
|
||||
if (!Parent->Items)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Item = Parent->Items->Items[Index];
|
||||
PhRemoveItemList(Parent->Items, Index);
|
||||
Item->Parent = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all children from a menu item.
|
||||
*
|
||||
* \param Parent The parent menu item.
|
||||
*/
|
||||
VOID PhRemoveAllEMenuItems(
|
||||
_Inout_ PPH_EMENU_ITEM Parent
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (!Parent->Items)
|
||||
return;
|
||||
|
||||
for (i = 0; i < Parent->Items->Count; i++)
|
||||
{
|
||||
PhpDestroyEMenuItem(Parent->Items->Items[i]);
|
||||
}
|
||||
|
||||
PhClearList(Parent->Items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a root menu.
|
||||
*/
|
||||
PPH_EMENU PhCreateEMenu(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PPH_EMENU menu;
|
||||
|
||||
menu = PhAllocate(sizeof(PH_EMENU));
|
||||
memset(menu, 0, sizeof(PH_EMENU));
|
||||
menu->Items = PhCreateList(16);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees resources used by a root menu and its children.
|
||||
*
|
||||
* \param Menu A root menu.
|
||||
*/
|
||||
VOID PhDestroyEMenu(
|
||||
_In_ PPH_EMENU Menu
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < Menu->Items->Count; i++)
|
||||
{
|
||||
PhpDestroyEMenuItem(Menu->Items->Items[i]);
|
||||
}
|
||||
|
||||
PhDereferenceObject(Menu->Items);
|
||||
PhFree(Menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a data structure containing additional information resulting from a call to
|
||||
* PhEMenuToHMenu().
|
||||
*/
|
||||
VOID PhInitializeEMenuData(
|
||||
_Out_ PPH_EMENU_DATA Data
|
||||
)
|
||||
{
|
||||
Data->IdToItem = PhCreateList(16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees resources used by a data structure initialized by PhInitializeEMenuData().
|
||||
*/
|
||||
VOID PhDeleteEMenuData(
|
||||
_Inout_ PPH_EMENU_DATA Data
|
||||
)
|
||||
{
|
||||
PhDereferenceObject(Data->IdToItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an EMENU to a Windows menu object.
|
||||
*
|
||||
* \param Menu The menu item to convert.
|
||||
* \param Flags A combination of the following:
|
||||
* \li \c PH_EMENU_CONVERT_ID Automatically assigns a unique identifier to each converted menu item.
|
||||
* The resulting mappings are placed in \a Data.
|
||||
* \param Data Additional data resulting from the conversion. The data structure must be initialized
|
||||
* by PhInitializeEMenuData() prior to calling this function.
|
||||
*
|
||||
* \return A menu handle. The menu object must be destroyed using DestroyMenu() when it is no longer
|
||||
* needed.
|
||||
*/
|
||||
HMENU PhEMenuToHMenu(
|
||||
_In_ PPH_EMENU_ITEM Menu,
|
||||
_In_ ULONG Flags,
|
||||
_Inout_opt_ PPH_EMENU_DATA Data
|
||||
)
|
||||
{
|
||||
HMENU menuHandle;
|
||||
|
||||
menuHandle = CreatePopupMenu();
|
||||
|
||||
if (!menuHandle)
|
||||
return NULL;
|
||||
|
||||
PhEMenuToHMenu2(menuHandle, Menu, Flags, Data);
|
||||
|
||||
if (!(Menu->Flags & PH_EMENU_SEPARATECHECKSPACE))
|
||||
{
|
||||
MENUINFO menuInfo;
|
||||
|
||||
memset(&menuInfo, 0, sizeof(MENUINFO));
|
||||
menuInfo.cbSize = sizeof(MENUINFO);
|
||||
menuInfo.fMask = MIM_STYLE;
|
||||
menuInfo.dwStyle = MNS_CHECKORBMP;
|
||||
SetMenuInfo(menuHandle, &menuInfo);
|
||||
}
|
||||
|
||||
return menuHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an EMENU to a Windows menu object.
|
||||
*
|
||||
* \param MenuHandle A handle to a Windows menu object.
|
||||
* \param Menu The menu item to convert. The items are appended to \a MenuHandle.
|
||||
* \param Flags A combination of the following:
|
||||
* \li \c PH_EMENU_CONVERT_ID Automatically assigns a unique identifier to each converted menu item.
|
||||
* The resulting mappings are placed in \a Data.
|
||||
* \param Data Additional data resulting from the conversion. The data structure must be initialized
|
||||
* by PhInitializeEMenuData() prior to calling this function.
|
||||
*/
|
||||
VOID PhEMenuToHMenu2(
|
||||
_In_ HMENU MenuHandle,
|
||||
_In_ PPH_EMENU_ITEM Menu,
|
||||
_In_ ULONG Flags,
|
||||
_Inout_opt_ PPH_EMENU_DATA Data
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
PPH_EMENU_ITEM item;
|
||||
MENUITEMINFO menuItemInfo;
|
||||
|
||||
for (i = 0; i < Menu->Items->Count; i++)
|
||||
{
|
||||
item = Menu->Items->Items[i];
|
||||
|
||||
memset(&menuItemInfo, 0, sizeof(MENUITEMINFO));
|
||||
menuItemInfo.cbSize = sizeof(MENUITEMINFO);
|
||||
|
||||
// Type
|
||||
|
||||
menuItemInfo.fMask = MIIM_FTYPE | MIIM_STATE;
|
||||
|
||||
if (item->Flags & PH_EMENU_SEPARATOR)
|
||||
{
|
||||
menuItemInfo.fType = MFT_SEPARATOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
menuItemInfo.fType = MFT_STRING;
|
||||
menuItemInfo.fMask |= MIIM_STRING;
|
||||
menuItemInfo.dwTypeData = item->Text;
|
||||
}
|
||||
|
||||
PhMapFlags1(
|
||||
&menuItemInfo.fType,
|
||||
item->Flags,
|
||||
EMenuTypeMappings,
|
||||
sizeof(EMenuTypeMappings) / sizeof(PH_FLAG_MAPPING)
|
||||
);
|
||||
|
||||
// Bitmap
|
||||
|
||||
if (item->Bitmap)
|
||||
{
|
||||
menuItemInfo.fMask |= MIIM_BITMAP;
|
||||
menuItemInfo.hbmpItem = item->Bitmap;
|
||||
}
|
||||
|
||||
// Id
|
||||
|
||||
if (Flags & PH_EMENU_CONVERT_ID)
|
||||
{
|
||||
ULONG id;
|
||||
|
||||
if (Data)
|
||||
{
|
||||
PhAddItemList(Data->IdToItem, item);
|
||||
id = Data->IdToItem->Count;
|
||||
|
||||
menuItemInfo.fMask |= MIIM_ID;
|
||||
menuItemInfo.wID = id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item->Id)
|
||||
{
|
||||
menuItemInfo.fMask |= MIIM_ID;
|
||||
menuItemInfo.wID = item->Id;
|
||||
}
|
||||
}
|
||||
|
||||
// State
|
||||
|
||||
PhMapFlags1(
|
||||
&menuItemInfo.fState,
|
||||
item->Flags,
|
||||
EMenuStateMappings,
|
||||
sizeof(EMenuStateMappings) / sizeof(PH_FLAG_MAPPING)
|
||||
);
|
||||
|
||||
// Context
|
||||
|
||||
menuItemInfo.fMask |= MIIM_DATA;
|
||||
menuItemInfo.dwItemData = (ULONG_PTR)item;
|
||||
|
||||
// Submenu
|
||||
|
||||
if (item->Items && item->Items->Count != 0)
|
||||
{
|
||||
menuItemInfo.fMask |= MIIM_SUBMENU;
|
||||
menuItemInfo.hSubMenu = PhEMenuToHMenu(item, Flags, Data);
|
||||
}
|
||||
|
||||
InsertMenuItem(MenuHandle, MAXINT, TRUE, &menuItemInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Windows menu object to an EMENU.
|
||||
*
|
||||
* \param MenuItem The menu item in which the converted menu items will be placed.
|
||||
* \param MenuHandle A menu handle.
|
||||
*/
|
||||
VOID PhHMenuToEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM MenuItem,
|
||||
_In_ HMENU MenuHandle
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
ULONG count;
|
||||
|
||||
count = GetMenuItemCount(MenuHandle);
|
||||
|
||||
if (count != -1)
|
||||
{
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
MENUITEMINFO menuItemInfo;
|
||||
WCHAR buffer[256];
|
||||
PPH_EMENU_ITEM menuItem;
|
||||
|
||||
menuItemInfo.cbSize = sizeof(menuItemInfo);
|
||||
menuItemInfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE | MIIM_STRING | MIIM_SUBMENU;
|
||||
menuItemInfo.cch = sizeof(buffer) / sizeof(WCHAR);
|
||||
menuItemInfo.dwTypeData = buffer;
|
||||
|
||||
if (!GetMenuItemInfo(MenuHandle, i, TRUE, &menuItemInfo))
|
||||
continue;
|
||||
|
||||
menuItem = PhCreateEMenuItem(
|
||||
PH_EMENU_TEXT_OWNED,
|
||||
menuItemInfo.wID,
|
||||
PhDuplicateStringZ(buffer),
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (menuItemInfo.fType & MFT_SEPARATOR)
|
||||
menuItem->Flags |= PH_EMENU_SEPARATOR;
|
||||
|
||||
PhMapFlags2(
|
||||
&menuItem->Flags,
|
||||
menuItemInfo.fType,
|
||||
EMenuTypeMappings,
|
||||
sizeof(EMenuTypeMappings) / sizeof(PH_FLAG_MAPPING)
|
||||
);
|
||||
PhMapFlags2(
|
||||
&menuItem->Flags,
|
||||
menuItemInfo.fState,
|
||||
EMenuStateMappings,
|
||||
sizeof(EMenuStateMappings) / sizeof(PH_FLAG_MAPPING)
|
||||
);
|
||||
|
||||
if (menuItemInfo.hSubMenu)
|
||||
PhHMenuToEMenuItem(menuItem, menuItemInfo.hSubMenu);
|
||||
|
||||
PhInsertEMenuItem(MenuItem, menuItem, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a menu resource and converts it to an EMENU.
|
||||
*
|
||||
* \param MenuItem The menu item in which the converted menu items will be placed.
|
||||
* \param InstanceHandle The module containing the menu resource.
|
||||
* \param Resource The resource identifier.
|
||||
* \param SubMenuIndex The index of the sub menu to use, or -1 to use the root menu.
|
||||
*/
|
||||
VOID PhLoadResourceEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM MenuItem,
|
||||
_In_ HINSTANCE InstanceHandle,
|
||||
_In_ PWSTR Resource,
|
||||
_In_ ULONG SubMenuIndex
|
||||
)
|
||||
{
|
||||
HMENU menu;
|
||||
HMENU realMenu;
|
||||
|
||||
menu = LoadMenu(InstanceHandle, Resource);
|
||||
|
||||
if (SubMenuIndex != -1)
|
||||
realMenu = GetSubMenu(menu, SubMenuIndex);
|
||||
else
|
||||
realMenu = menu;
|
||||
|
||||
PhHMenuToEMenuItem(MenuItem, realMenu);
|
||||
|
||||
DestroyMenu(menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a menu.
|
||||
*
|
||||
* \param Menu A menu.
|
||||
* \param WindowHandle The window that owns the popup menu.
|
||||
* \param Flags A combination of the following:
|
||||
* \li \c PH_EMENU_SHOW_SEND_COMMAND A WM_COMMAND message is sent to the window when the user clicks
|
||||
* on a menu item.
|
||||
* \li \c PH_EMENU_SHOW_LEFTRIGHT The user can select menu items with both the left and right mouse
|
||||
* buttons.
|
||||
* \param Align The alignment of the menu.
|
||||
* \param X The horizontal location of the menu.
|
||||
* \param Y The vertical location of the menu.
|
||||
*
|
||||
* \return The selected menu item, or NULL if the menu was cancelled.
|
||||
*/
|
||||
PPH_EMENU_ITEM PhShowEMenu(
|
||||
_In_ PPH_EMENU Menu,
|
||||
_In_ HWND WindowHandle,
|
||||
_In_ ULONG Flags,
|
||||
_In_ ULONG Align,
|
||||
_In_ ULONG X,
|
||||
_In_ ULONG Y
|
||||
)
|
||||
{
|
||||
PPH_EMENU_ITEM selectedItem;
|
||||
ULONG result;
|
||||
ULONG flags;
|
||||
PH_EMENU_DATA data;
|
||||
HMENU popupMenu;
|
||||
|
||||
selectedItem = NULL;
|
||||
flags = TPM_RETURNCMD | TPM_NONOTIFY;
|
||||
|
||||
// Flags
|
||||
|
||||
if (Flags & PH_EMENU_SHOW_LEFTRIGHT)
|
||||
flags |= TPM_RIGHTBUTTON;
|
||||
else
|
||||
flags |= TPM_LEFTBUTTON;
|
||||
|
||||
// Align
|
||||
|
||||
if (Align & PH_ALIGN_LEFT)
|
||||
flags |= TPM_LEFTALIGN;
|
||||
else if (Align & PH_ALIGN_RIGHT)
|
||||
flags |= TPM_RIGHTALIGN;
|
||||
else
|
||||
flags |= TPM_CENTERALIGN;
|
||||
|
||||
if (Align & PH_ALIGN_TOP)
|
||||
flags |= TPM_TOPALIGN;
|
||||
else if (Align & PH_ALIGN_BOTTOM)
|
||||
flags |= TPM_BOTTOMALIGN;
|
||||
else
|
||||
flags |= TPM_VCENTERALIGN;
|
||||
|
||||
PhInitializeEMenuData(&data);
|
||||
|
||||
if (popupMenu = PhEMenuToHMenu(Menu, PH_EMENU_CONVERT_ID, &data))
|
||||
{
|
||||
result = TrackPopupMenu(
|
||||
popupMenu,
|
||||
flags,
|
||||
X,
|
||||
Y,
|
||||
0,
|
||||
WindowHandle,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
selectedItem = data.IdToItem->Items[result - 1];
|
||||
}
|
||||
|
||||
DestroyMenu(popupMenu);
|
||||
}
|
||||
|
||||
PhDeleteEMenuData(&data);
|
||||
|
||||
if ((Flags & PH_EMENU_SHOW_SEND_COMMAND) && selectedItem && selectedItem->Id != 0)
|
||||
SendMessage(WindowHandle, WM_COMMAND, MAKEWPARAM(selectedItem->Id, 0), 0);
|
||||
|
||||
return selectedItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flags of a menu item.
|
||||
*
|
||||
* \param Item The parent menu item.
|
||||
* \param Id The identifier of the child menu item.
|
||||
* \param Mask The flags to modify.
|
||||
* \param Value The new value of the flags.
|
||||
*/
|
||||
BOOLEAN PhSetFlagsEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Id,
|
||||
_In_ ULONG Mask,
|
||||
_In_ ULONG Value
|
||||
)
|
||||
{
|
||||
PPH_EMENU_ITEM item;
|
||||
|
||||
item = PhFindEMenuItem(Item, PH_EMENU_FIND_DESCEND, NULL, Id);
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->Flags &= ~Mask;
|
||||
item->Flags |= Value;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets flags for all children of a menu item.
|
||||
*
|
||||
* \param Item The parent menu item.
|
||||
* \param Mask The flags to modify.
|
||||
* \param Value The new value of the flags.
|
||||
*/
|
||||
VOID PhSetFlagsAllEMenuItems(
|
||||
_In_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Mask,
|
||||
_In_ ULONG Value
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < Item->Items->Count; i++)
|
||||
{
|
||||
PPH_EMENU_ITEM item = Item->Items->Items[i];
|
||||
|
||||
item->Flags &= ~Mask;
|
||||
item->Flags |= Value;
|
||||
}
|
||||
}
|
||||
|
||||
VOID PhModifyEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG ModifyFlags,
|
||||
_In_ ULONG OwnedFlags,
|
||||
_In_opt_ PWSTR Text,
|
||||
_In_opt_ HBITMAP Bitmap
|
||||
)
|
||||
{
|
||||
if (ModifyFlags & PH_EMENU_MODIFY_TEXT)
|
||||
{
|
||||
if ((Item->Flags & PH_EMENU_TEXT_OWNED) && Item->Text)
|
||||
PhFree(Item->Text);
|
||||
|
||||
Item->Text = Text;
|
||||
Item->Flags &= ~PH_EMENU_TEXT_OWNED;
|
||||
Item->Flags |= OwnedFlags & PH_EMENU_TEXT_OWNED;
|
||||
}
|
||||
|
||||
if (ModifyFlags & PH_EMENU_MODIFY_BITMAP)
|
||||
{
|
||||
if ((Item->Flags & PH_EMENU_BITMAP_OWNED) && Item->Bitmap)
|
||||
DeleteObject(Item->Bitmap);
|
||||
|
||||
Item->Bitmap = Bitmap;
|
||||
Item->Flags &= ~PH_EMENU_BITMAP_OWNED;
|
||||
Item->Flags |= OwnedFlags & PH_EMENU_BITMAP_OWNED;
|
||||
}
|
||||
}
|
||||
92
phlib/error.c
Normal file
92
phlib/error.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* error codes
|
||||
*
|
||||
* Copyright (C) 2010-2011 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <phbase.h>
|
||||
|
||||
/**
|
||||
* Converts a NTSTATUS value to a Win32 error code.
|
||||
*
|
||||
* \remarks This function handles FACILITY_NTWIN32 status values properly, unlike
|
||||
* RtlNtStatusToDosError.
|
||||
*/
|
||||
ULONG PhNtStatusToDosError(
|
||||
_In_ NTSTATUS Status
|
||||
)
|
||||
{
|
||||
if (NT_NTWIN32(Status)) // RtlNtStatusToDosError doesn't seem to handle these cases correctly
|
||||
return WIN32_FROM_NTSTATUS(Status);
|
||||
else
|
||||
return RtlNtStatusToDosError(Status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Win32 error code to a NTSTATUS value.
|
||||
*
|
||||
* \remarks Only a small number of cases are currently supported. Other status values are wrapped
|
||||
* using FACILITY_NTWIN32.
|
||||
*/
|
||||
NTSTATUS PhDosErrorToNtStatus(
|
||||
_In_ ULONG DosError
|
||||
)
|
||||
{
|
||||
switch (DosError)
|
||||
{
|
||||
case ERROR_INVALID_FUNCTION: return STATUS_ILLEGAL_FUNCTION;
|
||||
case ERROR_FILE_NOT_FOUND: return STATUS_NO_SUCH_FILE;
|
||||
case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
|
||||
case ERROR_INVALID_HANDLE: return STATUS_INVALID_HANDLE;
|
||||
case ERROR_HANDLE_EOF: return STATUS_END_OF_FILE;
|
||||
case ERROR_NOT_SUPPORTED: return STATUS_NOT_SUPPORTED;
|
||||
case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
|
||||
case ERROR_NOT_LOCKED: return STATUS_NOT_LOCKED;
|
||||
case ERROR_MORE_DATA: return STATUS_MORE_ENTRIES;
|
||||
case ERROR_NOACCESS: return STATUS_ACCESS_VIOLATION;
|
||||
case ERROR_STACK_OVERFLOW: return STATUS_STACK_OVERFLOW;
|
||||
case ERROR_INTERNAL_ERROR: return STATUS_INTERNAL_ERROR;
|
||||
default: return NTSTATUS_FROM_WIN32(DosError);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a NTSTATUS value indicates that a file cannot be not found.
|
||||
*/
|
||||
BOOLEAN PhNtStatusFileNotFound(
|
||||
_In_ NTSTATUS Status
|
||||
)
|
||||
{
|
||||
switch (Status)
|
||||
{
|
||||
case STATUS_NO_SUCH_FILE:
|
||||
return TRUE;
|
||||
case STATUS_OBJECT_NAME_INVALID:
|
||||
return TRUE;
|
||||
case STATUS_OBJECT_NAME_NOT_FOUND:
|
||||
return TRUE;
|
||||
case STATUS_OBJECT_NO_LONGER_EXISTS:
|
||||
return TRUE;
|
||||
case STATUS_OBJECT_PATH_INVALID:
|
||||
return TRUE;
|
||||
case STATUS_OBJECT_PATH_NOT_FOUND:
|
||||
return TRUE;
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
748
phlib/extlv.c
Normal file
748
phlib/extlv.c
Normal file
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* extended list view
|
||||
*
|
||||
* Copyright (C) 2010-2012 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The extended list view adds some functionality to the default list view control, such as sorting,
|
||||
* item colors and fonts, better redraw disabling, and the ability to change the cursor. This is
|
||||
* currently implemented by hooking the window procedure.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <guisup.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#define PH_MAX_COMPARE_FUNCTIONS 16
|
||||
|
||||
typedef struct _PH_EXTLV_CONTEXT
|
||||
{
|
||||
HWND Handle;
|
||||
WNDPROC OldWndProc;
|
||||
PVOID Context;
|
||||
|
||||
// Sorting
|
||||
|
||||
BOOLEAN TriState;
|
||||
ULONG SortColumn;
|
||||
PH_SORT_ORDER SortOrder;
|
||||
BOOLEAN SortFast;
|
||||
|
||||
PPH_COMPARE_FUNCTION TriStateCompareFunction;
|
||||
PPH_COMPARE_FUNCTION CompareFunctions[PH_MAX_COMPARE_FUNCTIONS];
|
||||
ULONG FallbackColumns[PH_MAX_COMPARE_FUNCTIONS];
|
||||
ULONG NumberOfFallbackColumns;
|
||||
|
||||
// Color and Font
|
||||
PPH_EXTLV_GET_ITEM_COLOR ItemColorFunction;
|
||||
PPH_EXTLV_GET_ITEM_FONT ItemFontFunction;
|
||||
|
||||
// Misc.
|
||||
|
||||
LONG EnableRedraw;
|
||||
HCURSOR Cursor;
|
||||
} PH_EXTLV_CONTEXT, *PPH_EXTLV_CONTEXT;
|
||||
|
||||
LRESULT CALLBACK PhpExtendedListViewWndProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
);
|
||||
|
||||
INT PhpExtendedListViewCompareFunc(
|
||||
_In_ LPARAM lParam1,
|
||||
_In_ LPARAM lParam2,
|
||||
_In_ LPARAM lParamSort
|
||||
);
|
||||
|
||||
INT PhpExtendedListViewCompareFastFunc(
|
||||
_In_ LPARAM lParam1,
|
||||
_In_ LPARAM lParam2,
|
||||
_In_ LPARAM lParamSort
|
||||
);
|
||||
|
||||
INT PhpCompareListViewItems(
|
||||
_In_ PPH_EXTLV_CONTEXT Context,
|
||||
_In_ INT X,
|
||||
_In_ INT Y,
|
||||
_In_ PVOID XParam,
|
||||
_In_ PVOID YParam,
|
||||
_In_ ULONG Column,
|
||||
_In_ BOOLEAN EnableDefault
|
||||
);
|
||||
|
||||
INT PhpDefaultCompareListViewItems(
|
||||
_In_ PPH_EXTLV_CONTEXT Context,
|
||||
_In_ INT X,
|
||||
_In_ INT Y,
|
||||
_In_ ULONG Column
|
||||
);
|
||||
|
||||
static PWSTR PhpMakeExtLvContextAtom(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PH_DEFINE_MAKE_ATOM(L"PhLib_ExtLvContext");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables extended list view support for a list view control.
|
||||
*
|
||||
* \param hWnd A handle to the list view control.
|
||||
*/
|
||||
VOID PhSetExtendedListView(
|
||||
_In_ HWND hWnd
|
||||
)
|
||||
{
|
||||
WNDPROC oldWndProc;
|
||||
PPH_EXTLV_CONTEXT context;
|
||||
|
||||
oldWndProc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
|
||||
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)PhpExtendedListViewWndProc);
|
||||
|
||||
context = PhAllocate(sizeof(PH_EXTLV_CONTEXT));
|
||||
|
||||
context->Handle = hWnd;
|
||||
context->OldWndProc = oldWndProc;
|
||||
context->Context = NULL;
|
||||
context->TriState = FALSE;
|
||||
context->SortColumn = 0;
|
||||
context->SortOrder = AscendingSortOrder;
|
||||
context->SortFast = FALSE;
|
||||
context->TriStateCompareFunction = NULL;
|
||||
memset(context->CompareFunctions, 0, sizeof(context->CompareFunctions));
|
||||
context->NumberOfFallbackColumns = 0;
|
||||
|
||||
context->ItemColorFunction = NULL;
|
||||
context->ItemFontFunction = NULL;
|
||||
|
||||
context->EnableRedraw = 1;
|
||||
context->Cursor = NULL;
|
||||
|
||||
SetProp(hWnd, PhpMakeExtLvContextAtom(), (HANDLE)context);
|
||||
|
||||
ExtendedListView_Init(hWnd);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK PhpExtendedListViewWndProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
{
|
||||
PPH_EXTLV_CONTEXT context;
|
||||
WNDPROC oldWndProc;
|
||||
|
||||
context = (PPH_EXTLV_CONTEXT)GetProp(hwnd, PhpMakeExtLvContextAtom());
|
||||
oldWndProc = context->OldWndProc;
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
{
|
||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)oldWndProc);
|
||||
PhFree(context);
|
||||
RemoveProp(hwnd, PhpMakeExtLvContextAtom());
|
||||
}
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
LPNMHDR header = (LPNMHDR)lParam;
|
||||
|
||||
switch (header->code)
|
||||
{
|
||||
case HDN_ITEMCLICK:
|
||||
{
|
||||
HWND headerHandle;
|
||||
|
||||
headerHandle = (HWND)CallWindowProc(context->OldWndProc, hwnd, LVM_GETHEADER, 0, 0);
|
||||
|
||||
if (header->hwndFrom == headerHandle)
|
||||
{
|
||||
LPNMHEADER header2 = (LPNMHEADER)header;
|
||||
|
||||
if (header2->iItem == context->SortColumn)
|
||||
{
|
||||
if (context->TriState)
|
||||
{
|
||||
if (context->SortOrder == AscendingSortOrder)
|
||||
context->SortOrder = DescendingSortOrder;
|
||||
else if (context->SortOrder == DescendingSortOrder)
|
||||
context->SortOrder = NoSortOrder;
|
||||
else
|
||||
context->SortOrder = AscendingSortOrder;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context->SortOrder == AscendingSortOrder)
|
||||
context->SortOrder = DescendingSortOrder;
|
||||
else
|
||||
context->SortOrder = AscendingSortOrder;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context->SortColumn = header2->iItem;
|
||||
context->SortOrder = AscendingSortOrder;
|
||||
}
|
||||
|
||||
PhSetHeaderSortIcon(headerHandle, context->SortColumn, context->SortOrder);
|
||||
ExtendedListView_SortItems(hwnd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_REFLECT + WM_NOTIFY:
|
||||
{
|
||||
LPNMHDR header = (LPNMHDR)lParam;
|
||||
|
||||
switch (header->code)
|
||||
{
|
||||
case NM_CUSTOMDRAW:
|
||||
{
|
||||
if (header->hwndFrom == hwnd)
|
||||
{
|
||||
LPNMLVCUSTOMDRAW customDraw = (LPNMLVCUSTOMDRAW)header;
|
||||
|
||||
switch (customDraw->nmcd.dwDrawStage)
|
||||
{
|
||||
case CDDS_PREPAINT:
|
||||
return CDRF_NOTIFYITEMDRAW;
|
||||
case CDDS_ITEMPREPAINT:
|
||||
{
|
||||
BOOLEAN colorChanged = FALSE;
|
||||
HFONT newFont = NULL;
|
||||
|
||||
if (context->ItemColorFunction)
|
||||
{
|
||||
customDraw->clrTextBk = context->ItemColorFunction(
|
||||
(INT)customDraw->nmcd.dwItemSpec,
|
||||
(PVOID)customDraw->nmcd.lItemlParam,
|
||||
context->Context
|
||||
);
|
||||
colorChanged = TRUE;
|
||||
}
|
||||
|
||||
if (context->ItemFontFunction)
|
||||
{
|
||||
newFont = context->ItemFontFunction(
|
||||
(INT)customDraw->nmcd.dwItemSpec,
|
||||
(PVOID)customDraw->nmcd.lItemlParam,
|
||||
context->Context
|
||||
);
|
||||
}
|
||||
|
||||
if (newFont)
|
||||
SelectObject(customDraw->nmcd.hdc, newFont);
|
||||
|
||||
if (colorChanged)
|
||||
{
|
||||
if (PhGetColorBrightness(customDraw->clrTextBk) > 100) // slightly less than half
|
||||
customDraw->clrText = RGB(0x00, 0x00, 0x00);
|
||||
else
|
||||
customDraw->clrText = RGB(0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
if (!newFont)
|
||||
return CDRF_DODEFAULT;
|
||||
else
|
||||
return CDRF_NEWFONT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_SETCURSOR:
|
||||
{
|
||||
if (context->Cursor)
|
||||
{
|
||||
SetCursor(context->Cursor);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_UPDATEUISTATE:
|
||||
{
|
||||
// Disable focus rectangles by setting or masking out the flag where appropriate.
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case UIS_SET:
|
||||
wParam |= UISF_HIDEFOCUS << 16;
|
||||
break;
|
||||
case UIS_CLEAR:
|
||||
case UIS_INITIALIZE:
|
||||
wParam &= ~(UISF_HIDEFOCUS << 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ELVM_ADDFALLBACKCOLUMN:
|
||||
{
|
||||
if (context->NumberOfFallbackColumns < PH_MAX_COMPARE_FUNCTIONS)
|
||||
context->FallbackColumns[context->NumberOfFallbackColumns++] = (ULONG)wParam;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_ADDFALLBACKCOLUMNS:
|
||||
{
|
||||
ULONG numberOfColumns = (ULONG)wParam;
|
||||
PULONG columns = (PULONG)lParam;
|
||||
|
||||
if (context->NumberOfFallbackColumns + numberOfColumns <= PH_MAX_COMPARE_FUNCTIONS)
|
||||
{
|
||||
memcpy(
|
||||
&context->FallbackColumns[context->NumberOfFallbackColumns],
|
||||
columns,
|
||||
numberOfColumns * sizeof(ULONG)
|
||||
);
|
||||
context->NumberOfFallbackColumns += numberOfColumns;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_INIT:
|
||||
{
|
||||
PhSetHeaderSortIcon(ListView_GetHeader(hwnd), context->SortColumn, context->SortOrder);
|
||||
|
||||
// HACK to fix tooltips showing behind Always On Top windows.
|
||||
SetWindowPos(ListView_GetToolTips(hwnd), HWND_TOPMOST, 0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
||||
|
||||
// Make sure focus rectangles are disabled.
|
||||
SendMessage(hwnd, WM_CHANGEUISTATE, MAKELONG(UIS_SET, UISF_HIDEFOCUS), 0);
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETCOLUMNWIDTH:
|
||||
{
|
||||
ULONG column = (ULONG)wParam;
|
||||
LONG width = (LONG)lParam;
|
||||
|
||||
if (width == ELVSCW_AUTOSIZE_REMAININGSPACE)
|
||||
{
|
||||
RECT clientRect;
|
||||
LONG availableWidth;
|
||||
ULONG i;
|
||||
LVCOLUMN lvColumn;
|
||||
|
||||
GetClientRect(hwnd, &clientRect);
|
||||
availableWidth = clientRect.right;
|
||||
i = 0;
|
||||
lvColumn.mask = LVCF_WIDTH;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (i != column)
|
||||
{
|
||||
if (CallWindowProc(oldWndProc, hwnd, LVM_GETCOLUMN, i, (LPARAM)&lvColumn))
|
||||
{
|
||||
availableWidth -= lvColumn.cx;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (availableWidth >= 40)
|
||||
return CallWindowProc(oldWndProc, hwnd, LVM_SETCOLUMNWIDTH, column, availableWidth);
|
||||
}
|
||||
|
||||
return CallWindowProc(oldWndProc, hwnd, LVM_SETCOLUMNWIDTH, column, width);
|
||||
}
|
||||
break;
|
||||
case ELVM_SETCOMPAREFUNCTION:
|
||||
{
|
||||
ULONG column = (ULONG)wParam;
|
||||
PPH_COMPARE_FUNCTION compareFunction = (PPH_COMPARE_FUNCTION)lParam;
|
||||
|
||||
if (column >= PH_MAX_COMPARE_FUNCTIONS)
|
||||
return FALSE;
|
||||
|
||||
context->CompareFunctions[column] = compareFunction;
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETCONTEXT:
|
||||
{
|
||||
context->Context = (PVOID)lParam;
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETCURSOR:
|
||||
{
|
||||
context->Cursor = (HCURSOR)lParam;
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETITEMCOLORFUNCTION:
|
||||
{
|
||||
context->ItemColorFunction = (PPH_EXTLV_GET_ITEM_COLOR)lParam;
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETITEMFONTFUNCTION:
|
||||
{
|
||||
context->ItemFontFunction = (PPH_EXTLV_GET_ITEM_FONT)lParam;
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETREDRAW:
|
||||
{
|
||||
if (wParam)
|
||||
context->EnableRedraw++;
|
||||
else
|
||||
context->EnableRedraw--;
|
||||
|
||||
if (context->EnableRedraw == 1)
|
||||
{
|
||||
SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
|
||||
InvalidateRect(hwnd, NULL, FALSE);
|
||||
}
|
||||
else if (context->EnableRedraw == 0)
|
||||
{
|
||||
SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETSORT:
|
||||
{
|
||||
context->SortColumn = (ULONG)wParam;
|
||||
context->SortOrder = (PH_SORT_ORDER)lParam;
|
||||
|
||||
PhSetHeaderSortIcon(ListView_GetHeader(hwnd), context->SortColumn, context->SortOrder);
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETSORTFAST:
|
||||
{
|
||||
context->SortFast = !!wParam;
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETTRISTATE:
|
||||
{
|
||||
context->TriState = !!wParam;
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SETTRISTATECOMPAREFUNCTION:
|
||||
{
|
||||
context->TriStateCompareFunction = (PPH_COMPARE_FUNCTION)lParam;
|
||||
}
|
||||
return TRUE;
|
||||
case ELVM_SORTITEMS:
|
||||
{
|
||||
if (context->SortFast)
|
||||
{
|
||||
// This sort method is faster than the normal sort because our comparison function
|
||||
// doesn't have to call the list view window procedure to get the item lParam
|
||||
// values. The disadvantage of this method is that default sorting is not available
|
||||
// - if a column doesn't have a comparison function, it doesn't get sorted at all.
|
||||
|
||||
ListView_SortItems(
|
||||
hwnd,
|
||||
PhpExtendedListViewCompareFastFunc,
|
||||
(LPARAM)context
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
ListView_SortItemsEx(
|
||||
hwnd,
|
||||
PhpExtendedListViewCompareFunc,
|
||||
(LPARAM)context
|
||||
);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visually indicates the sort order of a header control item.
|
||||
*
|
||||
* \param hwnd A handle to the header control.
|
||||
* \param Index The index of the item.
|
||||
* \param Order The sort order of the item.
|
||||
*/
|
||||
VOID PhSetHeaderSortIcon(
|
||||
_In_ HWND hwnd,
|
||||
_In_ INT Index,
|
||||
_In_ PH_SORT_ORDER Order
|
||||
)
|
||||
{
|
||||
ULONG count;
|
||||
ULONG i;
|
||||
|
||||
count = Header_GetItemCount(hwnd);
|
||||
|
||||
if (count == -1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
HDITEM item;
|
||||
|
||||
item.mask = HDI_FORMAT;
|
||||
Header_GetItem(hwnd, i, &item);
|
||||
|
||||
if (Order != NoSortOrder && i == Index)
|
||||
{
|
||||
if (Order == AscendingSortOrder)
|
||||
{
|
||||
item.fmt &= ~HDF_SORTDOWN;
|
||||
item.fmt |= HDF_SORTUP;
|
||||
}
|
||||
else if (Order == DescendingSortOrder)
|
||||
{
|
||||
item.fmt &= ~HDF_SORTUP;
|
||||
item.fmt |= HDF_SORTDOWN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
|
||||
}
|
||||
|
||||
Header_SetItem(hwnd, i, &item);
|
||||
}
|
||||
}
|
||||
|
||||
static INT PhpExtendedListViewCompareFunc(
|
||||
_In_ LPARAM lParam1,
|
||||
_In_ LPARAM lParam2,
|
||||
_In_ LPARAM lParamSort
|
||||
)
|
||||
{
|
||||
PPH_EXTLV_CONTEXT context = (PPH_EXTLV_CONTEXT)lParamSort;
|
||||
INT result;
|
||||
INT x = (INT)lParam1;
|
||||
INT y = (INT)lParam2;
|
||||
ULONG i;
|
||||
PULONG fallbackColumns;
|
||||
LVITEM xItem;
|
||||
LVITEM yItem;
|
||||
|
||||
// Get the param values.
|
||||
|
||||
xItem.mask = LVIF_PARAM | LVIF_STATE;
|
||||
xItem.iItem = x;
|
||||
xItem.iSubItem = 0;
|
||||
|
||||
yItem.mask = LVIF_PARAM | LVIF_STATE;
|
||||
yItem.iItem = y;
|
||||
yItem.iSubItem = 0;
|
||||
|
||||
// Don't use SendMessage/ListView_* because it will call our new window procedure, which will
|
||||
// use GetProp. This calls NtUserGetProp, and obviously having a system call in a comparison
|
||||
// function is very, very bad for performance.
|
||||
|
||||
if (!CallWindowProc(context->OldWndProc, context->Handle, LVM_GETITEM, 0, (LPARAM)&xItem))
|
||||
return 0;
|
||||
if (!CallWindowProc(context->OldWndProc, context->Handle, LVM_GETITEM, 0, (LPARAM)&yItem))
|
||||
return 0;
|
||||
|
||||
// First, do tri-state sorting.
|
||||
|
||||
if (
|
||||
context->TriState &&
|
||||
context->SortOrder == NoSortOrder &&
|
||||
context->TriStateCompareFunction
|
||||
)
|
||||
{
|
||||
result = context->TriStateCompareFunction(
|
||||
(PVOID)xItem.lParam,
|
||||
(PVOID)yItem.lParam,
|
||||
context->Context
|
||||
);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compare using the user-selected column and move on to the fallback columns if necessary.
|
||||
|
||||
result = PhpCompareListViewItems(context, x, y, (PVOID)xItem.lParam, (PVOID)yItem.lParam, context->SortColumn, TRUE);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
fallbackColumns = context->FallbackColumns;
|
||||
|
||||
for (i = context->NumberOfFallbackColumns; i != 0; i--)
|
||||
{
|
||||
ULONG fallbackColumn = *fallbackColumns++;
|
||||
|
||||
if (fallbackColumn == context->SortColumn)
|
||||
continue;
|
||||
|
||||
result = PhpCompareListViewItems(context, x, y, (PVOID)xItem.lParam, (PVOID)yItem.lParam, fallbackColumn, TRUE);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT PhpExtendedListViewCompareFastFunc(
|
||||
_In_ LPARAM lParam1,
|
||||
_In_ LPARAM lParam2,
|
||||
_In_ LPARAM lParamSort
|
||||
)
|
||||
{
|
||||
PPH_EXTLV_CONTEXT context = (PPH_EXTLV_CONTEXT)lParamSort;
|
||||
INT result;
|
||||
ULONG i;
|
||||
PULONG fallbackColumns;
|
||||
|
||||
if (!lParam1 || !lParam2)
|
||||
return 0;
|
||||
|
||||
// First, do tri-state sorting.
|
||||
|
||||
if (
|
||||
context->TriState &&
|
||||
context->SortOrder == NoSortOrder &&
|
||||
context->TriStateCompareFunction
|
||||
)
|
||||
{
|
||||
result = context->TriStateCompareFunction(
|
||||
(PVOID)lParam1,
|
||||
(PVOID)lParam2,
|
||||
context->Context
|
||||
);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Compare using the user-selected column and move on to the fallback columns if necessary.
|
||||
|
||||
result = PhpCompareListViewItems(context, 0, 0, (PVOID)lParam1, (PVOID)lParam2, context->SortColumn, FALSE);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
fallbackColumns = context->FallbackColumns;
|
||||
|
||||
for (i = context->NumberOfFallbackColumns; i != 0; i--)
|
||||
{
|
||||
ULONG fallbackColumn = *fallbackColumns++;
|
||||
|
||||
if (fallbackColumn == context->SortColumn)
|
||||
continue;
|
||||
|
||||
result = PhpCompareListViewItems(context, 0, 0, (PVOID)lParam1, (PVOID)lParam2, fallbackColumn, FALSE);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FORCEINLINE INT PhpCompareListViewItems(
|
||||
_In_ PPH_EXTLV_CONTEXT Context,
|
||||
_In_ INT X,
|
||||
_In_ INT Y,
|
||||
_In_ PVOID XParam,
|
||||
_In_ PVOID YParam,
|
||||
_In_ ULONG Column,
|
||||
_In_ BOOLEAN EnableDefault
|
||||
)
|
||||
{
|
||||
INT result = 0;
|
||||
|
||||
if (
|
||||
Column < PH_MAX_COMPARE_FUNCTIONS &&
|
||||
Context->CompareFunctions[Column]
|
||||
)
|
||||
{
|
||||
result = PhModifySort(
|
||||
Context->CompareFunctions[Column](XParam, YParam, Context->Context),
|
||||
Context->SortOrder
|
||||
);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (EnableDefault)
|
||||
{
|
||||
return PhModifySort(
|
||||
PhpDefaultCompareListViewItems(Context, X, Y, Column),
|
||||
Context->SortOrder
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static INT PhpDefaultCompareListViewItems(
|
||||
_In_ PPH_EXTLV_CONTEXT Context,
|
||||
_In_ INT X,
|
||||
_In_ INT Y,
|
||||
_In_ ULONG Column
|
||||
)
|
||||
{
|
||||
WCHAR xText[261];
|
||||
WCHAR yText[261];
|
||||
LVITEM item;
|
||||
|
||||
// Get the X item text.
|
||||
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = X;
|
||||
item.iSubItem = Column;
|
||||
item.pszText = xText;
|
||||
item.cchTextMax = 260;
|
||||
|
||||
xText[0] = 0;
|
||||
CallWindowProc(Context->OldWndProc, Context->Handle, LVM_GETITEM, 0, (LPARAM)&item);
|
||||
|
||||
// Get the Y item text.
|
||||
|
||||
item.iItem = Y;
|
||||
item.pszText = yText;
|
||||
item.cchTextMax = 260;
|
||||
|
||||
yText[0] = 0;
|
||||
CallWindowProc(Context->OldWndProc, Context->Handle, LVM_GETITEM, 0, (LPARAM)&item);
|
||||
|
||||
// Compare them.
|
||||
|
||||
#if 1
|
||||
return PhCompareStringZNatural(xText, yText, TRUE);
|
||||
#else
|
||||
return _wcsicmp(xText, yText);
|
||||
#endif
|
||||
}
|
||||
384
phlib/fastlock.c
Normal file
384
phlib/fastlock.c
Normal file
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* fast resource lock
|
||||
*
|
||||
* Copyright (C) 2009-2010 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <phbase.h>
|
||||
#include <fastlock.h>
|
||||
|
||||
// FastLock is a port of FastResourceLock from PH 1.x.
|
||||
//
|
||||
// The code contains no comments because it is a direct port. Please see FastResourceLock.cs in PH
|
||||
// 1.x for details.
|
||||
|
||||
// The fast lock is around 7% faster than the critical section when there is no contention, when
|
||||
// used solely for mutual exclusion. It is also much smaller than the critical section.
|
||||
|
||||
#define PH_LOCK_OWNED 0x1
|
||||
#define PH_LOCK_EXCLUSIVE_WAKING 0x2
|
||||
|
||||
#define PH_LOCK_SHARED_OWNERS_SHIFT 2
|
||||
#define PH_LOCK_SHARED_OWNERS_MASK 0x3ff
|
||||
#define PH_LOCK_SHARED_OWNERS_INC 0x4
|
||||
|
||||
#define PH_LOCK_SHARED_WAITERS_SHIFT 12
|
||||
#define PH_LOCK_SHARED_WAITERS_MASK 0x3ff
|
||||
#define PH_LOCK_SHARED_WAITERS_INC 0x1000
|
||||
|
||||
#define PH_LOCK_EXCLUSIVE_WAITERS_SHIFT 22
|
||||
#define PH_LOCK_EXCLUSIVE_WAITERS_MASK 0x3ff
|
||||
#define PH_LOCK_EXCLUSIVE_WAITERS_INC 0x400000
|
||||
|
||||
#define PH_LOCK_EXCLUSIVE_MASK \
|
||||
(PH_LOCK_EXCLUSIVE_WAKING | \
|
||||
(PH_LOCK_EXCLUSIVE_WAITERS_MASK << PH_LOCK_EXCLUSIVE_WAITERS_SHIFT))
|
||||
|
||||
VOID PhInitializeFastLock(
|
||||
_Out_ PPH_FAST_LOCK FastLock
|
||||
)
|
||||
{
|
||||
FastLock->Value = 0;
|
||||
FastLock->ExclusiveWakeEvent = NULL;
|
||||
FastLock->SharedWakeEvent = NULL;
|
||||
}
|
||||
|
||||
VOID PhDeleteFastLock(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
)
|
||||
{
|
||||
if (FastLock->ExclusiveWakeEvent)
|
||||
{
|
||||
NtClose(FastLock->ExclusiveWakeEvent);
|
||||
FastLock->ExclusiveWakeEvent = NULL;
|
||||
}
|
||||
|
||||
if (FastLock->SharedWakeEvent)
|
||||
{
|
||||
NtClose(FastLock->SharedWakeEvent);
|
||||
FastLock->SharedWakeEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhpEnsureEventCreated(
|
||||
_Inout_ PHANDLE Handle
|
||||
)
|
||||
{
|
||||
HANDLE handle;
|
||||
|
||||
if (*Handle != NULL)
|
||||
return;
|
||||
|
||||
NtCreateSemaphore(&handle, SEMAPHORE_ALL_ACCESS, NULL, 0, MAXLONG);
|
||||
|
||||
if (_InterlockedCompareExchangePointer(
|
||||
Handle,
|
||||
handle,
|
||||
NULL
|
||||
) != NULL)
|
||||
{
|
||||
NtClose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE ULONG PhpGetSpinCount(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if ((ULONG)PhSystemBasicInformation.NumberOfProcessors > 1)
|
||||
return 4000;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
_May_raise_
|
||||
_Acquires_exclusive_lock_(*FastLock)
|
||||
VOID FASTCALL PhfAcquireFastLockExclusive(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
)
|
||||
{
|
||||
ULONG value;
|
||||
ULONG i = 0;
|
||||
ULONG spinCount;
|
||||
|
||||
spinCount = PhpGetSpinCount();
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
value = FastLock->Value;
|
||||
|
||||
if (!(value & (PH_LOCK_OWNED | PH_LOCK_EXCLUSIVE_WAKING)))
|
||||
{
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value + PH_LOCK_OWNED,
|
||||
value
|
||||
) == value)
|
||||
break;
|
||||
}
|
||||
else if (i >= spinCount)
|
||||
{
|
||||
PhpEnsureEventCreated(&FastLock->ExclusiveWakeEvent);
|
||||
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value + PH_LOCK_EXCLUSIVE_WAITERS_INC,
|
||||
value
|
||||
) == value)
|
||||
{
|
||||
if (NtWaitForSingleObject(
|
||||
FastLock->ExclusiveWakeEvent,
|
||||
FALSE,
|
||||
NULL
|
||||
) != STATUS_WAIT_0)
|
||||
PhRaiseStatus(STATUS_UNSUCCESSFUL);
|
||||
|
||||
do
|
||||
{
|
||||
value = FastLock->Value;
|
||||
} while (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value + PH_LOCK_OWNED - PH_LOCK_EXCLUSIVE_WAKING,
|
||||
value
|
||||
) != value);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
YieldProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
_May_raise_
|
||||
_Acquires_shared_lock_(*FastLock)
|
||||
VOID FASTCALL PhfAcquireFastLockShared(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
)
|
||||
{
|
||||
ULONG value;
|
||||
ULONG i = 0;
|
||||
ULONG spinCount;
|
||||
|
||||
spinCount = PhpGetSpinCount();
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
value = FastLock->Value;
|
||||
|
||||
if (!(value & (
|
||||
PH_LOCK_OWNED |
|
||||
(PH_LOCK_SHARED_OWNERS_MASK << PH_LOCK_SHARED_OWNERS_SHIFT) |
|
||||
PH_LOCK_EXCLUSIVE_MASK
|
||||
)))
|
||||
{
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value + PH_LOCK_OWNED + PH_LOCK_SHARED_OWNERS_INC,
|
||||
value
|
||||
) == value)
|
||||
break;
|
||||
}
|
||||
else if (
|
||||
(value & PH_LOCK_OWNED) &&
|
||||
((value >> PH_LOCK_SHARED_OWNERS_SHIFT) & PH_LOCK_SHARED_OWNERS_MASK) > 0 &&
|
||||
!(value & PH_LOCK_EXCLUSIVE_MASK)
|
||||
)
|
||||
{
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value + PH_LOCK_SHARED_OWNERS_INC,
|
||||
value
|
||||
) == value)
|
||||
break;
|
||||
}
|
||||
else if (i >= spinCount)
|
||||
{
|
||||
PhpEnsureEventCreated(&FastLock->SharedWakeEvent);
|
||||
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value + PH_LOCK_SHARED_WAITERS_INC,
|
||||
value
|
||||
) == value)
|
||||
{
|
||||
if (NtWaitForSingleObject(
|
||||
FastLock->SharedWakeEvent,
|
||||
FALSE,
|
||||
NULL
|
||||
) != STATUS_WAIT_0)
|
||||
PhRaiseStatus(STATUS_UNSUCCESSFUL);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
YieldProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
_Releases_exclusive_lock_(*FastLock)
|
||||
VOID FASTCALL PhfReleaseFastLockExclusive(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
)
|
||||
{
|
||||
ULONG value;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
value = FastLock->Value;
|
||||
|
||||
if ((value >> PH_LOCK_EXCLUSIVE_WAITERS_SHIFT) & PH_LOCK_EXCLUSIVE_WAITERS_MASK)
|
||||
{
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value - PH_LOCK_OWNED + PH_LOCK_EXCLUSIVE_WAKING - PH_LOCK_EXCLUSIVE_WAITERS_INC,
|
||||
value
|
||||
) == value)
|
||||
{
|
||||
NtReleaseSemaphore(FastLock->ExclusiveWakeEvent, 1, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ULONG sharedWaiters;
|
||||
|
||||
sharedWaiters = (value >> PH_LOCK_SHARED_WAITERS_SHIFT) & PH_LOCK_SHARED_WAITERS_MASK;
|
||||
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value & ~(PH_LOCK_OWNED | (PH_LOCK_SHARED_WAITERS_MASK << PH_LOCK_SHARED_WAITERS_SHIFT)),
|
||||
value
|
||||
) == value)
|
||||
{
|
||||
if (sharedWaiters)
|
||||
NtReleaseSemaphore(FastLock->SharedWakeEvent, sharedWaiters, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
YieldProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
_Releases_shared_lock_(*FastLock)
|
||||
VOID FASTCALL PhfReleaseFastLockShared(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
)
|
||||
{
|
||||
ULONG value;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
value = FastLock->Value;
|
||||
|
||||
if (((value >> PH_LOCK_SHARED_OWNERS_SHIFT) & PH_LOCK_SHARED_OWNERS_MASK) > 1)
|
||||
{
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value - PH_LOCK_SHARED_OWNERS_INC,
|
||||
value
|
||||
) == value)
|
||||
break;
|
||||
}
|
||||
else if ((value >> PH_LOCK_EXCLUSIVE_WAITERS_SHIFT) & PH_LOCK_EXCLUSIVE_WAITERS_MASK)
|
||||
{
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value - PH_LOCK_OWNED + PH_LOCK_EXCLUSIVE_WAKING -
|
||||
PH_LOCK_SHARED_OWNERS_INC - PH_LOCK_EXCLUSIVE_WAITERS_INC,
|
||||
value
|
||||
) == value)
|
||||
{
|
||||
NtReleaseSemaphore(FastLock->ExclusiveWakeEvent, 1, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value - PH_LOCK_OWNED - PH_LOCK_SHARED_OWNERS_INC,
|
||||
value
|
||||
) == value)
|
||||
break;
|
||||
}
|
||||
|
||||
YieldProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
_When_(return != 0, _Acquires_exclusive_lock_(*FastLock))
|
||||
BOOLEAN FASTCALL PhfTryAcquireFastLockExclusive(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
)
|
||||
{
|
||||
ULONG value;
|
||||
|
||||
value = FastLock->Value;
|
||||
|
||||
if (value & (PH_LOCK_OWNED | PH_LOCK_EXCLUSIVE_WAKING))
|
||||
return FALSE;
|
||||
|
||||
return _InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value + PH_LOCK_OWNED,
|
||||
value
|
||||
) == value;
|
||||
}
|
||||
|
||||
_When_(return != 0, _Acquires_shared_lock_(*FastLock))
|
||||
BOOLEAN FASTCALL PhfTryAcquireFastLockShared(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
)
|
||||
{
|
||||
ULONG value;
|
||||
|
||||
value = FastLock->Value;
|
||||
|
||||
if (value & PH_LOCK_EXCLUSIVE_MASK)
|
||||
return FALSE;
|
||||
|
||||
if (!(value & PH_LOCK_OWNED))
|
||||
{
|
||||
return _InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value + PH_LOCK_OWNED + PH_LOCK_SHARED_OWNERS_INC,
|
||||
value
|
||||
) == value;
|
||||
}
|
||||
else if ((value >> PH_LOCK_SHARED_OWNERS_SHIFT) & PH_LOCK_SHARED_OWNERS_MASK)
|
||||
{
|
||||
return _InterlockedCompareExchange(
|
||||
&FastLock->Value,
|
||||
value + PH_LOCK_SHARED_OWNERS_INC,
|
||||
value
|
||||
) == value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
1510
phlib/filepool.c
Normal file
1510
phlib/filepool.c
Normal file
File diff suppressed because it is too large
Load Diff
876
phlib/filestream.c
Normal file
876
phlib/filestream.c
Normal file
@@ -0,0 +1,876 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* file stream object
|
||||
*
|
||||
* Copyright (C) 2010-2011 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <filestream.h>
|
||||
#include <filestreamp.h>
|
||||
|
||||
PPH_OBJECT_TYPE PhFileStreamType;
|
||||
|
||||
BOOLEAN PhFileStreamInitialization(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PH_OBJECT_TYPE_PARAMETERS parameters;
|
||||
|
||||
parameters.FreeListSize = sizeof(PH_FILE_STREAM);
|
||||
parameters.FreeListCount = 16;
|
||||
|
||||
PhFileStreamType = PhCreateObjectTypeEx(L"FileStream", PH_OBJECT_TYPE_USE_FREE_LIST, PhpFileStreamDeleteProcedure, ¶meters);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NTSTATUS PhCreateFileStream(
|
||||
_Out_ PPH_FILE_STREAM *FileStream,
|
||||
_In_ PWSTR FileName,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ ULONG ShareAccess,
|
||||
_In_ ULONG CreateDisposition,
|
||||
_In_ ULONG Flags
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PPH_FILE_STREAM fileStream;
|
||||
HANDLE fileHandle;
|
||||
ULONG createOptions;
|
||||
|
||||
if (Flags & PH_FILE_STREAM_ASYNCHRONOUS)
|
||||
createOptions = FILE_NON_DIRECTORY_FILE;
|
||||
else
|
||||
createOptions = FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT;
|
||||
|
||||
if (!NT_SUCCESS(status = PhCreateFileWin32(
|
||||
&fileHandle,
|
||||
FileName,
|
||||
DesiredAccess,
|
||||
0,
|
||||
ShareAccess,
|
||||
CreateDisposition,
|
||||
createOptions
|
||||
)))
|
||||
return status;
|
||||
|
||||
if (!NT_SUCCESS(status = PhCreateFileStream2(
|
||||
&fileStream,
|
||||
fileHandle,
|
||||
Flags,
|
||||
PAGE_SIZE
|
||||
)))
|
||||
{
|
||||
NtClose(fileHandle);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Flags & PH_FILE_STREAM_APPEND)
|
||||
{
|
||||
LARGE_INTEGER zero;
|
||||
|
||||
zero.QuadPart = 0;
|
||||
|
||||
if (!NT_SUCCESS(PhSeekFileStream(
|
||||
fileStream,
|
||||
&zero,
|
||||
SeekEnd
|
||||
)))
|
||||
{
|
||||
PhDereferenceObject(fileStream);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
*FileStream = fileStream;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhCreateFileStream2(
|
||||
_Out_ PPH_FILE_STREAM *FileStream,
|
||||
_In_ HANDLE FileHandle,
|
||||
_In_ ULONG Flags,
|
||||
_In_ ULONG BufferLength
|
||||
)
|
||||
{
|
||||
PPH_FILE_STREAM fileStream;
|
||||
|
||||
fileStream = PhCreateObject(sizeof(PH_FILE_STREAM), PhFileStreamType);
|
||||
fileStream->FileHandle = FileHandle;
|
||||
fileStream->Flags = Flags;
|
||||
fileStream->Position.QuadPart = 0;
|
||||
|
||||
if (!(Flags & PH_FILE_STREAM_UNBUFFERED))
|
||||
{
|
||||
fileStream->Buffer = NULL;
|
||||
fileStream->BufferLength = BufferLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileStream->Buffer = NULL;
|
||||
fileStream->BufferLength = 0;
|
||||
}
|
||||
|
||||
fileStream->ReadPosition = 0;
|
||||
fileStream->ReadLength = 0;
|
||||
fileStream->WritePosition = 0;
|
||||
|
||||
*FileStream = fileStream;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID NTAPI PhpFileStreamDeleteProcedure(
|
||||
_In_ PVOID Object,
|
||||
_In_ ULONG Flags
|
||||
)
|
||||
{
|
||||
PPH_FILE_STREAM fileStream = (PPH_FILE_STREAM)Object;
|
||||
|
||||
PhFlushFileStream(fileStream, FALSE);
|
||||
|
||||
if (!(fileStream->Flags & PH_FILE_STREAM_HANDLE_UNOWNED))
|
||||
NtClose(fileStream->FileHandle);
|
||||
|
||||
if (fileStream->Buffer)
|
||||
PhFreePage(fileStream->Buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a file stream's position matches the position held by the file object.
|
||||
*/
|
||||
VOID PhVerifyFileStream(
|
||||
_In_ PPH_FILE_STREAM FileStream
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
// If the file object is asynchronous, the file object doesn't maintain its position.
|
||||
if (!(FileStream->Flags & (
|
||||
PH_FILE_STREAM_OWN_POSITION |
|
||||
PH_FILE_STREAM_ASYNCHRONOUS
|
||||
)))
|
||||
{
|
||||
FILE_POSITION_INFORMATION positionInfo;
|
||||
IO_STATUS_BLOCK isb;
|
||||
|
||||
if (!NT_SUCCESS(status = NtQueryInformationFile(
|
||||
FileStream->FileHandle,
|
||||
&isb,
|
||||
&positionInfo,
|
||||
sizeof(FILE_POSITION_INFORMATION),
|
||||
FilePositionInformation
|
||||
)))
|
||||
PhRaiseStatus(status);
|
||||
|
||||
if (FileStream->Position.QuadPart != positionInfo.CurrentByteOffset.QuadPart)
|
||||
PhRaiseStatus(STATUS_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS PhpAllocateBufferFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream
|
||||
)
|
||||
{
|
||||
FileStream->Buffer = PhAllocatePage(FileStream->BufferLength, NULL);
|
||||
|
||||
if (FileStream->Buffer)
|
||||
return STATUS_SUCCESS;
|
||||
else
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
NTSTATUS PhpReadFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_Out_writes_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length,
|
||||
_Out_opt_ PULONG ReadLength
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK isb;
|
||||
PLARGE_INTEGER position;
|
||||
|
||||
position = NULL;
|
||||
|
||||
if (FileStream->Flags & PH_FILE_STREAM_OWN_POSITION)
|
||||
position = &FileStream->Position;
|
||||
|
||||
status = NtReadFile(
|
||||
FileStream->FileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&isb,
|
||||
Buffer,
|
||||
Length,
|
||||
position,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (status == STATUS_PENDING)
|
||||
{
|
||||
// Wait for the operation to finish. This probably means we got called on an asynchronous
|
||||
// file object.
|
||||
status = NtWaitForSingleObject(FileStream->FileHandle, FALSE, NULL);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
status = isb.Status;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
FileStream->Position.QuadPart += isb.Information;
|
||||
|
||||
if (ReadLength)
|
||||
*ReadLength = (ULONG)isb.Information;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhReadFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_Out_writes_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length,
|
||||
_Out_opt_ PULONG ReadLength
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
ULONG availableLength;
|
||||
ULONG readLength;
|
||||
|
||||
if (FileStream->Flags & PH_FILE_STREAM_UNBUFFERED)
|
||||
{
|
||||
return PhpReadFileStream(
|
||||
FileStream,
|
||||
Buffer,
|
||||
Length,
|
||||
ReadLength
|
||||
);
|
||||
}
|
||||
|
||||
// How much do we have available to copy out of the buffer?
|
||||
availableLength = FileStream->ReadLength - FileStream->ReadPosition;
|
||||
|
||||
if (availableLength == 0)
|
||||
{
|
||||
// Make sure buffered writes are flushed.
|
||||
if (FileStream->WritePosition != 0)
|
||||
{
|
||||
if (!NT_SUCCESS(status = PhpFlushWriteFileStream(FileStream)))
|
||||
return status;
|
||||
}
|
||||
|
||||
// If this read is too big, pass it through.
|
||||
if (Length >= FileStream->BufferLength)
|
||||
{
|
||||
// These are now invalid.
|
||||
FileStream->ReadPosition = 0;
|
||||
FileStream->ReadLength = 0;
|
||||
|
||||
return PhpReadFileStream(
|
||||
FileStream,
|
||||
Buffer,
|
||||
Length,
|
||||
ReadLength
|
||||
);
|
||||
}
|
||||
|
||||
if (!FileStream->Buffer)
|
||||
{
|
||||
if (!NT_SUCCESS(status = PhpAllocateBufferFileStream(FileStream)))
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read as much as we can into our buffer.
|
||||
if (!NT_SUCCESS(status = PhpReadFileStream(
|
||||
FileStream,
|
||||
FileStream->Buffer,
|
||||
FileStream->BufferLength,
|
||||
&readLength
|
||||
)))
|
||||
return status;
|
||||
|
||||
if (readLength == 0)
|
||||
{
|
||||
// No data read.
|
||||
if (ReadLength)
|
||||
*ReadLength = readLength;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FileStream->ReadPosition = 0;
|
||||
FileStream->ReadLength = readLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
readLength = availableLength;
|
||||
}
|
||||
|
||||
if (readLength > Length)
|
||||
readLength = Length;
|
||||
|
||||
// Try to satisfy the request from the buffer.
|
||||
memcpy(
|
||||
Buffer,
|
||||
(PCHAR)FileStream->Buffer + FileStream->ReadPosition,
|
||||
readLength
|
||||
);
|
||||
FileStream->ReadPosition += readLength;
|
||||
|
||||
// If we didn't completely satisfy the request, read some more.
|
||||
if (
|
||||
readLength < Length &&
|
||||
// Don't try to read more if the buffer wasn't even filled up last time. (No more to read.)
|
||||
FileStream->ReadLength == FileStream->BufferLength
|
||||
)
|
||||
{
|
||||
ULONG readLength2;
|
||||
|
||||
if (NT_SUCCESS(status = PhpReadFileStream(
|
||||
FileStream,
|
||||
(PCHAR)Buffer + readLength,
|
||||
Length - readLength,
|
||||
&readLength2
|
||||
)))
|
||||
{
|
||||
readLength += readLength2;
|
||||
// These are now invalid.
|
||||
FileStream->ReadPosition = 0;
|
||||
FileStream->ReadLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
if (ReadLength)
|
||||
*ReadLength = readLength;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhpWriteFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_reads_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK isb;
|
||||
PLARGE_INTEGER position;
|
||||
|
||||
position = NULL;
|
||||
|
||||
if (FileStream->Flags & PH_FILE_STREAM_OWN_POSITION)
|
||||
position = &FileStream->Position;
|
||||
|
||||
status = NtWriteFile(
|
||||
FileStream->FileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&isb,
|
||||
Buffer,
|
||||
Length,
|
||||
position,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (status == STATUS_PENDING)
|
||||
{
|
||||
// Wait for the operation to finish. This probably means we got called on an asynchronous
|
||||
// file object.
|
||||
status = NtWaitForSingleObject(FileStream->FileHandle, FALSE, NULL);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
status = isb.Status;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
FileStream->Position.QuadPart += isb.Information;
|
||||
FileStream->Flags |= PH_FILE_STREAM_WRITTEN;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhWriteFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_reads_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
ULONG availableLength;
|
||||
ULONG writtenLength;
|
||||
|
||||
if (FileStream->Flags & PH_FILE_STREAM_UNBUFFERED)
|
||||
{
|
||||
return PhpWriteFileStream(
|
||||
FileStream,
|
||||
Buffer,
|
||||
Length
|
||||
);
|
||||
}
|
||||
|
||||
if (FileStream->WritePosition == 0)
|
||||
{
|
||||
// Make sure buffered reads are flushed.
|
||||
if (!NT_SUCCESS(status = PhpFlushReadFileStream(FileStream)))
|
||||
return status;
|
||||
}
|
||||
|
||||
if (FileStream->WritePosition != 0)
|
||||
{
|
||||
availableLength = FileStream->BufferLength - FileStream->WritePosition;
|
||||
|
||||
// Try to satisfy the request by copying the data to the buffer.
|
||||
if (availableLength != 0)
|
||||
{
|
||||
writtenLength = availableLength;
|
||||
|
||||
if (writtenLength > Length)
|
||||
writtenLength = Length;
|
||||
|
||||
memcpy(
|
||||
(PCHAR)FileStream->Buffer + FileStream->WritePosition,
|
||||
Buffer,
|
||||
writtenLength
|
||||
);
|
||||
FileStream->WritePosition += writtenLength;
|
||||
|
||||
if (writtenLength == Length)
|
||||
{
|
||||
// The request has been completely satisfied.
|
||||
return status;
|
||||
}
|
||||
|
||||
Buffer = (PCHAR)Buffer + writtenLength;
|
||||
Length -= writtenLength;
|
||||
}
|
||||
|
||||
// If we didn't completely satisfy the request, it's because the buffer is full. Flush it.
|
||||
if (!NT_SUCCESS(status = PhpWriteFileStream(
|
||||
FileStream,
|
||||
FileStream->Buffer,
|
||||
FileStream->WritePosition
|
||||
)))
|
||||
return status;
|
||||
|
||||
FileStream->WritePosition = 0;
|
||||
}
|
||||
|
||||
// If the write is too big, pass it through.
|
||||
if (Length >= FileStream->BufferLength)
|
||||
{
|
||||
if (!NT_SUCCESS(status = PhpWriteFileStream(
|
||||
FileStream,
|
||||
Buffer,
|
||||
Length
|
||||
)))
|
||||
return status;
|
||||
}
|
||||
else if (Length != 0)
|
||||
{
|
||||
if (!FileStream->Buffer)
|
||||
{
|
||||
if (!NT_SUCCESS(status = PhpAllocateBufferFileStream(FileStream)))
|
||||
return status;
|
||||
}
|
||||
|
||||
// Completely satisfy the request by copying the data to the buffer.
|
||||
memcpy(
|
||||
FileStream->Buffer,
|
||||
Buffer,
|
||||
Length
|
||||
);
|
||||
FileStream->WritePosition = Length;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhpFlushReadFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
if (FileStream->ReadLength - FileStream->ReadPosition != 0)
|
||||
{
|
||||
LARGE_INTEGER offset;
|
||||
|
||||
// We have some buffered read data, so our position is too far ahead. We need to move it
|
||||
// back to the first unused byte.
|
||||
offset.QuadPart = -(LONG)(FileStream->ReadLength - FileStream->ReadPosition);
|
||||
|
||||
if (!NT_SUCCESS(status = PhpSeekFileStream(
|
||||
FileStream,
|
||||
&offset,
|
||||
SeekCurrent
|
||||
)))
|
||||
return status;
|
||||
}
|
||||
|
||||
FileStream->ReadPosition = 0;
|
||||
FileStream->ReadLength = 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhpFlushWriteFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
if (!NT_SUCCESS(status = PhpWriteFileStream(
|
||||
FileStream,
|
||||
FileStream->Buffer,
|
||||
FileStream->WritePosition
|
||||
)))
|
||||
return status;
|
||||
|
||||
FileStream->WritePosition = 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the file stream.
|
||||
*
|
||||
* \param FileStream A file stream object.
|
||||
* \param Full TRUE to flush the file object through the operating system, otherwise FALSE to only
|
||||
* ensure the buffer is flushed to the operating system.
|
||||
*/
|
||||
NTSTATUS PhFlushFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ BOOLEAN Full
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
if (FileStream->WritePosition != 0)
|
||||
{
|
||||
if (!NT_SUCCESS(status = PhpFlushWriteFileStream(FileStream)))
|
||||
return status;
|
||||
}
|
||||
|
||||
if (FileStream->ReadPosition != 0)
|
||||
{
|
||||
if (!NT_SUCCESS(status = PhpFlushReadFileStream(FileStream)))
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Full && (FileStream->Flags & PH_FILE_STREAM_WRITTEN))
|
||||
{
|
||||
IO_STATUS_BLOCK isb;
|
||||
|
||||
if (!NT_SUCCESS(status = NtFlushBuffersFile(
|
||||
FileStream->FileHandle,
|
||||
&isb
|
||||
)))
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID PhGetPositionFileStream(
|
||||
_In_ PPH_FILE_STREAM FileStream,
|
||||
_Out_ PLARGE_INTEGER Position
|
||||
)
|
||||
{
|
||||
Position->QuadPart =
|
||||
FileStream->Position.QuadPart +
|
||||
(FileStream->ReadPosition - FileStream->ReadLength) +
|
||||
FileStream->WritePosition;
|
||||
}
|
||||
|
||||
NTSTATUS PhpSeekFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PLARGE_INTEGER Offset,
|
||||
_In_ PH_SEEK_ORIGIN Origin
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
switch (Origin)
|
||||
{
|
||||
case SeekStart:
|
||||
{
|
||||
FileStream->Position = *Offset;
|
||||
}
|
||||
break;
|
||||
case SeekCurrent:
|
||||
{
|
||||
FileStream->Position.QuadPart += Offset->QuadPart;
|
||||
}
|
||||
break;
|
||||
case SeekEnd:
|
||||
{
|
||||
if (!NT_SUCCESS(status = PhGetFileSize(
|
||||
FileStream->FileHandle,
|
||||
&FileStream->Position
|
||||
)))
|
||||
return status;
|
||||
|
||||
FileStream->Position.QuadPart += Offset->QuadPart;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(FileStream->Flags & PH_FILE_STREAM_OWN_POSITION))
|
||||
{
|
||||
FILE_POSITION_INFORMATION positionInfo;
|
||||
IO_STATUS_BLOCK isb;
|
||||
|
||||
positionInfo.CurrentByteOffset = FileStream->Position;
|
||||
|
||||
if (!NT_SUCCESS(status = NtSetInformationFile(
|
||||
FileStream->FileHandle,
|
||||
&isb,
|
||||
&positionInfo,
|
||||
sizeof(FILE_POSITION_INFORMATION),
|
||||
FilePositionInformation
|
||||
)))
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhSeekFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PLARGE_INTEGER Offset,
|
||||
_In_ PH_SEEK_ORIGIN Origin
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
LARGE_INTEGER offset;
|
||||
|
||||
offset = *Offset;
|
||||
|
||||
if (FileStream->WritePosition != 0)
|
||||
{
|
||||
if (!NT_SUCCESS(status = PhpFlushWriteFileStream(FileStream)))
|
||||
return status;
|
||||
}
|
||||
else if (FileStream->ReadPosition != 0)
|
||||
{
|
||||
if (Origin == SeekCurrent)
|
||||
{
|
||||
// We have buffered read data, which means our position is too far ahead. Subtract this
|
||||
// difference from the offset (which will affect the position accordingly).
|
||||
offset.QuadPart -= FileStream->ReadLength - FileStream->ReadPosition;
|
||||
}
|
||||
|
||||
// TODO: Try to keep some of the read buffer.
|
||||
FileStream->ReadPosition = 0;
|
||||
FileStream->ReadLength = 0;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status = PhpSeekFileStream(
|
||||
FileStream,
|
||||
&offset,
|
||||
Origin
|
||||
)))
|
||||
return status;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhLockFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PLARGE_INTEGER Position,
|
||||
_In_ PLARGE_INTEGER Length,
|
||||
_In_ BOOLEAN Wait,
|
||||
_In_ BOOLEAN Shared
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
IO_STATUS_BLOCK isb;
|
||||
|
||||
status = NtLockFile(
|
||||
FileStream->FileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&isb,
|
||||
Position,
|
||||
Length,
|
||||
0,
|
||||
!Wait,
|
||||
!Shared
|
||||
);
|
||||
|
||||
if (status == STATUS_PENDING)
|
||||
{
|
||||
// Wait for the operation to finish. This probably means we got called on an asynchronous
|
||||
// file object.
|
||||
NtWaitForSingleObject(FileStream->FileHandle, FALSE, NULL);
|
||||
status = isb.Status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhUnlockFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PLARGE_INTEGER Position,
|
||||
_In_ PLARGE_INTEGER Length
|
||||
)
|
||||
{
|
||||
IO_STATUS_BLOCK isb;
|
||||
|
||||
return NtUnlockFile(
|
||||
FileStream->FileHandle,
|
||||
&isb,
|
||||
Position,
|
||||
Length,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
NTSTATUS PhWriteStringAsUtf8FileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PPH_STRINGREF String
|
||||
)
|
||||
{
|
||||
return PhWriteStringAsUtf8FileStreamEx(FileStream, String->Buffer, String->Length);
|
||||
}
|
||||
|
||||
NTSTATUS PhWriteStringAsUtf8FileStream2(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PWSTR String
|
||||
)
|
||||
{
|
||||
PH_STRINGREF string;
|
||||
|
||||
PhInitializeStringRef(&string, String);
|
||||
|
||||
return PhWriteStringAsUtf8FileStream(FileStream, &string);
|
||||
}
|
||||
|
||||
NTSTATUS PhWriteStringAsUtf8FileStreamEx(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PWSTR Buffer,
|
||||
_In_ SIZE_T Length
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
PH_STRINGREF block;
|
||||
SIZE_T inPlaceUtf8Size;
|
||||
PCHAR inPlaceUtf8 = NULL;
|
||||
PPH_BYTES utf8 = NULL;
|
||||
|
||||
if (Length > PAGE_SIZE)
|
||||
{
|
||||
// In UTF-8, the maximum number of bytes per code point is 4.
|
||||
inPlaceUtf8Size = PAGE_SIZE / sizeof(WCHAR) * 4;
|
||||
inPlaceUtf8 = PhAllocatePage(inPlaceUtf8Size, NULL);
|
||||
}
|
||||
|
||||
while (Length != 0)
|
||||
{
|
||||
block.Buffer = Buffer;
|
||||
block.Length = PAGE_SIZE;
|
||||
|
||||
if (block.Length > Length)
|
||||
block.Length = Length;
|
||||
|
||||
if (inPlaceUtf8)
|
||||
{
|
||||
SIZE_T bytesInUtf8String;
|
||||
|
||||
if (!PhConvertUtf16ToUtf8Buffer(
|
||||
inPlaceUtf8,
|
||||
inPlaceUtf8Size,
|
||||
&bytesInUtf8String,
|
||||
block.Buffer,
|
||||
block.Length
|
||||
))
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto CleanupExit;
|
||||
}
|
||||
|
||||
status = PhWriteFileStream(FileStream, inPlaceUtf8, (ULONG)bytesInUtf8String);
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8 = PhConvertUtf16ToUtf8Ex(block.Buffer, block.Length);
|
||||
|
||||
if (!utf8)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto CleanupExit;
|
||||
}
|
||||
|
||||
status = PhWriteFileStream(FileStream, utf8->Buffer, (ULONG)utf8->Length);
|
||||
PhDereferenceObject(utf8);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
goto CleanupExit;
|
||||
|
||||
Buffer += block.Length / sizeof(WCHAR);
|
||||
Length -= block.Length;
|
||||
}
|
||||
|
||||
CleanupExit:
|
||||
if (inPlaceUtf8)
|
||||
PhFreePage(inPlaceUtf8);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhWriteStringFormatAsUtf8FileStream_V(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ _Printf_format_string_ PWSTR Format,
|
||||
_In_ va_list ArgPtr
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PPH_STRING string;
|
||||
|
||||
string = PhFormatString_V(Format, ArgPtr);
|
||||
status = PhWriteStringAsUtf8FileStream(FileStream, &string->sr);
|
||||
PhDereferenceObject(string);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhWriteStringFormatAsUtf8FileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ _Printf_format_string_ PWSTR Format,
|
||||
...
|
||||
)
|
||||
{
|
||||
va_list argptr;
|
||||
|
||||
va_start(argptr, Format);
|
||||
|
||||
return PhWriteStringFormatAsUtf8FileStream_V(FileStream, Format, argptr);
|
||||
}
|
||||
276
phlib/format.c
Normal file
276
phlib/format.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* string formatting
|
||||
*
|
||||
* Copyright (C) 2010-2015 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module provides a high-performance string formatting mechanism. Instead of using format
|
||||
* strings, the user supplies an array of structures. This system is 2-5 times faster than
|
||||
* printf-based functions.
|
||||
*
|
||||
* This file contains the public interfaces, while including the real formatting code from
|
||||
* elsewhere. There are currently two functions: PhFormat, which returns a string object containing
|
||||
* the formatted string, and PhFormatToBuffer, which writes the formatted string to a buffer. The
|
||||
* latter is a bit faster due to the lack of resizing logic.
|
||||
*/
|
||||
|
||||
#include <phbase.h>
|
||||
#include <locale.h>
|
||||
|
||||
extern ULONG PhMaxSizeUnit;
|
||||
|
||||
#define SMALL_BUFFER_LENGTH (PH_OBJECT_SMALL_OBJECT_SIZE - FIELD_OFFSET(PH_STRING, Data) - sizeof(WCHAR))
|
||||
#define BUFFER_SIZE 512
|
||||
|
||||
#define PHP_FORMAT_NEGATIVE 0x1
|
||||
#define PHP_FORMAT_POSITIVE 0x2
|
||||
#define PHP_FORMAT_PAD 0x4
|
||||
|
||||
// Internal CRT routine needed for floating-point conversion
|
||||
|
||||
errno_t __cdecl _cfltcvt_l(double *arg, char *buffer, size_t sizeInBytes,
|
||||
int format, int precision, int caps, _locale_t plocinfo);
|
||||
|
||||
// Keep in sync with PhSizeUnitNames
|
||||
static PH_STRINGREF PhpSizeUnitNamesCounted[7] =
|
||||
{
|
||||
PH_STRINGREF_INIT(L"B"),
|
||||
PH_STRINGREF_INIT(L"kB"),
|
||||
PH_STRINGREF_INIT(L"MB"),
|
||||
PH_STRINGREF_INIT(L"GB"),
|
||||
PH_STRINGREF_INIT(L"TB"),
|
||||
PH_STRINGREF_INIT(L"PB"),
|
||||
PH_STRINGREF_INIT(L"EB")
|
||||
};
|
||||
|
||||
static PH_INITONCE PhpFormatInitOnce = PH_INITONCE_INIT;
|
||||
static WCHAR PhpFormatDecimalSeparator = '.';
|
||||
static WCHAR PhpFormatThousandSeparator = ',';
|
||||
static _locale_t PhpFormatUserLocale = NULL;
|
||||
|
||||
#if (_MSC_VER >= 1900)
|
||||
|
||||
// See Source\10.0.10150.0\ucrt\convert\cvt.cpp in SDK v10.
|
||||
errno_t __cdecl __acrt_fp_format(
|
||||
double const* const value,
|
||||
char* const result_buffer,
|
||||
size_t const result_buffer_count,
|
||||
char* const scratch_buffer,
|
||||
size_t const scratch_buffer_count,
|
||||
int const format,
|
||||
int const precision,
|
||||
UINT64 const options,
|
||||
_locale_t const locale
|
||||
);
|
||||
|
||||
static errno_t __cdecl _cfltcvt_l(double *arg, char *buffer, size_t sizeInBytes,
|
||||
int format, int precision, int caps, _locale_t plocinfo)
|
||||
{
|
||||
char scratch_buffer[_CVTBUFSIZE + 1];
|
||||
|
||||
if (caps & 1)
|
||||
format -= 32; // Make uppercase
|
||||
|
||||
return __acrt_fp_format(arg, buffer, sizeInBytes, scratch_buffer, sizeof(scratch_buffer),
|
||||
format, precision, 0, plocinfo);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// From Source\10.0.10150.0\ucrt\inc\corecrt_internal_stdio_output.h in SDK v10.
|
||||
VOID PhpCropZeros(
|
||||
_Inout_ PCHAR Buffer,
|
||||
_In_ _locale_t Locale
|
||||
)
|
||||
{
|
||||
CHAR decimalSeparator = (CHAR)PhpFormatDecimalSeparator;
|
||||
|
||||
while (*Buffer && *Buffer != decimalSeparator)
|
||||
++Buffer;
|
||||
|
||||
if (*Buffer++)
|
||||
{
|
||||
while (*Buffer && *Buffer != 'e' && *Buffer != 'E')
|
||||
++Buffer;
|
||||
|
||||
PCHAR stop = Buffer--;
|
||||
|
||||
while (*Buffer == '0')
|
||||
--Buffer;
|
||||
|
||||
if (*Buffer == decimalSeparator)
|
||||
--Buffer;
|
||||
|
||||
while ((*++Buffer = *stop++) != '\0')
|
||||
NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
PPH_STRING PhpResizeFormatBuffer(
|
||||
_In_ PPH_STRING String,
|
||||
_Inout_ PSIZE_T AllocatedLength,
|
||||
_In_ SIZE_T UsedLength,
|
||||
_In_ SIZE_T NeededLength
|
||||
)
|
||||
{
|
||||
PPH_STRING newString;
|
||||
SIZE_T allocatedLength;
|
||||
|
||||
allocatedLength = *AllocatedLength;
|
||||
allocatedLength *= 2;
|
||||
|
||||
if (allocatedLength < UsedLength + NeededLength)
|
||||
allocatedLength = UsedLength + NeededLength;
|
||||
|
||||
newString = PhCreateStringEx(NULL, allocatedLength);
|
||||
memcpy(newString->Buffer, String->Buffer, UsedLength);
|
||||
PhDereferenceObject(String);
|
||||
|
||||
*AllocatedLength = allocatedLength;
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a formatted string.
|
||||
*
|
||||
* \param Format An array of format structures.
|
||||
* \param Count The number of structures supplied in \a Format.
|
||||
* \param InitialCapacity The number of bytes to reserve initially for the string. If 0 is
|
||||
* specified, a default value is used.
|
||||
*/
|
||||
PPH_STRING PhFormat(
|
||||
_In_reads_(Count) PPH_FORMAT Format,
|
||||
_In_ ULONG Count,
|
||||
_In_opt_ SIZE_T InitialCapacity
|
||||
)
|
||||
{
|
||||
PPH_STRING string;
|
||||
SIZE_T allocatedLength;
|
||||
PWSTR buffer;
|
||||
SIZE_T usedLength;
|
||||
|
||||
// Set up the buffer.
|
||||
|
||||
// If the specified initial capacity is too small (or zero), use the largest buffer size which
|
||||
// will still be eligible for allocation from the small object free list.
|
||||
if (InitialCapacity < SMALL_BUFFER_LENGTH)
|
||||
InitialCapacity = SMALL_BUFFER_LENGTH;
|
||||
|
||||
string = PhCreateStringEx(NULL, InitialCapacity);
|
||||
allocatedLength = InitialCapacity;
|
||||
buffer = string->Buffer;
|
||||
usedLength = 0;
|
||||
|
||||
#undef ENSURE_BUFFER
|
||||
#undef OK_BUFFER
|
||||
#undef ADVANCE_BUFFER
|
||||
|
||||
#define ENSURE_BUFFER(NeededLength) \
|
||||
do { \
|
||||
if (allocatedLength < usedLength + (NeededLength)) \
|
||||
{ \
|
||||
string = PhpResizeFormatBuffer(string, &allocatedLength, usedLength, (NeededLength)); \
|
||||
buffer = string->Buffer + usedLength / sizeof(WCHAR); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define OK_BUFFER (TRUE)
|
||||
|
||||
#define ADVANCE_BUFFER(Length) \
|
||||
do { buffer += (Length) / sizeof(WCHAR); usedLength += (Length); } while (0)
|
||||
|
||||
#include "format_i.h"
|
||||
|
||||
string->Length = usedLength;
|
||||
// Null-terminate the string.
|
||||
string->Buffer[usedLength / sizeof(WCHAR)] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a formatted string to a buffer.
|
||||
*
|
||||
* \param Format An array of format structures.
|
||||
* \param Count The number of structures supplied in \a Format.
|
||||
* \param Buffer A buffer. If NULL, no data is written.
|
||||
* \param BufferLength The number of bytes available in \a Buffer, including space for the null
|
||||
* terminator.
|
||||
* \param ReturnLength The number of bytes required to hold the string, including the null
|
||||
* terminator.
|
||||
*
|
||||
* \return TRUE if the buffer was large enough and the string was written (i.e. \a BufferLength >=
|
||||
* \a ReturnLength), otherwise FALSE. In either case, the required number of bytes is stored in
|
||||
* \a ReturnLength.
|
||||
*
|
||||
* \remarks If the function fails but \a BufferLength != 0, a single null byte is written to the
|
||||
* start of \a Buffer.
|
||||
*/
|
||||
BOOLEAN PhFormatToBuffer(
|
||||
_In_reads_(Count) PPH_FORMAT Format,
|
||||
_In_ ULONG Count,
|
||||
_Out_writes_bytes_opt_(BufferLength) PWSTR Buffer,
|
||||
_In_opt_ SIZE_T BufferLength,
|
||||
_Out_opt_ PSIZE_T ReturnLength
|
||||
)
|
||||
{
|
||||
PWSTR buffer;
|
||||
SIZE_T usedLength;
|
||||
BOOLEAN overrun;
|
||||
|
||||
buffer = Buffer;
|
||||
usedLength = 0;
|
||||
overrun = FALSE;
|
||||
|
||||
// Make sure we don't try to write anything if we don't have a buffer.
|
||||
if (!Buffer)
|
||||
overrun = TRUE;
|
||||
|
||||
#undef ENSURE_BUFFER
|
||||
#undef OK_BUFFER
|
||||
#undef ADVANCE_BUFFER
|
||||
|
||||
#define ENSURE_BUFFER(NeededLength) \
|
||||
do { \
|
||||
if (!overrun && (BufferLength < usedLength + (NeededLength))) \
|
||||
overrun = TRUE; \
|
||||
} while (0)
|
||||
|
||||
#define OK_BUFFER (!overrun)
|
||||
|
||||
#define ADVANCE_BUFFER(Length) \
|
||||
do { buffer += (Length) / sizeof(WCHAR); usedLength += (Length); } while (0)
|
||||
|
||||
#include "format_i.h"
|
||||
|
||||
// Write the null-terminator.
|
||||
ENSURE_BUFFER(sizeof(WCHAR));
|
||||
if (OK_BUFFER)
|
||||
*buffer = 0;
|
||||
else if (Buffer && BufferLength != 0) // try to null-terminate even if this function fails
|
||||
*Buffer = 0;
|
||||
ADVANCE_BUFFER(sizeof(WCHAR));
|
||||
|
||||
if (ReturnLength)
|
||||
*ReturnLength = usedLength;
|
||||
|
||||
return OK_BUFFER;
|
||||
}
|
||||
568
phlib/format_i.h
Normal file
568
phlib/format_i.h
Normal file
@@ -0,0 +1,568 @@
|
||||
/*
|
||||
* This file contains the actual formatting code used by various public interface functions.
|
||||
*
|
||||
* There are three macros defined by the parent function which control how this code writes the
|
||||
* formatted string:
|
||||
* * ENSURE_BUFFER - This macro is passed the number of bytes required whenever characters need to
|
||||
* be written to the buffer. The macro can resize the buffer if needed.
|
||||
* * OK_BUFFER - This macro returns TRUE if it is OK to write to the buffer, otherwise FALSE when
|
||||
* the buffer is too large, is not specified, or some other error has occurred.
|
||||
* * ADVANCE_BUFFER - This macro is passed the number of bytes written to the buffer and should
|
||||
* increment the "buffer" pointer and "usedLength" counter.
|
||||
* In addition to these macros, the "buffer" and "usedLength" variables are assumed to be present.
|
||||
*
|
||||
* The below code defines many macros; this is so that composite formatting types can be constructed
|
||||
* (e.g. the "size" type).
|
||||
*/
|
||||
|
||||
{
|
||||
if (PhBeginInitOnce(&PhpFormatInitOnce))
|
||||
{
|
||||
WCHAR localeBuffer[4];
|
||||
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, localeBuffer, 4) &&
|
||||
(localeBuffer[0] != 0 && localeBuffer[1] == 0))
|
||||
{
|
||||
PhpFormatDecimalSeparator = localeBuffer[0];
|
||||
}
|
||||
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, localeBuffer, 4) &&
|
||||
(localeBuffer[0] != 0 && localeBuffer[1] == 0))
|
||||
{
|
||||
PhpFormatThousandSeparator = localeBuffer[0];
|
||||
}
|
||||
|
||||
if (PhpFormatDecimalSeparator != '.')
|
||||
PhpFormatUserLocale = _create_locale(LC_ALL, "");
|
||||
|
||||
PhEndInitOnce(&PhpFormatInitOnce);
|
||||
}
|
||||
|
||||
while (Count--)
|
||||
{
|
||||
PPH_FORMAT format;
|
||||
SIZE_T partLength;
|
||||
WCHAR tempBuffer[BUFFER_SIZE];
|
||||
ULONG flags;
|
||||
ULONG int32;
|
||||
ULONG64 int64;
|
||||
|
||||
format = Format++;
|
||||
|
||||
// Save the currently used length so we can compute the part length later.
|
||||
partLength = usedLength;
|
||||
|
||||
flags = 0;
|
||||
|
||||
switch (format->Type & FormatTypeMask)
|
||||
{
|
||||
|
||||
// Characters and Strings
|
||||
|
||||
case CharFormatType:
|
||||
ENSURE_BUFFER(sizeof(WCHAR));
|
||||
if (OK_BUFFER)
|
||||
*buffer = format->u.Char;
|
||||
ADVANCE_BUFFER(sizeof(WCHAR));
|
||||
break;
|
||||
case StringFormatType:
|
||||
ENSURE_BUFFER(format->u.String.Length);
|
||||
if (OK_BUFFER)
|
||||
memcpy(buffer, format->u.String.Buffer, format->u.String.Length);
|
||||
ADVANCE_BUFFER(format->u.String.Length);
|
||||
break;
|
||||
case StringZFormatType:
|
||||
{
|
||||
SIZE_T count;
|
||||
|
||||
count = PhCountStringZ(format->u.StringZ);
|
||||
ENSURE_BUFFER(count * sizeof(WCHAR));
|
||||
if (OK_BUFFER)
|
||||
memcpy(buffer, format->u.StringZ, count * sizeof(WCHAR));
|
||||
ADVANCE_BUFFER(count * sizeof(WCHAR));
|
||||
}
|
||||
break;
|
||||
case MultiByteStringFormatType:
|
||||
case MultiByteStringZFormatType:
|
||||
{
|
||||
ULONG bytesInUnicodeString;
|
||||
PSTR multiByteBuffer;
|
||||
SIZE_T multiByteLength;
|
||||
|
||||
if (format->Type == MultiByteStringFormatType)
|
||||
{
|
||||
multiByteBuffer = format->u.MultiByteString.Buffer;
|
||||
multiByteLength = format->u.MultiByteString.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
multiByteBuffer = format->u.MultiByteStringZ;
|
||||
multiByteLength = strlen(multiByteBuffer);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(RtlMultiByteToUnicodeSize(
|
||||
&bytesInUnicodeString,
|
||||
multiByteBuffer,
|
||||
(ULONG)multiByteLength
|
||||
)))
|
||||
{
|
||||
ENSURE_BUFFER(bytesInUnicodeString);
|
||||
|
||||
if (!OK_BUFFER || NT_SUCCESS(RtlMultiByteToUnicodeN(
|
||||
buffer,
|
||||
bytesInUnicodeString,
|
||||
NULL,
|
||||
multiByteBuffer,
|
||||
(ULONG)multiByteLength
|
||||
)))
|
||||
{
|
||||
ADVANCE_BUFFER(bytesInUnicodeString);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Integers
|
||||
|
||||
#define PROCESS_DIGIT(Input) \
|
||||
do { \
|
||||
r = (ULONG)(Input % radix); \
|
||||
Input /= radix; \
|
||||
*temp-- = integerToChar[r]; \
|
||||
tempCount++; \
|
||||
} while (0)
|
||||
|
||||
#define COMMON_INTEGER_FORMAT(Input, Format) \
|
||||
do { \
|
||||
ULONG radix; \
|
||||
PCHAR integerToChar; \
|
||||
PWSTR temp; \
|
||||
ULONG tempCount; \
|
||||
ULONG r; \
|
||||
ULONG preCount; \
|
||||
ULONG padCount; \
|
||||
\
|
||||
radix = 10; \
|
||||
if (((Format)->Type & FormatUseRadix) && (Format)->Radix >= 2 && (Format)->Radix <= 69) \
|
||||
radix = (Format)->Radix; \
|
||||
integerToChar = PhIntegerToChar; \
|
||||
if ((Format)->Type & FormatUpperCase) \
|
||||
integerToChar = PhIntegerToCharUpper; \
|
||||
temp = tempBuffer + BUFFER_SIZE - 1; \
|
||||
tempCount = 0; \
|
||||
\
|
||||
if (Input != 0) \
|
||||
{ \
|
||||
if ((Format)->Type & FormatGroupDigits) \
|
||||
{ \
|
||||
ULONG needsSep = 0; \
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
PROCESS_DIGIT(Input); \
|
||||
\
|
||||
if (++needsSep == 3 && Input != 0) /* get rid of trailing separator */ \
|
||||
{ \
|
||||
*temp-- = PhpFormatThousandSeparator; \
|
||||
tempCount++; \
|
||||
needsSep = 0; \
|
||||
} \
|
||||
} while (Input != 0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
do \
|
||||
{ \
|
||||
PROCESS_DIGIT(Input); \
|
||||
} while (Input != 0); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
*temp-- = '0'; \
|
||||
tempCount++; \
|
||||
} \
|
||||
\
|
||||
preCount = 0; \
|
||||
\
|
||||
if (flags & PHP_FORMAT_NEGATIVE) \
|
||||
preCount++; \
|
||||
else if ((Format)->Type & FormatPrefixSign) \
|
||||
preCount++; \
|
||||
\
|
||||
if (((Format)->Type & FormatPadZeros) && !((Format)->Type & FormatGroupDigits)) \
|
||||
{ \
|
||||
if (preCount + tempCount < (Format)->Width) \
|
||||
{ \
|
||||
flags |= PHP_FORMAT_PAD; \
|
||||
padCount = (Format)->Width - (preCount + tempCount); \
|
||||
preCount += padCount; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
temp++; \
|
||||
ENSURE_BUFFER((preCount + tempCount) * sizeof(WCHAR)); \
|
||||
if (OK_BUFFER) \
|
||||
{ \
|
||||
if (flags & PHP_FORMAT_NEGATIVE) \
|
||||
*buffer++ = '-'; \
|
||||
else if ((Format)->Type & FormatPrefixSign) \
|
||||
*buffer++ = '+'; \
|
||||
\
|
||||
if (flags & PHP_FORMAT_PAD) \
|
||||
{ \
|
||||
wmemset(buffer, '0', padCount); \
|
||||
buffer += padCount; \
|
||||
} \
|
||||
\
|
||||
memcpy(buffer, temp, tempCount * sizeof(WCHAR)); \
|
||||
buffer += tempCount; \
|
||||
} \
|
||||
usedLength += (preCount + tempCount) * sizeof(WCHAR); \
|
||||
} while (0)
|
||||
|
||||
#ifndef _WIN64
|
||||
case IntPtrFormatType:
|
||||
int32 = format->u.IntPtr;
|
||||
goto CommonMaybeNegativeInt32Format;
|
||||
#endif
|
||||
case Int32FormatType:
|
||||
int32 = format->u.Int32;
|
||||
|
||||
#ifndef _WIN64
|
||||
CommonMaybeNegativeInt32Format:
|
||||
#endif
|
||||
if ((LONG)int32 < 0)
|
||||
{
|
||||
int32 = -(LONG)int32;
|
||||
flags |= PHP_FORMAT_NEGATIVE;
|
||||
}
|
||||
|
||||
goto CommonInt32Format;
|
||||
#ifndef _WIN64
|
||||
case UIntPtrFormatType:
|
||||
int32 = format->u.UIntPtr;
|
||||
goto CommonInt32Format;
|
||||
#endif
|
||||
case UInt32FormatType:
|
||||
int32 = format->u.UInt32;
|
||||
CommonInt32Format:
|
||||
COMMON_INTEGER_FORMAT(int32, format);
|
||||
break;
|
||||
#ifdef _WIN64
|
||||
case IntPtrFormatType:
|
||||
int64 = format->u.IntPtr;
|
||||
goto CommonMaybeNegativeInt64Format;
|
||||
#endif
|
||||
case Int64FormatType:
|
||||
int64 = format->u.Int64;
|
||||
|
||||
#ifdef _WIN64
|
||||
CommonMaybeNegativeInt64Format:
|
||||
#endif
|
||||
if ((LONG64)int64 < 0)
|
||||
{
|
||||
int64 = -(LONG64)int64;
|
||||
flags |= PHP_FORMAT_NEGATIVE;
|
||||
}
|
||||
|
||||
goto CommonInt64Format;
|
||||
#ifdef _WIN64
|
||||
case UIntPtrFormatType:
|
||||
int64 = format->u.UIntPtr;
|
||||
goto CommonInt64Format;
|
||||
#endif
|
||||
case UInt64FormatType:
|
||||
int64 = format->u.UInt64;
|
||||
CommonInt64Format:
|
||||
COMMON_INTEGER_FORMAT(int64, format);
|
||||
break;
|
||||
|
||||
// Floating point numbers
|
||||
|
||||
#define COMMON_DOUBLE_FORMAT(Format) \
|
||||
do { \
|
||||
ULONG precision; \
|
||||
DOUBLE value; \
|
||||
CHAR c; \
|
||||
PSTR temp; \
|
||||
ULONG length; \
|
||||
\
|
||||
if ((Format)->Type & FormatUsePrecision) \
|
||||
{ \
|
||||
precision = (Format)->Precision; \
|
||||
\
|
||||
if (precision > BUFFER_SIZE - 1 - _CVTBUFSIZE) \
|
||||
precision = BUFFER_SIZE - 1 - _CVTBUFSIZE; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
precision = 6; \
|
||||
} \
|
||||
\
|
||||
c = 'f'; \
|
||||
\
|
||||
if ((Format)->Type & FormatStandardForm) \
|
||||
c = 'e'; \
|
||||
else if ((Format)->Type & FormatHexadecimalForm) \
|
||||
c = 'a'; \
|
||||
\
|
||||
/* Use MS CRT routines to do the work. */ \
|
||||
\
|
||||
value = (Format)->u.Double; \
|
||||
temp = (PSTR)tempBuffer + 1; /* leave one character so we can insert a prefix if needed */ \
|
||||
_cfltcvt_l( \
|
||||
&value, \
|
||||
temp, \
|
||||
sizeof(tempBuffer) - 1, \
|
||||
c, \
|
||||
precision, \
|
||||
!!((Format)->Type & FormatUpperCase), \
|
||||
PhpFormatUserLocale \
|
||||
); \
|
||||
\
|
||||
/* if (((Format)->Type & FormatForceDecimalPoint) && precision == 0) */ \
|
||||
/* _forcdecpt_l(tempBufferAnsi, PhpFormatUserLocale); */ \
|
||||
if ((Format)->Type & FormatCropZeros) \
|
||||
PhpCropZeros(temp, PhpFormatUserLocale); \
|
||||
\
|
||||
length = (ULONG)strlen(temp); \
|
||||
\
|
||||
if (temp[0] == '-') \
|
||||
{ \
|
||||
flags |= PHP_FORMAT_NEGATIVE; \
|
||||
temp++; \
|
||||
length--; \
|
||||
} \
|
||||
else if ((Format)->Type & FormatPrefixSign) \
|
||||
{ \
|
||||
flags |= PHP_FORMAT_POSITIVE; \
|
||||
} \
|
||||
\
|
||||
if (((Format)->Type & FormatGroupDigits) && !((Format)->Type & (FormatStandardForm | FormatHexadecimalForm))) \
|
||||
{ \
|
||||
PSTR whole; \
|
||||
PSTR decimalPoint; \
|
||||
ULONG wholeCount; \
|
||||
ULONG sepsCount; \
|
||||
ULONG ensureLength; \
|
||||
ULONG copyCount; \
|
||||
ULONG needsSep; \
|
||||
\
|
||||
/* Find the first non-digit character and assume that is the */ \
|
||||
/* decimal point (or the end of the string). */ \
|
||||
\
|
||||
whole = temp; \
|
||||
decimalPoint = temp; \
|
||||
\
|
||||
while ((UCHAR)(*decimalPoint - '0') < 10) \
|
||||
decimalPoint++; \
|
||||
\
|
||||
/* Copy the characters to the output buffer, and at the same time */ \
|
||||
/* insert the separators. */ \
|
||||
\
|
||||
wholeCount = (ULONG)(decimalPoint - temp); \
|
||||
\
|
||||
if (wholeCount != 0) \
|
||||
sepsCount = (wholeCount + 2) / 3 - 1; \
|
||||
else \
|
||||
sepsCount = 0; \
|
||||
\
|
||||
ensureLength = (length + sepsCount) * sizeof(WCHAR); \
|
||||
if (flags & (PHP_FORMAT_NEGATIVE | PHP_FORMAT_POSITIVE)) \
|
||||
ensureLength += sizeof(WCHAR); \
|
||||
ENSURE_BUFFER(ensureLength); \
|
||||
\
|
||||
copyCount = wholeCount; \
|
||||
needsSep = (wholeCount + 2) % 3; \
|
||||
\
|
||||
if (OK_BUFFER) \
|
||||
{ \
|
||||
if (flags & PHP_FORMAT_NEGATIVE) \
|
||||
*buffer++ = '-'; \
|
||||
else if (flags & PHP_FORMAT_POSITIVE) \
|
||||
*buffer++ = '+'; \
|
||||
\
|
||||
while (copyCount--) \
|
||||
{ \
|
||||
*buffer++ = *whole++; \
|
||||
\
|
||||
if (needsSep-- == 0 && copyCount != 0) /* get rid of trailing separator */ \
|
||||
{ \
|
||||
*buffer++ = PhpFormatThousandSeparator; \
|
||||
needsSep = 2; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (flags & (PHP_FORMAT_NEGATIVE | PHP_FORMAT_POSITIVE)) \
|
||||
usedLength += sizeof(WCHAR); \
|
||||
usedLength += (wholeCount + sepsCount) * sizeof(WCHAR); \
|
||||
\
|
||||
/* Copy the rest. */ \
|
||||
\
|
||||
copyCount = length - wholeCount; \
|
||||
\
|
||||
if (OK_BUFFER) \
|
||||
{ \
|
||||
PhZeroExtendToUtf16Buffer(decimalPoint, copyCount, buffer); \
|
||||
ADVANCE_BUFFER(copyCount * sizeof(WCHAR)); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
SIZE_T preLength; \
|
||||
SIZE_T padLength; \
|
||||
\
|
||||
/* Take care of the sign and zero padding. */ \
|
||||
preLength = 0; \
|
||||
\
|
||||
if (flags & (PHP_FORMAT_NEGATIVE | PHP_FORMAT_POSITIVE)) \
|
||||
preLength++; \
|
||||
\
|
||||
if ((Format)->Type & FormatPadZeros) \
|
||||
{ \
|
||||
if (preLength + length < (Format)->Width) \
|
||||
{ \
|
||||
flags |= PHP_FORMAT_PAD; \
|
||||
padLength = (Format)->Width - (preLength + length); \
|
||||
preLength += padLength; \
|
||||
} \
|
||||
} \
|
||||
/* We don't need to group digits, so directly copy the characters */ \
|
||||
/* to the output buffer. */ \
|
||||
\
|
||||
ENSURE_BUFFER((preLength + length) * sizeof(WCHAR)); \
|
||||
\
|
||||
if (OK_BUFFER) \
|
||||
{ \
|
||||
if (flags & PHP_FORMAT_NEGATIVE) \
|
||||
*buffer++ = '-'; \
|
||||
else if (flags & PHP_FORMAT_POSITIVE) \
|
||||
*buffer++ = '+'; \
|
||||
\
|
||||
if (flags & PHP_FORMAT_PAD) \
|
||||
{ \
|
||||
wmemset(buffer, '0', padLength); \
|
||||
buffer += padLength; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
usedLength += preLength * sizeof(WCHAR); \
|
||||
\
|
||||
if (OK_BUFFER) \
|
||||
{ \
|
||||
PhZeroExtendToUtf16Buffer((PSTR)temp, length, buffer); \
|
||||
ADVANCE_BUFFER(length * sizeof(WCHAR)); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
case DoubleFormatType:
|
||||
flags = 0;
|
||||
COMMON_DOUBLE_FORMAT(format);
|
||||
break;
|
||||
|
||||
// Additional types
|
||||
|
||||
case SizeFormatType:
|
||||
{
|
||||
ULONG i = 0;
|
||||
ULONG maxSizeUnit;
|
||||
DOUBLE s;
|
||||
PH_FORMAT doubleFormat;
|
||||
|
||||
s = (DOUBLE)format->u.Size;
|
||||
|
||||
if (format->u.Size == 0)
|
||||
{
|
||||
ENSURE_BUFFER(sizeof(WCHAR));
|
||||
if (OK_BUFFER)
|
||||
*buffer = '0';
|
||||
ADVANCE_BUFFER(sizeof(WCHAR));
|
||||
goto ContinueLoop;
|
||||
}
|
||||
|
||||
if (format->Type & FormatUseRadix)
|
||||
maxSizeUnit = format->Radix;
|
||||
else
|
||||
maxSizeUnit = PhMaxSizeUnit;
|
||||
|
||||
while (
|
||||
s >= 1000 &&
|
||||
i < sizeof(PhpSizeUnitNamesCounted) / sizeof(PH_STRINGREF) &&
|
||||
i < maxSizeUnit
|
||||
)
|
||||
{
|
||||
s /= 1024;
|
||||
i++;
|
||||
}
|
||||
|
||||
// Format the number, then append the unit name.
|
||||
|
||||
doubleFormat.Type = DoubleFormatType | FormatUsePrecision | FormatCropZeros | FormatGroupDigits;
|
||||
doubleFormat.Precision = (format->Type & FormatUsePrecision) ? format->Precision : 2;
|
||||
doubleFormat.Width = 0; // stupid compiler
|
||||
doubleFormat.u.Double = s;
|
||||
flags = 0;
|
||||
COMMON_DOUBLE_FORMAT(&doubleFormat);
|
||||
|
||||
ENSURE_BUFFER(sizeof(WCHAR) + PhpSizeUnitNamesCounted[i].Length);
|
||||
if (OK_BUFFER)
|
||||
{
|
||||
*buffer = ' ';
|
||||
memcpy(buffer + 1, PhpSizeUnitNamesCounted[i].Buffer, PhpSizeUnitNamesCounted[i].Length);
|
||||
}
|
||||
ADVANCE_BUFFER(sizeof(WCHAR) + PhpSizeUnitNamesCounted[i].Length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ContinueLoop:
|
||||
partLength = usedLength - partLength;
|
||||
|
||||
if (format->Type & (FormatLeftAlign | FormatRightAlign))
|
||||
{
|
||||
SIZE_T newLength;
|
||||
SIZE_T addLength;
|
||||
|
||||
newLength = format->Width * sizeof(WCHAR);
|
||||
|
||||
// We only pad and never truncate.
|
||||
if (partLength < newLength)
|
||||
{
|
||||
addLength = newLength - partLength;
|
||||
ENSURE_BUFFER(addLength);
|
||||
|
||||
if (OK_BUFFER)
|
||||
{
|
||||
WCHAR pad;
|
||||
|
||||
if (format->Type & FormatUsePad)
|
||||
pad = format->Pad;
|
||||
else
|
||||
pad = ' ';
|
||||
|
||||
if (format->Type & FormatLeftAlign)
|
||||
{
|
||||
// Left alignment is easy; we just fill the remaining space with the pad
|
||||
// character.
|
||||
wmemset(buffer, pad, addLength / sizeof(WCHAR));
|
||||
}
|
||||
else
|
||||
{
|
||||
PWSTR start;
|
||||
|
||||
// Right alignment is much slower and involves moving the text forward, then
|
||||
// filling in the space before it.
|
||||
start = buffer - partLength / sizeof(WCHAR);
|
||||
memmove(start + addLength / sizeof(WCHAR), start, partLength);
|
||||
wmemset(start, pad, addLength / sizeof(WCHAR));
|
||||
}
|
||||
}
|
||||
|
||||
ADVANCE_BUFFER(addLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
238
phlib/global.c
Normal file
238
phlib/global.c
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* global variables and initialization functions
|
||||
*
|
||||
* Copyright (C) 2010-2013 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <phintrnl.h>
|
||||
#include <filestream.h>
|
||||
#include <symprv.h>
|
||||
|
||||
BOOLEAN PhInitializeSystem(
|
||||
_In_ ULONG Flags
|
||||
);
|
||||
|
||||
VOID PhInitializeSystemInformation(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID PhInitializeWindowsVersion(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI PVOID PhLibImageBase;
|
||||
|
||||
PHLIBAPI PWSTR PhApplicationName = L"Application";
|
||||
PHLIBAPI ULONG PhGlobalDpi = 96;
|
||||
PHLIBAPI PVOID PhHeapHandle;
|
||||
PHLIBAPI RTL_OSVERSIONINFOEXW PhOsVersion;
|
||||
PHLIBAPI SYSTEM_BASIC_INFORMATION PhSystemBasicInformation;
|
||||
PHLIBAPI ULONG WindowsVersion;
|
||||
|
||||
PHLIBAPI ACCESS_MASK ProcessQueryAccess;
|
||||
PHLIBAPI ACCESS_MASK ProcessAllAccess;
|
||||
PHLIBAPI ACCESS_MASK ThreadQueryAccess;
|
||||
PHLIBAPI ACCESS_MASK ThreadSetAccess;
|
||||
PHLIBAPI ACCESS_MASK ThreadAllAccess;
|
||||
|
||||
// Internal data
|
||||
#ifdef DEBUG
|
||||
PHLIB_STATISTICS_BLOCK PhLibStatisticsBlock;
|
||||
#endif
|
||||
|
||||
NTSTATUS PhInitializePhLib(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return PhInitializePhLibEx(
|
||||
0xffffffff, // all possible features
|
||||
0,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
NTSTATUS PhInitializePhLibEx(
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ SIZE_T HeapReserveSize,
|
||||
_In_opt_ SIZE_T HeapCommitSize
|
||||
)
|
||||
{
|
||||
PhHeapHandle = RtlCreateHeap(
|
||||
HEAP_GROWABLE | HEAP_CLASS_1,
|
||||
NULL,
|
||||
HeapReserveSize ? HeapReserveSize : 2 * 1024 * 1024, // 2 MB
|
||||
HeapCommitSize ? HeapCommitSize : 1024 * 1024, // 1 MB
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!PhHeapHandle)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
PhLibImageBase = NtCurrentPeb()->ImageBaseAddress;
|
||||
|
||||
PhInitializeWindowsVersion();
|
||||
PhInitializeSystemInformation();
|
||||
|
||||
if (!PhQueuedLockInitialization())
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (!NT_SUCCESS(PhRefInitialization()))
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
if (!PhBaseInitialization())
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
if (!PhInitializeSystem(Flags))
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef _WIN64
|
||||
BOOLEAN PhIsExecutingInWow64(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
static BOOLEAN valid = FALSE;
|
||||
static BOOLEAN isWow64;
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
PhGetProcessIsWow64(NtCurrentProcess(), &isWow64);
|
||||
MemoryBarrier();
|
||||
valid = TRUE;
|
||||
}
|
||||
|
||||
return isWow64;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOLEAN PhInitializeSystem(
|
||||
_In_ ULONG Flags
|
||||
)
|
||||
{
|
||||
if (Flags & PHLIB_INIT_MODULE_FILE_STREAM)
|
||||
{
|
||||
if (!PhFileStreamInitialization())
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Flags & PHLIB_INIT_MODULE_SYMBOL_PROVIDER)
|
||||
{
|
||||
if (!PhSymbolProviderInitialization())
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID PhInitializeSystemInformation(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
NtQuerySystemInformation(
|
||||
SystemBasicInformation,
|
||||
&PhSystemBasicInformation,
|
||||
sizeof(SYSTEM_BASIC_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
static VOID PhInitializeWindowsVersion(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
RTL_OSVERSIONINFOEXW versionInfo;
|
||||
ULONG majorVersion;
|
||||
ULONG minorVersion;
|
||||
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
|
||||
|
||||
if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo)))
|
||||
{
|
||||
WindowsVersion = WINDOWS_NEW;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&PhOsVersion, &versionInfo, sizeof(RTL_OSVERSIONINFOEXW));
|
||||
majorVersion = versionInfo.dwMajorVersion;
|
||||
minorVersion = versionInfo.dwMinorVersion;
|
||||
|
||||
if (majorVersion == 5 && minorVersion < 1 || majorVersion < 5)
|
||||
{
|
||||
WindowsVersion = WINDOWS_ANCIENT;
|
||||
}
|
||||
/* Windows XP */
|
||||
else if (majorVersion == 5 && minorVersion == 1)
|
||||
{
|
||||
WindowsVersion = WINDOWS_XP;
|
||||
}
|
||||
/* Windows Server 2003 */
|
||||
else if (majorVersion == 5 && minorVersion == 2)
|
||||
{
|
||||
WindowsVersion = WINDOWS_SERVER_2003;
|
||||
}
|
||||
/* Windows Vista, Windows Server 2008 */
|
||||
else if (majorVersion == 6 && minorVersion == 0)
|
||||
{
|
||||
WindowsVersion = WINDOWS_VISTA;
|
||||
}
|
||||
/* Windows 7, Windows Server 2008 R2 */
|
||||
else if (majorVersion == 6 && minorVersion == 1)
|
||||
{
|
||||
WindowsVersion = WINDOWS_7;
|
||||
}
|
||||
/* Windows 8 */
|
||||
else if (majorVersion == 6 && minorVersion == 2)
|
||||
{
|
||||
WindowsVersion = WINDOWS_8;
|
||||
}
|
||||
/* Windows 8.1 */
|
||||
else if (majorVersion == 6 && minorVersion == 3)
|
||||
{
|
||||
WindowsVersion = WINDOWS_8_1;
|
||||
}
|
||||
/* Windows 10 */
|
||||
else if (majorVersion == 10 && minorVersion == 0)
|
||||
{
|
||||
WindowsVersion = WINDOWS_10;
|
||||
}
|
||||
else if (majorVersion == 10 && minorVersion > 0 || majorVersion > 10)
|
||||
{
|
||||
WindowsVersion = WINDOWS_NEW;
|
||||
}
|
||||
|
||||
if (WINDOWS_HAS_LIMITED_ACCESS)
|
||||
{
|
||||
ProcessQueryAccess = PROCESS_QUERY_LIMITED_INFORMATION;
|
||||
ProcessAllAccess = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1fff;
|
||||
ThreadQueryAccess = THREAD_QUERY_LIMITED_INFORMATION;
|
||||
ThreadSetAccess = THREAD_SET_LIMITED_INFORMATION;
|
||||
ThreadAllAccess = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xfff;
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessQueryAccess = PROCESS_QUERY_INFORMATION;
|
||||
ProcessAllAccess = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xfff;
|
||||
ThreadQueryAccess = THREAD_QUERY_INFORMATION;
|
||||
ThreadSetAccess = THREAD_SET_INFORMATION;
|
||||
ThreadAllAccess = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff;
|
||||
}
|
||||
}
|
||||
1332
phlib/graph.c
Normal file
1332
phlib/graph.c
Normal file
File diff suppressed because it is too large
Load Diff
1372
phlib/guisup.c
Normal file
1372
phlib/guisup.c
Normal file
File diff suppressed because it is too large
Load Diff
1097
phlib/handle.c
Normal file
1097
phlib/handle.c
Normal file
File diff suppressed because it is too large
Load Diff
1865
phlib/hexedit.c
Normal file
1865
phlib/hexedit.c
Normal file
File diff suppressed because it is too large
Load Diff
1763
phlib/hndlinfo.c
Normal file
1763
phlib/hndlinfo.c
Normal file
File diff suppressed because it is too large
Load Diff
237
phlib/icotobmp.c
Normal file
237
phlib/icotobmp.c
Normal file
@@ -0,0 +1,237 @@
|
||||
#include <ph.h>
|
||||
#include <guisup.h>
|
||||
#include <uxtheme.h>
|
||||
|
||||
// code from http://msdn.microsoft.com/en-us/library/bb757020.aspx
|
||||
|
||||
typedef HPAINTBUFFER (*_BeginBufferedPaint)(
|
||||
_In_ HDC hdcTarget,
|
||||
_In_ const RECT *prcTarget,
|
||||
_In_ BP_BUFFERFORMAT dwFormat,
|
||||
_In_ BP_PAINTPARAMS *pPaintParams,
|
||||
_Out_ HDC *phdc
|
||||
);
|
||||
|
||||
typedef HRESULT (*_EndBufferedPaint)(
|
||||
_In_ HPAINTBUFFER hBufferedPaint,
|
||||
_In_ BOOL fUpdateTarget
|
||||
);
|
||||
|
||||
typedef HRESULT (*_GetBufferedPaintBits)(
|
||||
_In_ HPAINTBUFFER hBufferedPaint,
|
||||
_Out_ RGBQUAD **ppbBuffer,
|
||||
_Out_ int *pcxRow
|
||||
);
|
||||
|
||||
static BOOLEAN ImportsInitialized = FALSE;
|
||||
static _BeginBufferedPaint BeginBufferedPaint_I = NULL;
|
||||
static _EndBufferedPaint EndBufferedPaint_I = NULL;
|
||||
static _GetBufferedPaintBits GetBufferedPaintBits_I = NULL;
|
||||
|
||||
static HBITMAP PhpCreateBitmap32(
|
||||
_In_ HDC hdc,
|
||||
_In_ ULONG Width,
|
||||
_In_ ULONG Height,
|
||||
_Outptr_opt_ PVOID *Bits
|
||||
)
|
||||
{
|
||||
BITMAPINFO bitmapInfo;
|
||||
|
||||
memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
|
||||
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfo.bmiHeader.biPlanes = 1;
|
||||
bitmapInfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
bitmapInfo.bmiHeader.biWidth = Width;
|
||||
bitmapInfo.bmiHeader.biHeight = Height;
|
||||
bitmapInfo.bmiHeader.biBitCount = 32;
|
||||
|
||||
return CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, Bits, NULL, 0);
|
||||
}
|
||||
|
||||
static BOOLEAN PhpHasAlpha(
|
||||
_In_ PULONG Argb,
|
||||
_In_ ULONG Width,
|
||||
_In_ ULONG Height,
|
||||
_In_ ULONG RowWidth
|
||||
)
|
||||
{
|
||||
ULONG delta;
|
||||
ULONG x;
|
||||
ULONG y;
|
||||
|
||||
delta = RowWidth - Width;
|
||||
|
||||
for (y = Width; y; y--)
|
||||
{
|
||||
for (x = Height; x; x--)
|
||||
{
|
||||
if (*Argb++ & 0xff000000)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Argb += delta;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static VOID PhpConvertToPArgb32(
|
||||
_In_ HDC hdc,
|
||||
_Inout_ PULONG Argb,
|
||||
_In_ HBITMAP Bitmap,
|
||||
_In_ ULONG Width,
|
||||
_In_ ULONG Height,
|
||||
_In_ ULONG RowWidth
|
||||
)
|
||||
{
|
||||
BITMAPINFO bitmapInfo;
|
||||
PVOID bits;
|
||||
|
||||
memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
|
||||
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmapInfo.bmiHeader.biPlanes = 1;
|
||||
bitmapInfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
bitmapInfo.bmiHeader.biWidth = Width;
|
||||
bitmapInfo.bmiHeader.biHeight = Height;
|
||||
bitmapInfo.bmiHeader.biBitCount = 32;
|
||||
|
||||
bits = PhAllocate(Width * sizeof(ULONG) * Height);
|
||||
|
||||
if (GetDIBits(hdc, Bitmap, 0, Height, bits, &bitmapInfo, DIB_RGB_COLORS) == Height)
|
||||
{
|
||||
PULONG argbMask;
|
||||
ULONG delta;
|
||||
ULONG x;
|
||||
ULONG y;
|
||||
|
||||
argbMask = (PULONG)bits;
|
||||
delta = RowWidth - Width;
|
||||
|
||||
for (y = Height; y; y--)
|
||||
{
|
||||
for (x = Width; x; x--)
|
||||
{
|
||||
if (*argbMask++)
|
||||
{
|
||||
*Argb++ = 0; // transparent
|
||||
}
|
||||
else
|
||||
{
|
||||
*Argb++ |= 0xff000000; // opaque
|
||||
}
|
||||
}
|
||||
|
||||
Argb += delta;
|
||||
}
|
||||
}
|
||||
|
||||
PhFree(bits);
|
||||
}
|
||||
|
||||
static VOID PhpConvertToPArgb32IfNeeded(
|
||||
_In_ HPAINTBUFFER PaintBuffer,
|
||||
_In_ HDC hdc,
|
||||
_In_ HICON Icon,
|
||||
_In_ ULONG Width,
|
||||
_In_ ULONG Height
|
||||
)
|
||||
{
|
||||
RGBQUAD *quad;
|
||||
ULONG rowWidth;
|
||||
|
||||
if (SUCCEEDED(GetBufferedPaintBits_I(PaintBuffer, &quad, &rowWidth)))
|
||||
{
|
||||
PULONG argb = (PULONG)quad;
|
||||
|
||||
if (!PhpHasAlpha(argb, Width, Height, rowWidth))
|
||||
{
|
||||
ICONINFO iconInfo;
|
||||
|
||||
if (GetIconInfo(Icon, &iconInfo))
|
||||
{
|
||||
if (iconInfo.hbmMask)
|
||||
{
|
||||
PhpConvertToPArgb32(hdc, argb, iconInfo.hbmMask, Width, Height, rowWidth);
|
||||
}
|
||||
|
||||
DeleteObject(iconInfo.hbmColor);
|
||||
DeleteObject(iconInfo.hbmMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HBITMAP PhIconToBitmap(
|
||||
_In_ HICON Icon,
|
||||
_In_ ULONG Width,
|
||||
_In_ ULONG Height
|
||||
)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
RECT iconRectangle;
|
||||
HDC screenHdc;
|
||||
HDC hdc;
|
||||
HBITMAP oldBitmap;
|
||||
BLENDFUNCTION blendFunction = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
|
||||
BP_PAINTPARAMS paintParams = { sizeof(paintParams) };
|
||||
HDC bufferHdc;
|
||||
HPAINTBUFFER paintBuffer;
|
||||
|
||||
iconRectangle.left = 0;
|
||||
iconRectangle.top = 0;
|
||||
iconRectangle.right = Width;
|
||||
iconRectangle.bottom = Height;
|
||||
|
||||
if (!ImportsInitialized)
|
||||
{
|
||||
HMODULE uxtheme;
|
||||
|
||||
uxtheme = GetModuleHandle(L"uxtheme.dll");
|
||||
BeginBufferedPaint_I = PhGetProcedureAddress(uxtheme, "BeginBufferedPaint", 0);
|
||||
EndBufferedPaint_I = PhGetProcedureAddress(uxtheme, "EndBufferedPaint", 0);
|
||||
GetBufferedPaintBits_I = PhGetProcedureAddress(uxtheme, "GetBufferedPaintBits", 0);
|
||||
ImportsInitialized = TRUE;
|
||||
}
|
||||
|
||||
if (!BeginBufferedPaint_I || !EndBufferedPaint_I || !GetBufferedPaintBits_I)
|
||||
{
|
||||
// Probably XP.
|
||||
|
||||
screenHdc = GetDC(NULL);
|
||||
hdc = CreateCompatibleDC(screenHdc);
|
||||
bitmap = CreateCompatibleBitmap(screenHdc, Width, Height);
|
||||
ReleaseDC(NULL, screenHdc);
|
||||
|
||||
oldBitmap = SelectObject(hdc, bitmap);
|
||||
FillRect(hdc, &iconRectangle, (HBRUSH)(COLOR_WINDOW + 1));
|
||||
DrawIconEx(hdc, 0, 0, Icon, Width, Height, 0, NULL, DI_NORMAL);
|
||||
SelectObject(hdc, oldBitmap);
|
||||
|
||||
DeleteDC(hdc);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
screenHdc = GetDC(NULL);
|
||||
hdc = CreateCompatibleDC(screenHdc);
|
||||
bitmap = PhpCreateBitmap32(screenHdc, Width, Height, NULL);
|
||||
ReleaseDC(NULL, screenHdc);
|
||||
oldBitmap = SelectObject(hdc, bitmap);
|
||||
|
||||
paintParams.dwFlags = BPPF_ERASE;
|
||||
paintParams.pBlendFunction = &blendFunction;
|
||||
|
||||
paintBuffer = BeginBufferedPaint_I(hdc, &iconRectangle, BPBF_DIB, &paintParams, &bufferHdc);
|
||||
DrawIconEx(bufferHdc, 0, 0, Icon, Width, Height, 0, NULL, DI_NORMAL);
|
||||
// If the icon did not have an alpha channel, we need to convert the buffer to PARGB.
|
||||
PhpConvertToPArgb32IfNeeded(paintBuffer, hdc, Icon, Width, Height);
|
||||
// This will write the buffer contents to the destination bitmap.
|
||||
EndBufferedPaint_I(paintBuffer, TRUE);
|
||||
|
||||
SelectObject(hdc, oldBitmap);
|
||||
DeleteDC(hdc);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
86
phlib/include/apiimport.h
Normal file
86
phlib/include/apiimport.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#ifndef _PH_APIIMPORT_H
|
||||
#define _PH_APIIMPORT_H
|
||||
|
||||
// comctl32
|
||||
|
||||
typedef HRESULT (WINAPI *_TaskDialogIndirect)(
|
||||
_In_ const struct _TASKDIALOGCONFIG *pTaskConfig,
|
||||
_In_ int *pnButton,
|
||||
_In_ int *pnRadioButton,
|
||||
_In_ BOOL *pfVerificationFlagChecked
|
||||
);
|
||||
|
||||
// ntdll
|
||||
|
||||
typedef NTSTATUS (NTAPI *_NtQueryInformationEnlistment)(
|
||||
_In_ HANDLE EnlistmentHandle,
|
||||
_In_ ENLISTMENT_INFORMATION_CLASS EnlistmentInformationClass,
|
||||
_Out_writes_bytes_(EnlistmentInformationLength) PVOID EnlistmentInformation,
|
||||
_In_ ULONG EnlistmentInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
typedef NTSTATUS (NTAPI *_NtQueryInformationResourceManager)(
|
||||
_In_ HANDLE ResourceManagerHandle,
|
||||
_In_ RESOURCEMANAGER_INFORMATION_CLASS ResourceManagerInformationClass,
|
||||
_Out_writes_bytes_(ResourceManagerInformationLength) PVOID ResourceManagerInformation,
|
||||
_In_ ULONG ResourceManagerInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
typedef NTSTATUS (NTAPI *_NtQueryInformationTransaction)(
|
||||
_In_ HANDLE TransactionHandle,
|
||||
_In_ TRANSACTION_INFORMATION_CLASS TransactionInformationClass,
|
||||
_Out_writes_bytes_(TransactionInformationLength) PVOID TransactionInformation,
|
||||
_In_ ULONG TransactionInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
typedef NTSTATUS (NTAPI *_NtQueryInformationTransactionManager)(
|
||||
_In_ HANDLE TransactionManagerHandle,
|
||||
_In_ TRANSACTIONMANAGER_INFORMATION_CLASS TransactionManagerInformationClass,
|
||||
_Out_writes_bytes_(TransactionManagerInformationLength) PVOID TransactionManagerInformation,
|
||||
_In_ ULONG TransactionManagerInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
// shell32
|
||||
|
||||
#if defined(_M_IX86)
|
||||
#define __unaligned
|
||||
#endif
|
||||
|
||||
typedef HRESULT (WINAPI *_SHCreateShellItem)(
|
||||
_In_opt_ const struct _ITEMIDLIST __unaligned *pidlParent,
|
||||
_In_opt_ struct IShellFolder *psfParent,
|
||||
_In_ const struct _ITEMIDLIST __unaligned *pidl,
|
||||
_Out_ struct IShellItem **ppsi
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI *_SHOpenFolderAndSelectItems)(
|
||||
_In_ const struct _ITEMIDLIST __unaligned *pidlFolder,
|
||||
_In_ UINT cidl,
|
||||
_In_reads_opt_(cidl) const struct _ITEMIDLIST __unaligned **apidl,
|
||||
_In_ DWORD dwFlags
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI *_SHParseDisplayName)(
|
||||
_In_ LPCWSTR pszName,
|
||||
_In_opt_ struct IBindCtx *pbc,
|
||||
_Out_ const struct _ITEMIDLIST __unaligned **ppidl,
|
||||
_In_ ULONG sfgaoIn,
|
||||
_Out_ ULONG *psfgaoOut
|
||||
);
|
||||
|
||||
#define PH_DECLARE_IMPORT(Name) _##Name Name##_Import(VOID)
|
||||
|
||||
PH_DECLARE_IMPORT(TaskDialogIndirect);
|
||||
PH_DECLARE_IMPORT(NtQueryInformationEnlistment);
|
||||
PH_DECLARE_IMPORT(NtQueryInformationResourceManager);
|
||||
PH_DECLARE_IMPORT(NtQueryInformationTransaction);
|
||||
PH_DECLARE_IMPORT(NtQueryInformationTransactionManager);
|
||||
PH_DECLARE_IMPORT(SHCreateShellItem);
|
||||
PH_DECLARE_IMPORT(SHOpenFolderAndSelectItems);
|
||||
PH_DECLARE_IMPORT(SHParseDisplayName);
|
||||
|
||||
#endif
|
||||
26
phlib/include/circbuf.h
Normal file
26
phlib/include/circbuf.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _PH_CIRCBUF_H
|
||||
#define _PH_CIRCBUF_H
|
||||
|
||||
#define PH_CIRCULAR_BUFFER_POWER_OF_TWO_SIZE
|
||||
|
||||
#undef T
|
||||
#define T ULONG
|
||||
#include "circbuf_h.h"
|
||||
|
||||
#undef T
|
||||
#define T ULONG64
|
||||
#include "circbuf_h.h"
|
||||
|
||||
#undef T
|
||||
#define T PVOID
|
||||
#include "circbuf_h.h"
|
||||
|
||||
#undef T
|
||||
#define T SIZE_T
|
||||
#include "circbuf_h.h"
|
||||
|
||||
#undef T
|
||||
#define T FLOAT
|
||||
#include "circbuf_h.h"
|
||||
|
||||
#endif
|
||||
140
phlib/include/circbuf_h.h
Normal file
140
phlib/include/circbuf_h.h
Normal file
@@ -0,0 +1,140 @@
|
||||
#ifdef T
|
||||
|
||||
#include <templ.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct T___(_PH_CIRCULAR_BUFFER, T)
|
||||
{
|
||||
ULONG Size;
|
||||
#ifdef PH_CIRCULAR_BUFFER_POWER_OF_TWO_SIZE
|
||||
ULONG SizeMinusOne;
|
||||
#endif
|
||||
ULONG Count;
|
||||
LONG Index;
|
||||
T *Data;
|
||||
} T___(PH_CIRCULAR_BUFFER, T), *T___(PPH_CIRCULAR_BUFFER, T);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
T___(PhInitializeCircularBuffer, T)(
|
||||
_Out_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_In_ ULONG Size
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
T___(PhDeleteCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
T___(PhResizeCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_In_ ULONG NewSize
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
T___(PhClearCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
T___(PhCopyCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_Out_writes_(Count) T *Destination,
|
||||
_In_ ULONG Count
|
||||
);
|
||||
|
||||
FORCEINLINE T T___(PhGetItemCircularBuffer, T)(
|
||||
_In_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_In_ LONG Index
|
||||
)
|
||||
{
|
||||
#ifdef PH_CIRCULAR_BUFFER_POWER_OF_TWO_SIZE
|
||||
return Buffer->Data[(Buffer->Index + Index) & Buffer->SizeMinusOne];
|
||||
#else
|
||||
ULONG size;
|
||||
|
||||
size = Buffer->Size;
|
||||
// Modulo is dividend-based.
|
||||
return Buffer->Data[(((Buffer->Index + Index) % size) + size) % size];
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE VOID T___(PhSetItemCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_In_ LONG Index,
|
||||
_In_ T Value
|
||||
)
|
||||
{
|
||||
#ifdef PH_CIRCULAR_BUFFER_POWER_OF_TWO_SIZE
|
||||
Buffer->Data[(Buffer->Index + Index) & Buffer->SizeMinusOne] = Value;
|
||||
#else
|
||||
ULONG size;
|
||||
|
||||
size = Buffer->Size;
|
||||
Buffer->Data[(((Buffer->Index + Index) % size) + size) % size] = Value;
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE VOID T___(PhAddItemCircularBuffer, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_In_ T Value
|
||||
)
|
||||
{
|
||||
#ifdef PH_CIRCULAR_BUFFER_POWER_OF_TWO_SIZE
|
||||
Buffer->Data[Buffer->Index = ((Buffer->Index - 1) & Buffer->SizeMinusOne)] = Value;
|
||||
#else
|
||||
ULONG size;
|
||||
|
||||
size = Buffer->Size;
|
||||
Buffer->Data[Buffer->Index = (((Buffer->Index - 1) % size) + size) % size] = Value;
|
||||
#endif
|
||||
|
||||
if (Buffer->Count < Buffer->Size)
|
||||
Buffer->Count++;
|
||||
}
|
||||
|
||||
FORCEINLINE T T___(PhAddItemCircularBuffer2, T)(
|
||||
_Inout_ T___(PPH_CIRCULAR_BUFFER, T) Buffer,
|
||||
_In_ T Value
|
||||
)
|
||||
{
|
||||
LONG index;
|
||||
T oldValue;
|
||||
|
||||
#ifdef PH_CIRCULAR_BUFFER_POWER_OF_TWO_SIZE
|
||||
index = ((Buffer->Index - 1) & Buffer->SizeMinusOne);
|
||||
#else
|
||||
ULONG size;
|
||||
|
||||
size = Buffer->Size;
|
||||
index = (((Buffer->Index - 1) % size) + size) % size;
|
||||
#endif
|
||||
|
||||
Buffer->Index = index;
|
||||
oldValue = Buffer->Data[index];
|
||||
Buffer->Data[index] = Value;
|
||||
|
||||
if (Buffer->Count < Buffer->Size)
|
||||
Buffer->Count++;
|
||||
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
30
phlib/include/colorbox.h
Normal file
30
phlib/include/colorbox.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef _PH_COLORBOX_H
|
||||
#define _PH_COLORBOX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PH_COLORBOX_CLASSNAME L"PhColorBox"
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhColorBoxInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
#define CBCM_SETCOLOR (WM_APP + 1501)
|
||||
#define CBCM_GETCOLOR (WM_APP + 1502)
|
||||
|
||||
#define ColorBox_SetColor(hWnd, Color) \
|
||||
SendMessage((hWnd), CBCM_SETCOLOR, (WPARAM)(Color), 0)
|
||||
|
||||
#define ColorBox_GetColor(hWnd) \
|
||||
((COLORREF)SendMessage((hWnd), CBCM_GETCOLOR, 0, 0))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
78
phlib/include/cpysave.h
Normal file
78
phlib/include/cpysave.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef _PH_CPYSAVE_H
|
||||
#define _PH_CPYSAVE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PH_EXPORT_MODE_TABS 0
|
||||
#define PH_EXPORT_MODE_SPACES 1
|
||||
#define PH_EXPORT_MODE_CSV 2
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhaCreateTextTable(
|
||||
_Out_ PPH_STRING ***Table,
|
||||
_In_ ULONG Rows,
|
||||
_In_ ULONG Columns
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_LIST PhaFormatTextTable(
|
||||
_In_ PPH_STRING **Table,
|
||||
_In_ ULONG Rows,
|
||||
_In_ ULONG Columns,
|
||||
_In_ ULONG Mode
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhMapDisplayIndexTreeNew(
|
||||
_In_ HWND TreeNewHandle,
|
||||
_Out_opt_ PULONG *DisplayToId,
|
||||
_Out_opt_ PWSTR **DisplayToText,
|
||||
_Out_ PULONG NumberOfColumns
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING PhGetTreeNewText(
|
||||
_In_ HWND TreeNewHandle,
|
||||
_Reserved_ ULONG Reserved
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_LIST PhGetGenericTreeNewLines(
|
||||
_In_ HWND TreeNewHandle,
|
||||
_In_ ULONG Mode
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhaMapDisplayIndexListView(
|
||||
_In_ HWND ListViewHandle,
|
||||
_Out_writes_(Count) PULONG DisplayToId,
|
||||
_Out_writes_opt_(Count) PPH_STRING *DisplayToText,
|
||||
_In_ ULONG Count,
|
||||
_Out_ PULONG NumberOfColumns
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING PhaGetListViewItemText(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT Index,
|
||||
_In_ INT SubItemIndex
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING PhGetListViewText(
|
||||
_In_ HWND ListViewHandle
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_LIST PhGetListViewLines(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ ULONG Mode
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
35
phlib/include/dltmgr.h
Normal file
35
phlib/include/dltmgr.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef _PH_DLTMGR_H
|
||||
#define _PH_DLTMGR_H
|
||||
|
||||
typedef struct _PH_SINGLE_DELTA
|
||||
{
|
||||
FLOAT Value;
|
||||
FLOAT Delta;
|
||||
} PH_SINGLE_DELTA, *PPH_SINGLE_DELTA;
|
||||
|
||||
typedef struct _PH_UINT32_DELTA
|
||||
{
|
||||
ULONG Value;
|
||||
ULONG Delta;
|
||||
} PH_UINT32_DELTA, *PPH_UINT32_DELTA;
|
||||
|
||||
typedef struct _PH_UINT64_DELTA
|
||||
{
|
||||
ULONG64 Value;
|
||||
ULONG64 Delta;
|
||||
} PH_UINT64_DELTA, *PPH_UINT64_DELTA;
|
||||
|
||||
typedef struct _PH_UINTPTR_DELTA
|
||||
{
|
||||
ULONG_PTR Value;
|
||||
ULONG_PTR Delta;
|
||||
} PH_UINTPTR_DELTA, *PPH_UINTPTR_DELTA;
|
||||
|
||||
#define PhInitializeDelta(DltMgr) \
|
||||
((DltMgr)->Value = 0, (DltMgr)->Delta = 0)
|
||||
|
||||
#define PhUpdateDelta(DltMgr, NewValue) \
|
||||
((DltMgr)->Delta = (NewValue) - (DltMgr)->Value, \
|
||||
(DltMgr)->Value = (NewValue), (DltMgr)->Delta)
|
||||
|
||||
#endif
|
||||
48
phlib/include/dspick.h
Normal file
48
phlib/include/dspick.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef _PH_DSPICK_H
|
||||
#define _PH_DSPICK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PH_DSPICK_MULTISELECT 0x1
|
||||
|
||||
typedef struct _PH_DSPICK_OBJECT
|
||||
{
|
||||
PPH_STRING Name;
|
||||
PSID Sid;
|
||||
} PH_DSPICK_OBJECT, *PPH_DSPICK_OBJECT;
|
||||
|
||||
typedef struct _PH_DSPICK_OBJECTS
|
||||
{
|
||||
ULONG NumberOfObjects;
|
||||
PH_DSPICK_OBJECT Objects[1];
|
||||
} PH_DSPICK_OBJECTS, *PPH_DSPICK_OBJECTS;
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhFreeDsObjectPickerDialog(
|
||||
_In_ PVOID PickerDialog
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID PhCreateDsObjectPickerDialog(
|
||||
_In_ ULONG Flags
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhShowDsObjectPickerDialog(
|
||||
_In_ HWND hWnd,
|
||||
_In_ PVOID PickerDialog,
|
||||
_Out_ PPH_DSPICK_OBJECTS *Objects
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhFreeDsObjectPickerObjects(
|
||||
_In_ PPH_DSPICK_OBJECTS Objects
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
219
phlib/include/emenu.h
Normal file
219
phlib/include/emenu.h
Normal file
@@ -0,0 +1,219 @@
|
||||
#ifndef _PH_EMENU_H
|
||||
#define _PH_EMENU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PH_EMENU_DISABLED 0x1
|
||||
#define PH_EMENU_CHECKED 0x2
|
||||
#define PH_EMENU_HIGHLIGHT 0x4
|
||||
#define PH_EMENU_MENUBARBREAK 0x8
|
||||
#define PH_EMENU_MENUBREAK 0x10
|
||||
#define PH_EMENU_DEFAULT 0x20
|
||||
#define PH_EMENU_MOUSESELECT 0x40
|
||||
#define PH_EMENU_RADIOCHECK 0x80
|
||||
|
||||
#define PH_EMENU_SEPARATECHECKSPACE 0x100000
|
||||
#define PH_EMENU_SEPARATOR 0x200000
|
||||
|
||||
#define PH_EMENU_TEXT_OWNED 0x80000000
|
||||
#define PH_EMENU_BITMAP_OWNED 0x40000000
|
||||
|
||||
struct _PH_EMENU_ITEM;
|
||||
|
||||
typedef VOID (NTAPI *PPH_EMENU_ITEM_DELETE_FUNCTION)(
|
||||
_In_ struct _PH_EMENU_ITEM *Item
|
||||
);
|
||||
|
||||
typedef struct _PH_EMENU_ITEM
|
||||
{
|
||||
ULONG Flags;
|
||||
ULONG Id;
|
||||
PWSTR Text;
|
||||
HBITMAP Bitmap;
|
||||
|
||||
PVOID Parameter;
|
||||
PVOID Context;
|
||||
PPH_EMENU_ITEM_DELETE_FUNCTION DeleteFunction;
|
||||
PVOID Reserved;
|
||||
|
||||
struct _PH_EMENU_ITEM *Parent;
|
||||
PPH_LIST Items;
|
||||
} PH_EMENU_ITEM, *PPH_EMENU_ITEM;
|
||||
|
||||
typedef struct _PH_EMENU_ITEM PH_EMENU, *PPH_EMENU;
|
||||
|
||||
PHLIBAPI
|
||||
PPH_EMENU_ITEM PhCreateEMenuItem(
|
||||
_In_ ULONG Flags,
|
||||
_In_ ULONG Id,
|
||||
_In_ PWSTR Text,
|
||||
_In_opt_ HBITMAP Bitmap,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDestroyEMenuItem(
|
||||
_In_ PPH_EMENU_ITEM Item
|
||||
);
|
||||
|
||||
#define PH_EMENU_FIND_DESCEND 0x1
|
||||
#define PH_EMENU_FIND_STARTSWITH 0x2
|
||||
#define PH_EMENU_FIND_LITERAL 0x4
|
||||
|
||||
PHLIBAPI
|
||||
PPH_EMENU_ITEM PhFindEMenuItem(
|
||||
_In_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ PWSTR Text,
|
||||
_In_opt_ ULONG Id
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_EMENU_ITEM PhFindEMenuItemEx(
|
||||
_In_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ PWSTR Text,
|
||||
_In_opt_ ULONG Id,
|
||||
_Out_opt_ PPH_EMENU_ITEM *FoundParent,
|
||||
_Out_opt_ PULONG FoundIndex
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
ULONG PhIndexOfEMenuItem(
|
||||
_In_ PPH_EMENU_ITEM Parent,
|
||||
_In_ PPH_EMENU_ITEM Item
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhInsertEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM Parent,
|
||||
_Inout_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Index
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhRemoveEMenuItem(
|
||||
_Inout_opt_ PPH_EMENU_ITEM Parent,
|
||||
_In_opt_ PPH_EMENU_ITEM Item,
|
||||
_In_opt_ ULONG Index
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhRemoveAllEMenuItems(
|
||||
_Inout_ PPH_EMENU_ITEM Parent
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_EMENU PhCreateEMenu(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDestroyEMenu(
|
||||
_In_ PPH_EMENU Menu
|
||||
);
|
||||
|
||||
#define PH_EMENU_CONVERT_ID 0x1
|
||||
|
||||
typedef struct _PH_EMENU_DATA
|
||||
{
|
||||
PPH_LIST IdToItem;
|
||||
} PH_EMENU_DATA, *PPH_EMENU_DATA;
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhInitializeEMenuData(
|
||||
_Out_ PPH_EMENU_DATA Data
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDeleteEMenuData(
|
||||
_Inout_ PPH_EMENU_DATA Data
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
HMENU PhEMenuToHMenu(
|
||||
_In_ PPH_EMENU_ITEM Menu,
|
||||
_In_ ULONG Flags,
|
||||
_Inout_opt_ PPH_EMENU_DATA Data
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhEMenuToHMenu2(
|
||||
_In_ HMENU MenuHandle,
|
||||
_In_ PPH_EMENU_ITEM Menu,
|
||||
_In_ ULONG Flags,
|
||||
_Inout_opt_ PPH_EMENU_DATA Data
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhHMenuToEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM MenuItem,
|
||||
_In_ HMENU MenuHandle
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhLoadResourceEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM MenuItem,
|
||||
_In_ HINSTANCE InstanceHandle,
|
||||
_In_ PWSTR Resource,
|
||||
_In_ ULONG SubMenuIndex
|
||||
);
|
||||
|
||||
#define PH_EMENU_SHOW_SEND_COMMAND 0x1
|
||||
#define PH_EMENU_SHOW_LEFTRIGHT 0x2
|
||||
|
||||
PHLIBAPI
|
||||
PPH_EMENU_ITEM PhShowEMenu(
|
||||
_In_ PPH_EMENU Menu,
|
||||
_In_ HWND WindowHandle,
|
||||
_In_ ULONG Flags,
|
||||
_In_ ULONG Align,
|
||||
_In_ ULONG X,
|
||||
_In_ ULONG Y
|
||||
);
|
||||
|
||||
// Convenience functions
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhSetFlagsEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Id,
|
||||
_In_ ULONG Mask,
|
||||
_In_ ULONG Value
|
||||
);
|
||||
|
||||
FORCEINLINE BOOLEAN PhEnableEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Id,
|
||||
_In_ BOOLEAN Enable
|
||||
)
|
||||
{
|
||||
return PhSetFlagsEMenuItem(Item, Id, PH_EMENU_DISABLED, Enable ? 0 : PH_EMENU_DISABLED);
|
||||
}
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetFlagsAllEMenuItems(
|
||||
_In_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG Mask,
|
||||
_In_ ULONG Value
|
||||
);
|
||||
|
||||
#define PH_EMENU_MODIFY_TEXT 0x1
|
||||
#define PH_EMENU_MODIFY_BITMAP 0x2
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhModifyEMenuItem(
|
||||
_Inout_ PPH_EMENU_ITEM Item,
|
||||
_In_ ULONG ModifyFlags,
|
||||
_In_ ULONG OwnedFlags,
|
||||
_In_opt_ PWSTR Text,
|
||||
_In_opt_ HBITMAP Bitmap
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
93
phlib/include/fastlock.h
Normal file
93
phlib/include/fastlock.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#ifndef _PH_FASTLOCK_H
|
||||
#define _PH_FASTLOCK_H
|
||||
|
||||
// FastLock is a port of FastResourceLock from PH 1.x.
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _PH_FAST_LOCK
|
||||
{
|
||||
ULONG Value;
|
||||
HANDLE ExclusiveWakeEvent;
|
||||
HANDLE SharedWakeEvent;
|
||||
} PH_FAST_LOCK, *PPH_FAST_LOCK;
|
||||
|
||||
#define PH_FAST_LOCK_INIT { 0, NULL, NULL }
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhInitializeFastLock(
|
||||
_Out_ PPH_FAST_LOCK FastLock
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhDeleteFastLock(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
);
|
||||
|
||||
#define PhAcquireFastLockExclusive PhfAcquireFastLockExclusive
|
||||
_May_raise_
|
||||
_Acquires_exclusive_lock_(*FastLock)
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfAcquireFastLockExclusive(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
);
|
||||
|
||||
#define PhAcquireFastLockShared PhfAcquireFastLockShared
|
||||
_May_raise_
|
||||
_Acquires_shared_lock_(*FastLock)
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfAcquireFastLockShared(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
);
|
||||
|
||||
#define PhReleaseFastLockExclusive PhfReleaseFastLockExclusive
|
||||
_Releases_exclusive_lock_(*FastLock)
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfReleaseFastLockExclusive(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
);
|
||||
|
||||
#define PhReleaseFastLockShared PhfReleaseFastLockShared
|
||||
_Releases_shared_lock_(*FastLock)
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfReleaseFastLockShared(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
);
|
||||
|
||||
#define PhTryAcquireFastLockExclusive PhfTryAcquireFastLockExclusive
|
||||
_When_(return != 0, _Acquires_exclusive_lock_(*FastLock))
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
PhfTryAcquireFastLockExclusive(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
);
|
||||
|
||||
#define PhTryAcquireFastLockShared PhfTryAcquireFastLockShared
|
||||
_When_(return != 0, _Acquires_shared_lock_(*FastLock))
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
PhfTryAcquireFastLockShared(
|
||||
_Inout_ PPH_FAST_LOCK FastLock
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
196
phlib/include/filepool.h
Normal file
196
phlib/include/filepool.h
Normal file
@@ -0,0 +1,196 @@
|
||||
#ifndef _PH_FILEPOOL_H
|
||||
#define _PH_FILEPOOL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// On-disk structures
|
||||
|
||||
// Each file has at least one segment. Each segment has a number of blocks, which are allocated from
|
||||
// a bitmap. The segment header is always in the first block of each segment, except for the first
|
||||
// segment. In the first segment, the file header is in the first few blocks, followed by the
|
||||
// segment header.
|
||||
//
|
||||
// The segments are placed in a particular free list depending on how many blocks they have free;
|
||||
// this allows allocators to simply skip the segments which don't have enough segments free, and
|
||||
// allocate new segments if necessary. The free list does not however guarantee that a particular
|
||||
// segment has a particular number of contiguous blocks free; low performance can still occur when
|
||||
// there is fragmentation.
|
||||
|
||||
/** The number of 32-bit integers used for each allocation bitmap. */
|
||||
#define PH_FP_BITMAP_SIZE 64
|
||||
/** The power-of-two index of the bitmap size. */
|
||||
#define PH_FP_BITMAP_SIZE_SHIFT 6
|
||||
/** The number of blocks that are available in each segment. */
|
||||
#define PH_FP_BLOCK_COUNT (PH_FP_BITMAP_SIZE * 32)
|
||||
/** The power-of-two index of the block count. */
|
||||
#define PH_FP_BLOCK_COUNT_SHIFT (PH_FP_BITMAP_SIZE_SHIFT + 5)
|
||||
/** The number of free lists for segments. */
|
||||
#define PH_FP_FREE_LIST_COUNT 8
|
||||
|
||||
// Block flags
|
||||
/** The block is the beginning of a large allocation (one that spans several segments). */
|
||||
#define PH_FP_BLOCK_LARGE_ALLOCATION 0x1
|
||||
|
||||
typedef struct _PH_FP_BLOCK_HEADER
|
||||
{
|
||||
ULONG Flags; // PH_FP_BLOCK_*
|
||||
/** The number of blocks in the entire logical block, or the number
|
||||
* of segments in a large allocation. */
|
||||
ULONG Span;
|
||||
ULONGLONG Body;
|
||||
} PH_FP_BLOCK_HEADER, *PPH_FP_BLOCK_HEADER;
|
||||
|
||||
typedef struct _PH_FP_SEGMENT_HEADER
|
||||
{
|
||||
ULONG Bitmap[PH_FP_BITMAP_SIZE];
|
||||
ULONG FreeBlocks;
|
||||
ULONG FreeFlink;
|
||||
ULONG FreeBlink;
|
||||
ULONG Reserved[13];
|
||||
} PH_FP_SEGMENT_HEADER, *PPH_FP_SEGMENT_HEADER;
|
||||
|
||||
#define PH_FP_MAGIC ('loPF')
|
||||
|
||||
typedef struct _PH_FP_FILE_HEADER
|
||||
{
|
||||
ULONG Magic;
|
||||
ULONG SegmentShift;
|
||||
ULONG SegmentCount;
|
||||
ULONGLONG UserContext;
|
||||
ULONG FreeLists[PH_FP_FREE_LIST_COUNT];
|
||||
} PH_FP_FILE_HEADER, *PPH_FP_FILE_HEADER;
|
||||
|
||||
// Runtime
|
||||
|
||||
typedef struct _PH_FILE_POOL_PARAMETERS
|
||||
{
|
||||
// File options
|
||||
|
||||
/**
|
||||
* The base-2 logarithm of the size of each segment. This value must be between 16 and 28,
|
||||
* inclusive.
|
||||
*/
|
||||
ULONG SegmentShift;
|
||||
|
||||
// Runtime options
|
||||
|
||||
/** The maximum number of inactive segments to keep mapped. */
|
||||
ULONG MaximumInactiveViews;
|
||||
} PH_FILE_POOL_PARAMETERS, *PPH_FILE_POOL_PARAMETERS;
|
||||
|
||||
typedef struct _PH_FILE_POOL
|
||||
{
|
||||
HANDLE FileHandle;
|
||||
HANDLE SectionHandle;
|
||||
BOOLEAN ReadOnly;
|
||||
|
||||
PH_FREE_LIST ViewFreeList;
|
||||
PLIST_ENTRY *ByIndexBuckets;
|
||||
ULONG ByIndexSize;
|
||||
PH_AVL_TREE ByBaseSet;
|
||||
|
||||
ULONG MaximumInactiveViews;
|
||||
ULONG NumberOfInactiveViews;
|
||||
LIST_ENTRY InactiveViewsListHead;
|
||||
|
||||
PPH_FP_BLOCK_HEADER FirstBlockOfFirstSegment;
|
||||
PPH_FP_FILE_HEADER Header;
|
||||
ULONG SegmentShift; // The power-of-two size of each segment
|
||||
ULONG SegmentSize; // The size of each segment
|
||||
ULONG BlockShift; // The power-of-two size of each block in each segment
|
||||
ULONG BlockSize; // The size of each block in each segment
|
||||
ULONG FileHeaderBlockSpan; // The number of blocks needed to store a file header
|
||||
ULONG SegmentHeaderBlockSpan; // The number of blocks needed to store a segment header
|
||||
} PH_FILE_POOL, *PPH_FILE_POOL;
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS PhCreateFilePool(
|
||||
_Out_ PPH_FILE_POOL *Pool,
|
||||
_In_ HANDLE FileHandle,
|
||||
_In_ BOOLEAN ReadOnly,
|
||||
_In_opt_ PPH_FILE_POOL_PARAMETERS Parameters
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS PhCreateFilePool2(
|
||||
_Out_ PPH_FILE_POOL *Pool,
|
||||
_In_ PWSTR FileName,
|
||||
_In_ BOOLEAN ReadOnly,
|
||||
_In_ ULONG ShareAccess,
|
||||
_In_ ULONG CreateDisposition,
|
||||
_In_opt_ PPH_FILE_POOL_PARAMETERS Parameters
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDestroyFilePool(
|
||||
_In_ _Post_invalid_ PPH_FILE_POOL Pool
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID PhAllocateFilePool(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG Size,
|
||||
_Out_opt_ PULONG Rva
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhFreeFilePool(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PVOID Block
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhFreeFilePoolByRva(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG Rva
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhReferenceFilePool(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PVOID Address
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDereferenceFilePool(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PVOID Address
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID PhReferenceFilePoolByRva(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG Rva
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhDereferenceFilePoolByRva(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG Rva
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
ULONG PhEncodeRvaFilePool(
|
||||
_In_ PPH_FILE_POOL Pool,
|
||||
_In_ PVOID Address
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhGetUserContextFilePool(
|
||||
_In_ PPH_FILE_POOL Pool,
|
||||
_Out_ PULONGLONG Context
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetUserContextFilePool(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PULONGLONG Context
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
204
phlib/include/filepoolp.h
Normal file
204
phlib/include/filepoolp.h
Normal file
@@ -0,0 +1,204 @@
|
||||
#ifndef _PH_FILEPOOLP_H
|
||||
#define _PH_FILEPOOLP_H
|
||||
|
||||
typedef struct _PH_FILE_POOL_VIEW
|
||||
{
|
||||
LIST_ENTRY ByIndexListEntry;
|
||||
PH_AVL_LINKS ByBaseLinks;
|
||||
LIST_ENTRY InactiveViewsListEntry;
|
||||
|
||||
ULONG RefCount;
|
||||
ULONG SegmentIndex;
|
||||
PVOID Base;
|
||||
} PH_FILE_POOL_VIEW, *PPH_FILE_POOL_VIEW;
|
||||
|
||||
NTSTATUS PhpValidateFilePoolParameters(
|
||||
_Inout_ PPH_FILE_POOL_PARAMETERS Parameters
|
||||
);
|
||||
|
||||
VOID PhpSetDefaultFilePoolParameters(
|
||||
_Out_ PPH_FILE_POOL_PARAMETERS Parameters
|
||||
);
|
||||
|
||||
// Range mapping
|
||||
|
||||
NTSTATUS PhFppExtendRange(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG NewSize
|
||||
);
|
||||
|
||||
NTSTATUS PhFppMapRange(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG Offset,
|
||||
_In_ ULONG Size,
|
||||
_Out_ PVOID *Base
|
||||
);
|
||||
|
||||
NTSTATUS PhFppUnmapRange(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PVOID Base
|
||||
);
|
||||
|
||||
// Segments
|
||||
|
||||
VOID PhFppInitializeSegment(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Out_ PPH_FP_BLOCK_HEADER BlockOfSegmentHeader,
|
||||
_In_ ULONG AdditionalBlocksUsed
|
||||
);
|
||||
|
||||
PPH_FP_BLOCK_HEADER PhFppAllocateSegment(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Out_ PULONG NewSegmentIndex
|
||||
);
|
||||
|
||||
PPH_FP_SEGMENT_HEADER PhFppGetHeaderSegment(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PPH_FP_BLOCK_HEADER FirstBlock
|
||||
);
|
||||
|
||||
// Views
|
||||
|
||||
VOID PhFppAddViewByIndex(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Inout_ PPH_FILE_POOL_VIEW View
|
||||
);
|
||||
|
||||
VOID PhFppRemoveViewByIndex(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Inout_ PPH_FILE_POOL_VIEW View
|
||||
);
|
||||
|
||||
PPH_FILE_POOL_VIEW PhFppFindViewByIndex(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG SegmentIndex
|
||||
);
|
||||
|
||||
LONG NTAPI PhpFilePoolViewByBaseCompareFunction(
|
||||
_In_ PPH_AVL_LINKS Links1,
|
||||
_In_ PPH_AVL_LINKS Links2
|
||||
);
|
||||
|
||||
VOID PhFppAddViewByBase(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Inout_ PPH_FILE_POOL_VIEW View
|
||||
);
|
||||
|
||||
VOID PhFppRemoveViewByBase(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Inout_ PPH_FILE_POOL_VIEW View
|
||||
);
|
||||
|
||||
PPH_FILE_POOL_VIEW PhFppFindViewByBase(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PVOID Base
|
||||
);
|
||||
|
||||
PPH_FILE_POOL_VIEW PhFppCreateView(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG SegmentIndex
|
||||
);
|
||||
|
||||
VOID PhFppDestroyView(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Inout_ PPH_FILE_POOL_VIEW View
|
||||
);
|
||||
|
||||
VOID PhFppActivateView(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Inout_ PPH_FILE_POOL_VIEW View
|
||||
);
|
||||
|
||||
VOID PhFppDeactivateView(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Inout_ PPH_FILE_POOL_VIEW View
|
||||
);
|
||||
|
||||
VOID PhFppReferenceView(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Inout_ PPH_FILE_POOL_VIEW View
|
||||
);
|
||||
|
||||
VOID PhFppDereferenceView(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_Inout_ PPH_FILE_POOL_VIEW View
|
||||
);
|
||||
|
||||
PPH_FP_BLOCK_HEADER PhFppReferenceSegment(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG SegmentIndex
|
||||
);
|
||||
|
||||
VOID PhFppDereferenceSegment(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG SegmentIndex
|
||||
);
|
||||
|
||||
VOID PhFppReferenceSegmentByBase(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PVOID Base
|
||||
);
|
||||
|
||||
VOID PhFppDereferenceSegmentByBase(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PVOID Base
|
||||
);
|
||||
|
||||
// Bitmap allocation
|
||||
|
||||
PPH_FP_BLOCK_HEADER PhFppAllocateBlocks(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PPH_FP_BLOCK_HEADER FirstBlock,
|
||||
_Inout_ PPH_FP_SEGMENT_HEADER SegmentHeader,
|
||||
_In_ ULONG NumberOfBlocks
|
||||
);
|
||||
|
||||
VOID PhFppFreeBlocks(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ PPH_FP_BLOCK_HEADER FirstBlock,
|
||||
_Inout_ PPH_FP_SEGMENT_HEADER SegmentHeader,
|
||||
_In_ PPH_FP_BLOCK_HEADER BlockHeader
|
||||
);
|
||||
|
||||
// Free list
|
||||
|
||||
ULONG PhFppComputeFreeListIndex(
|
||||
_In_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG NumberOfBlocks
|
||||
);
|
||||
|
||||
BOOLEAN PhFppInsertFreeList(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG FreeListIndex,
|
||||
_In_ ULONG SegmentIndex,
|
||||
_In_ PPH_FP_SEGMENT_HEADER SegmentHeader
|
||||
);
|
||||
|
||||
BOOLEAN PhFppRemoveFreeList(
|
||||
_Inout_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG FreeListIndex,
|
||||
_In_ ULONG SegmentIndex,
|
||||
_In_ PPH_FP_SEGMENT_HEADER SegmentHeader
|
||||
);
|
||||
|
||||
// Misc.
|
||||
|
||||
PPH_FP_BLOCK_HEADER PhFppGetHeaderBlock(
|
||||
_In_ PPH_FILE_POOL Pool,
|
||||
_In_ PVOID Block
|
||||
);
|
||||
|
||||
ULONG PhFppEncodeRva(
|
||||
_In_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG SegmentIndex,
|
||||
_In_ PPH_FP_BLOCK_HEADER FirstBlock,
|
||||
_In_ PVOID Address
|
||||
);
|
||||
|
||||
ULONG PhFppDecodeRva(
|
||||
_In_ PPH_FILE_POOL Pool,
|
||||
_In_ ULONG Rva,
|
||||
_Out_ PULONG SegmentIndex
|
||||
);
|
||||
|
||||
#endif
|
||||
204
phlib/include/filestream.h
Normal file
204
phlib/include/filestream.h
Normal file
@@ -0,0 +1,204 @@
|
||||
#ifndef _PH_FILESTREAM_H
|
||||
#define _PH_FILESTREAM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Core flags (PhCreateFileStream2)
|
||||
/** Indicates that the file stream object should not close the file handle upon deletion. */
|
||||
#define PH_FILE_STREAM_HANDLE_UNOWNED 0x1
|
||||
/**
|
||||
* Indicates that the file stream object should not buffer I/O operations. Note that this does not
|
||||
* prevent the operating system from buffering I/O.
|
||||
*/
|
||||
#define PH_FILE_STREAM_UNBUFFERED 0x2
|
||||
/**
|
||||
* Indicates that the file handle supports asynchronous operations. The file handle must not have
|
||||
* been opened with FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT.
|
||||
*/
|
||||
#define PH_FILE_STREAM_ASYNCHRONOUS 0x4
|
||||
/**
|
||||
* Indicates that the file stream object should maintain the file position and not use the file
|
||||
* object's own file position.
|
||||
*/
|
||||
#define PH_FILE_STREAM_OWN_POSITION 0x8
|
||||
|
||||
// Higher-level flags (PhCreateFileStream)
|
||||
#define PH_FILE_STREAM_APPEND 0x00010000
|
||||
|
||||
// Internal flags
|
||||
/** Indicates that at least one write has been issued to the file handle. */
|
||||
#define PH_FILE_STREAM_WRITTEN 0x80000000
|
||||
|
||||
// Seek
|
||||
typedef enum _PH_SEEK_ORIGIN
|
||||
{
|
||||
SeekStart,
|
||||
SeekCurrent,
|
||||
SeekEnd
|
||||
} PH_SEEK_ORIGIN;
|
||||
|
||||
typedef struct _PH_FILE_STREAM
|
||||
{
|
||||
HANDLE FileHandle;
|
||||
ULONG Flags;
|
||||
LARGE_INTEGER Position; // file object position, *not* the actual position
|
||||
|
||||
PVOID Buffer;
|
||||
ULONG BufferLength;
|
||||
|
||||
ULONG ReadPosition; // read position in buffer
|
||||
ULONG ReadLength; // how much available to read from buffer
|
||||
ULONG WritePosition; // write position in buffer
|
||||
} PH_FILE_STREAM, *PPH_FILE_STREAM;
|
||||
|
||||
extern PPH_OBJECT_TYPE PhFileStreamType;
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhFileStreamInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhCreateFileStream(
|
||||
_Out_ PPH_FILE_STREAM *FileStream,
|
||||
_In_ PWSTR FileName,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ ULONG ShareMode,
|
||||
_In_ ULONG CreateDisposition,
|
||||
_In_ ULONG Flags
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhCreateFileStream2(
|
||||
_Out_ PPH_FILE_STREAM *FileStream,
|
||||
_In_ HANDLE FileHandle,
|
||||
_In_ ULONG Flags,
|
||||
_In_ ULONG BufferLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhVerifyFileStream(
|
||||
_In_ PPH_FILE_STREAM FileStream
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhReadFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_Out_writes_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length,
|
||||
_Out_opt_ PULONG ReadLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhWriteFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_reads_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhFlushFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ BOOLEAN Full
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhGetPositionFileStream(
|
||||
_In_ PPH_FILE_STREAM FileStream,
|
||||
_Out_ PLARGE_INTEGER Position
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhSeekFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PLARGE_INTEGER Offset,
|
||||
_In_ PH_SEEK_ORIGIN Origin
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhLockFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PLARGE_INTEGER Position,
|
||||
_In_ PLARGE_INTEGER Length,
|
||||
_In_ BOOLEAN Wait,
|
||||
_In_ BOOLEAN Shared
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhUnlockFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PLARGE_INTEGER Position,
|
||||
_In_ PLARGE_INTEGER Length
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhWriteStringAsUtf8FileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PPH_STRINGREF String
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhWriteStringAsUtf8FileStream2(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PWSTR String
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhWriteStringAsUtf8FileStreamEx(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PWSTR Buffer,
|
||||
_In_ SIZE_T Length
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhWriteStringFormatAsUtf8FileStream_V(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ _Printf_format_string_ PWSTR Format,
|
||||
_In_ va_list ArgPtr
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhWriteStringFormatAsUtf8FileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ _Printf_format_string_ PWSTR Format,
|
||||
...
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
40
phlib/include/filestreamp.h
Normal file
40
phlib/include/filestreamp.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef _PH_FILESTREAMP_H
|
||||
#define _PH_FILESTREAMP_H
|
||||
|
||||
VOID NTAPI PhpFileStreamDeleteProcedure(
|
||||
_In_ PVOID Object,
|
||||
_In_ ULONG Flags
|
||||
);
|
||||
|
||||
NTSTATUS PhpAllocateBufferFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream
|
||||
);
|
||||
|
||||
NTSTATUS PhpReadFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_Out_writes_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length,
|
||||
_Out_opt_ PULONG ReadLength
|
||||
);
|
||||
|
||||
NTSTATUS PhpWriteFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_reads_bytes_(Length) PVOID Buffer,
|
||||
_In_ ULONG Length
|
||||
);
|
||||
|
||||
NTSTATUS PhpFlushReadFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream
|
||||
);
|
||||
|
||||
NTSTATUS PhpFlushWriteFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream
|
||||
);
|
||||
|
||||
NTSTATUS PhpSeekFileStream(
|
||||
_Inout_ PPH_FILE_STREAM FileStream,
|
||||
_In_ PLARGE_INTEGER Offset,
|
||||
_In_ PH_SEEK_ORIGIN Origin
|
||||
);
|
||||
|
||||
#endif
|
||||
255
phlib/include/graph.h
Normal file
255
phlib/include/graph.h
Normal file
@@ -0,0 +1,255 @@
|
||||
#ifndef _PH_GRAPH_H
|
||||
#define _PH_GRAPH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Graph drawing
|
||||
|
||||
extern RECT PhNormalGraphTextMargin;
|
||||
extern RECT PhNormalGraphTextPadding;
|
||||
|
||||
#define PH_GRAPH_USE_GRID_X 0x1
|
||||
#define PH_GRAPH_USE_GRID_Y 0x2
|
||||
#define PH_GRAPH_LOGARITHMIC_GRID_Y 0x4
|
||||
#define PH_GRAPH_USE_LINE_2 0x10
|
||||
#define PH_GRAPH_OVERLAY_LINE_2 0x20
|
||||
#define PH_GRAPH_LABEL_MAX_Y 0x1000
|
||||
|
||||
typedef PPH_STRING (NTAPI *PPH_GRAPH_LABEL_Y_FUNCTION)(
|
||||
_In_ struct _PH_GRAPH_DRAW_INFO *DrawInfo,
|
||||
_In_ ULONG DataIndex,
|
||||
_In_ FLOAT Value,
|
||||
_In_ FLOAT Parameter
|
||||
);
|
||||
|
||||
typedef struct _PH_GRAPH_DRAW_INFO
|
||||
{
|
||||
// Basic
|
||||
ULONG Width;
|
||||
ULONG Height;
|
||||
ULONG Flags;
|
||||
ULONG Step;
|
||||
COLORREF BackColor;
|
||||
|
||||
// Data/lines
|
||||
ULONG LineDataCount;
|
||||
PFLOAT LineData1;
|
||||
PFLOAT LineData2;
|
||||
COLORREF LineColor1;
|
||||
COLORREF LineColor2;
|
||||
COLORREF LineBackColor1;
|
||||
COLORREF LineBackColor2;
|
||||
|
||||
// Grid
|
||||
COLORREF GridColor;
|
||||
ULONG GridWidth;
|
||||
FLOAT GridHeight;
|
||||
ULONG GridXOffset;
|
||||
ULONG GridYThreshold;
|
||||
FLOAT GridBase; // Base for logarithmic grid
|
||||
|
||||
// y-axis label
|
||||
PPH_GRAPH_LABEL_Y_FUNCTION LabelYFunction;
|
||||
FLOAT LabelYFunctionParameter;
|
||||
HFONT LabelYFont;
|
||||
COLORREF LabelYColor;
|
||||
ULONG LabelMaxYIndexLimit;
|
||||
|
||||
// Text
|
||||
PH_STRINGREF Text;
|
||||
RECT TextRect;
|
||||
RECT TextBoxRect;
|
||||
HFONT TextFont;
|
||||
COLORREF TextColor;
|
||||
COLORREF TextBoxColor;
|
||||
} PH_GRAPH_DRAW_INFO, *PPH_GRAPH_DRAW_INFO;
|
||||
|
||||
// Graph control
|
||||
|
||||
#define PH_GRAPH_CLASSNAME L"PhGraph"
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhGraphControlInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDrawGraphDirect(
|
||||
_In_ HDC hdc,
|
||||
_In_ PVOID Bits,
|
||||
_In_ PPH_GRAPH_DRAW_INFO DrawInfo
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetGraphText(
|
||||
_In_ HDC hdc,
|
||||
_Inout_ PPH_GRAPH_DRAW_INFO DrawInfo,
|
||||
_In_ PPH_STRINGREF Text,
|
||||
_In_ PRECT Margin,
|
||||
_In_ PRECT Padding,
|
||||
_In_ ULONG Align
|
||||
);
|
||||
|
||||
// Configuration
|
||||
|
||||
typedef struct _PH_GRAPH_OPTIONS
|
||||
{
|
||||
COLORREF FadeOutBackColor;
|
||||
ULONG FadeOutWidth;
|
||||
HCURSOR DefaultCursor;
|
||||
} PH_GRAPH_OPTIONS, *PPH_GRAPH_OPTIONS;
|
||||
|
||||
// Styles
|
||||
|
||||
#define GC_STYLE_FADEOUT 0x1
|
||||
#define GC_STYLE_DRAW_PANEL 0x2
|
||||
|
||||
// Messages
|
||||
|
||||
#define GCM_GETDRAWINFO (WM_USER + 1301)
|
||||
#define GCM_SETDRAWINFO (WM_USER + 1302)
|
||||
#define GCM_DRAW (WM_USER + 1303)
|
||||
#define GCM_MOVEGRID (WM_USER + 1304)
|
||||
#define GCM_GETBUFFEREDCONTEXT (WM_USER + 1305)
|
||||
#define GCM_SETTOOLTIP (WM_USER + 1306)
|
||||
#define GCM_UPDATETOOLTIP (WM_USER + 1307)
|
||||
#define GCM_GETOPTIONS (WM_USER + 1308)
|
||||
#define GCM_SETOPTIONS (WM_USER + 1309)
|
||||
|
||||
#define Graph_GetDrawInfo(hWnd, DrawInfo) \
|
||||
SendMessage((hWnd), GCM_GETDRAWINFO, 0, (LPARAM)(DrawInfo))
|
||||
#define Graph_SetDrawInfo(hWnd, DrawInfo) \
|
||||
SendMessage((hWnd), GCM_SETDRAWINFO, 0, (LPARAM)(DrawInfo))
|
||||
#define Graph_Draw(hWnd) \
|
||||
SendMessage((hWnd), GCM_DRAW, 0, 0)
|
||||
#define Graph_MoveGrid(hWnd, Increment) \
|
||||
SendMessage((hWnd), GCM_MOVEGRID, (WPARAM)(Increment), 0)
|
||||
#define Graph_GetBufferedContext(hWnd) \
|
||||
((HDC)SendMessage((hWnd), GCM_GETBUFFEREDCONTEXT, 0, 0))
|
||||
#define Graph_SetTooltip(hWnd, Enable) \
|
||||
((HDC)SendMessage((hWnd), GCM_SETTOOLTIP, (WPARAM)(Enable), 0))
|
||||
#define Graph_UpdateTooltip(hWnd) \
|
||||
((HDC)SendMessage((hWnd), GCM_UPDATETOOLTIP, 0, 0))
|
||||
#define Graph_GetOptions(hWnd, Options) \
|
||||
SendMessage((hWnd), GCM_GETOPTIONS, 0, (LPARAM)(Options))
|
||||
#define Graph_SetOptions(hWnd, Options) \
|
||||
SendMessage((hWnd), GCM_SETOPTIONS, 0, (LPARAM)(Options))
|
||||
|
||||
// Notifications
|
||||
|
||||
#define GCN_GETDRAWINFO (WM_USER + 1351)
|
||||
#define GCN_GETTOOLTIPTEXT (WM_USER + 1352)
|
||||
#define GCN_MOUSEEVENT (WM_USER + 1353)
|
||||
#define GCN_DRAWPANEL (WM_USER + 1354)
|
||||
|
||||
typedef struct _PH_GRAPH_GETDRAWINFO
|
||||
{
|
||||
NMHDR Header;
|
||||
PPH_GRAPH_DRAW_INFO DrawInfo;
|
||||
} PH_GRAPH_GETDRAWINFO, *PPH_GRAPH_GETDRAWINFO;
|
||||
|
||||
typedef struct _PH_GRAPH_GETTOOLTIPTEXT
|
||||
{
|
||||
NMHDR Header;
|
||||
ULONG Index;
|
||||
ULONG TotalCount;
|
||||
|
||||
PH_STRINGREF Text; // must be null-terminated
|
||||
} PH_GRAPH_GETTOOLTIPTEXT, *PPH_GRAPH_GETTOOLTIPTEXT;
|
||||
|
||||
typedef struct _PH_GRAPH_MOUSEEVENT
|
||||
{
|
||||
NMHDR Header;
|
||||
ULONG Index;
|
||||
ULONG TotalCount;
|
||||
|
||||
ULONG Message;
|
||||
ULONG Keys;
|
||||
POINT Point;
|
||||
} PH_GRAPH_MOUSEEVENT, *PPH_GRAPH_MOUSEEVENT;
|
||||
|
||||
typedef struct _PH_GRAPH_DRAWPANEL
|
||||
{
|
||||
NMHDR Header;
|
||||
HDC hdc;
|
||||
RECT Rect;
|
||||
} PH_GRAPH_DRAWPANEL, *PPH_GRAPH_DRAWPANEL;
|
||||
|
||||
// Graph buffer management
|
||||
|
||||
#define PH_GRAPH_DATA_COUNT(Width, Step) (((Width) + (Step) - 1) / (Step) + 1) // round up in division
|
||||
|
||||
typedef struct _PH_GRAPH_BUFFERS
|
||||
{
|
||||
PFLOAT Data1; // invalidate by setting Valid to FALSE
|
||||
PFLOAT Data2; // invalidate by setting Valid to FALSE
|
||||
ULONG AllocatedCount;
|
||||
BOOLEAN Valid; // indicates the data is valid
|
||||
} PH_GRAPH_BUFFERS, *PPH_GRAPH_BUFFERS;
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhInitializeGraphBuffers(
|
||||
_Out_ PPH_GRAPH_BUFFERS Buffers
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDeleteGraphBuffers(
|
||||
_Inout_ PPH_GRAPH_BUFFERS Buffers
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhGetDrawInfoGraphBuffers(
|
||||
_Inout_ PPH_GRAPH_BUFFERS Buffers,
|
||||
_Inout_ PPH_GRAPH_DRAW_INFO DrawInfo,
|
||||
_In_ ULONG DataCount
|
||||
);
|
||||
|
||||
// Graph control state
|
||||
|
||||
// The basic buffer management structure was moved out of this section because
|
||||
// the text management is not needed for most cases.
|
||||
|
||||
typedef struct _PH_GRAPH_STATE
|
||||
{
|
||||
// Union for compatibility
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
PFLOAT Data1; // invalidate by setting Valid to FALSE
|
||||
PFLOAT Data2; // invalidate by setting Valid to FALSE
|
||||
ULONG AllocatedCount;
|
||||
BOOLEAN Valid; // indicates the data is valid
|
||||
};
|
||||
PH_GRAPH_BUFFERS Buffers;
|
||||
};
|
||||
|
||||
PPH_STRING Text;
|
||||
PPH_STRING TooltipText; // invalidate by setting TooltipIndex to -1
|
||||
ULONG TooltipIndex; // indicates the tooltip text is valid for this index
|
||||
} PH_GRAPH_STATE, *PPH_GRAPH_STATE;
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhInitializeGraphState(
|
||||
_Out_ PPH_GRAPH_STATE State
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDeleteGraphState(
|
||||
_Inout_ PPH_GRAPH_STATE State
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhGraphStateGetDrawInfo(
|
||||
_Inout_ PPH_GRAPH_STATE State,
|
||||
_In_ PPH_GRAPH_GETDRAWINFO GetDrawInfo,
|
||||
_In_ ULONG DataCount
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
723
phlib/include/guisup.h
Normal file
723
phlib/include/guisup.h
Normal file
@@ -0,0 +1,723 @@
|
||||
#ifndef _PH_PHGUI_H
|
||||
#define _PH_PHGUI_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <commctrl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// guisup
|
||||
|
||||
typedef BOOL (WINAPI *_ChangeWindowMessageFilter)(
|
||||
_In_ UINT message,
|
||||
_In_ DWORD dwFlag
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_IsImmersiveProcess)(
|
||||
_In_ HANDLE hProcess
|
||||
);
|
||||
|
||||
#define RFF_NOBROWSE 0x0001
|
||||
#define RFF_NODEFAULT 0x0002
|
||||
#define RFF_CALCDIRECTORY 0x0004
|
||||
#define RFF_NOLABEL 0x0008
|
||||
#define RFF_NOSEPARATEMEM 0x0020
|
||||
|
||||
#define RFN_VALIDATE (-510)
|
||||
|
||||
typedef struct _NMRUNFILEDLGW
|
||||
{
|
||||
NMHDR hdr;
|
||||
LPCWSTR lpszFile;
|
||||
LPCWSTR lpszDirectory;
|
||||
UINT nShow;
|
||||
} NMRUNFILEDLGW, *LPNMRUNFILEDLGW, *PNMRUNFILEDLGW;
|
||||
|
||||
typedef NMRUNFILEDLGW NMRUNFILEDLG;
|
||||
typedef PNMRUNFILEDLGW PNMRUNFILEDLG;
|
||||
typedef LPNMRUNFILEDLGW LPNMRUNFILEDLG;
|
||||
|
||||
#define RF_OK 0x0000
|
||||
#define RF_CANCEL 0x0001
|
||||
#define RF_RETRY 0x0002
|
||||
|
||||
typedef HANDLE HTHEME;
|
||||
|
||||
typedef BOOL (WINAPI *_RunFileDlg)(
|
||||
_In_ HWND hwndOwner,
|
||||
_In_opt_ HICON hIcon,
|
||||
_In_opt_ LPCWSTR lpszDirectory,
|
||||
_In_opt_ LPCWSTR lpszTitle,
|
||||
_In_opt_ LPCWSTR lpszDescription,
|
||||
_In_ ULONG uFlags
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI *_SHAutoComplete)(
|
||||
_In_ HWND hwndEdit,
|
||||
_In_ DWORD dwFlags
|
||||
);
|
||||
|
||||
extern _ChangeWindowMessageFilter ChangeWindowMessageFilter_I;
|
||||
extern _IsImmersiveProcess IsImmersiveProcess_I;
|
||||
extern _RunFileDlg RunFileDlg;
|
||||
extern _SHAutoComplete SHAutoComplete_I;
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhGuiSupportInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetControlTheme(
|
||||
_In_ HWND Handle,
|
||||
_In_ PWSTR Theme
|
||||
);
|
||||
|
||||
FORCEINLINE VOID PhSetWindowStyle(
|
||||
_In_ HWND Handle,
|
||||
_In_ LONG_PTR Mask,
|
||||
_In_ LONG_PTR Value
|
||||
)
|
||||
{
|
||||
LONG_PTR style;
|
||||
|
||||
style = GetWindowLongPtr(Handle, GWL_STYLE);
|
||||
style = (style & ~Mask) | (Value & Mask);
|
||||
SetWindowLongPtr(Handle, GWL_STYLE, style);
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhSetWindowExStyle(
|
||||
_In_ HWND Handle,
|
||||
_In_ LONG_PTR Mask,
|
||||
_In_ LONG_PTR Value
|
||||
)
|
||||
{
|
||||
LONG_PTR style;
|
||||
|
||||
style = GetWindowLongPtr(Handle, GWL_EXSTYLE);
|
||||
style = (style & ~Mask) | (Value & Mask);
|
||||
SetWindowLongPtr(Handle, GWL_EXSTYLE, style);
|
||||
}
|
||||
|
||||
#ifndef WM_REFLECT
|
||||
#define WM_REFLECT 0x2000
|
||||
#endif
|
||||
|
||||
#define REFLECT_MESSAGE(hwnd, msg, wParam, lParam) \
|
||||
{ \
|
||||
LRESULT result_ = PhReflectMessage(hwnd, msg, wParam, lParam); \
|
||||
\
|
||||
if (result_) \
|
||||
return result_; \
|
||||
}
|
||||
|
||||
#define REFLECT_MESSAGE_DLG(hwndDlg, hwnd, msg, wParam, lParam) \
|
||||
{ \
|
||||
LRESULT result_ = PhReflectMessage(hwnd, msg, wParam, lParam); \
|
||||
\
|
||||
if (result_) \
|
||||
{ \
|
||||
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, result_); \
|
||||
return TRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
FORCEINLINE LRESULT PhReflectMessage(
|
||||
_In_ HWND Handle,
|
||||
_In_ UINT Message,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
{
|
||||
if (Message == WM_NOTIFY)
|
||||
{
|
||||
LPNMHDR header = (LPNMHDR)lParam;
|
||||
|
||||
if (header->hwndFrom == Handle)
|
||||
return SendMessage(Handle, WM_REFLECT + Message, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PH_DEFINE_MAKE_ATOM(AtomName) \
|
||||
do { \
|
||||
static UNICODE_STRING atomName = RTL_CONSTANT_STRING(AtomName); \
|
||||
static PH_INITONCE initOnce = PH_INITONCE_INIT; \
|
||||
static RTL_ATOM atom = 0; \
|
||||
\
|
||||
if (PhBeginInitOnce(&initOnce)) \
|
||||
{ \
|
||||
NtAddAtom(atomName.Buffer, atomName.Length, &atom); \
|
||||
PhEndInitOnce(&initOnce); \
|
||||
} \
|
||||
\
|
||||
if (atom) \
|
||||
return (PWSTR)(ULONG_PTR)atom; \
|
||||
else \
|
||||
return atomName.Buffer; \
|
||||
} while (0)
|
||||
|
||||
FORCEINLINE VOID PhSetListViewStyle(
|
||||
_In_ HWND Handle,
|
||||
_In_ BOOLEAN AllowDragDrop,
|
||||
_In_ BOOLEAN ShowLabelTips
|
||||
)
|
||||
{
|
||||
ULONG style;
|
||||
|
||||
style = LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP;
|
||||
|
||||
if (AllowDragDrop)
|
||||
style |= LVS_EX_HEADERDRAGDROP;
|
||||
if (ShowLabelTips)
|
||||
style |= LVS_EX_LABELTIP;
|
||||
|
||||
ListView_SetExtendedListViewStyleEx(
|
||||
Handle,
|
||||
style,
|
||||
-1
|
||||
);
|
||||
}
|
||||
|
||||
PHLIBAPI
|
||||
INT PhAddListViewColumn(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT Index,
|
||||
_In_ INT DisplayIndex,
|
||||
_In_ INT SubItemIndex,
|
||||
_In_ INT Format,
|
||||
_In_ INT Width,
|
||||
_In_ PWSTR Text
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
INT PhAddListViewItem(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT Index,
|
||||
_In_ PWSTR Text,
|
||||
_In_opt_ PVOID Param
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
INT PhFindListViewItemByFlags(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT StartIndex,
|
||||
_In_ ULONG Flags
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
INT PhFindListViewItemByParam(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT StartIndex,
|
||||
_In_opt_ PVOID Param
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
LOGICAL PhGetListViewItemImageIndex(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT Index,
|
||||
_Out_ PINT ImageIndex
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
LOGICAL PhGetListViewItemParam(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT Index,
|
||||
_Out_ PVOID *Param
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhRemoveListViewItem(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT Index
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetListViewItemImageIndex(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT Index,
|
||||
_In_ INT ImageIndex
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetListViewSubItem(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ INT Index,
|
||||
_In_ INT SubItemIndex,
|
||||
_In_ PWSTR Text
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhLoadListViewColumnSettings(
|
||||
_In_ HWND ListViewHandle,
|
||||
_In_ PPH_STRING Settings
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING PhSaveListViewColumnSettings(
|
||||
_In_ HWND ListViewHandle
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
INT PhAddTabControlTab(
|
||||
_In_ HWND TabControlHandle,
|
||||
_In_ INT Index,
|
||||
_In_ PWSTR Text
|
||||
);
|
||||
|
||||
#define PhaGetDlgItemText(hwndDlg, id) \
|
||||
PH_AUTO_T(PH_STRING, PhGetWindowText(GetDlgItem(hwndDlg, id)))
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING PhGetWindowText(
|
||||
_In_ HWND hwnd
|
||||
);
|
||||
|
||||
#define PH_GET_WINDOW_TEXT_INTERNAL 0x1
|
||||
#define PH_GET_WINDOW_TEXT_LENGTH_ONLY 0x2
|
||||
|
||||
PHLIBAPI
|
||||
ULONG PhGetWindowTextEx(
|
||||
_In_ HWND hwnd,
|
||||
_In_ ULONG Flags,
|
||||
_Out_opt_ PPH_STRING *Text
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhAddComboBoxStrings(
|
||||
_In_ HWND hWnd,
|
||||
_In_ PWSTR *Strings,
|
||||
_In_ ULONG NumberOfStrings
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING PhGetComboBoxString(
|
||||
_In_ HWND hwnd,
|
||||
_In_ INT Index
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
INT PhSelectComboBoxString(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PWSTR String,
|
||||
_In_ BOOLEAN Partial
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING PhGetListBoxString(
|
||||
_In_ HWND hwnd,
|
||||
_In_ INT Index
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetStateAllListViewItems(
|
||||
_In_ HWND hWnd,
|
||||
_In_ ULONG State,
|
||||
_In_ ULONG Mask
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID PhGetSelectedListViewItemParam(
|
||||
_In_ HWND hWnd
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhGetSelectedListViewItemParams(
|
||||
_In_ HWND hWnd,
|
||||
_Out_ PVOID **Items,
|
||||
_Out_ PULONG NumberOfItems
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetImageListBitmap(
|
||||
_In_ HIMAGELIST ImageList,
|
||||
_In_ INT Index,
|
||||
_In_ HINSTANCE InstanceHandle,
|
||||
_In_ LPCWSTR BitmapName
|
||||
);
|
||||
|
||||
#define PH_LOAD_ICON_SHARED 0x1
|
||||
#define PH_LOAD_ICON_SIZE_SMALL 0x2
|
||||
#define PH_LOAD_ICON_SIZE_LARGE 0x4
|
||||
#define PH_LOAD_ICON_STRICT 0x8
|
||||
|
||||
PHLIBAPI
|
||||
HICON PhLoadIcon(
|
||||
_In_opt_ HINSTANCE InstanceHandle,
|
||||
_In_ PWSTR Name,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ ULONG Width,
|
||||
_In_opt_ ULONG Height
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhGetStockApplicationIcon(
|
||||
_Out_opt_ HICON *SmallIcon,
|
||||
_Out_opt_ HICON *LargeIcon
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
HICON PhGetFileShellIcon(
|
||||
_In_opt_ PWSTR FileName,
|
||||
_In_opt_ PWSTR DefaultExtension,
|
||||
_In_ BOOLEAN LargeIcon
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhSetClipboardString(
|
||||
_In_ HWND hWnd,
|
||||
_In_ PPH_STRINGREF String
|
||||
);
|
||||
|
||||
typedef struct _DLGTEMPLATEEX
|
||||
{
|
||||
WORD dlgVer;
|
||||
WORD signature;
|
||||
DWORD helpID;
|
||||
DWORD exStyle;
|
||||
DWORD style;
|
||||
WORD cDlgItems;
|
||||
short x;
|
||||
short y;
|
||||
short cx;
|
||||
short cy;
|
||||
} DLGTEMPLATEEX, *PDLGTEMPLATEEX;
|
||||
|
||||
PHLIBAPI
|
||||
HWND PhCreateDialogFromTemplate(
|
||||
_In_ HWND Parent,
|
||||
_In_ ULONG Style,
|
||||
_In_ PVOID Instance,
|
||||
_In_ PWSTR Template,
|
||||
_In_ DLGPROC DialogProc,
|
||||
_In_ PVOID Parameter
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhModalPropertySheet(
|
||||
_Inout_ PROPSHEETHEADER *Header
|
||||
);
|
||||
|
||||
#define PH_ANCHOR_LEFT 0x1
|
||||
#define PH_ANCHOR_TOP 0x2
|
||||
#define PH_ANCHOR_RIGHT 0x4
|
||||
#define PH_ANCHOR_BOTTOM 0x8
|
||||
#define PH_ANCHOR_ALL 0xf
|
||||
|
||||
// This interface is horrible and should be rewritten, but it works for now.
|
||||
|
||||
#define PH_LAYOUT_FORCE_INVALIDATE 0x1000 // invalidate the control when it is resized
|
||||
#define PH_LAYOUT_TAB_CONTROL 0x2000 // this is a dummy item, a hack for the tab control
|
||||
#define PH_LAYOUT_IMMEDIATE_RESIZE 0x4000 // needed for the tab control hack
|
||||
|
||||
#define PH_LAYOUT_DUMMY_MASK (PH_LAYOUT_TAB_CONTROL) // items that don't have a window handle, or don't actually get their window resized
|
||||
|
||||
typedef struct _PH_LAYOUT_ITEM
|
||||
{
|
||||
HWND Handle;
|
||||
struct _PH_LAYOUT_ITEM *ParentItem; // for rectangle calculation
|
||||
struct _PH_LAYOUT_ITEM *LayoutParentItem; // for actual resizing
|
||||
ULONG LayoutNumber;
|
||||
ULONG NumberOfChildren;
|
||||
HDWP DeferHandle;
|
||||
|
||||
RECT Rect;
|
||||
RECT OrigRect;
|
||||
RECT Margin;
|
||||
ULONG Anchor;
|
||||
} PH_LAYOUT_ITEM, *PPH_LAYOUT_ITEM;
|
||||
|
||||
typedef struct _PH_LAYOUT_MANAGER
|
||||
{
|
||||
PPH_LIST List;
|
||||
PH_LAYOUT_ITEM RootItem;
|
||||
|
||||
ULONG LayoutNumber;
|
||||
} PH_LAYOUT_MANAGER, *PPH_LAYOUT_MANAGER;
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhInitializeLayoutManager(
|
||||
_Out_ PPH_LAYOUT_MANAGER Manager,
|
||||
_In_ HWND RootWindowHandle
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhDeleteLayoutManager(
|
||||
_Inout_ PPH_LAYOUT_MANAGER Manager
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_LAYOUT_ITEM PhAddLayoutItem(
|
||||
_Inout_ PPH_LAYOUT_MANAGER Manager,
|
||||
_In_ HWND Handle,
|
||||
_In_opt_ PPH_LAYOUT_ITEM ParentItem,
|
||||
_In_ ULONG Anchor
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_LAYOUT_ITEM PhAddLayoutItemEx(
|
||||
_Inout_ PPH_LAYOUT_MANAGER Manager,
|
||||
_In_ HWND Handle,
|
||||
_In_opt_ PPH_LAYOUT_ITEM ParentItem,
|
||||
_In_ ULONG Anchor,
|
||||
_In_ RECT Margin
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID PhLayoutManagerLayout(
|
||||
_Inout_ PPH_LAYOUT_MANAGER Manager
|
||||
);
|
||||
|
||||
FORCEINLINE VOID PhResizingMinimumSize(
|
||||
_Inout_ PRECT Rect,
|
||||
_In_ WPARAM Edge,
|
||||
_In_ LONG MinimumWidth,
|
||||
_In_ LONG MinimumHeight
|
||||
)
|
||||
{
|
||||
if (Edge == WMSZ_BOTTOMRIGHT || Edge == WMSZ_RIGHT || Edge == WMSZ_TOPRIGHT)
|
||||
{
|
||||
if (Rect->right - Rect->left < MinimumWidth)
|
||||
Rect->right = Rect->left + MinimumWidth;
|
||||
}
|
||||
else if (Edge == WMSZ_BOTTOMLEFT || Edge == WMSZ_LEFT || Edge == WMSZ_TOPLEFT)
|
||||
{
|
||||
if (Rect->right - Rect->left < MinimumWidth)
|
||||
Rect->left = Rect->right - MinimumWidth;
|
||||
}
|
||||
|
||||
if (Edge == WMSZ_BOTTOMRIGHT || Edge == WMSZ_BOTTOM || Edge == WMSZ_BOTTOMLEFT)
|
||||
{
|
||||
if (Rect->bottom - Rect->top < MinimumHeight)
|
||||
Rect->bottom = Rect->top + MinimumHeight;
|
||||
}
|
||||
else if (Edge == WMSZ_TOPRIGHT || Edge == WMSZ_TOP || Edge == WMSZ_TOPLEFT)
|
||||
{
|
||||
if (Rect->bottom - Rect->top < MinimumHeight)
|
||||
Rect->top = Rect->bottom - MinimumHeight;
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhCopyControlRectangle(
|
||||
_In_ HWND ParentWindowHandle,
|
||||
_In_ HWND FromControlHandle,
|
||||
_In_ HWND ToControlHandle
|
||||
)
|
||||
{
|
||||
RECT windowRect;
|
||||
|
||||
GetWindowRect(FromControlHandle, &windowRect);
|
||||
MapWindowPoints(NULL, ParentWindowHandle, (POINT *)&windowRect, 2);
|
||||
MoveWindow(ToControlHandle, windowRect.left, windowRect.top,
|
||||
windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, FALSE);
|
||||
}
|
||||
|
||||
// icotobmp
|
||||
|
||||
PHLIBAPI
|
||||
HBITMAP
|
||||
NTAPI
|
||||
PhIconToBitmap(
|
||||
_In_ HICON Icon,
|
||||
_In_ ULONG Width,
|
||||
_In_ ULONG Height
|
||||
);
|
||||
|
||||
// extlv
|
||||
|
||||
#define PH_ALIGN_CENTER 0x0
|
||||
#define PH_ALIGN_LEFT 0x1
|
||||
#define PH_ALIGN_RIGHT 0x2
|
||||
#define PH_ALIGN_TOP 0x4
|
||||
#define PH_ALIGN_BOTTOM 0x8
|
||||
|
||||
typedef enum _PH_ITEM_STATE
|
||||
{
|
||||
// The item is normal. Use the ItemColorFunction to determine the color of the item.
|
||||
NormalItemState = 0,
|
||||
// The item is new. On the next tick, change the state to NormalItemState. When an item is in
|
||||
// this state, highlight it in NewColor.
|
||||
NewItemState,
|
||||
// The item is being removed. On the next tick, delete the item. When an item is in this state,
|
||||
// highlight it in RemovingColor.
|
||||
RemovingItemState
|
||||
} PH_ITEM_STATE;
|
||||
|
||||
typedef COLORREF (NTAPI *PPH_EXTLV_GET_ITEM_COLOR)(
|
||||
_In_ INT Index,
|
||||
_In_ PVOID Param,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
typedef HFONT (NTAPI *PPH_EXTLV_GET_ITEM_FONT)(
|
||||
_In_ INT Index,
|
||||
_In_ PVOID Param,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhSetExtendedListView(
|
||||
_In_ HWND hWnd
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhSetHeaderSortIcon(
|
||||
_In_ HWND hwnd,
|
||||
_In_ INT Index,
|
||||
_In_ PH_SORT_ORDER Order
|
||||
);
|
||||
|
||||
// next 1122
|
||||
|
||||
#define ELVM_ADDFALLBACKCOLUMN (WM_APP + 1106)
|
||||
#define ELVM_ADDFALLBACKCOLUMNS (WM_APP + 1109)
|
||||
#define ELVM_RESERVED5 (WM_APP + 1120)
|
||||
#define ELVM_INIT (WM_APP + 1102)
|
||||
#define ELVM_SETCOLUMNWIDTH (WM_APP + 1121)
|
||||
#define ELVM_SETCOMPAREFUNCTION (WM_APP + 1104)
|
||||
#define ELVM_SETCONTEXT (WM_APP + 1103)
|
||||
#define ELVM_SETCURSOR (WM_APP + 1114)
|
||||
#define ELVM_RESERVED4 (WM_APP + 1118)
|
||||
#define ELVM_SETITEMCOLORFUNCTION (WM_APP + 1111)
|
||||
#define ELVM_SETITEMFONTFUNCTION (WM_APP + 1117)
|
||||
#define ELVM_RESERVED1 (WM_APP + 1112)
|
||||
#define ELVM_SETREDRAW (WM_APP + 1116)
|
||||
#define ELVM_RESERVED2 (WM_APP + 1113)
|
||||
#define ELVM_SETSORT (WM_APP + 1108)
|
||||
#define ELVM_SETSORTFAST (WM_APP + 1119)
|
||||
#define ELVM_RESERVED0 (WM_APP + 1110)
|
||||
#define ELVM_SETTRISTATE (WM_APP + 1107)
|
||||
#define ELVM_SETTRISTATECOMPAREFUNCTION (WM_APP + 1105)
|
||||
#define ELVM_SORTITEMS (WM_APP + 1101)
|
||||
#define ELVM_RESERVED3 (WM_APP + 1115)
|
||||
|
||||
#define ExtendedListView_AddFallbackColumn(hWnd, Column) \
|
||||
SendMessage((hWnd), ELVM_ADDFALLBACKCOLUMN, (WPARAM)(Column), 0)
|
||||
#define ExtendedListView_AddFallbackColumns(hWnd, NumberOfColumns, Columns) \
|
||||
SendMessage((hWnd), ELVM_ADDFALLBACKCOLUMNS, (WPARAM)(NumberOfColumns), (LPARAM)(Columns))
|
||||
#define ExtendedListView_Init(hWnd) \
|
||||
SendMessage((hWnd), ELVM_INIT, 0, 0)
|
||||
#define ExtendedListView_SetColumnWidth(hWnd, Column, Width) \
|
||||
SendMessage((hWnd), ELVM_SETCOLUMNWIDTH, (WPARAM)(Column), (LPARAM)(Width))
|
||||
#define ExtendedListView_SetCompareFunction(hWnd, Column, CompareFunction) \
|
||||
SendMessage((hWnd), ELVM_SETCOMPAREFUNCTION, (WPARAM)(Column), (LPARAM)(CompareFunction))
|
||||
#define ExtendedListView_SetContext(hWnd, Context) \
|
||||
SendMessage((hWnd), ELVM_SETCONTEXT, 0, (LPARAM)(Context))
|
||||
#define ExtendedListView_SetCursor(hWnd, Cursor) \
|
||||
SendMessage((hWnd), ELVM_SETCURSOR, 0, (LPARAM)(Cursor))
|
||||
#define ExtendedListView_SetItemColorFunction(hWnd, ItemColorFunction) \
|
||||
SendMessage((hWnd), ELVM_SETITEMCOLORFUNCTION, 0, (LPARAM)(ItemColorFunction))
|
||||
#define ExtendedListView_SetItemFontFunction(hWnd, ItemFontFunction) \
|
||||
SendMessage((hWnd), ELVM_SETITEMFONTFUNCTION, 0, (LPARAM)(ItemFontFunction))
|
||||
#define ExtendedListView_SetRedraw(hWnd, Redraw) \
|
||||
SendMessage((hWnd), ELVM_SETREDRAW, (WPARAM)(Redraw), 0)
|
||||
#define ExtendedListView_SetSort(hWnd, Column, Order) \
|
||||
SendMessage((hWnd), ELVM_SETSORT, (WPARAM)(Column), (LPARAM)(Order))
|
||||
#define ExtendedListView_SetSortFast(hWnd, Fast) \
|
||||
SendMessage((hWnd), ELVM_SETSORTFAST, (WPARAM)(Fast), 0)
|
||||
#define ExtendedListView_SetTriState(hWnd, TriState) \
|
||||
SendMessage((hWnd), ELVM_SETTRISTATE, (WPARAM)(TriState), 0)
|
||||
#define ExtendedListView_SetTriStateCompareFunction(hWnd, CompareFunction) \
|
||||
SendMessage((hWnd), ELVM_SETTRISTATECOMPAREFUNCTION, 0, (LPARAM)(CompareFunction))
|
||||
#define ExtendedListView_SortItems(hWnd) \
|
||||
SendMessage((hWnd), ELVM_SORTITEMS, 0, 0)
|
||||
|
||||
#define ELVSCW_AUTOSIZE (-1)
|
||||
#define ELVSCW_AUTOSIZE_USEHEADER (-2)
|
||||
#define ELVSCW_AUTOSIZE_REMAININGSPACE (-3)
|
||||
|
||||
/**
|
||||
* Gets the brightness of a color.
|
||||
*
|
||||
* \param Color The color.
|
||||
*
|
||||
* \return A value ranging from 0 to 255, indicating the brightness of the color.
|
||||
*/
|
||||
FORCEINLINE
|
||||
ULONG
|
||||
PhGetColorBrightness(
|
||||
_In_ COLORREF Color
|
||||
)
|
||||
{
|
||||
ULONG r = Color & 0xff;
|
||||
ULONG g = (Color >> 8) & 0xff;
|
||||
ULONG b = (Color >> 16) & 0xff;
|
||||
ULONG min;
|
||||
ULONG max;
|
||||
|
||||
min = r;
|
||||
if (g < min) min = g;
|
||||
if (b < min) min = b;
|
||||
|
||||
max = r;
|
||||
if (g > max) max = g;
|
||||
if (b > max) max = b;
|
||||
|
||||
return (min + max) / 2;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
COLORREF
|
||||
PhHalveColorBrightness(
|
||||
_In_ COLORREF Color
|
||||
)
|
||||
{
|
||||
/*return RGB(
|
||||
(UCHAR)Color / 2,
|
||||
(UCHAR)(Color >> 8) / 2,
|
||||
(UCHAR)(Color >> 16) / 2
|
||||
);*/
|
||||
// Since all targets are little-endian, we can use the following method.
|
||||
*((PUCHAR)&Color) /= 2;
|
||||
*((PUCHAR)&Color + 1) /= 2;
|
||||
*((PUCHAR)&Color + 2) /= 2;
|
||||
|
||||
return Color;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
COLORREF
|
||||
PhMakeColorBrighter(
|
||||
_In_ COLORREF Color,
|
||||
_In_ UCHAR Increment
|
||||
)
|
||||
{
|
||||
UCHAR r;
|
||||
UCHAR g;
|
||||
UCHAR b;
|
||||
|
||||
r = (UCHAR)Color;
|
||||
g = (UCHAR)(Color >> 8);
|
||||
b = (UCHAR)(Color >> 16);
|
||||
|
||||
if (r <= 255 - Increment)
|
||||
r += Increment;
|
||||
else
|
||||
r = 255;
|
||||
|
||||
if (g <= 255 - Increment)
|
||||
g += Increment;
|
||||
else
|
||||
g = 255;
|
||||
|
||||
if (b <= 255 - Increment)
|
||||
b += Increment;
|
||||
else
|
||||
b = 255;
|
||||
|
||||
return RGB(r, g, b);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
43
phlib/include/guisupp.h
Normal file
43
phlib/include/guisupp.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef _PH_GUISUPP_H
|
||||
#define _PH_GUISUPP_H
|
||||
|
||||
typedef HRESULT (WINAPI *_LoadIconMetric)(
|
||||
_In_ HINSTANCE hinst,
|
||||
_In_ PCWSTR pszName,
|
||||
_In_ int lims,
|
||||
_Out_ HICON *phico
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI *_LoadIconWithScaleDown)(
|
||||
_In_ HINSTANCE hinst,
|
||||
_In_ PCWSTR pszName,
|
||||
_In_ int cx,
|
||||
_In_ int cy,
|
||||
_Out_ HICON *phico
|
||||
);
|
||||
|
||||
typedef struct _PHP_ICON_ENTRY
|
||||
{
|
||||
HINSTANCE InstanceHandle;
|
||||
PWSTR Name;
|
||||
ULONG Width;
|
||||
ULONG Height;
|
||||
HICON Icon;
|
||||
} PHP_ICON_ENTRY, *PPHP_ICON_ENTRY;
|
||||
|
||||
#define PHP_ICON_ENTRY_SIZE_SMALL (-1)
|
||||
#define PHP_ICON_ENTRY_SIZE_LARGE (-2)
|
||||
|
||||
FORCEINLINE ULONG PhpGetIconEntrySize(
|
||||
_In_ ULONG InputSize,
|
||||
_In_ ULONG Flags
|
||||
)
|
||||
{
|
||||
if (Flags & PH_LOAD_ICON_SIZE_SMALL)
|
||||
return PHP_ICON_ENTRY_SIZE_SMALL;
|
||||
if (Flags & PH_LOAD_ICON_SIZE_LARGE)
|
||||
return PHP_ICON_ENTRY_SIZE_LARGE;
|
||||
return InputSize;
|
||||
}
|
||||
|
||||
#endif
|
||||
167
phlib/include/handle.h
Normal file
167
phlib/include/handle.h
Normal file
@@ -0,0 +1,167 @@
|
||||
#ifndef _PH_HANDLE_H
|
||||
#define _PH_HANDLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct _PH_HANDLE_TABLE;
|
||||
typedef struct _PH_HANDLE_TABLE *PPH_HANDLE_TABLE;
|
||||
|
||||
typedef struct _PH_HANDLE_TABLE_ENTRY
|
||||
{
|
||||
union
|
||||
{
|
||||
PVOID Object;
|
||||
ULONG_PTR Value;
|
||||
struct
|
||||
{
|
||||
/** The type of the entry; 1 if the entry is free, otherwise 0 if the entry is in use. */
|
||||
ULONG_PTR Type : 1;
|
||||
/**
|
||||
* Whether the entry is not locked; 1 if the entry is not locked, otherwise 0 if the
|
||||
* entry is locked.
|
||||
*/
|
||||
ULONG_PTR Locked : 1;
|
||||
ULONG_PTR Value : sizeof(ULONG_PTR) * 8 - 2;
|
||||
} TypeAndValue;
|
||||
};
|
||||
union
|
||||
{
|
||||
ACCESS_MASK GrantedAccess;
|
||||
ULONG NextFreeValue;
|
||||
ULONG_PTR Value2;
|
||||
};
|
||||
} PH_HANDLE_TABLE_ENTRY, *PPH_HANDLE_TABLE_ENTRY;
|
||||
|
||||
#define PH_HANDLE_TABLE_SAFE
|
||||
#define PH_HANDLE_TABLE_FREE_COUNT 64
|
||||
|
||||
#define PH_HANDLE_TABLE_STRICT_FIFO 0x1
|
||||
#define PH_HANDLE_TABLE_VALID_FLAGS 0x1
|
||||
|
||||
PHLIBAPI
|
||||
PPH_HANDLE_TABLE
|
||||
NTAPI
|
||||
PhCreateHandleTable(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhDestroyHandleTable(
|
||||
_In_ _Post_invalid_ PPH_HANDLE_TABLE HandleTable
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhLockHandleTableEntry(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_Inout_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhUnlockHandleTableEntry(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_Inout_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
HANDLE
|
||||
NTAPI
|
||||
PhCreateHandle(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhDestroyHandle(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ HANDLE Handle,
|
||||
_In_opt_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_HANDLE_TABLE_ENTRY
|
||||
NTAPI
|
||||
PhLookupHandleTableEntry(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ HANDLE Handle
|
||||
);
|
||||
|
||||
typedef BOOLEAN (NTAPI *PPH_ENUM_HANDLE_TABLE_CALLBACK)(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ HANDLE Handle,
|
||||
_In_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhEnumHandleTable(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ PPH_ENUM_HANDLE_TABLE_CALLBACK Callback,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhSweepHandleTable(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ PPH_ENUM_HANDLE_TABLE_CALLBACK Callback,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
typedef enum _PH_HANDLE_TABLE_INFORMATION_CLASS
|
||||
{
|
||||
HandleTableBasicInformation,
|
||||
HandleTableFlagsInformation,
|
||||
MaxHandleTableInfoClass
|
||||
} PH_HANDLE_TABLE_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _PH_HANDLE_TABLE_BASIC_INFORMATION
|
||||
{
|
||||
ULONG Count;
|
||||
ULONG Flags;
|
||||
ULONG TableLevel;
|
||||
} PH_HANDLE_TABLE_BASIC_INFORMATION, *PPH_HANDLE_TABLE_BASIC_INFORMATION;
|
||||
|
||||
typedef struct _PH_HANDLE_TABLE_FLAGS_INFORMATION
|
||||
{
|
||||
ULONG Flags;
|
||||
} PH_HANDLE_TABLE_FLAGS_INFORMATION, *PPH_HANDLE_TABLE_FLAGS_INFORMATION;
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhQueryInformationHandleTable(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ PH_HANDLE_TABLE_INFORMATION_CLASS InformationClass,
|
||||
_Out_writes_bytes_opt_(BufferLength) PVOID Buffer,
|
||||
_In_ ULONG BufferLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhSetInformationHandleTable(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ PH_HANDLE_TABLE_INFORMATION_CLASS InformationClass,
|
||||
_In_reads_bytes_(BufferLength) PVOID Buffer,
|
||||
_In_ ULONG BufferLength
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
147
phlib/include/handlep.h
Normal file
147
phlib/include/handlep.h
Normal file
@@ -0,0 +1,147 @@
|
||||
#ifndef _PH_HANDLEP_H
|
||||
#define _PH_HANDLEP_H
|
||||
|
||||
#define PH_HANDLE_TABLE_ENTRY_TYPE 0x1
|
||||
#define PH_HANDLE_TABLE_ENTRY_IN_USE 0x0
|
||||
#define PH_HANDLE_TABLE_ENTRY_FREE 0x1
|
||||
|
||||
// Locked actually means Not Locked. This means that an in use, locked handle table entry can be
|
||||
// used as-is.
|
||||
#define PH_HANDLE_TABLE_ENTRY_LOCKED 0x2
|
||||
#define PH_HANDLE_TABLE_ENTRY_LOCKED_SHIFT 1
|
||||
|
||||
// There is initially one handle table level, with 256 entries. When the handle table is expanded,
|
||||
// the table is replaced with a level 1 table, which contains 256 pointers to level 0 tables (the
|
||||
// first entry already points to the initial level 0 table). Similarly, when the handle table is
|
||||
// expanded a second time, the table is replaced with a level 2 table, which contains 256 pointers
|
||||
// to level 1 tables.
|
||||
//
|
||||
// This provides a maximum of 16,777,216 handles.
|
||||
|
||||
#define PH_HANDLE_TABLE_LEVEL_ENTRIES 256
|
||||
#define PH_HANDLE_TABLE_LEVEL_MASK 0x3
|
||||
|
||||
#define PH_HANDLE_TABLE_LOCKS 8
|
||||
#define PH_HANDLE_TABLE_LOCK_INDEX(HandleValue) ((HandleValue) % PH_HANDLE_TABLE_LOCKS)
|
||||
|
||||
typedef struct _PH_HANDLE_TABLE
|
||||
{
|
||||
PH_QUEUED_LOCK Lock;
|
||||
PH_WAKE_EVENT HandleWakeEvent;
|
||||
|
||||
ULONG Count;
|
||||
ULONG_PTR TableValue;
|
||||
ULONG FreeValue;
|
||||
ULONG NextValue;
|
||||
ULONG FreeValueAlt;
|
||||
|
||||
ULONG Flags;
|
||||
|
||||
PH_QUEUED_LOCK Locks[PH_HANDLE_TABLE_LOCKS];
|
||||
} PH_HANDLE_TABLE, *PPH_HANDLE_TABLE;
|
||||
|
||||
FORCEINLINE VOID PhpLockHandleTableShared(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ ULONG Index
|
||||
)
|
||||
{
|
||||
PhAcquireQueuedLockShared(&HandleTable->Locks[Index]);
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhpUnlockHandleTableShared(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ ULONG Index
|
||||
)
|
||||
{
|
||||
PhReleaseQueuedLockShared(&HandleTable->Locks[Index]);
|
||||
}
|
||||
|
||||
// Handle values work by specifying indicies into each
|
||||
// level.
|
||||
//
|
||||
// Bits 0-7: level 0
|
||||
// Bits 8-15: level 1
|
||||
// Bits 16-23: level 2
|
||||
// Bits 24-31: reserved
|
||||
|
||||
#define PH_HANDLE_VALUE_INVALID ((ULONG)-1)
|
||||
#define PH_HANDLE_VALUE_SHIFT 2
|
||||
#define PH_HANDLE_VALUE_BIAS 4
|
||||
|
||||
#define PH_HANDLE_VALUE_LEVEL0(HandleValue) ((HandleValue) & 0xff)
|
||||
#define PH_HANDLE_VALUE_LEVEL1_U(HandleValue) ((HandleValue) >> 8)
|
||||
#define PH_HANDLE_VALUE_LEVEL1(HandleValue) (PH_HANDLE_VALUE_LEVEL1_U(HandleValue) & 0xff)
|
||||
#define PH_HANDLE_VALUE_LEVEL2_U(HandleValue) ((HandleValue) >> 16)
|
||||
#define PH_HANDLE_VALUE_LEVEL2(HandleValue) (PH_HANDLE_VALUE_LEVEL2_U(HandleValue) & 0xff)
|
||||
#define PH_HANDLE_VALUE_IS_INVALID(HandleValue) (((HandleValue) >> 24) != 0)
|
||||
|
||||
FORCEINLINE HANDLE PhpEncodeHandle(
|
||||
_In_ ULONG HandleValue
|
||||
)
|
||||
{
|
||||
return UlongToHandle(((HandleValue << PH_HANDLE_VALUE_SHIFT) + PH_HANDLE_VALUE_BIAS));
|
||||
}
|
||||
|
||||
FORCEINLINE ULONG PhpDecodeHandle(
|
||||
_In_ HANDLE Handle
|
||||
)
|
||||
{
|
||||
return (HandleToUlong(Handle) - PH_HANDLE_VALUE_BIAS) >> PH_HANDLE_VALUE_SHIFT;
|
||||
}
|
||||
|
||||
VOID PhpBlockOnLockedHandleTableEntry(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
|
||||
);
|
||||
|
||||
PPH_HANDLE_TABLE_ENTRY PhpAllocateHandleTableEntry(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_Out_ PULONG HandleValue
|
||||
);
|
||||
|
||||
VOID PhpFreeHandleTableEntry(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ ULONG HandleValue,
|
||||
_Inout_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry
|
||||
);
|
||||
|
||||
BOOLEAN PhpAllocateMoreHandleTableEntries(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ BOOLEAN Initialize
|
||||
);
|
||||
|
||||
PPH_HANDLE_TABLE_ENTRY PhpLookupHandleTableEntry(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ ULONG HandleValue
|
||||
);
|
||||
|
||||
ULONG PhpMoveFreeHandleTableEntries(
|
||||
_Inout_ PPH_HANDLE_TABLE HandleTable
|
||||
);
|
||||
|
||||
PPH_HANDLE_TABLE_ENTRY PhpCreateHandleTableLevel0(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable,
|
||||
_In_ BOOLEAN Initialize
|
||||
);
|
||||
|
||||
VOID PhpFreeHandleTableLevel0(
|
||||
_In_ PPH_HANDLE_TABLE_ENTRY Table
|
||||
);
|
||||
|
||||
PPH_HANDLE_TABLE_ENTRY *PhpCreateHandleTableLevel1(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable
|
||||
);
|
||||
|
||||
VOID PhpFreeHandleTableLevel1(
|
||||
_In_ PPH_HANDLE_TABLE_ENTRY *Table
|
||||
);
|
||||
|
||||
PPH_HANDLE_TABLE_ENTRY **PhpCreateHandleTableLevel2(
|
||||
_In_ PPH_HANDLE_TABLE HandleTable
|
||||
);
|
||||
|
||||
VOID PhpFreeHandleTableLevel2(
|
||||
_In_ PPH_HANDLE_TABLE_ENTRY **Table
|
||||
);
|
||||
|
||||
#endif
|
||||
49
phlib/include/hexedit.h
Normal file
49
phlib/include/hexedit.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef _PH_HEXEDIT_H
|
||||
#define _PH_HEXEDIT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PH_HEXEDIT_CLASSNAME L"PhHexEdit"
|
||||
|
||||
#define EDIT_NONE 0
|
||||
#define EDIT_ASCII 1
|
||||
#define EDIT_HIGH 2
|
||||
#define EDIT_LOW 3
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhHexEditInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
#define HEM_SETBUFFER (WM_USER + 1)
|
||||
#define HEM_SETDATA (WM_USER + 2)
|
||||
#define HEM_GETBUFFER (WM_USER + 3)
|
||||
#define HEM_SETSEL (WM_USER + 4)
|
||||
#define HEM_SETEDITMODE (WM_USER + 5)
|
||||
#define HEM_SETBYTESPERROW (WM_USER + 6)
|
||||
|
||||
#define HexEdit_SetBuffer(hWnd, Buffer, Length) \
|
||||
SendMessage((hWnd), HEM_SETBUFFER, (WPARAM)(Length), (LPARAM)(Buffer))
|
||||
|
||||
#define HexEdit_SetData(hWnd, Buffer, Length) \
|
||||
SendMessage((hWnd), HEM_SETDATA, (WPARAM)(Length), (LPARAM)(Buffer))
|
||||
|
||||
#define HexEdit_GetBuffer(hWnd, Length) \
|
||||
((PUCHAR)SendMessage((hWnd), HEM_GETBUFFER, (WPARAM)(Length), 0))
|
||||
|
||||
#define HexEdit_SetSel(hWnd, Start, End) \
|
||||
SendMessage((hWnd), HEM_SETSEL, (WPARAM)(Start), (LPARAM)(End))
|
||||
|
||||
#define HexEdit_SetEditMode(hWnd, Mode) \
|
||||
SendMessage((hWnd), HEM_SETEDITMODE, (WPARAM)(Mode), 0)
|
||||
|
||||
#define HexEdit_SetBytesPerRow(hWnd, BytesPerRow) \
|
||||
SendMessage((hWnd), HEM_SETBYTESPERROW, (WPARAM)(BytesPerRow), 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
201
phlib/include/hexeditp.h
Normal file
201
phlib/include/hexeditp.h
Normal file
@@ -0,0 +1,201 @@
|
||||
#ifndef _PH_HEXEDITP_H
|
||||
#define _PH_HEXEDITP_H
|
||||
|
||||
typedef struct _PHP_HEXEDIT_CONTEXT
|
||||
{
|
||||
PUCHAR Data;
|
||||
LONG Length;
|
||||
BOOLEAN UserBuffer;
|
||||
LONG TopIndex; // index of first visible byte on screen
|
||||
|
||||
LONG CurrentAddress;
|
||||
LONG CurrentMode;
|
||||
LONG SelStart;
|
||||
LONG SelEnd;
|
||||
|
||||
LONG BytesPerRow;
|
||||
LONG LinesPerPage;
|
||||
BOOLEAN ShowAddress;
|
||||
BOOLEAN ShowAscii;
|
||||
BOOLEAN ShowHex;
|
||||
BOOLEAN AddressIsWide;
|
||||
BOOLEAN AllowLengthChange;
|
||||
|
||||
BOOLEAN NoAddressChange;
|
||||
BOOLEAN HalfPage;
|
||||
|
||||
HFONT Font;
|
||||
LONG LineHeight;
|
||||
LONG NullWidth;
|
||||
PWCHAR CharBuffer;
|
||||
ULONG CharBufferLength;
|
||||
BOOLEAN Update;
|
||||
|
||||
LONG HexOffset;
|
||||
LONG AsciiOffset;
|
||||
LONG AddressOffset;
|
||||
|
||||
BOOLEAN HasCapture;
|
||||
POINT EditPosition;
|
||||
} PHP_HEXEDIT_CONTEXT, *PPHP_HEXEDIT_CONTEXT;
|
||||
|
||||
#define IS_PRINTABLE(Byte) ((ULONG)((Byte) - ' ') <= (ULONG)('~' - ' '))
|
||||
|
||||
#define TO_HEX(Buffer, Byte) \
|
||||
{ \
|
||||
*(Buffer)++ = PhIntegerToChar[(Byte) >> 4]; \
|
||||
*(Buffer)++ = PhIntegerToChar[(Byte) & 0xf]; \
|
||||
}
|
||||
|
||||
#define REDRAW_WINDOW(hwnd) \
|
||||
RedrawWindow((hwnd), NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE)
|
||||
|
||||
VOID PhpCreateHexEditContext(
|
||||
_Out_ PPHP_HEXEDIT_CONTEXT *Context
|
||||
);
|
||||
|
||||
VOID PhpFreeHexEditContext(
|
||||
_In_ _Post_invalid_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
LRESULT CALLBACK PhpHexEditWndProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
);
|
||||
|
||||
VOID PhpHexEditUpdateMetrics(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ BOOLEAN UpdateLineHeight,
|
||||
_In_opt_ HDC hdc
|
||||
);
|
||||
|
||||
VOID PhpHexEditOnPaint(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ PAINTSTRUCT *PaintStruct,
|
||||
_In_ HDC hdc
|
||||
);
|
||||
|
||||
VOID PhpHexEditUpdateScrollbars(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
FORCEINLINE BOOLEAN PhpHexEditHasSelected(
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
)
|
||||
{
|
||||
return Context->SelStart != -1;
|
||||
}
|
||||
|
||||
VOID PhpHexEditCreateAddressCaret(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhpHexEditCreateEditCaret(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhpHexEditRepositionCaret(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ LONG Position
|
||||
);
|
||||
|
||||
VOID PhpHexEditCalculatePosition(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ LONG X,
|
||||
_In_ LONG Y,
|
||||
_Out_ POINT *Point
|
||||
);
|
||||
|
||||
VOID PhpHexEditMove(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ LONG X,
|
||||
_In_ LONG Y
|
||||
);
|
||||
|
||||
VOID PhpHexEditSetSel(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ LONG S,
|
||||
_In_ LONG E
|
||||
);
|
||||
|
||||
VOID PhpHexEditScrollTo(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ LONG Position
|
||||
);
|
||||
|
||||
VOID PhpHexEditClearEdit(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhpHexEditCopyEdit(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhpHexEditCutEdit(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhpHexEditPasteEdit(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhpHexEditSelectAll(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhpHexEditUndoEdit(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhpHexEditNormalizeSel(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhpHexEditSelDelete(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ LONG S,
|
||||
_In_ LONG E
|
||||
);
|
||||
|
||||
VOID PhpHexEditSelInsert(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ LONG S,
|
||||
_In_ LONG L
|
||||
);
|
||||
|
||||
VOID PhpHexEditSetBuffer(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ PUCHAR Data,
|
||||
_In_ ULONG Length
|
||||
);
|
||||
|
||||
VOID PhpHexEditSetData(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPHP_HEXEDIT_CONTEXT Context,
|
||||
_In_ PUCHAR Data,
|
||||
_In_ ULONG Length
|
||||
);
|
||||
|
||||
#endif
|
||||
138
phlib/include/hndlinfo.h
Normal file
138
phlib/include/hndlinfo.h
Normal file
@@ -0,0 +1,138 @@
|
||||
#ifndef _PH_HNDLINFO_H
|
||||
#define _PH_HNDLINFO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_OBJECT_TYPE_NUMBER 257
|
||||
|
||||
typedef PPH_STRING (NTAPI *PPH_GET_CLIENT_ID_NAME)(
|
||||
_In_ PCLIENT_ID ClientId
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_GET_CLIENT_ID_NAME
|
||||
NTAPI
|
||||
PhSetHandleClientIdFunction(
|
||||
_In_ PPH_GET_CLIENT_ID_NAME GetClientIdName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING
|
||||
NTAPI
|
||||
PhFormatNativeKeyName(
|
||||
_In_ PPH_STRING Name
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetSectionFileName(
|
||||
_In_ HANDLE SectionHandle,
|
||||
_Out_ PPH_STRING *FileName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
_Callback_ PPH_STRING
|
||||
NTAPI
|
||||
PhStdGetClientIdName(
|
||||
_In_ PCLIENT_ID ClientId
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetHandleInformation(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ HANDLE Handle,
|
||||
_In_ ULONG ObjectTypeNumber,
|
||||
_Out_opt_ POBJECT_BASIC_INFORMATION BasicInformation,
|
||||
_Out_opt_ PPH_STRING *TypeName,
|
||||
_Out_opt_ PPH_STRING *ObjectName,
|
||||
_Out_opt_ PPH_STRING *BestObjectName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetHandleInformationEx(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ HANDLE Handle,
|
||||
_In_ ULONG ObjectTypeNumber,
|
||||
_Reserved_ ULONG Flags,
|
||||
_Out_opt_ PNTSTATUS SubStatus,
|
||||
_Out_opt_ POBJECT_BASIC_INFORMATION BasicInformation,
|
||||
_Out_opt_ PPH_STRING *TypeName,
|
||||
_Out_opt_ PPH_STRING *ObjectName,
|
||||
_Out_opt_ PPH_STRING *BestObjectName,
|
||||
_Reserved_ PVOID *ExtraInformation
|
||||
);
|
||||
|
||||
#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))
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhEnumObjectTypes(
|
||||
_Out_ POBJECT_TYPES_INFORMATION *ObjectTypes
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
PhGetObjectTypeNumber(
|
||||
_In_ PUNICODE_STRING TypeName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhCallWithTimeout(
|
||||
_In_ PUSER_THREAD_START_ROUTINE Routine,
|
||||
_In_opt_ PVOID Context,
|
||||
_In_opt_ PLARGE_INTEGER AcquireTimeout,
|
||||
_In_ PLARGE_INTEGER CallTimeout
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhCallNtQueryObjectWithTimeout(
|
||||
_In_ HANDLE Handle,
|
||||
_In_ OBJECT_INFORMATION_CLASS ObjectInformationClass,
|
||||
_Out_writes_bytes_opt_(ObjectInformationLength) PVOID ObjectInformation,
|
||||
_In_ ULONG ObjectInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhCallNtQuerySecurityObjectWithTimeout(
|
||||
_In_ HANDLE Handle,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_Out_writes_bytes_opt_(Length) PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
_In_ ULONG Length,
|
||||
_Out_ PULONG LengthNeeded
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhCallNtSetSecurityObjectWithTimeout(
|
||||
_In_ HANDLE Handle,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
242
phlib/include/kphapi.h
Normal file
242
phlib/include/kphapi.h
Normal file
@@ -0,0 +1,242 @@
|
||||
#ifndef _KPHAPI_H
|
||||
#define _KPHAPI_H
|
||||
|
||||
// This file contains KProcessHacker definitions shared across kernel-mode and user-mode.
|
||||
|
||||
// Process information
|
||||
|
||||
typedef enum _KPH_PROCESS_INFORMATION_CLASS
|
||||
{
|
||||
KphProcessReserved1 = 1,
|
||||
KphProcessReserved2 = 2,
|
||||
KphProcessReserved3 = 3,
|
||||
MaxKphProcessInfoClass
|
||||
} KPH_PROCESS_INFORMATION_CLASS;
|
||||
|
||||
// Thread information
|
||||
|
||||
typedef enum _KPH_THREAD_INFORMATION_CLASS
|
||||
{
|
||||
KphThreadReserved1 = 1,
|
||||
KphThreadReserved2 = 2,
|
||||
KphThreadReserved3 = 3,
|
||||
MaxKphThreadInfoClass
|
||||
} KPH_THREAD_INFORMATION_CLASS;
|
||||
|
||||
// Process handle information
|
||||
|
||||
typedef struct _KPH_PROCESS_HANDLE
|
||||
{
|
||||
HANDLE Handle;
|
||||
PVOID Object;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
USHORT ObjectTypeIndex;
|
||||
USHORT Reserved1;
|
||||
ULONG HandleAttributes;
|
||||
ULONG Reserved2;
|
||||
} KPH_PROCESS_HANDLE, *PKPH_PROCESS_HANDLE;
|
||||
|
||||
typedef struct _KPH_PROCESS_HANDLE_INFORMATION
|
||||
{
|
||||
ULONG HandleCount;
|
||||
KPH_PROCESS_HANDLE Handles[1];
|
||||
} KPH_PROCESS_HANDLE_INFORMATION, *PKPH_PROCESS_HANDLE_INFORMATION;
|
||||
|
||||
// Object information
|
||||
|
||||
typedef enum _KPH_OBJECT_INFORMATION_CLASS
|
||||
{
|
||||
KphObjectBasicInformation, // q: OBJECT_BASIC_INFORMATION
|
||||
KphObjectNameInformation, // q: OBJECT_NAME_INFORMATION
|
||||
KphObjectTypeInformation, // q: OBJECT_TYPE_INFORMATION
|
||||
KphObjectHandleFlagInformation, // qs: OBJECT_HANDLE_FLAG_INFORMATION
|
||||
KphObjectProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION
|
||||
KphObjectThreadBasicInformation, // q: THREAD_BASIC_INFORMATION
|
||||
KphObjectEtwRegBasicInformation, // q: ETWREG_BASIC_INFORMATION
|
||||
KphObjectFileObjectInformation, // q: KPH_FILE_OBJECT_INFORMATION
|
||||
KphObjectFileObjectDriver, // q: KPH_FILE_OBJECT_DRIVER
|
||||
MaxKphObjectInfoClass
|
||||
} KPH_OBJECT_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _KPH_FILE_OBJECT_INFORMATION
|
||||
{
|
||||
BOOLEAN LockOperation;
|
||||
BOOLEAN DeletePending;
|
||||
BOOLEAN ReadAccess;
|
||||
BOOLEAN WriteAccess;
|
||||
BOOLEAN DeleteAccess;
|
||||
BOOLEAN SharedRead;
|
||||
BOOLEAN SharedWrite;
|
||||
BOOLEAN SharedDelete;
|
||||
LARGE_INTEGER CurrentByteOffset;
|
||||
ULONG Flags;
|
||||
} KPH_FILE_OBJECT_INFORMATION, *PKPH_FILE_OBJECT_INFORMATION;
|
||||
|
||||
typedef struct _KPH_FILE_OBJECT_DRIVER
|
||||
{
|
||||
HANDLE DriverHandle;
|
||||
} KPH_FILE_OBJECT_DRIVER, *PKPH_FILE_OBJECT_DRIVER;
|
||||
|
||||
// Driver information
|
||||
|
||||
typedef enum _DRIVER_INFORMATION_CLASS
|
||||
{
|
||||
DriverBasicInformation,
|
||||
DriverNameInformation,
|
||||
DriverServiceKeyNameInformation,
|
||||
MaxDriverInfoClass
|
||||
} DRIVER_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _DRIVER_BASIC_INFORMATION
|
||||
{
|
||||
ULONG Flags;
|
||||
PVOID DriverStart;
|
||||
ULONG DriverSize;
|
||||
} DRIVER_BASIC_INFORMATION, *PDRIVER_BASIC_INFORMATION;
|
||||
|
||||
typedef struct _DRIVER_NAME_INFORMATION
|
||||
{
|
||||
UNICODE_STRING DriverName;
|
||||
} DRIVER_NAME_INFORMATION, *PDRIVER_NAME_INFORMATION;
|
||||
|
||||
typedef struct _DRIVER_SERVICE_KEY_NAME_INFORMATION
|
||||
{
|
||||
UNICODE_STRING ServiceKeyName;
|
||||
} DRIVER_SERVICE_KEY_NAME_INFORMATION, *PDRIVER_SERVICE_KEY_NAME_INFORMATION;
|
||||
|
||||
// ETW registration object information
|
||||
|
||||
typedef struct _ETWREG_BASIC_INFORMATION
|
||||
{
|
||||
GUID Guid;
|
||||
ULONG_PTR SessionId;
|
||||
} ETWREG_BASIC_INFORMATION, *PETWREG_BASIC_INFORMATION;
|
||||
|
||||
// Device
|
||||
|
||||
#define KPH_DEVICE_SHORT_NAME L"KProcessHacker3"
|
||||
#define KPH_DEVICE_TYPE 0x9999
|
||||
#define KPH_DEVICE_NAME (L"\\Device\\" KPH_DEVICE_SHORT_NAME)
|
||||
|
||||
// Parameters
|
||||
|
||||
typedef enum _KPH_SECURITY_LEVEL
|
||||
{
|
||||
KphSecurityNone = 0, // all clients are allowed
|
||||
KphSecurityPrivilegeCheck = 1, // require SeDebugPrivilege
|
||||
KphSecuritySignatureCheck = 2, // require trusted signature
|
||||
KphSecuritySignatureAndPrivilegeCheck = 3, // require trusted signature and SeDebugPrivilege
|
||||
KphMaxSecurityLevel
|
||||
} KPH_SECURITY_LEVEL, *PKPH_SECURITY_LEVEL;
|
||||
|
||||
typedef struct _KPH_DYN_STRUCT_DATA
|
||||
{
|
||||
SHORT EgeGuid;
|
||||
SHORT EpObjectTable;
|
||||
SHORT Reserved0;
|
||||
SHORT Reserved1;
|
||||
SHORT Reserved2;
|
||||
SHORT EreGuidEntry;
|
||||
SHORT HtHandleContentionEvent;
|
||||
SHORT OtName;
|
||||
SHORT OtIndex;
|
||||
SHORT ObDecodeShift;
|
||||
SHORT ObAttributesShift;
|
||||
} KPH_DYN_STRUCT_DATA, *PKPH_DYN_STRUCT_DATA;
|
||||
|
||||
typedef struct _KPH_DYN_PACKAGE
|
||||
{
|
||||
USHORT MajorVersion;
|
||||
USHORT MinorVersion;
|
||||
USHORT ServicePackMajor; // -1 to ignore
|
||||
USHORT BuildNumber; // -1 to ignore
|
||||
ULONG ResultingNtVersion; // PHNT_*
|
||||
KPH_DYN_STRUCT_DATA StructData;
|
||||
} KPH_DYN_PACKAGE, *PKPH_DYN_PACKAGE;
|
||||
|
||||
#define KPH_DYN_CONFIGURATION_VERSION 3
|
||||
#define KPH_DYN_MAXIMUM_PACKAGES 64
|
||||
|
||||
typedef struct _KPH_DYN_CONFIGURATION
|
||||
{
|
||||
ULONG Version;
|
||||
ULONG NumberOfPackages;
|
||||
KPH_DYN_PACKAGE Packages[1];
|
||||
} KPH_DYN_CONFIGURATION, *PKPH_DYN_CONFIGURATION;
|
||||
|
||||
// Verification
|
||||
|
||||
#ifdef __BCRYPT_H__
|
||||
#define KPH_SIGN_ALGORITHM BCRYPT_ECDSA_P256_ALGORITHM
|
||||
#define KPH_SIGN_ALGORITHM_BITS 256
|
||||
#define KPH_HASH_ALGORITHM BCRYPT_SHA256_ALGORITHM
|
||||
#define KPH_BLOB_PUBLIC BCRYPT_ECCPUBLIC_BLOB
|
||||
#endif
|
||||
|
||||
#define KPH_SIGNATURE_MAX_SIZE (128 * 1024) // 128 kB
|
||||
|
||||
typedef ULONG KPH_KEY, *PKPH_KEY;
|
||||
|
||||
typedef enum _KPH_KEY_LEVEL
|
||||
{
|
||||
KphKeyLevel1 = 1,
|
||||
KphKeyLevel2 = 2
|
||||
} KPH_KEY_LEVEL;
|
||||
|
||||
#define KPH_KEY_BACKOFF_TIME ((LONGLONG)(100 * 1000 * 10)) // 100ms
|
||||
|
||||
#define KPH_PROCESS_READ_ACCESS \
|
||||
(PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ)
|
||||
#define KPH_THREAD_READ_ACCESS \
|
||||
(THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION | THREAD_GET_CONTEXT)
|
||||
#define KPH_TOKEN_READ_ACCESS \
|
||||
(TOKEN_QUERY | TOKEN_QUERY_SOURCE)
|
||||
|
||||
// Features
|
||||
|
||||
// No features defined.
|
||||
|
||||
// Control codes
|
||||
|
||||
#define KPH_CTL_CODE(x) CTL_CODE(KPH_DEVICE_TYPE, 0x800 + x, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
|
||||
// General
|
||||
#define KPH_GETFEATURES KPH_CTL_CODE(0)
|
||||
#define KPH_VERIFYCLIENT KPH_CTL_CODE(1)
|
||||
#define KPH_RETRIEVEKEY KPH_CTL_CODE(2) // User-mode only
|
||||
|
||||
// Processes
|
||||
#define KPH_OPENPROCESS KPH_CTL_CODE(50) // L1/L2 protected API
|
||||
#define KPH_OPENPROCESSTOKEN KPH_CTL_CODE(51) // L1/L2 protected API
|
||||
#define KPH_OPENPROCESSJOB KPH_CTL_CODE(52)
|
||||
#define KPH_RESERVED53 KPH_CTL_CODE(53)
|
||||
#define KPH_RESERVED54 KPH_CTL_CODE(54)
|
||||
#define KPH_TERMINATEPROCESS KPH_CTL_CODE(55) // L2 protected API
|
||||
#define KPH_RESERVED56 KPH_CTL_CODE(56)
|
||||
#define KPH_RESERVED57 KPH_CTL_CODE(57)
|
||||
#define KPH_READVIRTUALMEMORYUNSAFE KPH_CTL_CODE(58) // L2 protected API
|
||||
#define KPH_QUERYINFORMATIONPROCESS KPH_CTL_CODE(59)
|
||||
#define KPH_SETINFORMATIONPROCESS KPH_CTL_CODE(60)
|
||||
|
||||
// Threads
|
||||
#define KPH_OPENTHREAD KPH_CTL_CODE(100) // L1/L2 protected API
|
||||
#define KPH_OPENTHREADPROCESS KPH_CTL_CODE(101)
|
||||
#define KPH_RESERVED102 KPH_CTL_CODE(102)
|
||||
#define KPH_RESERVED103 KPH_CTL_CODE(103)
|
||||
#define KPH_RESERVED104 KPH_CTL_CODE(104)
|
||||
#define KPH_RESERVED105 KPH_CTL_CODE(105)
|
||||
#define KPH_CAPTURESTACKBACKTRACETHREAD KPH_CTL_CODE(106)
|
||||
#define KPH_QUERYINFORMATIONTHREAD KPH_CTL_CODE(107)
|
||||
#define KPH_SETINFORMATIONTHREAD KPH_CTL_CODE(108)
|
||||
|
||||
// Handles
|
||||
#define KPH_ENUMERATEPROCESSHANDLES KPH_CTL_CODE(150)
|
||||
#define KPH_QUERYINFORMATIONOBJECT KPH_CTL_CODE(151)
|
||||
#define KPH_SETINFORMATIONOBJECT KPH_CTL_CODE(152)
|
||||
#define KPH_RESERVED153 KPH_CTL_CODE(153)
|
||||
|
||||
// Misc.
|
||||
#define KPH_OPENDRIVER KPH_CTL_CODE(200)
|
||||
#define KPH_QUERYINFORMATIONDRIVER KPH_CTL_CODE(201)
|
||||
|
||||
#endif
|
||||
300
phlib/include/kphuser.h
Normal file
300
phlib/include/kphuser.h
Normal file
@@ -0,0 +1,300 @@
|
||||
#ifndef _PH_KPHUSER_H
|
||||
#define _PH_KPHUSER_H
|
||||
|
||||
#include <kphapi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _KPH_PARAMETERS
|
||||
{
|
||||
KPH_SECURITY_LEVEL SecurityLevel;
|
||||
BOOLEAN CreateDynamicConfiguration;
|
||||
} KPH_PARAMETERS, *PKPH_PARAMETERS;
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphConnect(
|
||||
_In_opt_ PWSTR DeviceName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphConnect2(
|
||||
_In_opt_ PWSTR DeviceName,
|
||||
_In_ PWSTR FileName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphConnect2Ex(
|
||||
_In_opt_ PWSTR DeviceName,
|
||||
_In_ PWSTR FileName,
|
||||
_In_opt_ PKPH_PARAMETERS Parameters
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphDisconnect(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KphIsConnected(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KphIsVerified(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphSetParameters(
|
||||
_In_opt_ PWSTR DeviceName,
|
||||
_In_ PKPH_PARAMETERS Parameters
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphInstall(
|
||||
_In_opt_ PWSTR DeviceName,
|
||||
_In_ PWSTR FileName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphInstallEx(
|
||||
_In_opt_ PWSTR DeviceName,
|
||||
_In_ PWSTR FileName,
|
||||
_In_opt_ PKPH_PARAMETERS Parameters
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphUninstall(
|
||||
_In_opt_ PWSTR DeviceName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphGetFeatures(
|
||||
_Out_ PULONG Features
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphVerifyClient(
|
||||
_In_reads_bytes_(SignatureSize) PUCHAR Signature,
|
||||
_In_ ULONG SignatureSize
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphOpenProcess(
|
||||
_Out_ PHANDLE ProcessHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ PCLIENT_ID ClientId
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphOpenProcessToken(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_Out_ PHANDLE TokenHandle
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphOpenProcessJob(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_Out_ PHANDLE JobHandle
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphTerminateProcess(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ NTSTATUS ExitStatus
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphReadVirtualMemoryUnsafe(
|
||||
_In_opt_ HANDLE ProcessHandle,
|
||||
_In_ PVOID BaseAddress,
|
||||
_Out_writes_bytes_(BufferSize) PVOID Buffer,
|
||||
_In_ SIZE_T BufferSize,
|
||||
_Out_opt_ PSIZE_T NumberOfBytesRead
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphQueryInformationProcess(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass,
|
||||
_Out_writes_bytes_(ProcessInformationLength) PVOID ProcessInformation,
|
||||
_In_ ULONG ProcessInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphSetInformationProcess(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass,
|
||||
_In_reads_bytes_(ProcessInformationLength) PVOID ProcessInformation,
|
||||
_In_ ULONG ProcessInformationLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphOpenThread(
|
||||
_Out_ PHANDLE ThreadHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ PCLIENT_ID ClientId
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphOpenThreadProcess(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_Out_ PHANDLE ProcessHandle
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphCaptureStackBackTraceThread(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_In_ ULONG FramesToSkip,
|
||||
_In_ ULONG FramesToCapture,
|
||||
_Out_writes_(FramesToCapture) PVOID *BackTrace,
|
||||
_Out_opt_ PULONG CapturedFrames,
|
||||
_Out_opt_ PULONG BackTraceHash
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphQueryInformationThread(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_In_ KPH_THREAD_INFORMATION_CLASS ThreadInformationClass,
|
||||
_Out_writes_bytes_(ThreadInformationLength) PVOID ThreadInformation,
|
||||
_In_ ULONG ThreadInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphSetInformationThread(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_In_ KPH_THREAD_INFORMATION_CLASS ThreadInformationClass,
|
||||
_In_reads_bytes_(ThreadInformationLength) PVOID ThreadInformation,
|
||||
_In_ ULONG ThreadInformationLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphEnumerateProcessHandles(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_writes_bytes_(BufferLength) PVOID Buffer,
|
||||
_In_opt_ ULONG BufferLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphEnumerateProcessHandles2(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PKPH_PROCESS_HANDLE_INFORMATION *Handles
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphQueryInformationObject(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ HANDLE Handle,
|
||||
_In_ KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass,
|
||||
_Out_writes_bytes_(ObjectInformationLength) PVOID ObjectInformation,
|
||||
_In_ ULONG ObjectInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphSetInformationObject(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ HANDLE Handle,
|
||||
_In_ KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass,
|
||||
_In_reads_bytes_(ObjectInformationLength) PVOID ObjectInformation,
|
||||
_In_ ULONG ObjectInformationLength
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphOpenDriver(
|
||||
_Out_ PHANDLE DriverHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_ POBJECT_ATTRIBUTES ObjectAttributes
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphQueryInformationDriver(
|
||||
_In_ HANDLE DriverHandle,
|
||||
_In_ DRIVER_INFORMATION_CLASS DriverInformationClass,
|
||||
_Out_writes_bytes_(DriverInformationLength) PVOID DriverInformation,
|
||||
_In_ ULONG DriverInformationLength,
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
// kphdata
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KphInitializeDynamicPackage(
|
||||
_Out_ PKPH_DYN_PACKAGE Package
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
127
phlib/include/kphuserp.h
Normal file
127
phlib/include/kphuserp.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#ifndef _PH_KPHUSERP_H
|
||||
#define _PH_KPHUSERP_H
|
||||
|
||||
typedef NTSTATUS (NTAPI *PKPHP_WITH_KEY_CONTINUATION)(
|
||||
_In_ KPH_KEY Key,
|
||||
_In_ PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS KphpDeviceIoControl(
|
||||
_In_ ULONG KphControlCode,
|
||||
_In_ PVOID InBuffer,
|
||||
_In_ ULONG InBufferLength
|
||||
);
|
||||
|
||||
typedef struct _KPHP_RETRIEVE_KEY_CONTEXT
|
||||
{
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
PKPHP_WITH_KEY_CONTINUATION Continuation;
|
||||
PVOID Context;
|
||||
NTSTATUS Status;
|
||||
} KPHP_RETRIEVE_KEY_CONTEXT, *PKPHP_RETRIEVE_KEY_CONTEXT;
|
||||
|
||||
VOID KphpWithKeyApcRoutine(
|
||||
_In_ PVOID ApcContext,
|
||||
_In_ PIO_STATUS_BLOCK IoStatusBlock,
|
||||
_In_ ULONG Reserved
|
||||
);
|
||||
|
||||
NTSTATUS KphpWithKey(
|
||||
_In_ KPH_KEY_LEVEL KeyLevel,
|
||||
_In_ PKPHP_WITH_KEY_CONTINUATION Continuation,
|
||||
_In_ PVOID Context
|
||||
);
|
||||
|
||||
// Get L1 key
|
||||
|
||||
typedef struct _KPHP_GET_L1_KEY_CONTEXT
|
||||
{
|
||||
PKPH_KEY Key;
|
||||
} KPHP_GET_L1_KEY_CONTEXT, *PKPHP_GET_L1_KEY_CONTEXT;
|
||||
|
||||
NTSTATUS KphpGetL1KeyContinuation(
|
||||
_In_ KPH_KEY Key,
|
||||
_In_ PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS KphpGetL1Key(
|
||||
_Out_ PKPH_KEY Key
|
||||
);
|
||||
|
||||
// Open process
|
||||
|
||||
typedef struct _KPH_OPEN_PROCESS_INPUT
|
||||
{
|
||||
PHANDLE ProcessHandle;
|
||||
ACCESS_MASK DesiredAccess;
|
||||
PCLIENT_ID ClientId;
|
||||
KPH_KEY Key;
|
||||
} KPH_OPEN_PROCESS_INPUT, *PKPH_OPEN_PROCESS_INPUT;
|
||||
|
||||
NTSTATUS KphpOpenProcessContinuation(
|
||||
_In_ KPH_KEY Key,
|
||||
_In_ PVOID Context
|
||||
);
|
||||
|
||||
// Open process token
|
||||
|
||||
typedef struct _KPH_OPEN_PROCESS_TOKEN_INPUT
|
||||
{
|
||||
HANDLE ProcessHandle;
|
||||
ACCESS_MASK DesiredAccess;
|
||||
PHANDLE TokenHandle;
|
||||
KPH_KEY Key;
|
||||
} KPH_OPEN_PROCESS_TOKEN_INPUT, *PKPH_OPEN_PROCESS_TOKEN_INPUT;
|
||||
|
||||
NTSTATUS KphpOpenProcessTokenContinuation(
|
||||
_In_ KPH_KEY Key,
|
||||
_In_ PVOID Context
|
||||
);
|
||||
|
||||
// Terminate process
|
||||
|
||||
typedef struct _KPH_TERMINATE_PROCESS_INPUT
|
||||
{
|
||||
HANDLE ProcessHandle;
|
||||
NTSTATUS ExitStatus;
|
||||
KPH_KEY Key;
|
||||
} KPH_TERMINATE_PROCESS_INPUT, *PKPH_TERMINATE_PROCESS_INPUT;
|
||||
|
||||
NTSTATUS KphpTerminateProcessContinuation(
|
||||
_In_ KPH_KEY Key,
|
||||
_In_ PVOID Context
|
||||
);
|
||||
|
||||
// Read virtual memory, unsafe
|
||||
|
||||
typedef struct _KPH_READ_VIRTUAL_MEMORY_UNSAFE_INPUT
|
||||
{
|
||||
HANDLE ProcessHandle;
|
||||
PVOID BaseAddress;
|
||||
PVOID Buffer;
|
||||
SIZE_T BufferSize;
|
||||
PSIZE_T NumberOfBytesRead;
|
||||
KPH_KEY Key;
|
||||
} KPH_READ_VIRTUAL_MEMORY_UNSAFE_INPUT, *PKPH_READ_VIRTUAL_MEMORY_UNSAFE_INPUT;
|
||||
|
||||
NTSTATUS KphpReadVirtualMemoryUnsafeContinuation(
|
||||
_In_ KPH_KEY Key,
|
||||
_In_ PVOID Context
|
||||
);
|
||||
|
||||
// Open thread
|
||||
|
||||
typedef struct _KPH_OPEN_THREAD_INPUT
|
||||
{
|
||||
PHANDLE ThreadHandle;
|
||||
ACCESS_MASK DesiredAccess;
|
||||
PCLIENT_ID ClientId;
|
||||
KPH_KEY Key;
|
||||
} KPH_OPEN_THREAD_INPUT, *PKPH_OPEN_THREAD_INPUT;
|
||||
|
||||
NTSTATUS KphpOpenThreadContinuation(
|
||||
_In_ KPH_KEY Key,
|
||||
_In_ PVOID Context
|
||||
);
|
||||
|
||||
#endif
|
||||
88
phlib/include/lsasup.h
Normal file
88
phlib/include/lsasup.h
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef _PH_LSASUP_H
|
||||
#define _PH_LSASUP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhOpenLsaPolicy(
|
||||
_Out_ PLSA_HANDLE PolicyHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_opt_ PUNICODE_STRING SystemName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
LSA_HANDLE
|
||||
NTAPI
|
||||
PhGetLookupPolicyHandle(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhLookupPrivilegeName(
|
||||
_In_ PLUID PrivilegeValue,
|
||||
_Out_ PPH_STRING *PrivilegeName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhLookupPrivilegeDisplayName(
|
||||
_In_ PPH_STRINGREF PrivilegeName,
|
||||
_Out_ PPH_STRING *PrivilegeDisplayName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhLookupPrivilegeValue(
|
||||
_In_ PPH_STRINGREF PrivilegeName,
|
||||
_Out_ PLUID PrivilegeValue
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhLookupSid(
|
||||
_In_ PSID Sid,
|
||||
_Out_opt_ PPH_STRING *Name,
|
||||
_Out_opt_ PPH_STRING *DomainName,
|
||||
_Out_opt_ PSID_NAME_USE NameUse
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhLookupName(
|
||||
_In_ PPH_STRINGREF Name,
|
||||
_Out_opt_ PSID *Sid,
|
||||
_Out_opt_ PPH_STRING *DomainName,
|
||||
_Out_opt_ PSID_NAME_USE NameUse
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING
|
||||
NTAPI
|
||||
PhGetSidFullName(
|
||||
_In_ PSID Sid,
|
||||
_In_ BOOLEAN IncludeDomain,
|
||||
_Out_opt_ PSID_NAME_USE NameUse
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING
|
||||
NTAPI
|
||||
PhSidToStringSid(
|
||||
_In_ PSID Sid
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
388
phlib/include/mapimg.h
Normal file
388
phlib/include/mapimg.h
Normal file
@@ -0,0 +1,388 @@
|
||||
#ifndef _PH_MAPIMG_H
|
||||
#define _PH_MAPIMG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _PH_MAPPED_IMAGE
|
||||
{
|
||||
PVOID ViewBase;
|
||||
SIZE_T Size;
|
||||
|
||||
PIMAGE_NT_HEADERS NtHeaders;
|
||||
ULONG NumberOfSections;
|
||||
PIMAGE_SECTION_HEADER Sections;
|
||||
USHORT Magic;
|
||||
} PH_MAPPED_IMAGE, *PPH_MAPPED_IMAGE;
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhInitializeMappedImage(
|
||||
_Out_ PPH_MAPPED_IMAGE MappedImage,
|
||||
_In_ PVOID ViewBase,
|
||||
_In_ SIZE_T Size
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhLoadMappedImage(
|
||||
_In_opt_ PWSTR FileName,
|
||||
_In_opt_ HANDLE FileHandle,
|
||||
_In_ BOOLEAN ReadOnly,
|
||||
_Out_ PPH_MAPPED_IMAGE MappedImage
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhUnloadMappedImage(
|
||||
_Inout_ PPH_MAPPED_IMAGE MappedImage
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhMapViewOfEntireFile(
|
||||
_In_opt_ PWSTR FileName,
|
||||
_In_opt_ HANDLE FileHandle,
|
||||
_In_ BOOLEAN ReadOnly,
|
||||
_Out_ PVOID *ViewBase,
|
||||
_Out_ PSIZE_T Size
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PIMAGE_SECTION_HEADER
|
||||
NTAPI
|
||||
PhMappedImageRvaToSection(
|
||||
_In_ PPH_MAPPED_IMAGE MappedImage,
|
||||
_In_ ULONG Rva
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhMappedImageRvaToVa(
|
||||
_In_ PPH_MAPPED_IMAGE MappedImage,
|
||||
_In_ ULONG Rva,
|
||||
_Out_opt_ PIMAGE_SECTION_HEADER *Section
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhGetMappedImageSectionName(
|
||||
_In_ PIMAGE_SECTION_HEADER Section,
|
||||
_Out_writes_opt_z_(Count) PSTR Buffer,
|
||||
_In_ ULONG Count,
|
||||
_Out_opt_ PULONG ReturnCount
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageDataEntry(
|
||||
_In_ PPH_MAPPED_IMAGE MappedImage,
|
||||
_In_ ULONG Index,
|
||||
_Out_ PIMAGE_DATA_DIRECTORY *Entry
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageLoadConfig32(
|
||||
_In_ PPH_MAPPED_IMAGE MappedImage,
|
||||
_Out_ PIMAGE_LOAD_CONFIG_DIRECTORY32 *LoadConfig
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageLoadConfig64(
|
||||
_In_ PPH_MAPPED_IMAGE MappedImage,
|
||||
_Out_ PIMAGE_LOAD_CONFIG_DIRECTORY64 *LoadConfig
|
||||
);
|
||||
|
||||
typedef struct _PH_REMOTE_MAPPED_IMAGE
|
||||
{
|
||||
PVOID ViewBase;
|
||||
|
||||
PIMAGE_NT_HEADERS NtHeaders;
|
||||
ULONG NumberOfSections;
|
||||
PIMAGE_SECTION_HEADER Sections;
|
||||
USHORT Magic;
|
||||
} PH_REMOTE_MAPPED_IMAGE, *PPH_REMOTE_MAPPED_IMAGE;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhLoadRemoteMappedImage(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ PVOID ViewBase,
|
||||
_Out_ PPH_REMOTE_MAPPED_IMAGE RemoteMappedImage
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhUnloadRemoteMappedImage(
|
||||
_Inout_ PPH_REMOTE_MAPPED_IMAGE RemoteMappedImage
|
||||
);
|
||||
|
||||
typedef struct _PH_MAPPED_IMAGE_EXPORTS
|
||||
{
|
||||
PPH_MAPPED_IMAGE MappedImage;
|
||||
ULONG NumberOfEntries;
|
||||
|
||||
PIMAGE_DATA_DIRECTORY DataDirectory;
|
||||
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
||||
PULONG AddressTable;
|
||||
PULONG NamePointerTable;
|
||||
PUSHORT OrdinalTable;
|
||||
} PH_MAPPED_IMAGE_EXPORTS, *PPH_MAPPED_IMAGE_EXPORTS;
|
||||
|
||||
typedef struct _PH_MAPPED_IMAGE_EXPORT_ENTRY
|
||||
{
|
||||
USHORT Ordinal;
|
||||
PSTR Name;
|
||||
} PH_MAPPED_IMAGE_EXPORT_ENTRY, *PPH_MAPPED_IMAGE_EXPORT_ENTRY;
|
||||
|
||||
typedef struct _PH_MAPPED_IMAGE_EXPORT_FUNCTION
|
||||
{
|
||||
PVOID Function;
|
||||
PSTR ForwardedName;
|
||||
} PH_MAPPED_IMAGE_EXPORT_FUNCTION, *PPH_MAPPED_IMAGE_EXPORT_FUNCTION;
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageExports(
|
||||
_Out_ PPH_MAPPED_IMAGE_EXPORTS Exports,
|
||||
_In_ PPH_MAPPED_IMAGE MappedImage
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageExportEntry(
|
||||
_In_ PPH_MAPPED_IMAGE_EXPORTS Exports,
|
||||
_In_ ULONG Index,
|
||||
_Out_ PPH_MAPPED_IMAGE_EXPORT_ENTRY Entry
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageExportFunction(
|
||||
_In_ PPH_MAPPED_IMAGE_EXPORTS Exports,
|
||||
_In_opt_ PSTR Name,
|
||||
_In_opt_ USHORT Ordinal,
|
||||
_Out_ PPH_MAPPED_IMAGE_EXPORT_FUNCTION Function
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageExportFunctionRemote(
|
||||
_In_ PPH_MAPPED_IMAGE_EXPORTS Exports,
|
||||
_In_opt_ PSTR Name,
|
||||
_In_opt_ USHORT Ordinal,
|
||||
_In_ PVOID RemoteBase,
|
||||
_Out_ PVOID *Function
|
||||
);
|
||||
|
||||
#define PH_MAPPED_IMAGE_DELAY_IMPORTS 0x1
|
||||
|
||||
typedef struct _PH_MAPPED_IMAGE_IMPORTS
|
||||
{
|
||||
PPH_MAPPED_IMAGE MappedImage;
|
||||
ULONG Flags;
|
||||
ULONG NumberOfDlls;
|
||||
|
||||
union
|
||||
{
|
||||
PIMAGE_IMPORT_DESCRIPTOR DescriptorTable;
|
||||
PVOID DelayDescriptorTable;
|
||||
};
|
||||
} PH_MAPPED_IMAGE_IMPORTS, *PPH_MAPPED_IMAGE_IMPORTS;
|
||||
|
||||
typedef struct _PH_MAPPED_IMAGE_IMPORT_DLL
|
||||
{
|
||||
PPH_MAPPED_IMAGE MappedImage;
|
||||
ULONG Flags;
|
||||
PSTR Name;
|
||||
ULONG NumberOfEntries;
|
||||
|
||||
union
|
||||
{
|
||||
PIMAGE_IMPORT_DESCRIPTOR Descriptor;
|
||||
PVOID DelayDescriptor;
|
||||
};
|
||||
PVOID *LookupTable;
|
||||
} PH_MAPPED_IMAGE_IMPORT_DLL, *PPH_MAPPED_IMAGE_IMPORT_DLL;
|
||||
|
||||
typedef struct _PH_MAPPED_IMAGE_IMPORT_ENTRY
|
||||
{
|
||||
PSTR Name;
|
||||
union
|
||||
{
|
||||
USHORT Ordinal;
|
||||
USHORT NameHint;
|
||||
};
|
||||
} PH_MAPPED_IMAGE_IMPORT_ENTRY, *PPH_MAPPED_IMAGE_IMPORT_ENTRY;
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageImports(
|
||||
_Out_ PPH_MAPPED_IMAGE_IMPORTS Imports,
|
||||
_In_ PPH_MAPPED_IMAGE MappedImage
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageImportDll(
|
||||
_In_ PPH_MAPPED_IMAGE_IMPORTS Imports,
|
||||
_In_ ULONG Index,
|
||||
_Out_ PPH_MAPPED_IMAGE_IMPORT_DLL ImportDll
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageImportEntry(
|
||||
_In_ PPH_MAPPED_IMAGE_IMPORT_DLL ImportDll,
|
||||
_In_ ULONG Index,
|
||||
_Out_ PPH_MAPPED_IMAGE_IMPORT_ENTRY Entry
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedImageDelayImports(
|
||||
_Out_ PPH_MAPPED_IMAGE_IMPORTS Imports,
|
||||
_In_ PPH_MAPPED_IMAGE MappedImage
|
||||
);
|
||||
|
||||
USHORT
|
||||
NTAPI
|
||||
PhCheckSum(
|
||||
_In_ ULONG Sum,
|
||||
_In_reads_(Count) PUSHORT Buffer,
|
||||
_In_ ULONG Count
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
PhCheckSumMappedImage(
|
||||
_In_ PPH_MAPPED_IMAGE MappedImage
|
||||
);
|
||||
|
||||
// maplib
|
||||
|
||||
struct _PH_MAPPED_ARCHIVE;
|
||||
typedef struct _PH_MAPPED_ARCHIVE *PPH_MAPPED_ARCHIVE;
|
||||
|
||||
typedef enum _PH_MAPPED_ARCHIVE_MEMBER_TYPE
|
||||
{
|
||||
NormalArchiveMemberType,
|
||||
LinkerArchiveMemberType,
|
||||
LongnamesArchiveMemberType
|
||||
} PH_MAPPED_ARCHIVE_MEMBER_TYPE;
|
||||
|
||||
typedef struct _PH_MAPPED_ARCHIVE_MEMBER
|
||||
{
|
||||
PPH_MAPPED_ARCHIVE MappedArchive;
|
||||
PH_MAPPED_ARCHIVE_MEMBER_TYPE Type;
|
||||
PSTR Name;
|
||||
ULONG Size;
|
||||
PVOID Data;
|
||||
|
||||
PIMAGE_ARCHIVE_MEMBER_HEADER Header;
|
||||
CHAR NameBuffer[20];
|
||||
} PH_MAPPED_ARCHIVE_MEMBER, *PPH_MAPPED_ARCHIVE_MEMBER;
|
||||
|
||||
typedef struct _PH_MAPPED_ARCHIVE
|
||||
{
|
||||
PVOID ViewBase;
|
||||
SIZE_T Size;
|
||||
|
||||
PH_MAPPED_ARCHIVE_MEMBER FirstLinkerMember;
|
||||
PH_MAPPED_ARCHIVE_MEMBER SecondLinkerMember;
|
||||
PH_MAPPED_ARCHIVE_MEMBER LongnamesMember;
|
||||
BOOLEAN HasLongnamesMember;
|
||||
|
||||
PPH_MAPPED_ARCHIVE_MEMBER FirstStandardMember;
|
||||
PPH_MAPPED_ARCHIVE_MEMBER LastStandardMember;
|
||||
} PH_MAPPED_ARCHIVE, *PPH_MAPPED_ARCHIVE;
|
||||
|
||||
typedef struct _PH_MAPPED_ARCHIVE_IMPORT_ENTRY
|
||||
{
|
||||
PSTR Name;
|
||||
PSTR DllName;
|
||||
union
|
||||
{
|
||||
USHORT Ordinal;
|
||||
USHORT NameHint;
|
||||
};
|
||||
BYTE Type;
|
||||
BYTE NameType;
|
||||
USHORT Machine;
|
||||
} PH_MAPPED_ARCHIVE_IMPORT_ENTRY, *PPH_MAPPED_ARCHIVE_IMPORT_ENTRY;
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhInitializeMappedArchive(
|
||||
_Out_ PPH_MAPPED_ARCHIVE MappedArchive,
|
||||
_In_ PVOID ViewBase,
|
||||
_In_ SIZE_T Size
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhLoadMappedArchive(
|
||||
_In_opt_ PWSTR FileName,
|
||||
_In_opt_ HANDLE FileHandle,
|
||||
_In_ BOOLEAN ReadOnly,
|
||||
_Out_ PPH_MAPPED_ARCHIVE MappedArchive
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhUnloadMappedArchive(
|
||||
_Inout_ PPH_MAPPED_ARCHIVE MappedArchive
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetNextMappedArchiveMember(
|
||||
_In_ PPH_MAPPED_ARCHIVE_MEMBER Member,
|
||||
_Out_ PPH_MAPPED_ARCHIVE_MEMBER NextMember
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhIsMappedArchiveMemberShortFormat(
|
||||
_In_ PPH_MAPPED_ARCHIVE_MEMBER Member
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetMappedArchiveImportEntry(
|
||||
_In_ PPH_MAPPED_ARCHIVE_MEMBER Member,
|
||||
_Out_ PPH_MAPPED_ARCHIVE_IMPORT_ENTRY Entry
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
11
phlib/include/ph.h
Normal file
11
phlib/include/ph.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef _PH_PH_H
|
||||
#define _PH_PH_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <phbase.h>
|
||||
#include <phnative.h>
|
||||
#include <phnativeinl.h>
|
||||
#include <phutil.h>
|
||||
|
||||
#endif
|
||||
45
phlib/include/phbase.h
Normal file
45
phlib/include/phbase.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef _PH_PHBASE_H
|
||||
#define _PH_PHBASE_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef PHLIB_NO_DEFAULT_LIB
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
|
||||
#pragma comment(lib, "comctl32.lib")
|
||||
#pragma comment(lib, "version.lib")
|
||||
#endif
|
||||
|
||||
// nonstandard extension used : nameless struct/union
|
||||
#pragma warning(disable: 4201)
|
||||
// nonstandard extension used : bit field types other than int
|
||||
#pragma warning(disable: 4214)
|
||||
// 'function': attributes not present on previous declaration
|
||||
#pragma warning(disable: 4985)
|
||||
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#if !defined(_PHLIB_)
|
||||
#define PHLIBAPI __declspec(dllimport)
|
||||
#else
|
||||
#define PHLIBAPI
|
||||
#endif
|
||||
|
||||
#include <phnt_windows.h>
|
||||
#include <phnt.h>
|
||||
#include <phsup.h>
|
||||
#include <ref.h>
|
||||
#include <queuedlock.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <phconfig.h>
|
||||
#include <phbasesup.h>
|
||||
#include <phdata.h>
|
||||
|
||||
#endif
|
||||
3740
phlib/include/phbasesup.h
Normal file
3740
phlib/include/phbasesup.h
Normal file
File diff suppressed because it is too large
Load Diff
109
phlib/include/phconfig.h
Normal file
109
phlib/include/phconfig.h
Normal file
@@ -0,0 +1,109 @@
|
||||
#ifndef _PH_PHCONFIG_H
|
||||
#define _PH_PHCONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _User_set_
|
||||
|
||||
PHLIBAPI extern _User_set_ PVOID PhLibImageBase;
|
||||
|
||||
PHLIBAPI extern _User_set_ PWSTR PhApplicationName;
|
||||
PHLIBAPI extern _User_set_ ULONG PhGlobalDpi;
|
||||
PHLIBAPI extern PVOID PhHeapHandle;
|
||||
PHLIBAPI extern RTL_OSVERSIONINFOEXW PhOsVersion;
|
||||
PHLIBAPI extern SYSTEM_BASIC_INFORMATION PhSystemBasicInformation;
|
||||
PHLIBAPI extern ULONG WindowsVersion;
|
||||
|
||||
PHLIBAPI extern ACCESS_MASK ProcessQueryAccess;
|
||||
PHLIBAPI extern ACCESS_MASK ProcessAllAccess;
|
||||
PHLIBAPI extern ACCESS_MASK ThreadQueryAccess;
|
||||
PHLIBAPI extern ACCESS_MASK ThreadSetAccess;
|
||||
PHLIBAPI extern ACCESS_MASK ThreadAllAccess;
|
||||
|
||||
#define WINDOWS_ANCIENT 0
|
||||
#define WINDOWS_XP 51
|
||||
#define WINDOWS_SERVER_2003 52
|
||||
#define WINDOWS_VISTA 60
|
||||
#define WINDOWS_7 61
|
||||
#define WINDOWS_8 62
|
||||
#define WINDOWS_8_1 63
|
||||
#define WINDOWS_10 100
|
||||
#define WINDOWS_NEW MAXLONG
|
||||
|
||||
#define WINDOWS_HAS_CONSOLE_HOST (WindowsVersion >= WINDOWS_7)
|
||||
#define WINDOWS_HAS_CYCLE_TIME (WindowsVersion >= WINDOWS_VISTA)
|
||||
#define WINDOWS_HAS_IFILEDIALOG (WindowsVersion >= WINDOWS_VISTA)
|
||||
#define WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID (WindowsVersion >= WINDOWS_VISTA)
|
||||
#define WINDOWS_HAS_IMMERSIVE (WindowsVersion >= WINDOWS_8)
|
||||
#define WINDOWS_HAS_LIMITED_ACCESS (WindowsVersion >= WINDOWS_VISTA)
|
||||
#define WINDOWS_HAS_SERVICE_TAGS (WindowsVersion >= WINDOWS_VISTA)
|
||||
#define WINDOWS_HAS_UAC (WindowsVersion >= WINDOWS_VISTA)
|
||||
|
||||
// Debugging
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintf(format, ...) DbgPrint(format, __VA_ARGS__)
|
||||
#else
|
||||
#define dprintf(format, ...)
|
||||
#endif
|
||||
|
||||
// global
|
||||
|
||||
// Initialization flags
|
||||
|
||||
// Features
|
||||
|
||||
// Imports
|
||||
|
||||
#define PHLIB_INIT_MODULE_RESERVED1 0x1
|
||||
#define PHLIB_INIT_MODULE_RESERVED2 0x2
|
||||
/** Needed to use work queues. */
|
||||
#define PHLIB_INIT_MODULE_RESERVED3 0x4
|
||||
#define PHLIB_INIT_MODULE_RESERVED4 0x8
|
||||
/** Needed to use file streams. */
|
||||
#define PHLIB_INIT_MODULE_FILE_STREAM 0x10
|
||||
/** Needed to use symbol providers. */
|
||||
#define PHLIB_INIT_MODULE_SYMBOL_PROVIDER 0x20
|
||||
#define PHLIB_INIT_MODULE_RESERVED5 0x40
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhInitializePhLib(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhInitializePhLibEx(
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ SIZE_T HeapReserveSize,
|
||||
_In_opt_ SIZE_T HeapCommitSize
|
||||
);
|
||||
|
||||
#ifdef _WIN64
|
||||
FORCEINLINE
|
||||
BOOLEAN
|
||||
PhIsExecutingInWow64(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhIsExecutingInWow64(
|
||||
VOID
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
60
phlib/include/phdata.h
Normal file
60
phlib/include/phdata.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef _PH_PHDATA_H
|
||||
#define _PH_PHDATA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// SIDs
|
||||
|
||||
extern SID PhSeNobodySid;
|
||||
|
||||
extern SID PhSeEveryoneSid;
|
||||
|
||||
extern SID PhSeLocalSid;
|
||||
|
||||
extern SID PhSeCreatorOwnerSid;
|
||||
extern SID PhSeCreatorGroupSid;
|
||||
|
||||
extern SID PhSeDialupSid;
|
||||
extern SID PhSeNetworkSid;
|
||||
extern SID PhSeBatchSid;
|
||||
extern SID PhSeInteractiveSid;
|
||||
extern SID PhSeServiceSid;
|
||||
extern SID PhSeAnonymousLogonSid;
|
||||
extern SID PhSeProxySid;
|
||||
extern SID PhSeAuthenticatedUserSid;
|
||||
extern SID PhSeRestrictedCodeSid;
|
||||
extern SID PhSeTerminalServerUserSid;
|
||||
extern SID PhSeRemoteInteractiveLogonSid;
|
||||
extern SID PhSeLocalSystemSid;
|
||||
extern SID PhSeLocalServiceSid;
|
||||
extern SID PhSeNetworkServiceSid;
|
||||
|
||||
// Unicode
|
||||
|
||||
extern PH_STRINGREF PhUnicodeByteOrderMark;
|
||||
|
||||
// Characters
|
||||
|
||||
extern BOOLEAN PhCharIsPrintable[256];
|
||||
extern ULONG PhCharToInteger[256];
|
||||
extern CHAR PhIntegerToChar[69];
|
||||
extern CHAR PhIntegerToCharUpper[69];
|
||||
|
||||
// CRC32
|
||||
|
||||
extern ULONG PhCrc32Table[256];
|
||||
|
||||
// Enums
|
||||
|
||||
extern WCHAR *PhIoPriorityHintNames[MaxIoPriorityTypes];
|
||||
extern WCHAR *PhPagePriorityNames[MEMORY_PRIORITY_NORMAL + 1];
|
||||
extern WCHAR *PhKThreadStateNames[MaximumThreadState];
|
||||
extern WCHAR *PhKWaitReasonNames[MaximumWaitReason];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
49
phlib/include/phintrnl.h
Normal file
49
phlib/include/phintrnl.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef _PH_PHINTRNL_H
|
||||
#define _PH_PHINTRNL_H
|
||||
|
||||
typedef struct _PHLIB_STATISTICS_BLOCK
|
||||
{
|
||||
// basesup
|
||||
ULONG BaseThreadsCreated;
|
||||
ULONG BaseThreadsCreateFailed;
|
||||
ULONG BaseStringBuildersCreated;
|
||||
ULONG BaseStringBuildersResized;
|
||||
|
||||
// ref
|
||||
ULONG RefObjectsCreated;
|
||||
ULONG RefObjectsDestroyed;
|
||||
ULONG RefObjectsAllocated;
|
||||
ULONG RefObjectsFreed;
|
||||
ULONG RefObjectsAllocatedFromSmallFreeList;
|
||||
ULONG RefObjectsFreedToSmallFreeList;
|
||||
ULONG RefObjectsAllocatedFromTypeFreeList;
|
||||
ULONG RefObjectsFreedToTypeFreeList;
|
||||
ULONG RefObjectsDeleteDeferred;
|
||||
ULONG RefAutoPoolsCreated;
|
||||
ULONG RefAutoPoolsDestroyed;
|
||||
ULONG RefAutoPoolsDynamicAllocated;
|
||||
ULONG RefAutoPoolsDynamicResized;
|
||||
|
||||
// queuedlock
|
||||
ULONG QlBlockSpins;
|
||||
ULONG QlBlockWaits;
|
||||
ULONG QlAcquireExclusiveBlocks;
|
||||
ULONG QlAcquireSharedBlocks;
|
||||
|
||||
// workqueue
|
||||
ULONG WqWorkQueueThreadsCreated;
|
||||
ULONG WqWorkQueueThreadsCreateFailed;
|
||||
ULONG WqWorkItemsQueued;
|
||||
} PHLIB_STATISTICS_BLOCK;
|
||||
|
||||
#ifdef DEBUG
|
||||
extern PHLIB_STATISTICS_BLOCK PhLibStatisticsBlock;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define PHLIB_INC_STATISTIC(Name) (_InterlockedIncrement(&PhLibStatisticsBlock.Name))
|
||||
#else
|
||||
#define PHLIB_INC_STATISTIC(Name)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1042
phlib/include/phnative.h
Normal file
1042
phlib/include/phnative.h
Normal file
File diff suppressed because it is too large
Load Diff
968
phlib/include/phnativeinl.h
Normal file
968
phlib/include/phnativeinl.h
Normal file
@@ -0,0 +1,968 @@
|
||||
#ifndef _PH_PHNATINL_H
|
||||
#define _PH_PHNATINL_H
|
||||
|
||||
#pragma once
|
||||
|
||||
// This file contains inlined native API wrapper functions. These functions were previously
|
||||
// exported, but are now inlined because they are extremely simple wrappers around equivalent native
|
||||
// API functions.
|
||||
|
||||
/**
|
||||
* Gets basic information for a process.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have
|
||||
* PROCESS_QUERY_LIMITED_INFORMATION access.
|
||||
* \param BasicInformation A variable which receives the information.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessBasicInformation(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PPROCESS_BASIC_INFORMATION BasicInformation
|
||||
)
|
||||
{
|
||||
return NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessBasicInformation,
|
||||
BasicInformation,
|
||||
sizeof(PROCESS_BASIC_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets extended basic information for a process.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have
|
||||
* PROCESS_QUERY_LIMITED_INFORMATION access.
|
||||
* \param ExtendedBasicInformation A variable which receives the information.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessExtendedBasicInformation(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PPROCESS_EXTENDED_BASIC_INFORMATION ExtendedBasicInformation
|
||||
)
|
||||
{
|
||||
ExtendedBasicInformation->Size = sizeof(PROCESS_EXTENDED_BASIC_INFORMATION);
|
||||
|
||||
return NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessBasicInformation,
|
||||
ExtendedBasicInformation,
|
||||
sizeof(PROCESS_EXTENDED_BASIC_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets time information for a process.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have
|
||||
* PROCESS_QUERY_LIMITED_INFORMATION access.
|
||||
* \param Times A variable which receives the information.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessTimes(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PKERNEL_USER_TIMES Times
|
||||
)
|
||||
{
|
||||
return NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessTimes,
|
||||
Times,
|
||||
sizeof(KERNEL_USER_TIMES),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a process' session ID.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have
|
||||
* PROCESS_QUERY_LIMITED_INFORMATION access.
|
||||
* \param SessionId A variable which receives the process' session ID.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessSessionId(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PULONG SessionId
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PROCESS_SESSION_INFORMATION sessionInfo;
|
||||
|
||||
status = NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessSessionInformation,
|
||||
&sessionInfo,
|
||||
sizeof(PROCESS_SESSION_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*SessionId = sessionInfo.SessionId;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a process is running under 32-bit emulation.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have
|
||||
* PROCESS_QUERY_LIMITED_INFORMATION access.
|
||||
* \param IsWow64 A variable which receives a boolean indicating whether the process is 32-bit.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessIsWow64(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PBOOLEAN IsWow64
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG_PTR wow64;
|
||||
|
||||
status = NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessWow64Information,
|
||||
&wow64,
|
||||
sizeof(ULONG_PTR),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*IsWow64 = !!wow64;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a process' WOW64 PEB address.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have
|
||||
* PROCESS_QUERY_LIMITED_INFORMATION access.
|
||||
* \param Peb32 A variable which receives the base address of the process' WOW64 PEB. If the process
|
||||
* is 64-bit, the variable receives NULL.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessPeb32(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PVOID *Peb32
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG_PTR wow64;
|
||||
|
||||
status = NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessWow64Information,
|
||||
&wow64,
|
||||
sizeof(ULONG_PTR),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*Peb32 = (PVOID)wow64;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a process is being debugged.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have PROCESS_QUERY_INFORMATION
|
||||
* access.
|
||||
* \param IsBeingDebugged A variable which receives a boolean indicating whether the process is
|
||||
* being debugged.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessIsBeingDebugged(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PBOOLEAN IsBeingDebugged
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PVOID debugPort;
|
||||
|
||||
status = NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessDebugPort,
|
||||
&debugPort,
|
||||
sizeof(PVOID),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*IsBeingDebugged = !!debugPort;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a handle to a process' debug object.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have PROCESS_QUERY_INFORMATION
|
||||
* access.
|
||||
* \param DebugObjectHandle A variable which receives a handle to the debug object associated with
|
||||
* the process. You must close the handle when you no longer need it.
|
||||
*
|
||||
* \retval STATUS_PORT_NOT_SET The process is not being debugged and has no associated debug object.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessDebugObject(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PHANDLE DebugObjectHandle
|
||||
)
|
||||
{
|
||||
return NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessDebugObjectHandle,
|
||||
DebugObjectHandle,
|
||||
sizeof(HANDLE),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a process' no-execute status.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have PROCESS_QUERY_INFORMATION
|
||||
* access.
|
||||
* \param ExecuteFlags A variable which receives the no-execute flags.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessExecuteFlags(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PULONG ExecuteFlags
|
||||
)
|
||||
{
|
||||
return NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessExecuteFlags,
|
||||
ExecuteFlags,
|
||||
sizeof(ULONG),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a process' I/O priority.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have
|
||||
* PROCESS_QUERY_LIMITED_INFORMATION access.
|
||||
* \param IoPriority A variable which receives the I/O priority of the process.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessIoPriority(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ IO_PRIORITY_HINT *IoPriority
|
||||
)
|
||||
{
|
||||
return NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessIoPriority,
|
||||
IoPriority,
|
||||
sizeof(IO_PRIORITY_HINT),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a process' page priority.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have
|
||||
* PROCESS_QUERY_LIMITED_INFORMATION access.
|
||||
* \param PagePriority A variable which receives the page priority of the process.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessPagePriority(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PULONG PagePriority
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PAGE_PRIORITY_INFORMATION pagePriorityInfo;
|
||||
|
||||
status = NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessPagePriority,
|
||||
&pagePriorityInfo,
|
||||
sizeof(PAGE_PRIORITY_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*PagePriority = pagePriorityInfo.PagePriority;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a process' cycle count.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have
|
||||
* PROCESS_QUERY_LIMITED_INFORMATION access.
|
||||
* \param CycleTime A variable which receives the 64-bit cycle time.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessCycleTime(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PULONG64 CycleTime
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PROCESS_CYCLE_TIME_INFORMATION cycleTimeInfo;
|
||||
|
||||
status = NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessCycleTime,
|
||||
&cycleTimeInfo,
|
||||
sizeof(PROCESS_CYCLE_TIME_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
*CycleTime = cycleTimeInfo.AccumulatedCycles;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetProcessConsoleHostProcessId(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_Out_ PHANDLE ConsoleHostProcessId
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG_PTR consoleHostProcess;
|
||||
|
||||
status = NtQueryInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessConsoleHostProcess,
|
||||
&consoleHostProcess,
|
||||
sizeof(ULONG_PTR),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
*ConsoleHostProcessId = (HANDLE)consoleHostProcess;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a process' affinity mask.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have PROCESS_SET_INFORMATION access.
|
||||
* \param AffinityMask The new affinity mask.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhSetProcessAffinityMask(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ ULONG_PTR AffinityMask
|
||||
)
|
||||
{
|
||||
return NtSetInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessAffinityMask,
|
||||
&AffinityMask,
|
||||
sizeof(ULONG_PTR)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a process' I/O priority.
|
||||
*
|
||||
* \param ProcessHandle A handle to a process. The handle must have PROCESS_SET_INFORMATION access.
|
||||
* \param IoPriority The new I/O priority.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhSetProcessIoPriority(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ IO_PRIORITY_HINT IoPriority
|
||||
)
|
||||
{
|
||||
return NtSetInformationProcess(
|
||||
ProcessHandle,
|
||||
ProcessIoPriority,
|
||||
&IoPriority,
|
||||
sizeof(IO_PRIORITY_HINT)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets basic information for a thread.
|
||||
*
|
||||
* \param ThreadHandle A handle to a thread. The handle must have THREAD_QUERY_LIMITED_INFORMATION
|
||||
* access.
|
||||
* \param BasicInformation A variable which receives the information.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetThreadBasicInformation(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_Out_ PTHREAD_BASIC_INFORMATION BasicInformation
|
||||
)
|
||||
{
|
||||
return NtQueryInformationThread(
|
||||
ThreadHandle,
|
||||
ThreadBasicInformation,
|
||||
BasicInformation,
|
||||
sizeof(THREAD_BASIC_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a thread's I/O priority.
|
||||
*
|
||||
* \param ThreadHandle A handle to a thread. The handle must have THREAD_QUERY_LIMITED_INFORMATION
|
||||
* access.
|
||||
* \param IoPriority A variable which receives the I/O priority of the thread.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetThreadIoPriority(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_Out_ IO_PRIORITY_HINT *IoPriority
|
||||
)
|
||||
{
|
||||
return NtQueryInformationThread(
|
||||
ThreadHandle,
|
||||
ThreadIoPriority,
|
||||
IoPriority,
|
||||
sizeof(IO_PRIORITY_HINT),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a thread's page priority.
|
||||
*
|
||||
* \param ThreadHandle A handle to a thread. The handle must have THREAD_QUERY_LIMITED_INFORMATION
|
||||
* access.
|
||||
* \param PagePriority A variable which receives the page priority of the thread.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetThreadPagePriority(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_Out_ PULONG PagePriority
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PAGE_PRIORITY_INFORMATION pagePriorityInfo;
|
||||
|
||||
status = NtQueryInformationThread(
|
||||
ThreadHandle,
|
||||
ThreadPagePriority,
|
||||
&pagePriorityInfo,
|
||||
sizeof(PAGE_PRIORITY_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*PagePriority = pagePriorityInfo.PagePriority;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a thread's cycle count.
|
||||
*
|
||||
* \param ThreadHandle A handle to a thread. The handle must have THREAD_QUERY_LIMITED_INFORMATION
|
||||
* access.
|
||||
* \param CycleTime A variable which receives the 64-bit cycle time.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetThreadCycleTime(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_Out_ PULONG64 CycleTime
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
THREAD_CYCLE_TIME_INFORMATION cycleTimeInfo;
|
||||
|
||||
status = NtQueryInformationThread(
|
||||
ThreadHandle,
|
||||
ThreadCycleTime,
|
||||
&cycleTimeInfo,
|
||||
sizeof(THREAD_CYCLE_TIME_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
*CycleTime = cycleTimeInfo.AccumulatedCycles;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a thread's affinity mask.
|
||||
*
|
||||
* \param ThreadHandle A handle to a thread. The handle must have THREAD_SET_LIMITED_INFORMATION
|
||||
* access.
|
||||
* \param AffinityMask The new affinity mask.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhSetThreadAffinityMask(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_In_ ULONG_PTR AffinityMask
|
||||
)
|
||||
{
|
||||
return NtSetInformationThread(
|
||||
ThreadHandle,
|
||||
ThreadAffinityMask,
|
||||
&AffinityMask,
|
||||
sizeof(ULONG_PTR)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a thread's I/O priority.
|
||||
*
|
||||
* \param ThreadHandle A handle to a thread. The handle must have THREAD_SET_LIMITED_INFORMATION
|
||||
* access.
|
||||
* \param IoPriority The new I/O priority.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhSetThreadIoPriority(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_In_ IO_PRIORITY_HINT IoPriority
|
||||
)
|
||||
{
|
||||
return NtSetInformationThread(
|
||||
ThreadHandle,
|
||||
ThreadIoPriority,
|
||||
&IoPriority,
|
||||
sizeof(IO_PRIORITY_HINT)
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetJobBasicAndIoAccounting(
|
||||
_In_ HANDLE JobHandle,
|
||||
_Out_ PJOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION BasicAndIoAccounting
|
||||
)
|
||||
{
|
||||
return NtQueryInformationJobObject(
|
||||
JobHandle,
|
||||
JobObjectBasicAndIoAccountingInformation,
|
||||
BasicAndIoAccounting,
|
||||
sizeof(JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetJobBasicLimits(
|
||||
_In_ HANDLE JobHandle,
|
||||
_Out_ PJOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimits
|
||||
)
|
||||
{
|
||||
return NtQueryInformationJobObject(
|
||||
JobHandle,
|
||||
JobObjectBasicLimitInformation,
|
||||
BasicLimits,
|
||||
sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetJobExtendedLimits(
|
||||
_In_ HANDLE JobHandle,
|
||||
_Out_ PJOBOBJECT_EXTENDED_LIMIT_INFORMATION ExtendedLimits
|
||||
)
|
||||
{
|
||||
return NtQueryInformationJobObject(
|
||||
JobHandle,
|
||||
JobObjectExtendedLimitInformation,
|
||||
ExtendedLimits,
|
||||
sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetJobBasicUiRestrictions(
|
||||
_In_ HANDLE JobHandle,
|
||||
_Out_ PJOBOBJECT_BASIC_UI_RESTRICTIONS BasicUiRestrictions
|
||||
)
|
||||
{
|
||||
return NtQueryInformationJobObject(
|
||||
JobHandle,
|
||||
JobObjectBasicUIRestrictions,
|
||||
BasicUiRestrictions,
|
||||
sizeof(JOBOBJECT_BASIC_UI_RESTRICTIONS),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a token's session ID.
|
||||
*
|
||||
* \param TokenHandle A handle to a token. The handle must have TOKEN_QUERY access.
|
||||
* \param SessionId A variable which receives the session ID.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetTokenSessionId(
|
||||
_In_ HANDLE TokenHandle,
|
||||
_Out_ PULONG SessionId
|
||||
)
|
||||
{
|
||||
ULONG returnLength;
|
||||
|
||||
return NtQueryInformationToken(
|
||||
TokenHandle,
|
||||
TokenSessionId,
|
||||
SessionId,
|
||||
sizeof(ULONG),
|
||||
&returnLength
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a token's elevation type.
|
||||
*
|
||||
* \param TokenHandle A handle to a token. The handle must have TOKEN_QUERY access.
|
||||
* \param ElevationType A variable which receives the elevation type.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetTokenElevationType(
|
||||
_In_ HANDLE TokenHandle,
|
||||
_Out_ PTOKEN_ELEVATION_TYPE ElevationType
|
||||
)
|
||||
{
|
||||
ULONG returnLength;
|
||||
|
||||
return NtQueryInformationToken(
|
||||
TokenHandle,
|
||||
TokenElevationType,
|
||||
ElevationType,
|
||||
sizeof(TOKEN_ELEVATION_TYPE),
|
||||
&returnLength
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a token is elevated.
|
||||
*
|
||||
* \param TokenHandle A handle to a token. The handle must have TOKEN_QUERY access.
|
||||
* \param Elevated A variable which receives a boolean indicating whether the token is elevated.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetTokenIsElevated(
|
||||
_In_ HANDLE TokenHandle,
|
||||
_Out_ PBOOLEAN Elevated
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
TOKEN_ELEVATION elevation;
|
||||
ULONG returnLength;
|
||||
|
||||
status = NtQueryInformationToken(
|
||||
TokenHandle,
|
||||
TokenElevation,
|
||||
&elevation,
|
||||
sizeof(TOKEN_ELEVATION),
|
||||
&returnLength
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*Elevated = !!elevation.TokenIsElevated;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a token's statistics.
|
||||
*
|
||||
* \param TokenHandle A handle to a token. The handle must have TOKEN_QUERY access.
|
||||
* \param Statistics A variable which receives the token's statistics.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetTokenStatistics(
|
||||
_In_ HANDLE TokenHandle,
|
||||
_Out_ PTOKEN_STATISTICS Statistics
|
||||
)
|
||||
{
|
||||
ULONG returnLength;
|
||||
|
||||
return NtQueryInformationToken(
|
||||
TokenHandle,
|
||||
TokenStatistics,
|
||||
Statistics,
|
||||
sizeof(TOKEN_STATISTICS),
|
||||
&returnLength
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a token's source.
|
||||
*
|
||||
* \param TokenHandle A handle to a token. The handle must have TOKEN_QUERY_SOURCE access.
|
||||
* \param Source A variable which receives the token's source.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetTokenSource(
|
||||
_In_ HANDLE TokenHandle,
|
||||
_Out_ PTOKEN_SOURCE Source
|
||||
)
|
||||
{
|
||||
ULONG returnLength;
|
||||
|
||||
return NtQueryInformationToken(
|
||||
TokenHandle,
|
||||
TokenSource,
|
||||
Source,
|
||||
sizeof(TOKEN_SOURCE),
|
||||
&returnLength
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a handle to a token's linked token.
|
||||
*
|
||||
* \param TokenHandle A handle to a token. The handle must have TOKEN_QUERY access.
|
||||
* \param LinkedTokenHandle A variable which receives a handle to the linked token. You must close
|
||||
* the handle using NtClose() when you no longer need it.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetTokenLinkedToken(
|
||||
_In_ HANDLE TokenHandle,
|
||||
_Out_ PHANDLE LinkedTokenHandle
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG returnLength;
|
||||
TOKEN_LINKED_TOKEN linkedToken;
|
||||
|
||||
status = NtQueryInformationToken(
|
||||
TokenHandle,
|
||||
TokenLinkedToken,
|
||||
&linkedToken,
|
||||
sizeof(TOKEN_LINKED_TOKEN),
|
||||
&returnLength
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
*LinkedTokenHandle = linkedToken.LinkedToken;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether virtualization is allowed for a token.
|
||||
*
|
||||
* \param TokenHandle A handle to a token. The handle must have TOKEN_QUERY access.
|
||||
* \param IsVirtualizationAllowed A variable which receives a boolean indicating whether
|
||||
* virtualization is allowed for the token.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetTokenIsVirtualizationAllowed(
|
||||
_In_ HANDLE TokenHandle,
|
||||
_Out_ PBOOLEAN IsVirtualizationAllowed
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG returnLength;
|
||||
ULONG virtualizationAllowed;
|
||||
|
||||
status = NtQueryInformationToken(
|
||||
TokenHandle,
|
||||
TokenVirtualizationAllowed,
|
||||
&virtualizationAllowed,
|
||||
sizeof(ULONG),
|
||||
&returnLength
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
*IsVirtualizationAllowed = !!virtualizationAllowed;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether virtualization is enabled for a token.
|
||||
*
|
||||
* \param TokenHandle A handle to a token. The handle must have TOKEN_QUERY access.
|
||||
* \param IsVirtualizationEnabled A variable which receives a boolean indicating whether
|
||||
* virtualization is enabled for the token.
|
||||
*/
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetTokenIsVirtualizationEnabled(
|
||||
_In_ HANDLE TokenHandle,
|
||||
_Out_ PBOOLEAN IsVirtualizationEnabled
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG returnLength;
|
||||
ULONG virtualizationEnabled;
|
||||
|
||||
status = NtQueryInformationToken(
|
||||
TokenHandle,
|
||||
TokenVirtualizationEnabled,
|
||||
&virtualizationEnabled,
|
||||
sizeof(ULONG),
|
||||
&returnLength
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
*IsVirtualizationEnabled = !!virtualizationEnabled;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetEventBasicInformation(
|
||||
_In_ HANDLE EventHandle,
|
||||
_Out_ PEVENT_BASIC_INFORMATION BasicInformation
|
||||
)
|
||||
{
|
||||
return NtQueryEvent(
|
||||
EventHandle,
|
||||
EventBasicInformation,
|
||||
BasicInformation,
|
||||
sizeof(EVENT_BASIC_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetMutantBasicInformation(
|
||||
_In_ HANDLE MutantHandle,
|
||||
_Out_ PMUTANT_BASIC_INFORMATION BasicInformation
|
||||
)
|
||||
{
|
||||
return NtQueryMutant(
|
||||
MutantHandle,
|
||||
MutantBasicInformation,
|
||||
BasicInformation,
|
||||
sizeof(MUTANT_BASIC_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetMutantOwnerInformation(
|
||||
_In_ HANDLE MutantHandle,
|
||||
_Out_ PMUTANT_OWNER_INFORMATION OwnerInformation
|
||||
)
|
||||
{
|
||||
return NtQueryMutant(
|
||||
MutantHandle,
|
||||
MutantOwnerInformation,
|
||||
OwnerInformation,
|
||||
sizeof(MUTANT_OWNER_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetSectionBasicInformation(
|
||||
_In_ HANDLE SectionHandle,
|
||||
_Out_ PSECTION_BASIC_INFORMATION BasicInformation
|
||||
)
|
||||
{
|
||||
return NtQuerySection(
|
||||
SectionHandle,
|
||||
SectionBasicInformation,
|
||||
BasicInformation,
|
||||
sizeof(SECTION_BASIC_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetSemaphoreBasicInformation(
|
||||
_In_ HANDLE SemaphoreHandle,
|
||||
_Out_ PSEMAPHORE_BASIC_INFORMATION BasicInformation
|
||||
)
|
||||
{
|
||||
return NtQuerySemaphore(
|
||||
SemaphoreHandle,
|
||||
SemaphoreBasicInformation,
|
||||
BasicInformation,
|
||||
sizeof(SEMAPHORE_BASIC_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
NTSTATUS
|
||||
PhGetTimerBasicInformation(
|
||||
_In_ HANDLE TimerHandle,
|
||||
_Out_ PTIMER_BASIC_INFORMATION BasicInformation
|
||||
)
|
||||
{
|
||||
return NtQueryTimer(
|
||||
TimerHandle,
|
||||
TimerBasicInformation,
|
||||
BasicInformation,
|
||||
sizeof(TIMER_BASIC_INFORMATION),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
139
phlib/include/phnet.h
Normal file
139
phlib/include/phnet.h
Normal file
@@ -0,0 +1,139 @@
|
||||
#ifndef _PH_PHNET_H
|
||||
#define _PH_PHNET_H
|
||||
|
||||
#include <inaddr.h>
|
||||
#include <in6addr.h>
|
||||
|
||||
#define PH_IPV4_NETWORK_TYPE 0x1
|
||||
#define PH_IPV6_NETWORK_TYPE 0x2
|
||||
#define PH_NETWORK_TYPE_MASK 0x3
|
||||
|
||||
#define PH_TCP_PROTOCOL_TYPE 0x10
|
||||
#define PH_UDP_PROTOCOL_TYPE 0x20
|
||||
#define PH_PROTOCOL_TYPE_MASK 0x30
|
||||
|
||||
#define PH_NO_NETWORK_PROTOCOL 0x0
|
||||
#define PH_TCP4_NETWORK_PROTOCOL (PH_IPV4_NETWORK_TYPE | PH_TCP_PROTOCOL_TYPE)
|
||||
#define PH_TCP6_NETWORK_PROTOCOL (PH_IPV6_NETWORK_TYPE | PH_TCP_PROTOCOL_TYPE)
|
||||
#define PH_UDP4_NETWORK_PROTOCOL (PH_IPV4_NETWORK_TYPE | PH_UDP_PROTOCOL_TYPE)
|
||||
#define PH_UDP6_NETWORK_PROTOCOL (PH_IPV6_NETWORK_TYPE | PH_UDP_PROTOCOL_TYPE)
|
||||
|
||||
typedef struct _PH_IP_ADDRESS
|
||||
{
|
||||
ULONG Type;
|
||||
union
|
||||
{
|
||||
ULONG Ipv4;
|
||||
struct in_addr InAddr;
|
||||
UCHAR Ipv6[16];
|
||||
struct in6_addr In6Addr;
|
||||
};
|
||||
} PH_IP_ADDRESS, *PPH_IP_ADDRESS;
|
||||
|
||||
FORCEINLINE BOOLEAN PhEqualIpAddress(
|
||||
_In_ PPH_IP_ADDRESS Address1,
|
||||
_In_ PPH_IP_ADDRESS Address2
|
||||
)
|
||||
{
|
||||
if ((Address1->Type | Address2->Type) == 0) // don't check addresses if both are invalid
|
||||
return TRUE;
|
||||
if (Address1->Type != Address2->Type)
|
||||
return FALSE;
|
||||
|
||||
if (Address1->Type == PH_IPV4_NETWORK_TYPE)
|
||||
{
|
||||
return Address1->Ipv4 == Address2->Ipv4;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return
|
||||
*(PULONG64)(Address1->Ipv6) == *(PULONG64)(Address2->Ipv6) &&
|
||||
*(PULONG64)(Address1->Ipv6 + 8) == *(PULONG64)(Address2->Ipv6 + 8);
|
||||
#else
|
||||
return
|
||||
*(PULONG)(Address1->Ipv6) == *(PULONG)(Address2->Ipv6) &&
|
||||
*(PULONG)(Address1->Ipv6 + 4) == *(PULONG)(Address2->Ipv6 + 4) &&
|
||||
*(PULONG)(Address1->Ipv6 + 8) == *(PULONG)(Address2->Ipv6 + 8) &&
|
||||
*(PULONG)(Address1->Ipv6 + 12) == *(PULONG)(Address2->Ipv6 + 12);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE ULONG PhHashIpAddress(
|
||||
_In_ PPH_IP_ADDRESS Address
|
||||
)
|
||||
{
|
||||
ULONG hash = 0;
|
||||
|
||||
if (Address->Type == 0)
|
||||
return 0;
|
||||
|
||||
hash = Address->Type | (Address->Type << 16);
|
||||
|
||||
if (Address->Type == PH_IPV4_NETWORK_TYPE)
|
||||
{
|
||||
hash ^= Address->Ipv4;
|
||||
}
|
||||
else
|
||||
{
|
||||
hash += *(PULONG)(Address->Ipv6);
|
||||
hash ^= *(PULONG)(Address->Ipv6 + 4);
|
||||
hash += *(PULONG)(Address->Ipv6 + 8);
|
||||
hash ^= *(PULONG)(Address->Ipv6 + 12);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN PhIsNullIpAddress(
|
||||
_In_ PPH_IP_ADDRESS Address
|
||||
)
|
||||
{
|
||||
if (Address->Type == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else if (Address->Type == PH_IPV4_NETWORK_TYPE)
|
||||
{
|
||||
return Address->Ipv4 == 0;
|
||||
}
|
||||
else if (Address->Type == PH_IPV6_NETWORK_TYPE)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return (*(PULONG64)(Address->Ipv6) | *(PULONG64)(Address->Ipv6 + 8)) == 0;
|
||||
#else
|
||||
return (*(PULONG)(Address->Ipv6) | *(PULONG)(Address->Ipv6 + 4) |
|
||||
*(PULONG)(Address->Ipv6 + 8) | *(PULONG)(Address->Ipv6 + 12)) == 0;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _PH_IP_ENDPOINT
|
||||
{
|
||||
PH_IP_ADDRESS Address;
|
||||
ULONG Port;
|
||||
} PH_IP_ENDPOINT, *PPH_IP_ENDPOINT;
|
||||
|
||||
FORCEINLINE BOOLEAN PhEqualIpEndpoint(
|
||||
_In_ PPH_IP_ENDPOINT Endpoint1,
|
||||
_In_ PPH_IP_ENDPOINT Endpoint2
|
||||
)
|
||||
{
|
||||
return
|
||||
PhEqualIpAddress(&Endpoint1->Address, &Endpoint2->Address) &&
|
||||
Endpoint1->Port == Endpoint2->Port;
|
||||
}
|
||||
|
||||
FORCEINLINE ULONG PhHashIpEndpoint(
|
||||
_In_ PPH_IP_ENDPOINT Endpoint
|
||||
)
|
||||
{
|
||||
return PhHashIpAddress(&Endpoint->Address) ^ Endpoint->Port;
|
||||
}
|
||||
|
||||
#endif
|
||||
546
phlib/include/phsup.h
Normal file
546
phlib/include/phsup.h
Normal file
@@ -0,0 +1,546 @@
|
||||
#ifndef _PH_PHSUP_H
|
||||
#define _PH_PHSUP_H
|
||||
|
||||
// This header file provides some useful definitions specific to phlib.
|
||||
|
||||
#include <intrin.h>
|
||||
#include <wchar.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Memory
|
||||
|
||||
#define PTR_ADD_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) + (ULONG_PTR)(Offset)))
|
||||
#define PTR_SUB_OFFSET(Pointer, Offset) ((PVOID)((ULONG_PTR)(Pointer) - (ULONG_PTR)(Offset)))
|
||||
#define ALIGN_UP_BY(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1))
|
||||
#define ALIGN_UP_POINTER_BY(Pointer, Align) ((PVOID)ALIGN_UP_BY(Pointer, Align))
|
||||
#define ALIGN_UP(Address, Type) ALIGN_UP_BY(Address, sizeof(Type))
|
||||
#define ALIGN_UP_POINTER(Pointer, Type) ((PVOID)ALIGN_UP(Pointer, Type))
|
||||
|
||||
#define PAGE_SIZE 0x1000
|
||||
|
||||
#define PH_LARGE_BUFFER_SIZE (256 * 1024 * 1024)
|
||||
|
||||
// Exceptions
|
||||
|
||||
#define PhRaiseStatus(Status) RtlRaiseStatus(Status)
|
||||
|
||||
#define SIMPLE_EXCEPTION_FILTER(Condition) \
|
||||
((Condition) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
||||
|
||||
// Compiler
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ASSUME_ASSERT(Expression) assert(Expression)
|
||||
#define ASSUME_NO_DEFAULT assert(FALSE)
|
||||
#else
|
||||
#define ASSUME_ASSERT(Expression) __assume(Expression)
|
||||
#define ASSUME_NO_DEFAULT __assume(FALSE)
|
||||
#endif
|
||||
|
||||
// Time
|
||||
|
||||
#define PH_TICKS_PER_NS ((LONG64)1 * 10)
|
||||
#define PH_TICKS_PER_MS (PH_TICKS_PER_NS * 1000)
|
||||
#define PH_TICKS_PER_SEC (PH_TICKS_PER_MS * 1000)
|
||||
#define PH_TICKS_PER_MIN (PH_TICKS_PER_SEC * 60)
|
||||
#define PH_TICKS_PER_HOUR (PH_TICKS_PER_MIN * 60)
|
||||
#define PH_TICKS_PER_DAY (PH_TICKS_PER_HOUR * 24)
|
||||
|
||||
#define PH_TICKS_PARTIAL_MS(Ticks) (((ULONG64)(Ticks) / PH_TICKS_PER_MS) % 1000)
|
||||
#define PH_TICKS_PARTIAL_SEC(Ticks) (((ULONG64)(Ticks) / PH_TICKS_PER_SEC) % 60)
|
||||
#define PH_TICKS_PARTIAL_MIN(Ticks) (((ULONG64)(Ticks) / PH_TICKS_PER_MIN) % 60)
|
||||
#define PH_TICKS_PARTIAL_HOURS(Ticks) (((ULONG64)(Ticks) / PH_TICKS_PER_HOUR) % 24)
|
||||
#define PH_TICKS_PARTIAL_DAYS(Ticks) ((ULONG64)(Ticks) / PH_TICKS_PER_DAY)
|
||||
|
||||
#define PH_TIMEOUT_MS PH_TICKS_PER_MS
|
||||
#define PH_TIMEOUT_SEC PH_TICKS_PER_SEC
|
||||
|
||||
// Annotations
|
||||
|
||||
/**
|
||||
* Indicates that a function assumes the specified number of references are available for the
|
||||
* object.
|
||||
*
|
||||
* \remarks Usually functions reference objects if they store them for later usage; this annotation
|
||||
* specifies that the caller must supply these extra references itself. In effect these references
|
||||
* are "transferred" to the function and must not be used. E.g. if you create an object and
|
||||
* immediately call a function with _Assume_refs_(1), you may no longer use the object since that
|
||||
* one reference you held is no longer yours.
|
||||
*/
|
||||
#define _Assume_refs_(count)
|
||||
|
||||
#define _Callback_
|
||||
|
||||
/**
|
||||
* Indicates that a function may raise a software exception.
|
||||
*
|
||||
* \remarks Do not use this annotation for temporary usages of exceptions, e.g. unimplemented
|
||||
* functions.
|
||||
*/
|
||||
#define _May_raise_
|
||||
|
||||
/**
|
||||
* Indicates that a function requires the specified value to be aligned at the specified number of
|
||||
* bytes.
|
||||
*/
|
||||
#define _Needs_align_(align)
|
||||
|
||||
// Casts
|
||||
|
||||
// Zero extension and sign extension macros
|
||||
#define C_1uTo2(x) ((unsigned short)(unsigned char)(x))
|
||||
#define C_1sTo2(x) ((unsigned short)(signed char)(x))
|
||||
#define C_1uTo4(x) ((unsigned int)(unsigned char)(x))
|
||||
#define C_1sTo4(x) ((unsigned int)(signed char)(x))
|
||||
#define C_2uTo4(x) ((unsigned int)(unsigned short)(x))
|
||||
#define C_2sTo4(x) ((unsigned int)(signed short)(x))
|
||||
#define C_4uTo8(x) ((unsigned __int64)(unsigned int)(x))
|
||||
#define C_4sTo8(x) ((unsigned __int64)(signed int)(x))
|
||||
|
||||
// Sorting
|
||||
|
||||
typedef enum _PH_SORT_ORDER
|
||||
{
|
||||
NoSortOrder = 0,
|
||||
AscendingSortOrder,
|
||||
DescendingSortOrder
|
||||
} PH_SORT_ORDER, *PPH_SORT_ORDER;
|
||||
|
||||
FORCEINLINE LONG PhModifySort(
|
||||
_In_ LONG Result,
|
||||
_In_ PH_SORT_ORDER Order
|
||||
)
|
||||
{
|
||||
if (Order == AscendingSortOrder)
|
||||
return Result;
|
||||
else if (Order == DescendingSortOrder)
|
||||
return -Result;
|
||||
else
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define PH_BUILTIN_COMPARE(value1, value2) \
|
||||
if (value1 > value2) \
|
||||
return 1; \
|
||||
else if (value1 < value2) \
|
||||
return -1; \
|
||||
\
|
||||
return 0
|
||||
|
||||
FORCEINLINE int charcmp(
|
||||
_In_ signed char value1,
|
||||
_In_ signed char value2
|
||||
)
|
||||
{
|
||||
return C_1sTo4(value1 - value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int ucharcmp(
|
||||
_In_ unsigned char value1,
|
||||
_In_ unsigned char value2
|
||||
)
|
||||
{
|
||||
PH_BUILTIN_COMPARE(value1, value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int shortcmp(
|
||||
_In_ signed short value1,
|
||||
_In_ signed short value2
|
||||
)
|
||||
{
|
||||
return C_2sTo4(value1 - value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int ushortcmp(
|
||||
_In_ unsigned short value1,
|
||||
_In_ unsigned short value2
|
||||
)
|
||||
{
|
||||
PH_BUILTIN_COMPARE(value1, value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int intcmp(
|
||||
_In_ int value1,
|
||||
_In_ int value2
|
||||
)
|
||||
{
|
||||
return value1 - value2;
|
||||
}
|
||||
|
||||
FORCEINLINE int uintcmp(
|
||||
_In_ unsigned int value1,
|
||||
_In_ unsigned int value2
|
||||
)
|
||||
{
|
||||
PH_BUILTIN_COMPARE(value1, value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int int64cmp(
|
||||
_In_ __int64 value1,
|
||||
_In_ __int64 value2
|
||||
)
|
||||
{
|
||||
PH_BUILTIN_COMPARE(value1, value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int uint64cmp(
|
||||
_In_ unsigned __int64 value1,
|
||||
_In_ unsigned __int64 value2
|
||||
)
|
||||
{
|
||||
PH_BUILTIN_COMPARE(value1, value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int intptrcmp(
|
||||
_In_ LONG_PTR value1,
|
||||
_In_ LONG_PTR value2
|
||||
)
|
||||
{
|
||||
PH_BUILTIN_COMPARE(value1, value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int uintptrcmp(
|
||||
_In_ ULONG_PTR value1,
|
||||
_In_ ULONG_PTR value2
|
||||
)
|
||||
{
|
||||
PH_BUILTIN_COMPARE(value1, value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int singlecmp(
|
||||
_In_ float value1,
|
||||
_In_ float value2
|
||||
)
|
||||
{
|
||||
PH_BUILTIN_COMPARE(value1, value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int doublecmp(
|
||||
_In_ double value1,
|
||||
_In_ double value2
|
||||
)
|
||||
{
|
||||
PH_BUILTIN_COMPARE(value1, value2);
|
||||
}
|
||||
|
||||
FORCEINLINE int wcsicmp2(
|
||||
_In_opt_ PWSTR Value1,
|
||||
_In_opt_ PWSTR Value2
|
||||
)
|
||||
{
|
||||
if (Value1 && Value2)
|
||||
return _wcsicmp(Value1, Value2);
|
||||
else if (!Value1)
|
||||
return !Value2 ? 0 : -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef int (__cdecl *PC_COMPARE_FUNCTION)(void *, const void *, const void *);
|
||||
|
||||
// Synchronization
|
||||
|
||||
#ifndef _WIN64
|
||||
|
||||
#ifndef _InterlockedCompareExchangePointer
|
||||
void *_InterlockedCompareExchangePointer(
|
||||
void *volatile *Destination,
|
||||
void *Exchange,
|
||||
void *Comparand
|
||||
);
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER < 1900)
|
||||
#ifndef _InterlockedExchangePointer
|
||||
FORCEINLINE void *_InterlockedExchangePointer(
|
||||
void *volatile *Destination,
|
||||
void *Exchange
|
||||
)
|
||||
{
|
||||
return (PVOID)_InterlockedExchange(
|
||||
(PLONG_PTR)Destination,
|
||||
(LONG_PTR)Exchange
|
||||
);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
FORCEINLINE LONG_PTR _InterlockedExchangeAddPointer(
|
||||
_Inout_ _Interlocked_operand_ LONG_PTR volatile *Addend,
|
||||
_In_ LONG_PTR Value
|
||||
)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return (LONG_PTR)_InterlockedExchangeAdd64((PLONG64)Addend, (LONG64)Value);
|
||||
#else
|
||||
return (LONG_PTR)_InterlockedExchangeAdd((PLONG)Addend, (LONG)Value);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE LONG_PTR _InterlockedIncrementPointer(
|
||||
_Inout_ _Interlocked_operand_ LONG_PTR volatile *Addend
|
||||
)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return (LONG_PTR)_InterlockedIncrement64((PLONG64)Addend);
|
||||
#else
|
||||
return (LONG_PTR)_InterlockedIncrement((PLONG)Addend);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE LONG_PTR _InterlockedDecrementPointer(
|
||||
_Inout_ _Interlocked_operand_ LONG_PTR volatile *Addend
|
||||
)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return (LONG_PTR)_InterlockedDecrement64((PLONG64)Addend);
|
||||
#else
|
||||
return (LONG_PTR)_InterlockedDecrement((PLONG)Addend);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN _InterlockedBitTestAndResetPointer(
|
||||
_Inout_ _Interlocked_operand_ LONG_PTR volatile *Base,
|
||||
_In_ LONG_PTR Bit
|
||||
)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return _interlockedbittestandreset64((PLONG64)Base, (LONG64)Bit);
|
||||
#else
|
||||
return _interlockedbittestandreset((PLONG)Base, (LONG)Bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN _InterlockedBitTestAndSetPointer(
|
||||
_Inout_ _Interlocked_operand_ LONG_PTR volatile *Base,
|
||||
_In_ LONG_PTR Bit
|
||||
)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return _interlockedbittestandset64((PLONG64)Base, (LONG64)Bit);
|
||||
#else
|
||||
return _interlockedbittestandset((PLONG)Base, (LONG)Bit);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN _InterlockedIncrementNoZero(
|
||||
_Inout_ _Interlocked_operand_ LONG volatile *Addend
|
||||
)
|
||||
{
|
||||
LONG value;
|
||||
LONG newValue;
|
||||
|
||||
value = *Addend;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (value == 0)
|
||||
return FALSE;
|
||||
|
||||
if ((newValue = _InterlockedCompareExchange(
|
||||
Addend,
|
||||
value + 1,
|
||||
value
|
||||
)) == value)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
value = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN _InterlockedIncrementPositive(
|
||||
_Inout_ _Interlocked_operand_ LONG volatile *Addend
|
||||
)
|
||||
{
|
||||
LONG value;
|
||||
LONG newValue;
|
||||
|
||||
value = *Addend;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (value <= 0)
|
||||
return FALSE;
|
||||
|
||||
if ((newValue = _InterlockedCompareExchange(
|
||||
Addend,
|
||||
value + 1,
|
||||
value
|
||||
)) == value)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
value = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Strings
|
||||
|
||||
#define PH_INT32_STR_LEN 12
|
||||
#define PH_INT32_STR_LEN_1 (PH_INT32_STR_LEN + 1)
|
||||
|
||||
#define PH_INT64_STR_LEN 50
|
||||
#define PH_INT64_STR_LEN_1 (PH_INT64_STR_LEN + 1)
|
||||
|
||||
#define PH_PTR_STR_LEN 24
|
||||
#define PH_PTR_STR_LEN_1 (PH_PTR_STR_LEN + 1)
|
||||
|
||||
FORCEINLINE VOID PhPrintInt32(
|
||||
_Out_writes_(PH_INT32_STR_LEN_1) PWSTR Destination,
|
||||
_In_ LONG Int32
|
||||
)
|
||||
{
|
||||
_ltow(Int32, Destination, 10);
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhPrintUInt32(
|
||||
_Out_writes_(PH_INT32_STR_LEN_1) PWSTR Destination,
|
||||
_In_ ULONG UInt32
|
||||
)
|
||||
{
|
||||
_ultow(UInt32, Destination, 10);
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhPrintInt64(
|
||||
_Out_writes_(PH_INT64_STR_LEN_1) PWSTR Destination,
|
||||
_In_ LONG64 Int64
|
||||
)
|
||||
{
|
||||
_i64tow(Int64, Destination, 10);
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhPrintUInt64(
|
||||
_Out_writes_(PH_INT64_STR_LEN_1) PWSTR Destination,
|
||||
_In_ ULONG64 UInt64
|
||||
)
|
||||
{
|
||||
_ui64tow(UInt64, Destination, 10);
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhPrintPointer(
|
||||
_Out_writes_(PH_PTR_STR_LEN_1) PWSTR Destination,
|
||||
_In_ PVOID Pointer
|
||||
)
|
||||
{
|
||||
Destination[0] = '0';
|
||||
Destination[1] = 'x';
|
||||
#ifdef _WIN64
|
||||
_ui64tow((ULONG64)Pointer, &Destination[2], 16);
|
||||
#else
|
||||
_ultow((ULONG)Pointer, &Destination[2], 16);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Misc.
|
||||
|
||||
FORCEINLINE ULONG PhCountBits(
|
||||
_In_ ULONG Value
|
||||
)
|
||||
{
|
||||
ULONG count = 0;
|
||||
|
||||
while (Value)
|
||||
{
|
||||
count++;
|
||||
Value &= Value - 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
FORCEINLINE ULONG PhRoundNumber(
|
||||
_In_ ULONG Value,
|
||||
_In_ ULONG Granularity
|
||||
)
|
||||
{
|
||||
return (Value + Granularity / 2) / Granularity * Granularity;
|
||||
}
|
||||
|
||||
FORCEINLINE ULONG PhMultiplyDivide(
|
||||
_In_ ULONG Number,
|
||||
_In_ ULONG Numerator,
|
||||
_In_ ULONG Denominator
|
||||
)
|
||||
{
|
||||
return (ULONG)(((ULONG64)Number * (ULONG64)Numerator + Denominator / 2) / (ULONG64)Denominator);
|
||||
}
|
||||
|
||||
FORCEINLINE LONG PhMultiplyDivideSigned(
|
||||
_In_ LONG Number,
|
||||
_In_ ULONG Numerator,
|
||||
_In_ ULONG Denominator
|
||||
)
|
||||
{
|
||||
if (Number >= 0)
|
||||
return PhMultiplyDivide(Number, Numerator, Denominator);
|
||||
else
|
||||
return -(LONG)PhMultiplyDivide(-Number, Numerator, Denominator);
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhProbeAddress(
|
||||
_In_ PVOID UserAddress,
|
||||
_In_ SIZE_T UserLength,
|
||||
_In_ PVOID BufferAddress,
|
||||
_In_ SIZE_T BufferLength,
|
||||
_In_ ULONG Alignment
|
||||
)
|
||||
{
|
||||
if (UserLength != 0)
|
||||
{
|
||||
if (((ULONG_PTR)UserAddress & (Alignment - 1)) != 0)
|
||||
PhRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
|
||||
|
||||
if (
|
||||
((ULONG_PTR)UserAddress + UserLength < (ULONG_PTR)UserAddress) ||
|
||||
((ULONG_PTR)UserAddress < (ULONG_PTR)BufferAddress) ||
|
||||
((ULONG_PTR)UserAddress + UserLength > (ULONG_PTR)BufferAddress + BufferLength)
|
||||
)
|
||||
PhRaiseStatus(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE PLARGE_INTEGER PhTimeoutFromMilliseconds(
|
||||
_Out_ PLARGE_INTEGER Timeout,
|
||||
_In_ ULONG Milliseconds
|
||||
)
|
||||
{
|
||||
if (Milliseconds == INFINITE)
|
||||
return NULL;
|
||||
|
||||
Timeout->QuadPart = -(LONGLONG)UInt32x32To64(Milliseconds, PH_TIMEOUT_MS);
|
||||
|
||||
return Timeout;
|
||||
}
|
||||
|
||||
FORCEINLINE NTSTATUS PhGetLastWin32ErrorAsNtStatus()
|
||||
{
|
||||
ULONG win32Result;
|
||||
|
||||
// This is needed because NTSTATUS_FROM_WIN32 uses the argument multiple times.
|
||||
win32Result = GetLastError();
|
||||
|
||||
return NTSTATUS_FROM_WIN32(win32Result);
|
||||
}
|
||||
|
||||
FORCEINLINE PVOID PhGetModuleProcAddress(
|
||||
_In_ PWSTR ModuleName,
|
||||
_In_ PSTR ProcName
|
||||
)
|
||||
{
|
||||
HMODULE module;
|
||||
|
||||
module = GetModuleHandle(ModuleName);
|
||||
|
||||
if (module)
|
||||
return GetProcAddress(module, ProcName);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
1049
phlib/include/phutil.h
Normal file
1049
phlib/include/phutil.h
Normal file
File diff suppressed because it is too large
Load Diff
139
phlib/include/provider.h
Normal file
139
phlib/include/provider.h
Normal file
@@ -0,0 +1,139 @@
|
||||
#ifndef _PH_PROVIDER_H
|
||||
#define _PH_PROVIDER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
extern PPH_LIST PhDbgProviderList;
|
||||
extern PH_QUEUED_LOCK PhDbgProviderListLock;
|
||||
#endif
|
||||
|
||||
typedef enum _PH_PROVIDER_THREAD_STATE
|
||||
{
|
||||
ProviderThreadRunning,
|
||||
ProviderThreadStopped,
|
||||
ProviderThreadStopping
|
||||
} PH_PROVIDER_THREAD_STATE;
|
||||
|
||||
typedef VOID (NTAPI *PPH_PROVIDER_FUNCTION)(
|
||||
_In_ PVOID Object
|
||||
);
|
||||
|
||||
struct _PH_PROVIDER_THREAD;
|
||||
typedef struct _PH_PROVIDER_THREAD *PPH_PROVIDER_THREAD;
|
||||
|
||||
typedef struct _PH_PROVIDER_REGISTRATION
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
PPH_PROVIDER_THREAD ProviderThread;
|
||||
PPH_PROVIDER_FUNCTION Function;
|
||||
PVOID Object;
|
||||
ULONG RunId;
|
||||
BOOLEAN Enabled;
|
||||
BOOLEAN Unregistering;
|
||||
BOOLEAN Boosting;
|
||||
} PH_PROVIDER_REGISTRATION, *PPH_PROVIDER_REGISTRATION;
|
||||
|
||||
typedef struct _PH_PROVIDER_THREAD
|
||||
{
|
||||
HANDLE ThreadHandle;
|
||||
HANDLE TimerHandle;
|
||||
ULONG Interval;
|
||||
PH_PROVIDER_THREAD_STATE State;
|
||||
|
||||
PH_QUEUED_LOCK Lock;
|
||||
LIST_ENTRY ListHead;
|
||||
ULONG BoostCount;
|
||||
} PH_PROVIDER_THREAD, *PPH_PROVIDER_THREAD;
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhInitializeProviderThread(
|
||||
_Out_ PPH_PROVIDER_THREAD ProviderThread,
|
||||
_In_ ULONG Interval
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhDeleteProviderThread(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhStartProviderThread(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhStopProviderThread(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhSetIntervalProviderThread(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread,
|
||||
_In_ ULONG Interval
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhRegisterProvider(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread,
|
||||
_In_ PPH_PROVIDER_FUNCTION Function,
|
||||
_In_opt_ PVOID Object,
|
||||
_Out_ PPH_PROVIDER_REGISTRATION Registration
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhUnregisterProvider(
|
||||
_Inout_ PPH_PROVIDER_REGISTRATION Registration
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhBoostProvider(
|
||||
_Inout_ PPH_PROVIDER_REGISTRATION Registration,
|
||||
_Out_opt_ PULONG FutureRunId
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
PhGetRunIdProvider(
|
||||
_In_ PPH_PROVIDER_REGISTRATION Registration
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhGetEnabledProvider(
|
||||
_In_ PPH_PROVIDER_REGISTRATION Registration
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhSetEnabledProvider(
|
||||
_Inout_ PPH_PROVIDER_REGISTRATION Registration,
|
||||
_In_ BOOLEAN Enabled
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
349
phlib/include/queuedlock.h
Normal file
349
phlib/include/queuedlock.h
Normal file
@@ -0,0 +1,349 @@
|
||||
#ifndef _PH_QUEUEDLOCK_H
|
||||
#define _PH_QUEUEDLOCK_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PH_QUEUED_LOCK_OWNED ((ULONG_PTR)0x1)
|
||||
#define PH_QUEUED_LOCK_OWNED_SHIFT 0
|
||||
#define PH_QUEUED_LOCK_WAITERS ((ULONG_PTR)0x2)
|
||||
|
||||
// Valid only if Waiters = 0
|
||||
#define PH_QUEUED_LOCK_SHARED_INC ((ULONG_PTR)0x4)
|
||||
#define PH_QUEUED_LOCK_SHARED_SHIFT 2
|
||||
|
||||
// Valid only if Waiters = 1
|
||||
#define PH_QUEUED_LOCK_TRAVERSING ((ULONG_PTR)0x4)
|
||||
#define PH_QUEUED_LOCK_MULTIPLE_SHARED ((ULONG_PTR)0x8)
|
||||
|
||||
#define PH_QUEUED_LOCK_FLAGS ((ULONG_PTR)0xf)
|
||||
|
||||
#define PhGetQueuedLockSharedOwners(Value) \
|
||||
((ULONG_PTR)(Value) >> PH_QUEUED_LOCK_SHARED_SHIFT)
|
||||
#define PhGetQueuedLockWaitBlock(Value) \
|
||||
((PPH_QUEUED_WAIT_BLOCK)((ULONG_PTR)(Value) & ~PH_QUEUED_LOCK_FLAGS))
|
||||
|
||||
typedef struct _PH_QUEUED_LOCK
|
||||
{
|
||||
ULONG_PTR Value;
|
||||
} PH_QUEUED_LOCK, *PPH_QUEUED_LOCK;
|
||||
|
||||
#define PH_QUEUED_LOCK_INIT { 0 }
|
||||
|
||||
#define PH_QUEUED_WAITER_EXCLUSIVE 0x1
|
||||
#define PH_QUEUED_WAITER_SPINNING 0x2
|
||||
#define PH_QUEUED_WAITER_SPINNING_SHIFT 1
|
||||
|
||||
typedef struct DECLSPEC_ALIGN(16) _PH_QUEUED_WAIT_BLOCK
|
||||
{
|
||||
/** A pointer to the next wait block, i.e. the wait block pushed onto the list before this one. */
|
||||
struct _PH_QUEUED_WAIT_BLOCK *Next;
|
||||
/**
|
||||
* A pointer to the previous wait block, i.e. the wait block pushed onto the list after this
|
||||
* one.
|
||||
*/
|
||||
struct _PH_QUEUED_WAIT_BLOCK *Previous;
|
||||
/** A pointer to the last wait block, i.e. the first waiter pushed onto the list. */
|
||||
struct _PH_QUEUED_WAIT_BLOCK *Last;
|
||||
|
||||
ULONG SharedOwners;
|
||||
ULONG Flags;
|
||||
} PH_QUEUED_WAIT_BLOCK, *PPH_QUEUED_WAIT_BLOCK;
|
||||
|
||||
BOOLEAN PhQueuedLockInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
// Queued lock
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhInitializeQueuedLock(
|
||||
_Out_ PPH_QUEUED_LOCK QueuedLock
|
||||
)
|
||||
{
|
||||
QueuedLock->Value = 0;
|
||||
}
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfAcquireQueuedLockExclusive(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
);
|
||||
|
||||
_Acquires_exclusive_lock_(*QueuedLock)
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhAcquireQueuedLockExclusive(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
)
|
||||
{
|
||||
if (_InterlockedBitTestAndSetPointer((PLONG_PTR)&QueuedLock->Value, PH_QUEUED_LOCK_OWNED_SHIFT))
|
||||
{
|
||||
// Owned bit was already set. Slow path.
|
||||
PhfAcquireQueuedLockExclusive(QueuedLock);
|
||||
}
|
||||
}
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfAcquireQueuedLockShared(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
);
|
||||
|
||||
_Acquires_shared_lock_(*QueuedLock)
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhAcquireQueuedLockShared(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
)
|
||||
{
|
||||
if ((ULONG_PTR)_InterlockedCompareExchangePointer(
|
||||
(PVOID *)&QueuedLock->Value,
|
||||
(PVOID)(PH_QUEUED_LOCK_OWNED | PH_QUEUED_LOCK_SHARED_INC),
|
||||
(PVOID)0
|
||||
) != 0)
|
||||
{
|
||||
PhfAcquireQueuedLockShared(QueuedLock);
|
||||
}
|
||||
}
|
||||
|
||||
_When_(return != 0, _Acquires_exclusive_lock_(*QueuedLock))
|
||||
FORCEINLINE
|
||||
BOOLEAN
|
||||
PhTryAcquireQueuedLockExclusive(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
)
|
||||
{
|
||||
if (!_InterlockedBitTestAndSetPointer((PLONG_PTR)&QueuedLock->Value, PH_QUEUED_LOCK_OWNED_SHIFT))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfReleaseQueuedLockExclusive(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfWakeForReleaseQueuedLock(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock,
|
||||
_In_ ULONG_PTR Value
|
||||
);
|
||||
|
||||
_Releases_exclusive_lock_(*QueuedLock)
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhReleaseQueuedLockExclusive(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
)
|
||||
{
|
||||
ULONG_PTR value;
|
||||
|
||||
value = (ULONG_PTR)_InterlockedExchangeAddPointer((PLONG_PTR)&QueuedLock->Value, -(LONG_PTR)PH_QUEUED_LOCK_OWNED);
|
||||
|
||||
if ((value & (PH_QUEUED_LOCK_WAITERS | PH_QUEUED_LOCK_TRAVERSING)) == PH_QUEUED_LOCK_WAITERS)
|
||||
{
|
||||
PhfWakeForReleaseQueuedLock(QueuedLock, value - PH_QUEUED_LOCK_OWNED);
|
||||
}
|
||||
}
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfReleaseQueuedLockShared(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
);
|
||||
|
||||
_Releases_shared_lock_(*QueuedLock)
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhReleaseQueuedLockShared(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
)
|
||||
{
|
||||
ULONG_PTR value;
|
||||
|
||||
value = PH_QUEUED_LOCK_OWNED | PH_QUEUED_LOCK_SHARED_INC;
|
||||
|
||||
if ((ULONG_PTR)_InterlockedCompareExchangePointer(
|
||||
(PVOID *)&QueuedLock->Value,
|
||||
(PVOID)0,
|
||||
(PVOID)value
|
||||
) != value)
|
||||
{
|
||||
PhfReleaseQueuedLockShared(QueuedLock);
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhAcquireReleaseQueuedLockExclusive(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
)
|
||||
{
|
||||
BOOLEAN owned;
|
||||
|
||||
MemoryBarrier();
|
||||
owned = !!(QueuedLock->Value & PH_QUEUED_LOCK_OWNED);
|
||||
MemoryBarrier();
|
||||
|
||||
if (owned)
|
||||
{
|
||||
PhAcquireQueuedLockExclusive(QueuedLock);
|
||||
PhReleaseQueuedLockExclusive(QueuedLock);
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
BOOLEAN
|
||||
PhTryAcquireReleaseQueuedLockExclusive(
|
||||
_Inout_ PPH_QUEUED_LOCK QueuedLock
|
||||
)
|
||||
{
|
||||
BOOLEAN owned;
|
||||
|
||||
// Need two memory barriers because we don't want the compiler re-ordering the following check
|
||||
// in either direction.
|
||||
MemoryBarrier();
|
||||
owned = !(QueuedLock->Value & PH_QUEUED_LOCK_OWNED);
|
||||
MemoryBarrier();
|
||||
|
||||
return owned;
|
||||
}
|
||||
|
||||
// Condition variable
|
||||
|
||||
typedef struct _PH_QUEUED_LOCK PH_CONDITION, *PPH_CONDITION;
|
||||
|
||||
#define PH_CONDITION_INIT PH_QUEUED_LOCK_INIT
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhInitializeCondition(
|
||||
_Out_ PPH_CONDITION Condition
|
||||
)
|
||||
{
|
||||
PhInitializeQueuedLock(Condition);
|
||||
}
|
||||
|
||||
#define PhPulseCondition PhfPulseCondition
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfPulseCondition(
|
||||
_Inout_ PPH_CONDITION Condition
|
||||
);
|
||||
|
||||
#define PhPulseAllCondition PhfPulseAllCondition
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfPulseAllCondition(
|
||||
_Inout_ PPH_CONDITION Condition
|
||||
);
|
||||
|
||||
#define PhWaitForCondition PhfWaitForCondition
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfWaitForCondition(
|
||||
_Inout_ PPH_CONDITION Condition,
|
||||
_Inout_ PPH_QUEUED_LOCK Lock,
|
||||
_In_opt_ PLARGE_INTEGER Timeout
|
||||
);
|
||||
|
||||
#define PH_CONDITION_WAIT_QUEUED_LOCK 0x1
|
||||
#define PH_CONDITION_WAIT_CRITICAL_SECTION 0x2
|
||||
#define PH_CONDITION_WAIT_FAST_LOCK 0x4
|
||||
#define PH_CONDITION_WAIT_LOCK_TYPE_MASK 0xfff
|
||||
|
||||
#define PH_CONDITION_WAIT_SHARED 0x1000
|
||||
#define PH_CONDITION_WAIT_SPIN 0x2000
|
||||
|
||||
#define PhWaitForConditionEx PhfWaitForConditionEx
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfWaitForConditionEx(
|
||||
_Inout_ PPH_CONDITION Condition,
|
||||
_Inout_ PVOID Lock,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ PLARGE_INTEGER Timeout
|
||||
);
|
||||
|
||||
// Wake event
|
||||
|
||||
typedef struct _PH_QUEUED_LOCK PH_WAKE_EVENT, *PPH_WAKE_EVENT;
|
||||
|
||||
#define PH_WAKE_EVENT_INIT PH_QUEUED_LOCK_INIT
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhInitializeWakeEvent(
|
||||
_Out_ PPH_WAKE_EVENT WakeEvent
|
||||
)
|
||||
{
|
||||
PhInitializeQueuedLock(WakeEvent);
|
||||
}
|
||||
|
||||
#define PhQueueWakeEvent PhfQueueWakeEvent
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfQueueWakeEvent(
|
||||
_Inout_ PPH_WAKE_EVENT WakeEvent,
|
||||
_Out_ PPH_QUEUED_WAIT_BLOCK WaitBlock
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
FASTCALL
|
||||
PhfSetWakeEvent(
|
||||
_Inout_ PPH_WAKE_EVENT WakeEvent,
|
||||
_Inout_opt_ PPH_QUEUED_WAIT_BLOCK WaitBlock
|
||||
);
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhSetWakeEvent(
|
||||
_Inout_ PPH_WAKE_EVENT WakeEvent,
|
||||
_Inout_opt_ PPH_QUEUED_WAIT_BLOCK WaitBlock
|
||||
)
|
||||
{
|
||||
// The wake event is similar to a synchronization event in that it does not have thread-safe
|
||||
// pulsing; we can simply skip the function call if there's nothing to wake. However, if we're
|
||||
// cancelling a wait (WaitBlock != NULL) we need to make the call.
|
||||
|
||||
if (WakeEvent->Value || WaitBlock)
|
||||
PhfSetWakeEvent(WakeEvent, WaitBlock);
|
||||
}
|
||||
|
||||
#define PhWaitForWakeEvent PhfWaitForWakeEvent
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
PhfWaitForWakeEvent(
|
||||
_Inout_ PPH_WAKE_EVENT WakeEvent,
|
||||
_Inout_ PPH_QUEUED_WAIT_BLOCK WaitBlock,
|
||||
_In_ BOOLEAN Spin,
|
||||
_In_opt_ PLARGE_INTEGER Timeout
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
309
phlib/include/ref.h
Normal file
309
phlib/include/ref.h
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* internal object manager
|
||||
*
|
||||
* Copyright (C) 2009-2016 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PH_REF_H
|
||||
#define _PH_REF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Configuration
|
||||
|
||||
#define PH_OBJECT_SMALL_OBJECT_SIZE 48
|
||||
#define PH_OBJECT_SMALL_OBJECT_COUNT 512
|
||||
|
||||
// Object type flags
|
||||
#define PH_OBJECT_TYPE_USE_FREE_LIST 0x00000001
|
||||
#define PH_OBJECT_TYPE_VALID_FLAGS 0x00000001
|
||||
|
||||
// Object type callbacks
|
||||
|
||||
/**
|
||||
* The delete procedure for an object type, called when an object of the type is being freed.
|
||||
*
|
||||
* \param Object A pointer to the object being freed.
|
||||
* \param Flags Reserved.
|
||||
*/
|
||||
typedef VOID (NTAPI *PPH_TYPE_DELETE_PROCEDURE)(
|
||||
_In_ PVOID Object,
|
||||
_In_ ULONG Flags
|
||||
);
|
||||
|
||||
struct _PH_OBJECT_TYPE;
|
||||
typedef struct _PH_OBJECT_TYPE *PPH_OBJECT_TYPE;
|
||||
|
||||
struct _PH_QUEUED_LOCK;
|
||||
typedef struct _PH_QUEUED_LOCK PH_QUEUED_LOCK, *PPH_QUEUED_LOCK;
|
||||
|
||||
#ifdef DEBUG
|
||||
typedef VOID (NTAPI *PPH_CREATE_OBJECT_HOOK)(
|
||||
_In_ PVOID Object,
|
||||
_In_ SIZE_T Size,
|
||||
_In_ ULONG Flags,
|
||||
_In_ PPH_OBJECT_TYPE ObjectType
|
||||
);
|
||||
#endif
|
||||
|
||||
typedef struct _PH_OBJECT_TYPE_PARAMETERS
|
||||
{
|
||||
SIZE_T FreeListSize;
|
||||
ULONG FreeListCount;
|
||||
} PH_OBJECT_TYPE_PARAMETERS, *PPH_OBJECT_TYPE_PARAMETERS;
|
||||
|
||||
typedef struct _PH_OBJECT_TYPE_INFORMATION
|
||||
{
|
||||
PWSTR Name;
|
||||
ULONG NumberOfObjects;
|
||||
USHORT Flags;
|
||||
UCHAR TypeIndex;
|
||||
UCHAR Reserved;
|
||||
} PH_OBJECT_TYPE_INFORMATION, *PPH_OBJECT_TYPE_INFORMATION;
|
||||
|
||||
extern PPH_OBJECT_TYPE PhObjectTypeObject;
|
||||
extern PPH_OBJECT_TYPE PhAllocType;
|
||||
|
||||
#ifdef DEBUG
|
||||
extern LIST_ENTRY PhDbgObjectListHead;
|
||||
extern PH_QUEUED_LOCK PhDbgObjectListLock;
|
||||
extern PPH_CREATE_OBJECT_HOOK PhDbgCreateObjectHook;
|
||||
#endif
|
||||
|
||||
NTSTATUS PhRefInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
_May_raise_
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhCreateObject(
|
||||
_In_ SIZE_T ObjectSize,
|
||||
_In_ PPH_OBJECT_TYPE ObjectType
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhReferenceObject(
|
||||
_In_ PVOID Object
|
||||
);
|
||||
|
||||
_May_raise_
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhReferenceObjectEx(
|
||||
_In_ PVOID Object,
|
||||
_In_ LONG RefCount
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhReferenceObjectSafe(
|
||||
_In_ PVOID Object
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhDereferenceObject(
|
||||
_In_ PVOID Object
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhDereferenceObjectDeferDelete(
|
||||
_In_ PVOID Object
|
||||
);
|
||||
|
||||
_May_raise_
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhDereferenceObjectEx(
|
||||
_In_ PVOID Object,
|
||||
_In_ LONG RefCount,
|
||||
_In_ BOOLEAN DeferDelete
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_OBJECT_TYPE
|
||||
NTAPI
|
||||
PhGetObjectType(
|
||||
_In_ PVOID Object
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_OBJECT_TYPE
|
||||
NTAPI
|
||||
PhCreateObjectType(
|
||||
_In_ PWSTR Name,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ PPH_TYPE_DELETE_PROCEDURE DeleteProcedure
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_OBJECT_TYPE
|
||||
NTAPI
|
||||
PhCreateObjectTypeEx(
|
||||
_In_ PWSTR Name,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ PPH_TYPE_DELETE_PROCEDURE DeleteProcedure,
|
||||
_In_opt_ PPH_OBJECT_TYPE_PARAMETERS Parameters
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhGetObjectTypeInformation(
|
||||
_In_ PPH_OBJECT_TYPE ObjectType,
|
||||
_Out_ PPH_OBJECT_TYPE_INFORMATION Information
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhCreateAlloc(
|
||||
_In_ SIZE_T Size
|
||||
);
|
||||
|
||||
// Object reference functions
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhSwapReference(
|
||||
_Inout_ PVOID *ObjectReference,
|
||||
_In_opt_ PVOID NewObject
|
||||
)
|
||||
{
|
||||
PVOID oldObject;
|
||||
|
||||
oldObject = *ObjectReference;
|
||||
*ObjectReference = NewObject;
|
||||
|
||||
if (NewObject) PhReferenceObject(NewObject);
|
||||
if (oldObject) PhDereferenceObject(oldObject);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhMoveReference(
|
||||
_Inout_ PVOID *ObjectReference,
|
||||
_In_opt_ _Assume_refs_(1) PVOID NewObject
|
||||
)
|
||||
{
|
||||
PVOID oldObject;
|
||||
|
||||
oldObject = *ObjectReference;
|
||||
*ObjectReference = NewObject;
|
||||
|
||||
if (oldObject) PhDereferenceObject(oldObject);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhSetReference(
|
||||
_Out_ PVOID *ObjectReference,
|
||||
_In_opt_ PVOID NewObject
|
||||
)
|
||||
{
|
||||
*ObjectReference = NewObject;
|
||||
|
||||
if (NewObject) PhReferenceObject(NewObject);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
PhClearReference(
|
||||
_Inout_ PVOID *ObjectReference
|
||||
)
|
||||
{
|
||||
PhMoveReference(ObjectReference, NULL);
|
||||
}
|
||||
|
||||
// Auto-dereference pool
|
||||
|
||||
/** The size of the static array in an auto-release pool. */
|
||||
#define PH_AUTO_POOL_STATIC_SIZE 64
|
||||
/** The maximum size of the dynamic array for it to be kept after the auto-release pool is drained. */
|
||||
#define PH_AUTO_POOL_DYNAMIC_BIG_SIZE 256
|
||||
|
||||
/**
|
||||
* An auto-dereference pool can be used for semi-automatic reference counting. Batches of objects
|
||||
* are dereferenced at a certain time.
|
||||
*
|
||||
* This object is not thread-safe and cannot be used across thread boundaries. Always store them as
|
||||
* local variables.
|
||||
*/
|
||||
typedef struct _PH_AUTO_POOL
|
||||
{
|
||||
ULONG StaticCount;
|
||||
PVOID StaticObjects[PH_AUTO_POOL_STATIC_SIZE];
|
||||
|
||||
ULONG DynamicCount;
|
||||
ULONG DynamicAllocated;
|
||||
PVOID *DynamicObjects;
|
||||
|
||||
struct _PH_AUTO_POOL *NextPool;
|
||||
} PH_AUTO_POOL, *PPH_AUTO_POOL;
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhInitializeAutoPool(
|
||||
_Out_ PPH_AUTO_POOL AutoPool
|
||||
);
|
||||
|
||||
_May_raise_
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhDeleteAutoPool(
|
||||
_Inout_ PPH_AUTO_POOL AutoPool
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhDrainAutoPool(
|
||||
_In_ PPH_AUTO_POOL AutoPool
|
||||
);
|
||||
|
||||
_May_raise_
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhAutoDereferenceObject(
|
||||
_In_opt_ PVOID Object
|
||||
);
|
||||
|
||||
#define PH_AUTO PhAutoDereferenceObject
|
||||
#define PH_AUTO_T(Type, Object) ((Type *)PH_AUTO(Object))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
175
phlib/include/refp.h
Normal file
175
phlib/include/refp.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* internal object manager
|
||||
*
|
||||
* Copyright (C) 2009-2016 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PH_REFP_H
|
||||
#define _PH_REFP_H
|
||||
|
||||
#define PH_OBJECT_TYPE_TABLE_SIZE 256
|
||||
|
||||
/** The object was allocated from the small free list. */
|
||||
#define PH_OBJECT_FROM_SMALL_FREE_LIST 0x1
|
||||
/** The object was allocated from the type free list. */
|
||||
#define PH_OBJECT_FROM_TYPE_FREE_LIST 0x2
|
||||
|
||||
/**
|
||||
* The object header contains object manager information including the reference count of an object
|
||||
* and its type.
|
||||
*/
|
||||
typedef struct _PH_OBJECT_HEADER
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
USHORT TypeIndex;
|
||||
UCHAR Flags;
|
||||
UCHAR Reserved1;
|
||||
#ifdef _WIN64
|
||||
ULONG Reserved2;
|
||||
#endif
|
||||
union
|
||||
{
|
||||
LONG RefCount;
|
||||
struct
|
||||
{
|
||||
LONG SavedTypeIndex : 16;
|
||||
LONG SavedFlags : 8;
|
||||
LONG Reserved : 7;
|
||||
LONG DeferDelete : 1; // MUST be the high bit, so that RefCount < 0 when deferring delete
|
||||
};
|
||||
};
|
||||
#ifdef _WIN64
|
||||
ULONG Reserved3;
|
||||
#endif
|
||||
};
|
||||
SLIST_ENTRY DeferDeleteListEntry;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
PVOID StackBackTrace[16];
|
||||
LIST_ENTRY ObjectListEntry;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The body of the object. For use by the \ref PhObjectToObjectHeader and
|
||||
* \ref PhObjectHeaderToObject macros.
|
||||
*/
|
||||
QUAD_PTR Body;
|
||||
} PH_OBJECT_HEADER, *PPH_OBJECT_HEADER;
|
||||
|
||||
#ifndef DEBUG
|
||||
#ifdef _WIN64
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, TypeIndex) == 0x0);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, Flags) == 0x2);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, Reserved1) == 0x3);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, Reserved2) == 0x4);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, RefCount) == 0x8);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, Reserved3) == 0xc);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, DeferDeleteListEntry) == 0x0);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, Body) == 0x10);
|
||||
#else
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, TypeIndex) == 0x0);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, Flags) == 0x2);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, Reserved1) == 0x3);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, RefCount) == 0x4);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, DeferDeleteListEntry) == 0x0);
|
||||
C_ASSERT(FIELD_OFFSET(PH_OBJECT_HEADER, Body) == 0x8);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gets a pointer to the object header for an object.
|
||||
*
|
||||
* \param Object A pointer to an object.
|
||||
*
|
||||
* \return A pointer to the object header of the object.
|
||||
*/
|
||||
#define PhObjectToObjectHeader(Object) ((PPH_OBJECT_HEADER)CONTAINING_RECORD((PCHAR)(Object), PH_OBJECT_HEADER, Body))
|
||||
|
||||
/**
|
||||
* Gets a pointer to an object from an object header.
|
||||
*
|
||||
* \param ObjectHeader A pointer to an object header.
|
||||
*
|
||||
* \return A pointer to an object.
|
||||
*/
|
||||
#define PhObjectHeaderToObject(ObjectHeader) ((PVOID)&((PPH_OBJECT_HEADER)(ObjectHeader))->Body)
|
||||
|
||||
/**
|
||||
* Calculates the total size to allocate for an object.
|
||||
*
|
||||
* \param Size The size of the object to allocate.
|
||||
*
|
||||
* \return The new size, including space for the object header.
|
||||
*/
|
||||
#define PhAddObjectHeaderSize(Size) ((Size) + FIELD_OFFSET(PH_OBJECT_HEADER, Body))
|
||||
|
||||
/** An object type specifies a kind of object and its delete procedure. */
|
||||
typedef struct _PH_OBJECT_TYPE
|
||||
{
|
||||
/** The flags that were used to create the object type. */
|
||||
USHORT Flags;
|
||||
UCHAR TypeIndex;
|
||||
UCHAR Reserved;
|
||||
/** The total number of objects of this type that are alive. */
|
||||
ULONG NumberOfObjects;
|
||||
/** An optional procedure called when objects of this type are freed. */
|
||||
PPH_TYPE_DELETE_PROCEDURE DeleteProcedure;
|
||||
/** The name of the type. */
|
||||
PWSTR Name;
|
||||
/** A free list to use when allocating for this type. */
|
||||
PH_FREE_LIST FreeList;
|
||||
} PH_OBJECT_TYPE, *PPH_OBJECT_TYPE;
|
||||
|
||||
/**
|
||||
* Increments a reference count, but will never increment from a nonpositive value to 1.
|
||||
*
|
||||
* \param RefCount A pointer to a reference count.
|
||||
*/
|
||||
FORCEINLINE
|
||||
BOOLEAN
|
||||
PhpInterlockedIncrementSafe(
|
||||
_Inout_ PLONG RefCount
|
||||
)
|
||||
{
|
||||
/* Here we will attempt to increment the reference count, making sure that it is positive. */
|
||||
return _InterlockedIncrementPositive(RefCount);
|
||||
}
|
||||
|
||||
PPH_OBJECT_HEADER PhpAllocateObject(
|
||||
_In_ PPH_OBJECT_TYPE ObjectType,
|
||||
_In_ SIZE_T ObjectSize
|
||||
);
|
||||
|
||||
VOID PhpFreeObject(
|
||||
_In_ PPH_OBJECT_HEADER ObjectHeader
|
||||
);
|
||||
|
||||
VOID PhpDeferDeleteObject(
|
||||
_In_ PPH_OBJECT_HEADER ObjectHeader
|
||||
);
|
||||
|
||||
NTSTATUS PhpDeferDeleteObjectRoutine(
|
||||
_In_ PVOID Parameter
|
||||
);
|
||||
|
||||
#endif
|
||||
163
phlib/include/secedit.h
Normal file
163
phlib/include/secedit.h
Normal file
@@ -0,0 +1,163 @@
|
||||
#ifndef _PH_SECEDIT_H
|
||||
#define _PH_SECEDIT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// secedit
|
||||
|
||||
typedef struct _PH_ACCESS_ENTRY
|
||||
{
|
||||
PWSTR Name;
|
||||
ACCESS_MASK Access;
|
||||
BOOLEAN General;
|
||||
BOOLEAN Specific;
|
||||
PWSTR ShortName;
|
||||
} PH_ACCESS_ENTRY, *PPH_ACCESS_ENTRY;
|
||||
|
||||
PHLIBAPI
|
||||
HPROPSHEETPAGE
|
||||
NTAPI
|
||||
PhCreateSecurityPage(
|
||||
_In_ PWSTR ObjectName,
|
||||
_In_ PPH_GET_OBJECT_SECURITY GetObjectSecurity,
|
||||
_In_ PPH_SET_OBJECT_SECURITY SetObjectSecurity,
|
||||
_In_opt_ PVOID Context,
|
||||
_In_ PPH_ACCESS_ENTRY AccessEntries,
|
||||
_In_ ULONG NumberOfAccessEntries
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhEditSecurity(
|
||||
_In_ HWND hWnd,
|
||||
_In_ PWSTR ObjectName,
|
||||
_In_ PPH_GET_OBJECT_SECURITY GetObjectSecurity,
|
||||
_In_ PPH_SET_OBJECT_SECURITY SetObjectSecurity,
|
||||
_In_opt_ PVOID Context,
|
||||
_In_ PPH_ACCESS_ENTRY AccessEntries,
|
||||
_In_ ULONG NumberOfAccessEntries
|
||||
);
|
||||
|
||||
typedef struct _PH_STD_OBJECT_SECURITY
|
||||
{
|
||||
PPH_OPEN_OBJECT OpenObject;
|
||||
PWSTR ObjectType;
|
||||
PVOID Context;
|
||||
} PH_STD_OBJECT_SECURITY, *PPH_STD_OBJECT_SECURITY;
|
||||
|
||||
FORCEINLINE ACCESS_MASK PhGetAccessForGetSecurity(
|
||||
_In_ SECURITY_INFORMATION SecurityInformation
|
||||
)
|
||||
{
|
||||
ACCESS_MASK access = 0;
|
||||
|
||||
if (
|
||||
(SecurityInformation & OWNER_SECURITY_INFORMATION) ||
|
||||
(SecurityInformation & GROUP_SECURITY_INFORMATION) ||
|
||||
(SecurityInformation & DACL_SECURITY_INFORMATION)
|
||||
)
|
||||
{
|
||||
access |= READ_CONTROL;
|
||||
}
|
||||
|
||||
if (SecurityInformation & SACL_SECURITY_INFORMATION)
|
||||
{
|
||||
access |= ACCESS_SYSTEM_SECURITY;
|
||||
}
|
||||
|
||||
return access;
|
||||
}
|
||||
|
||||
FORCEINLINE ACCESS_MASK PhGetAccessForSetSecurity(
|
||||
_In_ SECURITY_INFORMATION SecurityInformation
|
||||
)
|
||||
{
|
||||
ACCESS_MASK access = 0;
|
||||
|
||||
if (
|
||||
(SecurityInformation & OWNER_SECURITY_INFORMATION) ||
|
||||
(SecurityInformation & GROUP_SECURITY_INFORMATION)
|
||||
)
|
||||
{
|
||||
access |= WRITE_OWNER;
|
||||
}
|
||||
|
||||
if (SecurityInformation & DACL_SECURITY_INFORMATION)
|
||||
{
|
||||
access |= WRITE_DAC;
|
||||
}
|
||||
|
||||
if (SecurityInformation & SACL_SECURITY_INFORMATION)
|
||||
{
|
||||
access |= ACCESS_SYSTEM_SECURITY;
|
||||
}
|
||||
|
||||
return access;
|
||||
}
|
||||
|
||||
PHLIBAPI
|
||||
_Callback_ NTSTATUS
|
||||
NTAPI
|
||||
PhStdGetObjectSecurity(
|
||||
_Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
_Callback_ NTSTATUS
|
||||
NTAPI
|
||||
PhStdSetObjectSecurity(
|
||||
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetSeObjectSecurity(
|
||||
_In_ HANDLE Handle,
|
||||
_In_ ULONG ObjectType,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhSetSeObjectSecurity(
|
||||
_In_ HANDLE Handle,
|
||||
_In_ ULONG ObjectType,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor
|
||||
);
|
||||
|
||||
// secdata
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhGetAccessEntries(
|
||||
_In_ PWSTR Type,
|
||||
_Out_ PPH_ACCESS_ENTRY *AccessEntries,
|
||||
_Out_ PULONG NumberOfAccessEntries
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING
|
||||
NTAPI
|
||||
PhGetAccessString(
|
||||
_In_ ACCESS_MASK Access,
|
||||
_In_ PPH_ACCESS_ENTRY AccessEntries,
|
||||
_In_ ULONG NumberOfAccessEntries
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
100
phlib/include/seceditp.h
Normal file
100
phlib/include/seceditp.h
Normal file
@@ -0,0 +1,100 @@
|
||||
#ifndef _PH_SECEDITP_H
|
||||
#define _PH_SECEDITP_H
|
||||
|
||||
#include <aclui.h>
|
||||
#include <aclapi.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISecurityInformationVtbl *VTable;
|
||||
|
||||
ULONG RefCount;
|
||||
|
||||
PPH_STRING ObjectName;
|
||||
PPH_GET_OBJECT_SECURITY GetObjectSecurity;
|
||||
PPH_SET_OBJECT_SECURITY SetObjectSecurity;
|
||||
PVOID Context;
|
||||
PSI_ACCESS AccessEntries;
|
||||
ULONG NumberOfAccessEntries;
|
||||
} PhSecurityInformation;
|
||||
|
||||
ISecurityInformation *PhSecurityInformation_Create(
|
||||
_In_ PWSTR ObjectName,
|
||||
_In_ PPH_GET_OBJECT_SECURITY GetObjectSecurity,
|
||||
_In_ PPH_SET_OBJECT_SECURITY SetObjectSecurity,
|
||||
_In_opt_ PVOID Context,
|
||||
_In_ PPH_ACCESS_ENTRY AccessEntries,
|
||||
_In_ ULONG NumberOfAccessEntries
|
||||
);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_QueryInterface(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ REFIID Riid,
|
||||
_Out_ PVOID *Object
|
||||
);
|
||||
|
||||
ULONG STDMETHODCALLTYPE PhSecurityInformation_AddRef(
|
||||
_In_ ISecurityInformation *This
|
||||
);
|
||||
|
||||
ULONG STDMETHODCALLTYPE PhSecurityInformation_Release(
|
||||
_In_ ISecurityInformation *This
|
||||
);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetObjectInformation(
|
||||
_In_ ISecurityInformation *This,
|
||||
_Out_ PSI_OBJECT_INFO ObjectInfo
|
||||
);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetSecurity(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ SECURITY_INFORMATION RequestedInformation,
|
||||
_Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor,
|
||||
_In_ BOOL Default
|
||||
);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_SetSecurity(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor
|
||||
);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetAccessRights(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ const GUID *ObjectType,
|
||||
_In_ ULONG Flags,
|
||||
_Out_ PSI_ACCESS *Access,
|
||||
_Out_ PULONG Accesses,
|
||||
_Out_ PULONG DefaultAccess
|
||||
);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_MapGeneric(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ const GUID *ObjectType,
|
||||
_In_ PUCHAR AceFlags,
|
||||
_Inout_ PACCESS_MASK Mask
|
||||
);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetInheritTypes(
|
||||
_In_ ISecurityInformation *This,
|
||||
_Out_ PSI_INHERIT_TYPE *InheritTypes,
|
||||
_Out_ PULONG InheritTypesCount
|
||||
);
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_PropertySheetPageCallback(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ SI_PAGE_TYPE uPage
|
||||
);
|
||||
|
||||
typedef HPROPSHEETPAGE (WINAPI *_CreateSecurityPage)(
|
||||
_In_ LPSECURITYINFO psi
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_EditSecurity)(
|
||||
_In_ HWND hwndOwner,
|
||||
_In_ LPSECURITYINFO psi
|
||||
);
|
||||
|
||||
#endif
|
||||
146
phlib/include/svcsup.h
Normal file
146
phlib/include/svcsup.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#ifndef _PH_SVCSUP_H
|
||||
#define _PH_SVCSUP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern WCHAR *PhServiceTypeStrings[10];
|
||||
extern WCHAR *PhServiceStartTypeStrings[5];
|
||||
extern WCHAR *PhServiceErrorControlStrings[4];
|
||||
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhEnumServices(
|
||||
_In_ SC_HANDLE ScManagerHandle,
|
||||
_In_opt_ ULONG Type,
|
||||
_In_opt_ ULONG State,
|
||||
_Out_ PULONG Count
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
SC_HANDLE
|
||||
NTAPI
|
||||
PhOpenService(
|
||||
_In_ PWSTR ServiceName,
|
||||
_In_ ACCESS_MASK DesiredAccess
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhGetServiceConfig(
|
||||
_In_ SC_HANDLE ServiceHandle
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
NTAPI
|
||||
PhQueryServiceVariableSize(
|
||||
_In_ SC_HANDLE ServiceHandle,
|
||||
_In_ ULONG InfoLevel
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING
|
||||
NTAPI
|
||||
PhGetServiceDescription(
|
||||
_In_ SC_HANDLE ServiceHandle
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhGetServiceDelayedAutoStart(
|
||||
_In_ SC_HANDLE ServiceHandle,
|
||||
_Out_ PBOOLEAN DelayedAutoStart
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhSetServiceDelayedAutoStart(
|
||||
_In_ SC_HANDLE ServiceHandle,
|
||||
_In_ BOOLEAN DelayedAutoStart
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PWSTR
|
||||
NTAPI
|
||||
PhGetServiceStateString(
|
||||
_In_ ULONG ServiceState
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PWSTR
|
||||
NTAPI
|
||||
PhGetServiceTypeString(
|
||||
_In_ ULONG ServiceType
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
PhGetServiceTypeInteger(
|
||||
_In_ PWSTR ServiceType
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PWSTR
|
||||
NTAPI
|
||||
PhGetServiceStartTypeString(
|
||||
_In_ ULONG ServiceStartType
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
PhGetServiceStartTypeInteger(
|
||||
_In_ PWSTR ServiceStartType
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PWSTR
|
||||
NTAPI
|
||||
PhGetServiceErrorControlString(
|
||||
_In_ ULONG ServiceErrorControl
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
PhGetServiceErrorControlInteger(
|
||||
_In_ PWSTR ServiceErrorControl
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING
|
||||
NTAPI
|
||||
PhGetServiceNameFromTag(
|
||||
_In_ HANDLE ProcessId,
|
||||
_In_ PVOID ServiceTag
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetThreadServiceTag(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_In_opt_ HANDLE ProcessHandle,
|
||||
_Out_ PVOID *ServiceTag
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhGetServiceDllParameter(
|
||||
_In_ PPH_STRINGREF ServiceName,
|
||||
_Out_ PPH_STRING *ServiceDll
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
303
phlib/include/symprv.h
Normal file
303
phlib/include/symprv.h
Normal file
@@ -0,0 +1,303 @@
|
||||
#ifndef _PH_SYMPRV_H
|
||||
#define _PH_SYMPRV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern PPH_OBJECT_TYPE PhSymbolProviderType;
|
||||
extern PH_CALLBACK PhSymInitCallback;
|
||||
|
||||
#define PH_MAX_SYMBOL_NAME_LEN 128
|
||||
|
||||
typedef struct _PH_SYMBOL_PROVIDER
|
||||
{
|
||||
LIST_ENTRY ModulesListHead;
|
||||
PH_QUEUED_LOCK ModulesListLock;
|
||||
HANDLE ProcessHandle;
|
||||
BOOLEAN IsRealHandle;
|
||||
BOOLEAN IsRegistered;
|
||||
|
||||
PH_INITONCE InitOnce;
|
||||
PH_AVL_TREE ModulesSet;
|
||||
PH_CALLBACK EventCallback;
|
||||
} PH_SYMBOL_PROVIDER, *PPH_SYMBOL_PROVIDER;
|
||||
|
||||
typedef enum _PH_SYMBOL_RESOLVE_LEVEL
|
||||
{
|
||||
PhsrlFunction,
|
||||
PhsrlModule,
|
||||
PhsrlAddress,
|
||||
PhsrlInvalid
|
||||
} PH_SYMBOL_RESOLVE_LEVEL, *PPH_SYMBOL_RESOLVE_LEVEL;
|
||||
|
||||
typedef struct _PH_SYMBOL_INFORMATION
|
||||
{
|
||||
ULONG64 Address;
|
||||
ULONG64 ModuleBase;
|
||||
ULONG Index;
|
||||
ULONG Size;
|
||||
} PH_SYMBOL_INFORMATION, *PPH_SYMBOL_INFORMATION;
|
||||
|
||||
typedef struct _PH_SYMBOL_LINE_INFORMATION
|
||||
{
|
||||
ULONG LineNumber;
|
||||
ULONG64 Address;
|
||||
} PH_SYMBOL_LINE_INFORMATION, *PPH_SYMBOL_LINE_INFORMATION;
|
||||
|
||||
typedef enum _PH_SYMBOL_EVENT_TYPE
|
||||
{
|
||||
SymbolDeferredSymbolLoadStart = 1,
|
||||
SymbolDeferredSymbolLoadComplete = 2,
|
||||
SymbolDeferredSymbolLoadFailure = 3,
|
||||
SymbolSymbolsUnloaded = 4,
|
||||
SymbolDeferredSymbolLoadCancel = 7
|
||||
} PH_SYMBOL_EVENT_TYPE;
|
||||
|
||||
typedef struct _PH_SYMBOL_EVENT_DATA
|
||||
{
|
||||
PPH_SYMBOL_PROVIDER SymbolProvider;
|
||||
PH_SYMBOL_EVENT_TYPE Type;
|
||||
|
||||
ULONG64 BaseAddress;
|
||||
ULONG CheckSum;
|
||||
ULONG TimeStamp;
|
||||
PPH_STRING FileName;
|
||||
} PH_SYMBOL_EVENT_DATA, *PPH_SYMBOL_EVENT_DATA;
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhSymbolProviderInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhSymbolProviderCompleteInitialization(
|
||||
_In_opt_ PVOID DbgHelpBase
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_SYMBOL_PROVIDER
|
||||
NTAPI
|
||||
PhCreateSymbolProvider(
|
||||
_In_opt_ HANDLE ProcessId
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhGetLineFromAddress(
|
||||
_In_ PPH_SYMBOL_PROVIDER SymbolProvider,
|
||||
_In_ ULONG64 Address,
|
||||
_Out_ PPH_STRING *FileName,
|
||||
_Out_opt_ PULONG Displacement,
|
||||
_Out_opt_ PPH_SYMBOL_LINE_INFORMATION Information
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
ULONG64
|
||||
NTAPI
|
||||
PhGetModuleFromAddress(
|
||||
_In_ PPH_SYMBOL_PROVIDER SymbolProvider,
|
||||
_In_ ULONG64 Address,
|
||||
_Out_opt_ PPH_STRING *FileName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING
|
||||
NTAPI
|
||||
PhGetSymbolFromAddress(
|
||||
_In_ PPH_SYMBOL_PROVIDER SymbolProvider,
|
||||
_In_ ULONG64 Address,
|
||||
_Out_opt_ PPH_SYMBOL_RESOLVE_LEVEL ResolveLevel,
|
||||
_Out_opt_ PPH_STRING *FileName,
|
||||
_Out_opt_ PPH_STRING *SymbolName,
|
||||
_Out_opt_ PULONG64 Displacement
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhGetSymbolFromName(
|
||||
_In_ PPH_SYMBOL_PROVIDER SymbolProvider,
|
||||
_In_ PWSTR Name,
|
||||
_Out_ PPH_SYMBOL_INFORMATION Information
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhLoadModuleSymbolProvider(
|
||||
_In_ PPH_SYMBOL_PROVIDER SymbolProvider,
|
||||
_In_ PWSTR FileName,
|
||||
_In_ ULONG64 BaseAddress,
|
||||
_In_ ULONG Size
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhSetOptionsSymbolProvider(
|
||||
_In_ ULONG Mask,
|
||||
_In_ ULONG Value
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhSetSearchPathSymbolProvider(
|
||||
_In_ PPH_SYMBOL_PROVIDER SymbolProvider,
|
||||
_In_ PWSTR Path
|
||||
);
|
||||
|
||||
#ifdef _WIN64
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhAccessOutOfProcessFunctionEntry(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ ULONG64 ControlPc,
|
||||
_Out_ PRUNTIME_FUNCTION Function
|
||||
);
|
||||
#endif
|
||||
|
||||
PHLIBAPI
|
||||
ULONG64
|
||||
__stdcall
|
||||
PhGetModuleBase64(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 dwAddr
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PVOID
|
||||
__stdcall
|
||||
PhFunctionTableAccess64(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 AddrBase
|
||||
);
|
||||
|
||||
#ifndef _DBGHELP_
|
||||
|
||||
// Some of the types used below are defined in dbghelp.h.
|
||||
|
||||
typedef struct _tagSTACKFRAME64 *LPSTACKFRAME64;
|
||||
typedef struct _tagADDRESS64 *LPADDRESS64;
|
||||
|
||||
typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 qwBaseAddress,
|
||||
_Out_writes_bytes_(nSize) PVOID lpBuffer,
|
||||
_In_ DWORD nSize,
|
||||
_Out_ LPDWORD lpNumberOfBytesRead
|
||||
);
|
||||
|
||||
typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)(
|
||||
_In_ HANDLE ahProcess,
|
||||
_In_ DWORD64 AddrBase
|
||||
);
|
||||
|
||||
typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 Address
|
||||
);
|
||||
|
||||
typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ HANDLE hThread,
|
||||
_In_ LPADDRESS64 lpaddr
|
||||
);
|
||||
|
||||
typedef enum _MINIDUMP_TYPE MINIDUMP_TYPE;
|
||||
typedef struct _MINIDUMP_EXCEPTION_INFORMATION *PMINIDUMP_EXCEPTION_INFORMATION;
|
||||
typedef struct _MINIDUMP_USER_STREAM_INFORMATION *PMINIDUMP_USER_STREAM_INFORMATION;
|
||||
typedef struct _MINIDUMP_CALLBACK_INFORMATION *PMINIDUMP_CALLBACK_INFORMATION;
|
||||
|
||||
#endif
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhStackWalk(
|
||||
_In_ ULONG MachineType,
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_Inout_ LPSTACKFRAME64 StackFrame,
|
||||
_Inout_ PVOID ContextRecord,
|
||||
_In_opt_ PPH_SYMBOL_PROVIDER SymbolProvider,
|
||||
_In_opt_ PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
|
||||
_In_opt_ PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
|
||||
_In_opt_ PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
|
||||
_In_opt_ PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
PhWriteMiniDumpProcess(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ HANDLE ProcessId,
|
||||
_In_ HANDLE FileHandle,
|
||||
_In_ MINIDUMP_TYPE DumpType,
|
||||
_In_opt_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
_In_opt_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||
_In_opt_ PMINIDUMP_CALLBACK_INFORMATION CallbackParam
|
||||
);
|
||||
|
||||
// High-level stack walking
|
||||
|
||||
#define PH_THREAD_STACK_FRAME_I386 0x1
|
||||
#define PH_THREAD_STACK_FRAME_AMD64 0x2
|
||||
#define PH_THREAD_STACK_FRAME_KERNEL 0x4
|
||||
#define PH_THREAD_STACK_FRAME_FPO_DATA_PRESENT 0x100
|
||||
|
||||
/** Contains information about a thread stack frame. */
|
||||
typedef struct _PH_THREAD_STACK_FRAME
|
||||
{
|
||||
PVOID PcAddress;
|
||||
PVOID ReturnAddress;
|
||||
PVOID FrameAddress;
|
||||
PVOID StackAddress;
|
||||
PVOID BStoreAddress;
|
||||
PVOID Params[4];
|
||||
ULONG Flags;
|
||||
} PH_THREAD_STACK_FRAME, *PPH_THREAD_STACK_FRAME;
|
||||
|
||||
#define PH_WALK_I386_STACK 0x1
|
||||
#define PH_WALK_AMD64_STACK 0x2
|
||||
#define PH_WALK_KERNEL_STACK 0x10
|
||||
|
||||
/**
|
||||
* A callback function passed to PhWalkThreadStack() and called for each stack frame.
|
||||
*
|
||||
* \param StackFrame A structure providing information about the stack frame.
|
||||
* \param Context A user-defined value passed to PhWalkThreadStack().
|
||||
*
|
||||
* \return TRUE to continue the stack walk, FALSE to stop.
|
||||
*/
|
||||
typedef BOOLEAN (NTAPI *PPH_WALK_THREAD_STACK_CALLBACK)(
|
||||
_In_ PPH_THREAD_STACK_FRAME StackFrame,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhWalkThreadStack(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_In_opt_ HANDLE ProcessHandle,
|
||||
_In_opt_ PCLIENT_ID ClientId,
|
||||
_In_opt_ PPH_SYMBOL_PROVIDER SymbolProvider,
|
||||
_In_ ULONG Flags,
|
||||
_In_ PPH_WALK_THREAD_STACK_CALLBACK Callback,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
170
phlib/include/symprvp.h
Normal file
170
phlib/include/symprvp.h
Normal file
@@ -0,0 +1,170 @@
|
||||
#ifndef _PH_SYMPRVP_H
|
||||
#define _PH_SYMPRVP_H
|
||||
|
||||
typedef BOOL (WINAPI *_SymInitialize)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_opt_ PCSTR UserSearchPath,
|
||||
_In_ BOOL fInvadeProcess
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymCleanup)(
|
||||
_In_ HANDLE hProcess
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymEnumSymbols)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ ULONG64 BaseOfDll,
|
||||
_In_opt_ PCSTR Mask,
|
||||
_In_ PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
|
||||
_In_opt_ const PVOID UserContext
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymEnumSymbolsW)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ ULONG64 BaseOfDll,
|
||||
_In_opt_ PCWSTR Mask,
|
||||
_In_ PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,
|
||||
_In_opt_ const PVOID UserContext
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymFromAddr)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 Address,
|
||||
_Out_opt_ PDWORD64 Displacement,
|
||||
_Inout_ PSYMBOL_INFO Symbol
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymFromAddrW)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 Address,
|
||||
_Out_opt_ PDWORD64 Displacement,
|
||||
_Inout_ PSYMBOL_INFOW Symbol
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymFromName)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ PCSTR Name,
|
||||
_Inout_ PSYMBOL_INFO Symbol
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymFromNameW)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ PCWSTR Name,
|
||||
_Inout_ PSYMBOL_INFOW Symbol
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymGetLineFromAddr64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 dwAddr,
|
||||
_Out_ PDWORD pdwDisplacement,
|
||||
_Out_ PIMAGEHLP_LINE64 Line
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymGetLineFromAddrW64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 dwAddr,
|
||||
_Out_ PDWORD pdwDisplacement,
|
||||
_Out_ PIMAGEHLP_LINEW64 Line
|
||||
);
|
||||
|
||||
typedef DWORD64 (WINAPI *_SymLoadModule64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_opt_ HANDLE hFile,
|
||||
_In_opt_ PCSTR ImageName,
|
||||
_In_opt_ PCSTR ModuleName,
|
||||
_In_ DWORD64 BaseOfDll,
|
||||
_In_ DWORD SizeOfDll
|
||||
);
|
||||
|
||||
typedef DWORD64 (WINAPI *_SymLoadModuleExW)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ HANDLE hFile,
|
||||
_In_ PCWSTR ImageName,
|
||||
_In_ PCWSTR ModuleName,
|
||||
_In_ DWORD64 BaseOfDll,
|
||||
_In_ DWORD DllSize,
|
||||
_In_ PMODLOAD_DATA Data,
|
||||
_In_ DWORD Flags
|
||||
);
|
||||
|
||||
typedef DWORD (WINAPI *_SymGetOptions)();
|
||||
|
||||
typedef DWORD (WINAPI *_SymSetOptions)(
|
||||
_In_ DWORD SymOptions
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymGetSearchPath)(
|
||||
_In_ HANDLE hProcess,
|
||||
_Out_ PSTR SearchPath,
|
||||
_In_ DWORD SearchPathLength
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymGetSearchPathW)(
|
||||
_In_ HANDLE hProcess,
|
||||
_Out_ PWSTR SearchPath,
|
||||
_In_ DWORD SearchPathLength
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymSetSearchPath)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_opt_ PCSTR SearchPath
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymSetSearchPathW)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_opt_ PCWSTR SearchPath
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymUnloadModule64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 BaseOfDll
|
||||
);
|
||||
|
||||
typedef PVOID (WINAPI *_SymFunctionTableAccess64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 AddrBase
|
||||
);
|
||||
|
||||
typedef DWORD64 (WINAPI *_SymGetModuleBase64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD64 dwAddr
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_SymRegisterCallbackW64)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,
|
||||
_In_ ULONG64 UserContext
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_StackWalk64)(
|
||||
_In_ DWORD MachineType,
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ HANDLE hThread,
|
||||
_Inout_ LPSTACKFRAME64 StackFrame,
|
||||
_Inout_ PVOID ContextRecord,
|
||||
_In_opt_ PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
|
||||
_In_opt_ PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
|
||||
_In_opt_ PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
|
||||
_In_opt_ PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_MiniDumpWriteDump)(
|
||||
_In_ HANDLE hProcess,
|
||||
_In_ DWORD ProcessId,
|
||||
_In_ HANDLE hFile,
|
||||
_In_ MINIDUMP_TYPE DumpType,
|
||||
_In_ PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
_In_ PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||
_In_ PMINIDUMP_CALLBACK_INFORMATION CallbackParam
|
||||
);
|
||||
|
||||
typedef UINT_PTR (CALLBACK *_SymbolServerGetOptions)(
|
||||
VOID
|
||||
);
|
||||
|
||||
typedef BOOL (CALLBACK *_SymbolServerSetOptions)(
|
||||
_In_ UINT_PTR options,
|
||||
_In_ ULONG64 data
|
||||
);
|
||||
|
||||
#endif
|
||||
7
phlib/include/templ.h
Normal file
7
phlib/include/templ.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef _PH_TEMPL_H
|
||||
#define _PH_TEMPL_H
|
||||
|
||||
#define TEMPLATE_(f,T) f##_##T
|
||||
#define T___(f,T) TEMPLATE_(f,T)
|
||||
|
||||
#endif
|
||||
672
phlib/include/treenew.h
Normal file
672
phlib/include/treenew.h
Normal file
@@ -0,0 +1,672 @@
|
||||
#ifndef _PH_TREENEW_H
|
||||
#define _PH_TREENEW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PH_TREENEW_CLASSNAME L"PhTreeNew"
|
||||
|
||||
#define PH_TREENEW_SEARCH_TIMEOUT 1000
|
||||
#define PH_TREENEW_SEARCH_MAXIMUM_LENGTH 1023
|
||||
|
||||
typedef struct _PH_TREENEW_COLUMN
|
||||
{
|
||||
union
|
||||
{
|
||||
ULONG Flags;
|
||||
struct
|
||||
{
|
||||
ULONG Visible : 1;
|
||||
ULONG CustomDraw : 1;
|
||||
ULONG Fixed : 1; // Whether this is the fixed column
|
||||
ULONG SortDescending : 1; // Sort descending on initial click rather than ascending
|
||||
ULONG DpiScaleOnAdd : 1; // Whether to DPI scale the width (only when adding)
|
||||
ULONG SpareFlags : 27;
|
||||
};
|
||||
};
|
||||
ULONG Id;
|
||||
PVOID Context;
|
||||
PWSTR Text;
|
||||
LONG Width;
|
||||
ULONG Alignment;
|
||||
ULONG DisplayIndex; // -1 for fixed column or invalid
|
||||
|
||||
ULONG TextFlags;
|
||||
|
||||
struct
|
||||
{
|
||||
LONG ViewIndex; // Actual index in header control
|
||||
LONG ViewX; // 0 for the fixed column, and an offset from the divider for normal columns
|
||||
} s;
|
||||
} PH_TREENEW_COLUMN, *PPH_TREENEW_COLUMN;
|
||||
|
||||
typedef struct _PH_TREENEW_NODE
|
||||
{
|
||||
union
|
||||
{
|
||||
ULONG Flags;
|
||||
struct
|
||||
{
|
||||
ULONG Visible : 1;
|
||||
ULONG Selected : 1;
|
||||
ULONG Expanded : 1;
|
||||
ULONG UseAutoForeColor : 1;
|
||||
ULONG UseTempBackColor : 1;
|
||||
ULONG Unselectable : 1;
|
||||
ULONG SpareFlags : 26;
|
||||
};
|
||||
};
|
||||
|
||||
COLORREF BackColor;
|
||||
COLORREF ForeColor;
|
||||
COLORREF TempBackColor;
|
||||
HFONT Font;
|
||||
HICON Icon;
|
||||
|
||||
PPH_STRINGREF TextCache;
|
||||
ULONG TextCacheSize;
|
||||
|
||||
ULONG Index; // Index within the flat list
|
||||
ULONG Level; // 0 for root, 1, 2, ...
|
||||
|
||||
struct
|
||||
{
|
||||
union
|
||||
{
|
||||
ULONG Flags2;
|
||||
struct
|
||||
{
|
||||
ULONG IsLeaf : 1;
|
||||
ULONG CachedColorValid : 1;
|
||||
ULONG CachedFontValid : 1;
|
||||
ULONG CachedIconValid : 1;
|
||||
ULONG PlusMinusHot : 1;
|
||||
ULONG SpareFlags2 : 27;
|
||||
};
|
||||
};
|
||||
|
||||
// Temp. drawing data
|
||||
COLORREF DrawBackColor;
|
||||
COLORREF DrawForeColor;
|
||||
} s;
|
||||
} PH_TREENEW_NODE, *PPH_TREENEW_NODE;
|
||||
|
||||
// Styles
|
||||
#define TN_STYLE_ICONS 0x1
|
||||
#define TN_STYLE_DOUBLE_BUFFERED 0x2
|
||||
#define TN_STYLE_NO_DIVIDER 0x4
|
||||
#define TN_STYLE_ANIMATE_DIVIDER 0x8
|
||||
#define TN_STYLE_NO_COLUMN_SORT 0x10
|
||||
#define TN_STYLE_NO_COLUMN_REORDER 0x20
|
||||
#define TN_STYLE_THIN_ROWS 0x40
|
||||
#define TN_STYLE_NO_COLUMN_HEADER 0x80
|
||||
|
||||
// Extended flags
|
||||
#define TN_FLAG_ITEM_DRAG_SELECT 0x1
|
||||
#define TN_FLAG_NO_UNFOLDING_TOOLTIPS 0x2
|
||||
|
||||
// Callback flags
|
||||
#define TN_CACHE 0x1
|
||||
#define TN_AUTO_FORECOLOR 0x1000
|
||||
|
||||
// Column change flags
|
||||
#define TN_COLUMN_CONTEXT 0x1
|
||||
#define TN_COLUMN_TEXT 0x2
|
||||
#define TN_COLUMN_WIDTH 0x4
|
||||
#define TN_COLUMN_ALIGNMENT 0x8
|
||||
#define TN_COLUMN_DISPLAYINDEX 0x10
|
||||
#define TN_COLUMN_TEXTFLAGS 0x20
|
||||
#define TN_COLUMN_FLAG_VISIBLE 0x100000
|
||||
#define TN_COLUMN_FLAG_CUSTOMDRAW 0x200000
|
||||
#define TN_COLUMN_FLAG_FIXED 0x400000
|
||||
#define TN_COLUMN_FLAG_SORTDESCENDING 0x800000
|
||||
#define TN_COLUMN_FLAG_NODPISCALEONADD 0x1000000
|
||||
#define TN_COLUMN_FLAGS 0xfff00000
|
||||
|
||||
// Cache flags
|
||||
#define TN_CACHE_COLOR 0x1
|
||||
#define TN_CACHE_FONT 0x2
|
||||
#define TN_CACHE_ICON 0x4
|
||||
|
||||
// Cell part input flags
|
||||
#define TN_MEASURE_TEXT 0x1
|
||||
|
||||
// Cell part flags
|
||||
#define TN_PART_CELL 0x1
|
||||
#define TN_PART_PLUSMINUS 0x2
|
||||
#define TN_PART_ICON 0x4
|
||||
#define TN_PART_CONTENT 0x8
|
||||
#define TN_PART_TEXT 0x10
|
||||
|
||||
// Hit test input flags
|
||||
#define TN_TEST_COLUMN 0x1
|
||||
#define TN_TEST_SUBITEM 0x2 // requires TN_TEST_COLUMN
|
||||
|
||||
// Hit test flags
|
||||
#define TN_HIT_LEFT 0x1
|
||||
#define TN_HIT_RIGHT 0x2
|
||||
#define TN_HIT_ABOVE 0x4
|
||||
#define TN_HIT_BELOW 0x8
|
||||
#define TN_HIT_ITEM 0x10
|
||||
#define TN_HIT_ITEM_PLUSMINUS 0x20 // requires TN_TEST_SUBITEM
|
||||
#define TN_HIT_ITEM_ICON 0x40 // requires TN_TEST_SUBITEM
|
||||
#define TN_HIT_ITEM_CONTENT 0x80 // requires TN_TEST_SUBITEM
|
||||
#define TN_HIT_DIVIDER 0x100
|
||||
|
||||
// Selection flags
|
||||
#define TN_SELECT_DESELECT 0x1
|
||||
#define TN_SELECT_TOGGLE 0x2
|
||||
#define TN_SELECT_RESET 0x4
|
||||
|
||||
// Auto-size flags
|
||||
#define TN_AUTOSIZE_REMAINING_SPACE 0x1
|
||||
|
||||
typedef struct _PH_TREENEW_CELL_PARTS
|
||||
{
|
||||
ULONG Flags;
|
||||
RECT RowRect;
|
||||
RECT CellRect; // TN_PART_CELL
|
||||
RECT PlusMinusRect; // TN_PART_PLUSMINUS
|
||||
RECT IconRect; // TN_PART_ICON
|
||||
RECT ContentRect; // TN_PART_CONTENT
|
||||
RECT TextRect; // TN_PART_TEXT
|
||||
PH_STRINGREF Text; // TN_PART_TEXT
|
||||
HFONT Font; // TN_PART_TEXT
|
||||
} PH_TREENEW_CELL_PARTS, *PPH_TREENEW_CELL_PARTS;
|
||||
|
||||
typedef struct _PH_TREENEW_HIT_TEST
|
||||
{
|
||||
POINT Point;
|
||||
ULONG InFlags;
|
||||
|
||||
ULONG Flags;
|
||||
PPH_TREENEW_NODE Node;
|
||||
PPH_TREENEW_COLUMN Column; // requires TN_TEST_COLUMN
|
||||
} PH_TREENEW_HIT_TEST, *PPH_TREENEW_HIT_TEST;
|
||||
|
||||
typedef enum _PH_TREENEW_MESSAGE
|
||||
{
|
||||
TreeNewGetChildren, // PPH_TREENEW_GET_CHILDREN Parameter1
|
||||
TreeNewIsLeaf, // PPH_TREENEW_IS_LEAF Parameter1
|
||||
TreeNewGetCellText, // PPH_TREENEW_GET_CELL_TEXT Parameter1
|
||||
TreeNewGetNodeColor, // PPH_TREENEW_GET_NODE_COLOR Parameter1
|
||||
TreeNewGetNodeFont, // PPH_TREENEW_GET_NODE_FONT Parameter1
|
||||
TreeNewGetNodeIcon, // PPH_TREENEW_GET_NODE_ICON Parameter1
|
||||
TreeNewGetCellTooltip, // PPH_TREENEW_GET_CELL_TOOLTIP Parameter1
|
||||
TreeNewCustomDraw, // PPH_TREENEW_CUSTOM_DRAW Parameter1
|
||||
|
||||
// Notifications
|
||||
TreeNewNodeExpanding, // PPH_TREENEW_NODE Parameter1, PPH_TREENEW_NODE_EVENT Parameter2
|
||||
TreeNewNodeSelecting, // PPH_TREENEW_NODE Parameter1
|
||||
|
||||
TreeNewSortChanged,
|
||||
TreeNewSelectionChanged,
|
||||
|
||||
TreeNewKeyDown, // PPH_TREENEW_KEY_EVENT Parameter1
|
||||
TreeNewLeftClick, // PPH_TREENEW_MOUSE_EVENT Parameter1
|
||||
TreeNewRightClick, // PPH_TREENEW_MOUSE_EVENT Parameter1
|
||||
TreeNewLeftDoubleClick, // PPH_TREENEW_MOUSE_EVENT Parameter1
|
||||
TreeNewRightDoubleClick, // PPH_TREENEW_MOUSE_EVENT Parameter1
|
||||
TreeNewContextMenu, // PPH_TREENEW_CONTEXT_MENU Parameter1
|
||||
|
||||
TreeNewHeaderRightClick, // PPH_TREENEW_HEADER_MOUSE_EVENT Parameter1
|
||||
TreeNewIncrementalSearch, // PPH_TREENEW_SEARCH_EVENT Parameter1
|
||||
|
||||
TreeNewColumnResized, // PPH_TREENEW_COLUMN Parameter1
|
||||
TreeNewColumnReordered,
|
||||
|
||||
TreeNewDestroying,
|
||||
TreeNewGetDialogCode, // ULONG Parameter1, PULONG Parameter2
|
||||
|
||||
MaxTreeNewMessage
|
||||
} PH_TREENEW_MESSAGE;
|
||||
|
||||
typedef BOOLEAN (NTAPI *PPH_TREENEW_CALLBACK)(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PH_TREENEW_MESSAGE Message,
|
||||
_In_opt_ PVOID Parameter1,
|
||||
_In_opt_ PVOID Parameter2,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
typedef struct _PH_TREENEW_GET_CHILDREN
|
||||
{
|
||||
ULONG Flags;
|
||||
PPH_TREENEW_NODE Node;
|
||||
|
||||
ULONG NumberOfChildren;
|
||||
PPH_TREENEW_NODE *Children; // can be NULL if no children
|
||||
} PH_TREENEW_GET_CHILDREN, *PPH_TREENEW_GET_CHILDREN;
|
||||
|
||||
typedef struct _PH_TREENEW_IS_LEAF
|
||||
{
|
||||
ULONG Flags;
|
||||
PPH_TREENEW_NODE Node;
|
||||
|
||||
BOOLEAN IsLeaf;
|
||||
} PH_TREENEW_IS_LEAF, *PPH_TREENEW_IS_LEAF;
|
||||
|
||||
typedef struct _PH_TREENEW_GET_CELL_TEXT
|
||||
{
|
||||
ULONG Flags;
|
||||
PPH_TREENEW_NODE Node;
|
||||
ULONG Id;
|
||||
|
||||
PH_STRINGREF Text;
|
||||
} PH_TREENEW_GET_CELL_TEXT, *PPH_TREENEW_GET_CELL_TEXT;
|
||||
|
||||
typedef struct _PH_TREENEW_GET_NODE_COLOR
|
||||
{
|
||||
ULONG Flags;
|
||||
PPH_TREENEW_NODE Node;
|
||||
|
||||
COLORREF BackColor;
|
||||
COLORREF ForeColor;
|
||||
} PH_TREENEW_GET_NODE_COLOR, *PPH_TREENEW_GET_NODE_COLOR;
|
||||
|
||||
typedef struct _PH_TREENEW_GET_NODE_FONT
|
||||
{
|
||||
ULONG Flags;
|
||||
PPH_TREENEW_NODE Node;
|
||||
|
||||
HFONT Font;
|
||||
} PH_TREENEW_GET_NODE_FONT, *PPH_TREENEW_GET_NODE_FONT;
|
||||
|
||||
typedef struct _PH_TREENEW_GET_NODE_ICON
|
||||
{
|
||||
ULONG Flags;
|
||||
PPH_TREENEW_NODE Node;
|
||||
|
||||
HICON Icon;
|
||||
} PH_TREENEW_GET_NODE_ICON, *PPH_TREENEW_GET_NODE_ICON;
|
||||
|
||||
typedef struct _PH_TREENEW_GET_CELL_TOOLTIP
|
||||
{
|
||||
ULONG Flags;
|
||||
PPH_TREENEW_NODE Node;
|
||||
PPH_TREENEW_COLUMN Column;
|
||||
|
||||
BOOLEAN Unfolding;
|
||||
PH_STRINGREF Text;
|
||||
HFONT Font;
|
||||
ULONG MaximumWidth;
|
||||
} PH_TREENEW_GET_CELL_TOOLTIP, *PPH_TREENEW_GET_CELL_TOOLTIP;
|
||||
|
||||
typedef struct _PH_TREENEW_CUSTOM_DRAW
|
||||
{
|
||||
PPH_TREENEW_NODE Node;
|
||||
PPH_TREENEW_COLUMN Column;
|
||||
|
||||
HDC Dc;
|
||||
RECT CellRect;
|
||||
RECT TextRect;
|
||||
} PH_TREENEW_CUSTOM_DRAW, *PPH_TREENEW_CUSTOM_DRAW;
|
||||
|
||||
typedef struct _PH_TREENEW_MOUSE_EVENT
|
||||
{
|
||||
POINT Location;
|
||||
PPH_TREENEW_NODE Node;
|
||||
PPH_TREENEW_COLUMN Column;
|
||||
ULONG KeyFlags;
|
||||
} PH_TREENEW_MOUSE_EVENT, *PPH_TREENEW_MOUSE_EVENT;
|
||||
|
||||
typedef struct _PH_TREENEW_KEY_EVENT
|
||||
{
|
||||
BOOLEAN Handled;
|
||||
ULONG VirtualKey;
|
||||
ULONG Data;
|
||||
} PH_TREENEW_KEY_EVENT, *PPH_TREENEW_KEY_EVENT;
|
||||
|
||||
typedef struct _PH_TREENEW_NODE_EVENT
|
||||
{
|
||||
BOOLEAN Handled;
|
||||
ULONG Flags;
|
||||
PVOID Reserved1;
|
||||
PVOID Reserved2;
|
||||
} PH_TREENEW_NODE_EVENT, *PPH_TREENEW_NODE_EVENT;
|
||||
|
||||
typedef struct _PH_TREENEW_CONTEXT_MENU
|
||||
{
|
||||
POINT Location;
|
||||
POINT ClientLocation;
|
||||
PPH_TREENEW_NODE Node;
|
||||
PPH_TREENEW_COLUMN Column;
|
||||
BOOLEAN KeyboardInvoked;
|
||||
} PH_TREENEW_CONTEXT_MENU, *PPH_TREENEW_CONTEXT_MENU;
|
||||
|
||||
typedef struct _PH_TREENEW_HEADER_MOUSE_EVENT
|
||||
{
|
||||
POINT ScreenLocation;
|
||||
POINT Location;
|
||||
POINT HeaderLocation;
|
||||
PPH_TREENEW_COLUMN Column;
|
||||
} PH_TREENEW_HEADER_MOUSE_EVENT, *PPH_TREENEW_HEADER_MOUSE_EVENT;
|
||||
|
||||
typedef struct _PH_TREENEW_SEARCH_EVENT
|
||||
{
|
||||
LONG FoundIndex;
|
||||
LONG StartIndex;
|
||||
PH_STRINGREF String;
|
||||
} PH_TREENEW_SEARCH_EVENT, *PPH_TREENEW_SEARCH_EVENT;
|
||||
|
||||
#define TNM_FIRST (WM_USER + 1)
|
||||
#define TNM_SETCALLBACK (WM_USER + 1)
|
||||
#define TNM_NODESADDED (WM_USER + 2) // unimplemented
|
||||
#define TNM_NODESREMOVED (WM_USER + 3) // unimplemented
|
||||
#define TNM_NODESSTRUCTURED (WM_USER + 4)
|
||||
#define TNM_ADDCOLUMN (WM_USER + 5)
|
||||
#define TNM_REMOVECOLUMN (WM_USER + 6)
|
||||
#define TNM_GETCOLUMN (WM_USER + 7)
|
||||
#define TNM_SETCOLUMN (WM_USER + 8)
|
||||
#define TNM_GETCOLUMNORDERARRAY (WM_USER + 9)
|
||||
#define TNM_SETCOLUMNORDERARRAY (WM_USER + 10)
|
||||
#define TNM_SETCURSOR (WM_USER + 11)
|
||||
#define TNM_GETSORT (WM_USER + 12)
|
||||
#define TNM_SETSORT (WM_USER + 13)
|
||||
#define TNM_SETTRISTATE (WM_USER + 14)
|
||||
#define TNM_ENSUREVISIBLE (WM_USER + 15)
|
||||
#define TNM_SCROLL (WM_USER + 16)
|
||||
#define TNM_GETFLATNODECOUNT (WM_USER + 17)
|
||||
#define TNM_GETFLATNODE (WM_USER + 18)
|
||||
#define TNM_GETCELLTEXT (WM_USER + 19)
|
||||
#define TNM_SETNODEEXPANDED (WM_USER + 20)
|
||||
#define TNM_GETMAXID (WM_USER + 21)
|
||||
#define TNM_SETMAXID (WM_USER + 22)
|
||||
#define TNM_INVALIDATENODE (WM_USER + 23)
|
||||
#define TNM_INVALIDATENODES (WM_USER + 24)
|
||||
#define TNM_GETFIXEDHEADER (WM_USER + 25)
|
||||
#define TNM_GETHEADER (WM_USER + 26)
|
||||
#define TNM_GETTOOLTIPS (WM_USER + 27)
|
||||
#define TNM_SELECTRANGE (WM_USER + 28)
|
||||
#define TNM_DESELECTRANGE (WM_USER + 29)
|
||||
#define TNM_GETCOLUMNCOUNT (WM_USER + 30)
|
||||
#define TNM_SETREDRAW (WM_USER + 31)
|
||||
#define TNM_GETVIEWPARTS (WM_USER + 32)
|
||||
#define TNM_GETFIXEDCOLUMN (WM_USER + 33)
|
||||
#define TNM_GETFIRSTCOLUMN (WM_USER + 34)
|
||||
#define TNM_SETFOCUSNODE (WM_USER + 35)
|
||||
#define TNM_SETMARKNODE (WM_USER + 36)
|
||||
#define TNM_SETHOTNODE (WM_USER + 37)
|
||||
#define TNM_SETEXTENDEDFLAGS (WM_USER + 38)
|
||||
#define TNM_GETCALLBACK (WM_USER + 39)
|
||||
#define TNM_HITTEST (WM_USER + 40)
|
||||
#define TNM_GETVISIBLECOLUMNCOUNT (WM_USER + 41)
|
||||
#define TNM_AUTOSIZECOLUMN (WM_USER + 42)
|
||||
#define TNM_SETEMPTYTEXT (WM_USER + 43)
|
||||
#define TNM_SETROWHEIGHT (WM_USER + 44)
|
||||
#define TNM_ISFLATNODEVALID (WM_USER + 45)
|
||||
#define TNM_LAST (WM_USER + 45)
|
||||
|
||||
#define TreeNew_SetCallback(hWnd, Callback, Context) \
|
||||
SendMessage((hWnd), TNM_SETCALLBACK, (WPARAM)(Context), (LPARAM)(Callback))
|
||||
|
||||
#define TreeNew_NodesStructured(hWnd) \
|
||||
SendMessage((hWnd), TNM_NODESSTRUCTURED, 0, 0)
|
||||
|
||||
#define TreeNew_AddColumn(hWnd, Column) \
|
||||
SendMessage((hWnd), TNM_ADDCOLUMN, 0, (LPARAM)(Column))
|
||||
|
||||
#define TreeNew_RemoveColumn(hWnd, Id) \
|
||||
SendMessage((hWnd), TNM_REMOVECOLUMN, (WPARAM)(Id), 0)
|
||||
|
||||
#define TreeNew_GetColumn(hWnd, Id, Column) \
|
||||
SendMessage((hWnd), TNM_GETCOLUMN, (WPARAM)(Id), (LPARAM)(Column))
|
||||
|
||||
#define TreeNew_SetColumn(hWnd, Mask, Column) \
|
||||
SendMessage((hWnd), TNM_SETCOLUMN, (WPARAM)(Mask), (LPARAM)(Column))
|
||||
|
||||
#define TreeNew_GetColumnOrderArray(hWnd, Count, Array) \
|
||||
SendMessage((hWnd), TNM_GETCOLUMNORDERARRAY, (WPARAM)(Count), (LPARAM)(Array))
|
||||
|
||||
#define TreeNew_SetColumnOrderArray(hWnd, Count, Array) \
|
||||
SendMessage((hWnd), TNM_SETCOLUMNORDERARRAY, (WPARAM)(Count), (LPARAM)(Array))
|
||||
|
||||
#define TreeNew_SetCursor(hWnd, Cursor) \
|
||||
SendMessage((hWnd), TNM_SETCURSOR, 0, (LPARAM)(Cursor))
|
||||
|
||||
#define TreeNew_GetSort(hWnd, Column, Order) \
|
||||
SendMessage((hWnd), TNM_GETSORT, (WPARAM)(Column), (LPARAM)(Order))
|
||||
|
||||
#define TreeNew_SetSort(hWnd, Column, Order) \
|
||||
SendMessage((hWnd), TNM_SETSORT, (WPARAM)(Column), (LPARAM)(Order))
|
||||
|
||||
#define TreeNew_SetTriState(hWnd, TriState) \
|
||||
SendMessage((hWnd), TNM_SETTRISTATE, (WPARAM)(TriState), 0)
|
||||
|
||||
#define TreeNew_EnsureVisible(hWnd, Node) \
|
||||
SendMessage((hWnd), TNM_ENSUREVISIBLE, 0, (LPARAM)(Node))
|
||||
|
||||
#define TreeNew_Scroll(hWnd, DeltaRows, DeltaX) \
|
||||
SendMessage((hWnd), TNM_SCROLL, (WPARAM)(DeltaRows), (LPARAM)(DeltaX))
|
||||
|
||||
#define TreeNew_GetFlatNodeCount(hWnd) \
|
||||
((ULONG)SendMessage((hWnd), TNM_GETFLATNODECOUNT, 0, 0))
|
||||
|
||||
#define TreeNew_GetFlatNode(hWnd, Index) \
|
||||
((PPH_TREENEW_NODE)SendMessage((hWnd), TNM_GETFLATNODE, (WPARAM)(Index), 0))
|
||||
|
||||
#define TreeNew_GetCellText(hWnd, GetCellText) \
|
||||
SendMessage((hWnd), TNM_GETCELLTEXT, 0, (LPARAM)(GetCellText))
|
||||
|
||||
#define TreeNew_SetNodeExpanded(hWnd, Node, Expanded) \
|
||||
SendMessage((hWnd), TNM_SETNODEEXPANDED, (WPARAM)(Expanded), (LPARAM)(Node))
|
||||
|
||||
#define TreeNew_GetMaxId(hWnd) \
|
||||
((ULONG)SendMessage((hWnd), TNM_GETMAXID, 0, 0))
|
||||
|
||||
#define TreeNew_SetMaxId(hWnd, MaxId) \
|
||||
SendMessage((hWnd), TNM_SETMAXID, (WPARAM)(MaxId), 0)
|
||||
|
||||
#define TreeNew_InvalidateNode(hWnd, Node) \
|
||||
SendMessage((hWnd), TNM_INVALIDATENODE, 0, (LPARAM)(Node))
|
||||
|
||||
#define TreeNew_InvalidateNodes(hWnd, Start, End) \
|
||||
SendMessage((hWnd), TNM_INVALIDATENODES, (WPARAM)(Start), (LPARAM)(End))
|
||||
|
||||
#define TreeNew_GetFixedHeader(hWnd) \
|
||||
((HWND)SendMessage((hWnd), TNM_GETFIXEDHEADER, 0, 0))
|
||||
|
||||
#define TreeNew_GetHeader(hWnd) \
|
||||
((HWND)SendMessage((hWnd), TNM_GETHEADER, 0, 0))
|
||||
|
||||
#define TreeNew_GetTooltips(hWnd) \
|
||||
((HWND)SendMessage((hWnd), TNM_GETTOOLTIPS, 0, 0))
|
||||
|
||||
#define TreeNew_SelectRange(hWnd, Start, End) \
|
||||
SendMessage((hWnd), TNM_SELECTRANGE, (WPARAM)(Start), (LPARAM)(End))
|
||||
|
||||
#define TreeNew_DeselectRange(hWnd, Start, End) \
|
||||
SendMessage((hWnd), TNM_DESELECTRANGE, (WPARAM)(Start), (LPARAM)(End))
|
||||
|
||||
#define TreeNew_GetColumnCount(hWnd) \
|
||||
((ULONG)SendMessage((hWnd), TNM_GETCOLUMNCOUNT, 0, 0))
|
||||
|
||||
#define TreeNew_SetRedraw(hWnd, Redraw) \
|
||||
((LONG)SendMessage((hWnd), TNM_SETREDRAW, (WPARAM)(Redraw), 0))
|
||||
|
||||
#define TreeNew_GetViewParts(hWnd, Parts) \
|
||||
SendMessage((hWnd), TNM_GETVIEWPARTS, 0, (LPARAM)(Parts))
|
||||
|
||||
#define TreeNew_GetFixedColumn(hWnd) \
|
||||
((PPH_TREENEW_COLUMN)SendMessage((hWnd), TNM_GETFIXEDCOLUMN, 0, 0))
|
||||
|
||||
#define TreeNew_GetFirstColumn(hWnd) \
|
||||
((PPH_TREENEW_COLUMN)SendMessage((hWnd), TNM_GETFIRSTCOLUMN, 0, 0))
|
||||
|
||||
#define TreeNew_SetFocusNode(hWnd, Node) \
|
||||
SendMessage((hWnd), TNM_SETFOCUSNODE, 0, (LPARAM)(Node))
|
||||
|
||||
#define TreeNew_SetMarkNode(hWnd, Node) \
|
||||
SendMessage((hWnd), TNM_SETMARKNODE, 0, (LPARAM)(Node))
|
||||
|
||||
#define TreeNew_SetHotNode(hWnd, Node) \
|
||||
SendMessage((hWnd), TNM_SETHOTNODE, 0, (LPARAM)(Node))
|
||||
|
||||
#define TreeNew_SetExtendedFlags(hWnd, Mask, Value) \
|
||||
SendMessage((hWnd), TNM_SETEXTENDEDFLAGS, (WPARAM)(Mask), (LPARAM)(Value))
|
||||
|
||||
#define TreeNew_GetCallback(hWnd, Callback, Context) \
|
||||
SendMessage((hWnd), TNM_GETCALLBACK, (WPARAM)(Context), (LPARAM)(Callback))
|
||||
|
||||
#define TreeNew_HitTest(hWnd, HitTest) \
|
||||
SendMessage((hWnd), TNM_HITTEST, 0, (LPARAM)(HitTest))
|
||||
|
||||
#define TreeNew_GetVisibleColumnCount(hWnd) \
|
||||
((ULONG)SendMessage((hWnd), TNM_GETVISIBLECOLUMNCOUNT, 0, 0))
|
||||
|
||||
#define TreeNew_AutoSizeColumn(hWnd, Id, Flags) \
|
||||
SendMessage((hWnd), TNM_AUTOSIZECOLUMN, (WPARAM)(Id), (LPARAM)(Flags))
|
||||
|
||||
#define TreeNew_SetEmptyText(hWnd, Text, Flags) \
|
||||
SendMessage((hWnd), TNM_SETEMPTYTEXT, (WPARAM)(Flags), (LPARAM)(Text))
|
||||
|
||||
#define TreeNew_SetRowHeight(hWnd, RowHeight) \
|
||||
SendMessage((hWnd), TNM_SETROWHEIGHT, (WPARAM)(RowHeight), 0)
|
||||
|
||||
#define TreeNew_IsFlatNodeValid(hWnd) \
|
||||
((BOOLEAN)SendMessage((hWnd), TNM_ISFLATNODEVALID, 0, 0))
|
||||
|
||||
typedef struct _PH_TREENEW_VIEW_PARTS
|
||||
{
|
||||
RECT ClientRect;
|
||||
LONG HeaderHeight;
|
||||
LONG RowHeight;
|
||||
ULONG VScrollWidth;
|
||||
ULONG HScrollHeight;
|
||||
LONG VScrollPosition;
|
||||
LONG HScrollPosition;
|
||||
LONG FixedWidth;
|
||||
LONG NormalLeft;
|
||||
LONG NormalWidth;
|
||||
} PH_TREENEW_VIEW_PARTS, *PPH_TREENEW_VIEW_PARTS;
|
||||
|
||||
PHLIBAPI
|
||||
BOOLEAN PhTreeNewInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
FORCEINLINE VOID PhInitializeTreeNewNode(
|
||||
_In_ PPH_TREENEW_NODE Node
|
||||
)
|
||||
{
|
||||
memset(Node, 0, sizeof(PH_TREENEW_NODE));
|
||||
|
||||
Node->Visible = TRUE;
|
||||
Node->Expanded = TRUE;
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhInvalidateTreeNewNode(
|
||||
_Inout_ PPH_TREENEW_NODE Node,
|
||||
_In_ ULONG Flags
|
||||
)
|
||||
{
|
||||
if (Flags & TN_CACHE_COLOR)
|
||||
Node->s.CachedColorValid = FALSE;
|
||||
if (Flags & TN_CACHE_FONT)
|
||||
Node->s.CachedFontValid = FALSE;
|
||||
if (Flags & TN_CACHE_ICON)
|
||||
Node->s.CachedIconValid = FALSE;
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN PhAddTreeNewColumn(
|
||||
_In_ HWND hwnd,
|
||||
_In_ ULONG Id,
|
||||
_In_ BOOLEAN Visible,
|
||||
_In_ PWSTR Text,
|
||||
_In_ ULONG Width,
|
||||
_In_ ULONG Alignment,
|
||||
_In_ ULONG DisplayIndex,
|
||||
_In_ ULONG TextFlags
|
||||
)
|
||||
{
|
||||
PH_TREENEW_COLUMN column;
|
||||
|
||||
memset(&column, 0, sizeof(PH_TREENEW_COLUMN));
|
||||
column.Id = Id;
|
||||
column.Visible = Visible;
|
||||
column.Text = Text;
|
||||
column.Width = Width;
|
||||
column.Alignment = Alignment;
|
||||
column.DisplayIndex = DisplayIndex;
|
||||
column.TextFlags = TextFlags;
|
||||
column.DpiScaleOnAdd = TRUE;
|
||||
|
||||
if (DisplayIndex == -2)
|
||||
column.Fixed = TRUE;
|
||||
|
||||
return !!TreeNew_AddColumn(hwnd, &column);
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN PhAddTreeNewColumnEx(
|
||||
_In_ HWND hwnd,
|
||||
_In_ ULONG Id,
|
||||
_In_ BOOLEAN Visible,
|
||||
_In_ PWSTR Text,
|
||||
_In_ ULONG Width,
|
||||
_In_ ULONG Alignment,
|
||||
_In_ ULONG DisplayIndex,
|
||||
_In_ ULONG TextFlags,
|
||||
_In_ BOOLEAN SortDescending
|
||||
)
|
||||
{
|
||||
PH_TREENEW_COLUMN column;
|
||||
|
||||
memset(&column, 0, sizeof(PH_TREENEW_COLUMN));
|
||||
column.Id = Id;
|
||||
column.Visible = Visible;
|
||||
column.Text = Text;
|
||||
column.Width = Width;
|
||||
column.Alignment = Alignment;
|
||||
column.DisplayIndex = DisplayIndex;
|
||||
column.TextFlags = TextFlags;
|
||||
column.DpiScaleOnAdd = TRUE;
|
||||
|
||||
if (DisplayIndex == -2)
|
||||
column.Fixed = TRUE;
|
||||
if (SortDescending)
|
||||
column.SortDescending = TRUE;
|
||||
|
||||
return !!TreeNew_AddColumn(hwnd, &column);
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN PhAddTreeNewColumnEx2(
|
||||
_In_ HWND hwnd,
|
||||
_In_ ULONG Id,
|
||||
_In_ BOOLEAN Visible,
|
||||
_In_ PWSTR Text,
|
||||
_In_ ULONG Width,
|
||||
_In_ ULONG Alignment,
|
||||
_In_ ULONG DisplayIndex,
|
||||
_In_ ULONG TextFlags,
|
||||
_In_ ULONG ExtraFlags
|
||||
)
|
||||
{
|
||||
PH_TREENEW_COLUMN column;
|
||||
|
||||
memset(&column, 0, sizeof(PH_TREENEW_COLUMN));
|
||||
column.Id = Id;
|
||||
column.Visible = Visible;
|
||||
column.Text = Text;
|
||||
column.Width = Width;
|
||||
column.Alignment = Alignment;
|
||||
column.DisplayIndex = DisplayIndex;
|
||||
column.TextFlags = TextFlags;
|
||||
|
||||
if (DisplayIndex == -2)
|
||||
column.Fixed = TRUE;
|
||||
if (ExtraFlags & TN_COLUMN_FLAG_CUSTOMDRAW)
|
||||
column.CustomDraw = TRUE;
|
||||
if (ExtraFlags & TN_COLUMN_FLAG_SORTDESCENDING)
|
||||
column.SortDescending = TRUE;
|
||||
if (!(ExtraFlags & TN_COLUMN_FLAG_NODPISCALEONADD))
|
||||
column.DpiScaleOnAdd = TRUE;
|
||||
|
||||
return !!TreeNew_AddColumn(hwnd, &column);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
802
phlib/include/treenewp.h
Normal file
802
phlib/include/treenewp.h
Normal file
@@ -0,0 +1,802 @@
|
||||
#ifndef _PH_TREENEWP_H
|
||||
#define _PH_TREENEWP_H
|
||||
|
||||
// Important notes about pointers:
|
||||
//
|
||||
// All memory allocation for nodes and strings is handled by the user. This usually means there is a
|
||||
// very limited time during which they can be safely accessed.
|
||||
//
|
||||
// Node pointers are valid through the duration of message processing, and also up to the next
|
||||
// restructure operation, either user- or control- initiated. This means that state such as the
|
||||
// focused node, hot node and mark node must be carefully preserved through restructuring. If
|
||||
// restructuring is suspended by a set-redraw call, all nodes must be considered invalid and no user
|
||||
// input can be handled.
|
||||
//
|
||||
// Strings are valid only through the duration of message processing.
|
||||
|
||||
typedef struct _PH_TREENEW_CONTEXT
|
||||
{
|
||||
HWND Handle;
|
||||
PVOID InstanceHandle;
|
||||
HWND FixedHeaderHandle;
|
||||
HWND HeaderHandle;
|
||||
HWND VScrollHandle;
|
||||
HWND HScrollHandle;
|
||||
HWND FillerBoxHandle;
|
||||
HWND TooltipsHandle;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG FontOwned : 1;
|
||||
ULONG Tracking : 1; // tracking for fixed divider
|
||||
ULONG VScrollVisible : 1;
|
||||
ULONG HScrollVisible : 1;
|
||||
ULONG FixedColumnVisible : 1;
|
||||
ULONG FixedDividerVisible : 1;
|
||||
ULONG AnimateDivider : 1;
|
||||
ULONG AnimateDividerFadingIn : 1;
|
||||
ULONG AnimateDividerFadingOut : 1;
|
||||
ULONG CanAnyExpand : 1;
|
||||
ULONG TriState : 1;
|
||||
ULONG HasFocus : 1;
|
||||
ULONG ThemeInitialized : 1; // delay load theme data
|
||||
ULONG ThemeActive : 1;
|
||||
ULONG ThemeHasItemBackground : 1;
|
||||
ULONG ThemeHasGlyph : 1;
|
||||
ULONG ThemeHasHotGlyph : 1;
|
||||
ULONG FocusNodeFound : 1; // used to preserve the focused node across restructuring
|
||||
ULONG SearchFailed : 1; // used to prevent multiple beeps
|
||||
ULONG SearchSingleCharMode : 1; // LV style single-character search
|
||||
ULONG TooltipUnfolding : 1; // whether the current tooltip is unfolding
|
||||
ULONG DoubleBuffered : 1;
|
||||
ULONG SuspendUpdateStructure : 1;
|
||||
ULONG SuspendUpdateLayout : 1;
|
||||
ULONG SuspendUpdateMoveMouse : 1;
|
||||
ULONG DragSelectionActive : 1;
|
||||
ULONG SelectionRectangleAlpha : 1; // use alpha blending for the selection rectangle
|
||||
ULONG CustomRowHeight : 1;
|
||||
ULONG Spare : 4;
|
||||
};
|
||||
ULONG Flags;
|
||||
};
|
||||
ULONG Style;
|
||||
ULONG ExtendedStyle;
|
||||
ULONG ExtendedFlags;
|
||||
|
||||
HFONT Font;
|
||||
HCURSOR Cursor;
|
||||
HCURSOR DividerCursor;
|
||||
|
||||
RECT ClientRect;
|
||||
LONG HeaderHeight;
|
||||
LONG RowHeight;
|
||||
ULONG VScrollWidth;
|
||||
ULONG HScrollHeight;
|
||||
LONG VScrollPosition;
|
||||
LONG HScrollPosition;
|
||||
LONG FixedWidth; // width of the fixed part of the tree list
|
||||
LONG FixedWidthMinimum;
|
||||
LONG NormalLeft; // FixedWidth + 1 if there is a fixed column, otherwise 0
|
||||
|
||||
PPH_TREENEW_NODE FocusNode;
|
||||
ULONG HotNodeIndex;
|
||||
ULONG MarkNodeIndex; // selection mark
|
||||
|
||||
ULONG MouseDownLast;
|
||||
POINT MouseDownLocation;
|
||||
|
||||
PPH_TREENEW_CALLBACK Callback;
|
||||
PVOID CallbackContext;
|
||||
|
||||
PPH_TREENEW_COLUMN *Columns; // columns, indexed by ID
|
||||
ULONG NextId;
|
||||
ULONG AllocatedColumns;
|
||||
ULONG NumberOfColumns; // just a statistic; do not use for actual logic
|
||||
|
||||
PPH_TREENEW_COLUMN *ColumnsByDisplay; // columns, indexed by display order (excluding the fixed column)
|
||||
ULONG AllocatedColumnsByDisplay;
|
||||
ULONG NumberOfColumnsByDisplay; // the number of visible columns (excluding the fixed column)
|
||||
LONG TotalViewX; // total width of normal columns
|
||||
PPH_TREENEW_COLUMN FixedColumn;
|
||||
PPH_TREENEW_COLUMN FirstColumn; // first column, by display order (including the fixed column)
|
||||
PPH_TREENEW_COLUMN LastColumn; // last column, by display order (including the fixed column)
|
||||
|
||||
PPH_TREENEW_COLUMN ResizingColumn;
|
||||
LONG OldColumnWidth;
|
||||
LONG TrackStartX;
|
||||
LONG TrackOldFixedWidth;
|
||||
ULONG DividerHot; // 0 for un-hot, 100 for completely hot
|
||||
|
||||
PPH_LIST FlatList;
|
||||
|
||||
ULONG SortColumn; // ID of the column to sort by
|
||||
PH_SORT_ORDER SortOrder;
|
||||
|
||||
FLOAT VScrollRemainder;
|
||||
FLOAT HScrollRemainder;
|
||||
|
||||
LONG SearchMessageTime;
|
||||
PWSTR SearchString;
|
||||
ULONG SearchStringCount;
|
||||
ULONG AllocatedSearchString;
|
||||
|
||||
ULONG TooltipIndex;
|
||||
ULONG TooltipId;
|
||||
PPH_STRING TooltipText;
|
||||
RECT TooltipRect; // text rectangle of an unfolding tooltip
|
||||
HFONT TooltipFont;
|
||||
HFONT NewTooltipFont;
|
||||
ULONG TooltipColumnId;
|
||||
WNDPROC FixedHeaderOldWndProc;
|
||||
WNDPROC HeaderOldWndProc;
|
||||
|
||||
TEXTMETRIC TextMetrics;
|
||||
HTHEME ThemeData;
|
||||
LONG SystemBorderX;
|
||||
LONG SystemBorderY;
|
||||
LONG SystemEdgeX;
|
||||
LONG SystemEdgeY;
|
||||
|
||||
HDC BufferedContext;
|
||||
HBITMAP BufferedOldBitmap;
|
||||
HBITMAP BufferedBitmap;
|
||||
RECT BufferedContextRect;
|
||||
|
||||
LONG SystemDragX;
|
||||
LONG SystemDragY;
|
||||
RECT DragRect;
|
||||
|
||||
LONG EnableRedraw;
|
||||
HRGN SuspendUpdateRegion;
|
||||
|
||||
PH_STRINGREF EmptyText;
|
||||
} PH_TREENEW_CONTEXT, *PPH_TREENEW_CONTEXT;
|
||||
|
||||
LRESULT CALLBACK PhTnpWndProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
);
|
||||
|
||||
BOOLEAN NTAPI PhTnpNullCallback(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PH_TREENEW_MESSAGE Message,
|
||||
_In_opt_ PVOID Parameter1,
|
||||
_In_opt_ PVOID Parameter2,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
VOID PhTnpCreateTreeNewContext(
|
||||
_Out_ PPH_TREENEW_CONTEXT *Context
|
||||
);
|
||||
|
||||
VOID PhTnpDestroyTreeNewContext(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
// Event handlers
|
||||
|
||||
BOOLEAN PhTnpOnCreate(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ CREATESTRUCT *CreateStruct
|
||||
);
|
||||
|
||||
VOID PhTnpOnSize(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpOnSetFont(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_opt_ HFONT Font,
|
||||
_In_ LOGICAL Redraw
|
||||
);
|
||||
|
||||
VOID PhTnpOnStyleChanged(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG Type,
|
||||
_In_ STYLESTRUCT *StyleStruct
|
||||
);
|
||||
|
||||
VOID PhTnpOnSettingChange(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpOnThemeChanged(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
ULONG PhTnpOnGetDlgCode(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG VirtualKey,
|
||||
_In_opt_ PMSG Message
|
||||
);
|
||||
|
||||
VOID PhTnpOnPaint(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpOnPrintClient(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ HDC hdc,
|
||||
_In_ ULONG Flags
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpOnNcPaint(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_opt_ HRGN UpdateRegion
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpOnSetCursor(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ HWND CursorWindowHandle
|
||||
);
|
||||
|
||||
VOID PhTnpOnTimer(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Id
|
||||
);
|
||||
|
||||
VOID PhTnpOnMouseMove(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG VirtualKeys,
|
||||
_In_ LONG CursorX,
|
||||
_In_ LONG CursorY
|
||||
);
|
||||
|
||||
VOID PhTnpOnMouseLeave(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpOnXxxButtonXxx(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Message,
|
||||
_In_ ULONG VirtualKeys,
|
||||
_In_ LONG CursorX,
|
||||
_In_ LONG CursorY
|
||||
);
|
||||
|
||||
VOID PhTnpOnCaptureChanged(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpOnKeyDown(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG VirtualKey,
|
||||
_In_ ULONG Data
|
||||
);
|
||||
|
||||
VOID PhTnpOnChar(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Character,
|
||||
_In_ ULONG Data
|
||||
);
|
||||
|
||||
VOID PhTnpOnMouseWheel(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG Distance,
|
||||
_In_ ULONG VirtualKeys,
|
||||
_In_ LONG CursorX,
|
||||
_In_ LONG CursorY
|
||||
);
|
||||
|
||||
VOID PhTnpOnMouseHWheel(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG Distance,
|
||||
_In_ ULONG VirtualKeys,
|
||||
_In_ LONG CursorX,
|
||||
_In_ LONG CursorY
|
||||
);
|
||||
|
||||
VOID PhTnpOnContextMenu(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG CursorScreenX,
|
||||
_In_ LONG CursorScreenY
|
||||
);
|
||||
|
||||
VOID PhTnpOnVScroll(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Request,
|
||||
_In_ USHORT Position
|
||||
);
|
||||
|
||||
VOID PhTnpOnHScroll(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Request,
|
||||
_In_ USHORT Position
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpOnNotify(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ NMHDR *Header,
|
||||
_Out_ LRESULT *Result
|
||||
);
|
||||
|
||||
ULONG_PTR PhTnpOnUserMessage(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Message,
|
||||
_In_ ULONG_PTR WParam,
|
||||
_In_ ULONG_PTR LParam
|
||||
);
|
||||
|
||||
// Misc.
|
||||
|
||||
VOID PhTnpSetFont(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_opt_ HFONT Font,
|
||||
_In_ BOOLEAN Redraw
|
||||
);
|
||||
|
||||
VOID PhTnpUpdateSystemMetrics(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpUpdateTextMetrics(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpUpdateThemeData(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpInitializeThemeData(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpCancelTrack(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpLayout(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpLayoutHeader(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpSetFixedWidth(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG FixedWidth
|
||||
);
|
||||
|
||||
VOID PhTnpSetRedraw(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ BOOLEAN Redraw
|
||||
);
|
||||
|
||||
VOID PhTnpSendMouseEvent(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PH_TREENEW_MESSAGE Message,
|
||||
_In_ LONG CursorX,
|
||||
_In_ LONG CursorY,
|
||||
_In_ PPH_TREENEW_NODE Node,
|
||||
_In_ PPH_TREENEW_COLUMN Column,
|
||||
_In_ ULONG VirtualKeys
|
||||
);
|
||||
|
||||
// Columns
|
||||
|
||||
PPH_TREENEW_COLUMN PhTnpLookupColumnById(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Id
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpAddColumn(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPH_TREENEW_COLUMN Column
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpRemoveColumn(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Id
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpCopyColumn(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Id,
|
||||
_Out_ PPH_TREENEW_COLUMN Column
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpChangeColumn(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Mask,
|
||||
_In_ ULONG Id,
|
||||
_In_ PPH_TREENEW_COLUMN Column
|
||||
);
|
||||
|
||||
VOID PhTnpExpandAllocatedColumns(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpUpdateColumnMaps(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
// Columns (header control)
|
||||
|
||||
LONG PhTnpInsertColumnHeader(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPH_TREENEW_COLUMN Column
|
||||
);
|
||||
|
||||
VOID PhTnpChangeColumnHeader(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Mask,
|
||||
_In_ PPH_TREENEW_COLUMN Column
|
||||
);
|
||||
|
||||
VOID PhTnpDeleteColumnHeader(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_Inout_ PPH_TREENEW_COLUMN Column
|
||||
);
|
||||
|
||||
VOID PhTnpUpdateColumnHeaders(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpProcessResizeColumn(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPH_TREENEW_COLUMN Column,
|
||||
_In_ LONG Delta
|
||||
);
|
||||
|
||||
VOID PhTnpProcessSortColumn(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPH_TREENEW_COLUMN NewColumn
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpSetColumnHeaderSortIcon(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_opt_ PPH_TREENEW_COLUMN SortColumnPointer
|
||||
);
|
||||
|
||||
VOID PhTnpAutoSizeColumnHeader(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ HWND HeaderHandle,
|
||||
_In_ PPH_TREENEW_COLUMN Column,
|
||||
_In_ ULONG Flags
|
||||
);
|
||||
|
||||
// Nodes
|
||||
|
||||
BOOLEAN PhTnpGetNodeChildren(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_opt_ PPH_TREENEW_NODE Node,
|
||||
_Out_ PPH_TREENEW_NODE **Children,
|
||||
_Out_ PULONG NumberOfChildren
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpIsNodeLeaf(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPH_TREENEW_NODE Node
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpGetCellText(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPH_TREENEW_NODE Node,
|
||||
_In_ ULONG Id,
|
||||
_Out_ PPH_STRINGREF Text
|
||||
);
|
||||
|
||||
VOID PhTnpRestructureNodes(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpInsertNodeChildren(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPH_TREENEW_NODE Node,
|
||||
_In_ ULONG Level
|
||||
);
|
||||
|
||||
VOID PhTnpSetExpandedNode(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPH_TREENEW_NODE Node,
|
||||
_In_ BOOLEAN Expanded
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpGetCellParts(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Index,
|
||||
_In_opt_ PPH_TREENEW_COLUMN Column,
|
||||
_In_ ULONG Flags,
|
||||
_Out_ PPH_TREENEW_CELL_PARTS Parts
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpGetRowRects(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Start,
|
||||
_In_ ULONG End,
|
||||
_In_ BOOLEAN Clip,
|
||||
_Out_ PRECT Rect
|
||||
);
|
||||
|
||||
VOID PhTnpHitTest(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_Inout_ PPH_TREENEW_HIT_TEST HitTest
|
||||
);
|
||||
|
||||
VOID PhTnpSelectRange(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Start,
|
||||
_In_ ULONG End,
|
||||
_In_ ULONG Flags,
|
||||
_Out_opt_ PULONG ChangedStart,
|
||||
_Out_opt_ PULONG ChangedEnd
|
||||
);
|
||||
|
||||
VOID PhTnpSetHotNode(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_opt_ PPH_TREENEW_NODE NewHotNode,
|
||||
_In_ BOOLEAN NewPlusMinusHot
|
||||
);
|
||||
|
||||
VOID PhTnpProcessSelectNode(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPH_TREENEW_NODE Node,
|
||||
_In_ LOGICAL ControlKey,
|
||||
_In_ LOGICAL ShiftKey,
|
||||
_In_ LOGICAL RightButton
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpEnsureVisibleNode(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Index
|
||||
);
|
||||
|
||||
// Mouse
|
||||
|
||||
VOID PhTnpProcessMoveMouse(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG CursorX,
|
||||
_In_ LONG CursorY
|
||||
);
|
||||
|
||||
VOID PhTnpProcessMouseVWheel(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG Distance
|
||||
);
|
||||
|
||||
VOID PhTnpProcessMouseHWheel(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG Distance
|
||||
);
|
||||
|
||||
// Keyboard
|
||||
|
||||
BOOLEAN PhTnpProcessFocusKey(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG VirtualKey
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpProcessNodeKey(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG VirtualKey
|
||||
);
|
||||
|
||||
VOID PhTnpProcessSearchKey(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG Character
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpDefaultIncrementalSearch(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_Inout_ PPH_TREENEW_SEARCH_EVENT SearchEvent,
|
||||
_In_ BOOLEAN Partial,
|
||||
_In_ BOOLEAN Wrap
|
||||
);
|
||||
|
||||
// Scrolling
|
||||
|
||||
VOID PhTnpUpdateScrollBars(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpScroll(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG DeltaRows,
|
||||
_In_ LONG DeltaX
|
||||
);
|
||||
|
||||
VOID PhTnpProcessScroll(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG DeltaRows,
|
||||
_In_ LONG DeltaX
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpCanScroll(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ BOOLEAN Horizontal,
|
||||
_In_ BOOLEAN Positive
|
||||
);
|
||||
|
||||
// Drawing
|
||||
|
||||
VOID PhTnpPaint(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ HDC hdc,
|
||||
_In_ PRECT PaintRect
|
||||
);
|
||||
|
||||
VOID PhTnpPrepareRowForDraw(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ HDC hdc,
|
||||
_Inout_ PPH_TREENEW_NODE Node
|
||||
);
|
||||
|
||||
VOID PhTnpDrawCell(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ HDC hdc,
|
||||
_In_ PRECT CellRect,
|
||||
_In_ PPH_TREENEW_NODE Node,
|
||||
_In_ PPH_TREENEW_COLUMN Column,
|
||||
_In_ LONG RowIndex,
|
||||
_In_ LONG ColumnIndex
|
||||
);
|
||||
|
||||
VOID PhTnpDrawDivider(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ HDC hdc
|
||||
);
|
||||
|
||||
VOID PhTnpDrawPlusMinusGlyph(
|
||||
_In_ HDC hdc,
|
||||
_In_ PRECT Rect,
|
||||
_In_ BOOLEAN Plus
|
||||
);
|
||||
|
||||
VOID PhTnpDrawSelectionRectangle(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ HDC hdc,
|
||||
_In_ PRECT Rect
|
||||
);
|
||||
|
||||
VOID PhTnpDrawThemedBorder(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ HDC hdc
|
||||
);
|
||||
|
||||
// Tooltips
|
||||
|
||||
VOID PhTnpInitializeTooltips(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpGetTooltipText(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ PPOINT Point,
|
||||
_Out_ PWSTR *Text
|
||||
);
|
||||
|
||||
BOOLEAN PhTnpPrepareTooltipShow(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpPrepareTooltipPop(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpPopTooltip(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
PPH_TREENEW_COLUMN PhTnpHitTestHeader(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ BOOLEAN Fixed,
|
||||
_In_ PPOINT Point,
|
||||
_Out_opt_ PRECT ItemRect
|
||||
);
|
||||
|
||||
VOID PhTnpGetHeaderTooltipText(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ BOOLEAN Fixed,
|
||||
_In_ PPOINT Point,
|
||||
_Out_ PWSTR *Text
|
||||
);
|
||||
|
||||
PWSTR PhTnpMakeContextAtom(
|
||||
VOID
|
||||
);
|
||||
|
||||
LRESULT CALLBACK PhTnpHeaderHookWndProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
);
|
||||
|
||||
// Drag selection
|
||||
|
||||
BOOLEAN PhTnpDetectDrag(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG CursorX,
|
||||
_In_ LONG CursorY,
|
||||
_In_ BOOLEAN DispatchMessages,
|
||||
_Out_opt_ PULONG CancelledByMessage
|
||||
);
|
||||
|
||||
VOID PhTnpDragSelect(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ LONG CursorX,
|
||||
_In_ LONG CursorY
|
||||
);
|
||||
|
||||
VOID PhTnpProcessDragSelect(
|
||||
_In_ PPH_TREENEW_CONTEXT Context,
|
||||
_In_ ULONG VirtualKeys,
|
||||
_In_ PRECT OldRect,
|
||||
_In_ PRECT NewRect,
|
||||
_In_ PRECT TotalRect
|
||||
);
|
||||
|
||||
// Double buffering
|
||||
|
||||
VOID PhTnpCreateBufferedContext(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID PhTnpDestroyBufferedContext(
|
||||
_In_ PPH_TREENEW_CONTEXT Context
|
||||
);
|
||||
|
||||
// Support functions
|
||||
|
||||
VOID PhTnpGetMessagePos(
|
||||
_In_ HWND hwnd,
|
||||
_Out_ PPOINT ClientPoint
|
||||
);
|
||||
|
||||
// Macros
|
||||
|
||||
#define HRGN_FULL ((HRGN)1) // passed by WM_NCPAINT even though it's completely undocumented
|
||||
|
||||
#define TNP_CELL_LEFT_MARGIN 6
|
||||
#define TNP_CELL_RIGHT_MARGIN 6
|
||||
#define TNP_ICON_RIGHT_PADDING 4
|
||||
|
||||
#define TNP_TIMER_NULL 1
|
||||
#define TNP_TIMER_ANIMATE_DIVIDER 2
|
||||
|
||||
#define TNP_TOOLTIPS_ITEM 0
|
||||
#define TNP_TOOLTIPS_FIXED_HEADER 1
|
||||
#define TNP_TOOLTIPS_HEADER 2
|
||||
#define TNP_TOOLTIPS_DEFAULT_MAXIMUM_WIDTH 550
|
||||
|
||||
#define TNP_ANIMATE_DIVIDER_INTERVAL 10
|
||||
#define TNP_ANIMATE_DIVIDER_INCREMENT 17
|
||||
#define TNP_ANIMATE_DIVIDER_DECREMENT 2
|
||||
|
||||
#define TNP_HIT_TEST_FIXED_DIVIDER(X, Context) \
|
||||
((Context)->FixedDividerVisible && (X) >= (Context)->FixedWidth - 8 && (X) < (Context)->FixedWidth + 8)
|
||||
#define TNP_HIT_TEST_PLUS_MINUS_GLYPH(X, NodeLevel) \
|
||||
(((X) >= TNP_CELL_LEFT_MARGIN + ((LONG)(NodeLevel) * SmallIconWidth)) && ((X) < TNP_CELL_LEFT_MARGIN + ((LONG)(NodeLevel) * SmallIconWidth) + SmallIconWidth))
|
||||
|
||||
#endif
|
||||
77
phlib/include/verify.h
Normal file
77
phlib/include/verify.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#ifndef _PH_VERIFY_H
|
||||
#define _PH_VERIFY_H
|
||||
|
||||
#include <wintrust.h>
|
||||
#include <softpub.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PH_VERIFY_DEFAULT_SIZE_LIMIT (32 * 1024 * 1024)
|
||||
|
||||
typedef enum _VERIFY_RESULT
|
||||
{
|
||||
VrUnknown = 0,
|
||||
VrNoSignature,
|
||||
VrTrusted,
|
||||
VrExpired,
|
||||
VrRevoked,
|
||||
VrDistrust,
|
||||
VrSecuritySettings,
|
||||
VrBadSignature
|
||||
} VERIFY_RESULT, *PVERIFY_RESULT;
|
||||
|
||||
#define PH_VERIFY_PREVENT_NETWORK_ACCESS 0x1
|
||||
#define PH_VERIFY_VIEW_PROPERTIES 0x2
|
||||
|
||||
typedef struct _PH_VERIFY_FILE_INFO
|
||||
{
|
||||
PWSTR FileName;
|
||||
ULONG Flags; // PH_VERIFY_*
|
||||
|
||||
ULONG FileSizeLimitForHash; // 0 for PH_VERIFY_DEFAULT_SIZE_LIMIT, -1 for unlimited
|
||||
ULONG NumberOfCatalogFileNames;
|
||||
PWSTR *CatalogFileNames;
|
||||
|
||||
HWND hWnd; // for PH_VERIFY_VIEW_PROPERTIES
|
||||
} PH_VERIFY_FILE_INFO, *PPH_VERIFY_FILE_INFO;
|
||||
|
||||
PHLIBAPI
|
||||
VERIFY_RESULT
|
||||
NTAPI
|
||||
PhVerifyFile(
|
||||
_In_ PWSTR FileName,
|
||||
_Out_opt_ PPH_STRING *SignerName
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PhVerifyFileEx(
|
||||
_In_ PPH_VERIFY_FILE_INFO Information,
|
||||
_Out_ VERIFY_RESULT *VerifyResult,
|
||||
_Out_opt_ PCERT_CONTEXT **Signatures,
|
||||
_Out_opt_ PULONG NumberOfSignatures
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhFreeVerifySignatures(
|
||||
_In_ PCERT_CONTEXT *Signatures,
|
||||
_In_ ULONG NumberOfSignatures
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_STRING
|
||||
NTAPI
|
||||
PhGetSignerNameFromCertificate(
|
||||
_In_ PCERT_CONTEXT Certificate
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
118
phlib/include/verifyp.h
Normal file
118
phlib/include/verifyp.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifndef _PH_VERIFYP_H
|
||||
#define _PH_VERIFYP_H
|
||||
|
||||
#include <commdlg.h>
|
||||
|
||||
typedef struct _CATALOG_INFO
|
||||
{
|
||||
DWORD cbStruct;
|
||||
WCHAR wszCatalogFile[MAX_PATH];
|
||||
} CATALOG_INFO, *PCATALOG_INFO;
|
||||
|
||||
typedef struct tagCRYPTUI_VIEWSIGNERINFO_STRUCT {
|
||||
DWORD dwSize;
|
||||
HWND hwndParent;
|
||||
DWORD dwFlags;
|
||||
LPCTSTR szTitle;
|
||||
CMSG_SIGNER_INFO *pSignerInfo;
|
||||
HCRYPTMSG hMsg;
|
||||
LPCSTR pszOID;
|
||||
DWORD_PTR dwReserved;
|
||||
DWORD cStores;
|
||||
HCERTSTORE *rghStores;
|
||||
DWORD cPropSheetPages;
|
||||
LPCPROPSHEETPAGE rgPropSheetPages;
|
||||
} CRYPTUI_VIEWSIGNERINFO_STRUCT, *PCRYPTUI_VIEWSIGNERINFO_STRUCT;
|
||||
|
||||
typedef BOOL (WINAPI *_CryptCATAdminCalcHashFromFileHandle)(
|
||||
HANDLE hFile,
|
||||
DWORD *pcbHash,
|
||||
BYTE *pbHash,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_CryptCATAdminCalcHashFromFileHandle2)(
|
||||
HCATADMIN hCatAdmin,
|
||||
HANDLE hFile,
|
||||
DWORD *pcbHash,
|
||||
BYTE *pbHash,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_CryptCATAdminAcquireContext)(
|
||||
HANDLE *phCatAdmin,
|
||||
GUID *pgSubsystem,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_CryptCATAdminAcquireContext2)(
|
||||
HCATADMIN *phCatAdmin,
|
||||
const GUID *pgSubsystem,
|
||||
PCWSTR pwszHashAlgorithm,
|
||||
PCCERT_STRONG_SIGN_PARA pStrongHashPolicy,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
typedef HANDLE (WINAPI *_CryptCATAdminEnumCatalogFromHash)(
|
||||
HANDLE hCatAdmin,
|
||||
BYTE *pbHash,
|
||||
DWORD cbHash,
|
||||
DWORD dwFlags,
|
||||
HANDLE *phPrevCatInfo
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_CryptCATCatalogInfoFromContext)(
|
||||
HANDLE hCatInfo,
|
||||
CATALOG_INFO *psCatInfo,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_CryptCATAdminReleaseCatalogContext)(
|
||||
HANDLE hCatAdmin,
|
||||
HANDLE hCatInfo,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_CryptCATAdminReleaseContext)(
|
||||
HANDLE hCatAdmin,
|
||||
DWORD dwFlags
|
||||
);
|
||||
|
||||
typedef PCRYPT_PROVIDER_DATA (WINAPI *_WTHelperProvDataFromStateData)(
|
||||
HANDLE hStateData
|
||||
);
|
||||
|
||||
typedef PCRYPT_PROVIDER_SGNR (WINAPI *_WTHelperGetProvSignerFromChain)(
|
||||
CRYPT_PROVIDER_DATA *pProvData,
|
||||
DWORD idxSigner,
|
||||
BOOL fCounterSigner,
|
||||
DWORD idxCounterSigner
|
||||
);
|
||||
|
||||
typedef LONG (WINAPI *_WinVerifyTrust)(
|
||||
HWND hWnd,
|
||||
GUID *pgActionID,
|
||||
LPVOID pWVTData
|
||||
);
|
||||
|
||||
typedef DWORD (WINAPI *_CertNameToStr)(
|
||||
DWORD dwCertEncodingType,
|
||||
PCERT_NAME_BLOB pName,
|
||||
DWORD dwStrType,
|
||||
LPTSTR psz,
|
||||
DWORD csz
|
||||
);
|
||||
|
||||
typedef PCCERT_CONTEXT (WINAPI *_CertDuplicateCertificateContext)(
|
||||
_In_ PCCERT_CONTEXT pCertContext
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_CertFreeCertificateContext)(
|
||||
_In_ PCCERT_CONTEXT pCertContext
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI *_CryptUIDlgViewSignerInfo)(
|
||||
_In_ CRYPTUI_VIEWSIGNERINFO_STRUCT *pcvsi
|
||||
);
|
||||
|
||||
#endif
|
||||
108
phlib/include/workqueue.h
Normal file
108
phlib/include/workqueue.h
Normal file
@@ -0,0 +1,108 @@
|
||||
#ifndef _PH_WORKQUEUE_H
|
||||
#define _PH_WORKQUEUE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
extern PPH_LIST PhDbgWorkQueueList;
|
||||
extern PH_QUEUED_LOCK PhDbgWorkQueueListLock;
|
||||
#endif
|
||||
|
||||
typedef struct _PH_WORK_QUEUE
|
||||
{
|
||||
PH_RUNDOWN_PROTECT RundownProtect;
|
||||
BOOLEAN Terminating;
|
||||
|
||||
LIST_ENTRY QueueListHead;
|
||||
PH_QUEUED_LOCK QueueLock;
|
||||
PH_CONDITION QueueEmptyCondition;
|
||||
|
||||
ULONG MaximumThreads;
|
||||
ULONG MinimumThreads;
|
||||
ULONG NoWorkTimeout;
|
||||
|
||||
PH_QUEUED_LOCK StateLock;
|
||||
HANDLE SemaphoreHandle;
|
||||
ULONG CurrentThreads;
|
||||
ULONG BusyCount;
|
||||
} PH_WORK_QUEUE, *PPH_WORK_QUEUE;
|
||||
|
||||
typedef VOID (NTAPI *PPH_WORK_QUEUE_ITEM_DELETE_FUNCTION)(
|
||||
_In_ PUSER_THREAD_START_ROUTINE Function,
|
||||
_In_ PVOID Context
|
||||
);
|
||||
|
||||
typedef struct _PH_WORK_QUEUE_ENVIRONMENT
|
||||
{
|
||||
LONG BasePriority : 6; // Base priority increment
|
||||
ULONG IoPriority : 3; // I/O priority hint
|
||||
ULONG PagePriority : 3; // Page/memory priority
|
||||
ULONG ForceUpdate : 1; // Always set priorities regardless of cached values
|
||||
ULONG SpareBits : 19;
|
||||
} PH_WORK_QUEUE_ENVIRONMENT, *PPH_WORK_QUEUE_ENVIRONMENT;
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhInitializeWorkQueue(
|
||||
_Out_ PPH_WORK_QUEUE WorkQueue,
|
||||
_In_ ULONG MinimumThreads,
|
||||
_In_ ULONG MaximumThreads,
|
||||
_In_ ULONG NoWorkTimeout
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhDeleteWorkQueue(
|
||||
_Inout_ PPH_WORK_QUEUE WorkQueue
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhWaitForWorkQueue(
|
||||
_Inout_ PPH_WORK_QUEUE WorkQueue
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhQueueItemWorkQueue(
|
||||
_Inout_ PPH_WORK_QUEUE WorkQueue,
|
||||
_In_ PUSER_THREAD_START_ROUTINE Function,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhQueueItemWorkQueueEx(
|
||||
_Inout_ PPH_WORK_QUEUE WorkQueue,
|
||||
_In_ PUSER_THREAD_START_ROUTINE Function,
|
||||
_In_opt_ PVOID Context,
|
||||
_In_opt_ PPH_WORK_QUEUE_ITEM_DELETE_FUNCTION DeleteFunction,
|
||||
_In_opt_ PPH_WORK_QUEUE_ENVIRONMENT Environment
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
VOID
|
||||
NTAPI
|
||||
PhInitializeWorkQueueEnvironment(
|
||||
_Out_ PPH_WORK_QUEUE_ENVIRONMENT Environment
|
||||
);
|
||||
|
||||
PHLIBAPI
|
||||
PPH_WORK_QUEUE
|
||||
NTAPI
|
||||
PhGetGlobalWorkQueue(
|
||||
VOID
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
49
phlib/include/workqueuep.h
Normal file
49
phlib/include/workqueuep.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef _PH_WORKQUEUEP_H
|
||||
#define _PH_WORKQUEUEP_H
|
||||
|
||||
typedef struct _PH_WORK_QUEUE_ITEM
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
PUSER_THREAD_START_ROUTINE Function;
|
||||
PVOID Context;
|
||||
PPH_WORK_QUEUE_ITEM_DELETE_FUNCTION DeleteFunction;
|
||||
PH_WORK_QUEUE_ENVIRONMENT Environment;
|
||||
} PH_WORK_QUEUE_ITEM, *PPH_WORK_QUEUE_ITEM;
|
||||
|
||||
VOID PhpGetDefaultWorkQueueEnvironment(
|
||||
_Out_ PPH_WORK_QUEUE_ENVIRONMENT Environment
|
||||
);
|
||||
|
||||
VOID PhpUpdateWorkQueueEnvironment(
|
||||
_Inout_ PPH_WORK_QUEUE_ENVIRONMENT CurrentEnvironment,
|
||||
_In_ PPH_WORK_QUEUE_ENVIRONMENT NewEnvironment
|
||||
);
|
||||
|
||||
PPH_WORK_QUEUE_ITEM PhpCreateWorkQueueItem(
|
||||
_In_ PUSER_THREAD_START_ROUTINE Function,
|
||||
_In_opt_ PVOID Context,
|
||||
_In_opt_ PPH_WORK_QUEUE_ITEM_DELETE_FUNCTION DeleteFunction,
|
||||
_In_opt_ PPH_WORK_QUEUE_ENVIRONMENT Environment
|
||||
);
|
||||
|
||||
VOID PhpDestroyWorkQueueItem(
|
||||
_In_ PPH_WORK_QUEUE_ITEM WorkQueueItem
|
||||
);
|
||||
|
||||
VOID PhpExecuteWorkQueueItem(
|
||||
_Inout_ PPH_WORK_QUEUE_ITEM WorkQueueItem
|
||||
);
|
||||
|
||||
HANDLE PhpGetSemaphoreWorkQueue(
|
||||
_Inout_ PPH_WORK_QUEUE WorkQueue
|
||||
);
|
||||
|
||||
BOOLEAN PhpCreateWorkQueueThread(
|
||||
_Inout_ PPH_WORK_QUEUE WorkQueue
|
||||
);
|
||||
|
||||
NTSTATUS PhpWorkQueueThreadStart(
|
||||
_In_ PVOID Parameter
|
||||
);
|
||||
|
||||
#endif
|
||||
1102
phlib/kph.c
Normal file
1102
phlib/kph.c
Normal file
File diff suppressed because it is too large
Load Diff
276
phlib/kphdata.c
Normal file
276
phlib/kphdata.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* KProcessHacker dynamic data definitions
|
||||
*
|
||||
* Copyright (C) 2011-2016 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <kphuser.h>
|
||||
|
||||
#ifdef _WIN64
|
||||
|
||||
ULONG KphpGetKernelRevisionNumber(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ULONG result;
|
||||
PPH_STRING kernelFileName;
|
||||
PVOID versionInfo;
|
||||
VS_FIXEDFILEINFO *rootBlock;
|
||||
ULONG rootBlockLength;
|
||||
|
||||
result = 0;
|
||||
kernelFileName = PhGetKernelFileName();
|
||||
PhMoveReference(&kernelFileName, PhGetFileName(kernelFileName));
|
||||
versionInfo = PhGetFileVersionInfo(kernelFileName->Buffer);
|
||||
PhDereferenceObject(kernelFileName);
|
||||
|
||||
if (versionInfo && VerQueryValue(versionInfo, L"\\", &rootBlock, &rootBlockLength) && rootBlockLength != 0)
|
||||
result = rootBlock->dwFileVersionLS & 0xffff;
|
||||
|
||||
PhFree(versionInfo);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NTSTATUS KphInitializeDynamicPackage(
|
||||
_Out_ PKPH_DYN_PACKAGE Package
|
||||
)
|
||||
{
|
||||
ULONG majorVersion, minorVersion, servicePack, buildNumber;
|
||||
|
||||
majorVersion = PhOsVersion.dwMajorVersion;
|
||||
minorVersion = PhOsVersion.dwMinorVersion;
|
||||
servicePack = PhOsVersion.wServicePackMajor;
|
||||
buildNumber = PhOsVersion.dwBuildNumber;
|
||||
|
||||
memset(&Package->StructData, -1, sizeof(KPH_DYN_STRUCT_DATA));
|
||||
|
||||
Package->MajorVersion = (USHORT)majorVersion;
|
||||
Package->MinorVersion = (USHORT)minorVersion;
|
||||
Package->ServicePackMajor = (USHORT)servicePack;
|
||||
Package->BuildNumber = -1;
|
||||
|
||||
// Windows 7, Windows Server 2008 R2
|
||||
if (majorVersion == 6 && minorVersion == 1)
|
||||
{
|
||||
Package->ResultingNtVersion = PHNT_WIN7;
|
||||
|
||||
if (servicePack == 0)
|
||||
{
|
||||
}
|
||||
else if (servicePack == 1)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
Package->StructData.EgeGuid = 0x14;
|
||||
Package->StructData.EpObjectTable = 0x200;
|
||||
Package->StructData.EreGuidEntry = 0x10;
|
||||
Package->StructData.OtName = 0x10;
|
||||
Package->StructData.OtIndex = 0x28; // now only a UCHAR, not a ULONG
|
||||
}
|
||||
// Windows 8, Windows Server 2012
|
||||
else if (majorVersion == 6 && minorVersion == 2 && buildNumber == 9200)
|
||||
{
|
||||
Package->BuildNumber = 9200;
|
||||
Package->ResultingNtVersion = PHNT_WIN8;
|
||||
|
||||
Package->StructData.EgeGuid = 0x14;
|
||||
Package->StructData.EpObjectTable = 0x408;
|
||||
Package->StructData.EreGuidEntry = 0x10;
|
||||
Package->StructData.HtHandleContentionEvent = 0x30;
|
||||
Package->StructData.OtName = 0x10;
|
||||
Package->StructData.OtIndex = 0x28;
|
||||
Package->StructData.ObDecodeShift = 19;
|
||||
Package->StructData.ObAttributesShift = 20;
|
||||
}
|
||||
// Windows 8.1, Windows Server 2012 R2
|
||||
else if (majorVersion == 6 && minorVersion == 3 && buildNumber == 9600)
|
||||
{
|
||||
ULONG revisionNumber = KphpGetKernelRevisionNumber();
|
||||
|
||||
Package->BuildNumber = 9600;
|
||||
Package->ResultingNtVersion = PHNT_WINBLUE;
|
||||
|
||||
Package->StructData.EgeGuid = 0x18;
|
||||
Package->StructData.EpObjectTable = 0x408;
|
||||
Package->StructData.EreGuidEntry = revisionNumber >= 17736 ? 0x20 : 0x10;
|
||||
Package->StructData.HtHandleContentionEvent = 0x30;
|
||||
Package->StructData.OtName = 0x10;
|
||||
Package->StructData.OtIndex = 0x28;
|
||||
Package->StructData.ObDecodeShift = 16;
|
||||
Package->StructData.ObAttributesShift = 17;
|
||||
}
|
||||
// Windows 10
|
||||
else if (majorVersion == 10 && minorVersion == 0 && buildNumber == 10240)
|
||||
{
|
||||
Package->BuildNumber = 10240;
|
||||
Package->ResultingNtVersion = PHNT_THRESHOLD;
|
||||
|
||||
Package->StructData.EgeGuid = 0x18;
|
||||
Package->StructData.EpObjectTable = 0x418;
|
||||
Package->StructData.EreGuidEntry = 0x20;
|
||||
Package->StructData.HtHandleContentionEvent = 0x30;
|
||||
Package->StructData.OtName = 0x10;
|
||||
Package->StructData.OtIndex = 0x28;
|
||||
Package->StructData.ObDecodeShift = 16;
|
||||
Package->StructData.ObAttributesShift = 17;
|
||||
}
|
||||
else if (majorVersion == 10 && minorVersion == 0 && buildNumber == 10586)
|
||||
{
|
||||
Package->BuildNumber = 10586;
|
||||
Package->ResultingNtVersion = PHNT_THRESHOLD2;
|
||||
|
||||
Package->StructData.EgeGuid = 0x18;
|
||||
Package->StructData.EpObjectTable = 0x418;
|
||||
Package->StructData.EreGuidEntry = 0x20;
|
||||
Package->StructData.HtHandleContentionEvent = 0x30;
|
||||
Package->StructData.OtName = 0x10;
|
||||
Package->StructData.OtIndex = 0x28;
|
||||
Package->StructData.ObDecodeShift = 16;
|
||||
Package->StructData.ObAttributesShift = 17;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
NTSTATUS KphInitializeDynamicPackage(
|
||||
_Out_ PKPH_DYN_PACKAGE Package
|
||||
)
|
||||
{
|
||||
ULONG majorVersion, minorVersion, servicePack, buildNumber;
|
||||
|
||||
majorVersion = PhOsVersion.dwMajorVersion;
|
||||
minorVersion = PhOsVersion.dwMinorVersion;
|
||||
servicePack = PhOsVersion.wServicePackMajor;
|
||||
buildNumber = PhOsVersion.dwBuildNumber;
|
||||
|
||||
memset(&Package->StructData, -1, sizeof(KPH_DYN_STRUCT_DATA));
|
||||
|
||||
Package->MajorVersion = (USHORT)majorVersion;
|
||||
Package->MinorVersion = (USHORT)minorVersion;
|
||||
Package->ServicePackMajor = (USHORT)servicePack;
|
||||
Package->BuildNumber = -1;
|
||||
|
||||
// Windows 7, Windows Server 2008 R2
|
||||
if (majorVersion == 6 && minorVersion == 1)
|
||||
{
|
||||
Package->ResultingNtVersion = PHNT_WIN7;
|
||||
|
||||
if (servicePack == 0)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
else if (servicePack == 1)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
Package->StructData.EgeGuid = 0xc;
|
||||
Package->StructData.EpObjectTable = 0xf4;
|
||||
Package->StructData.EreGuidEntry = 0x8;
|
||||
Package->StructData.OtName = 0x8;
|
||||
Package->StructData.OtIndex = 0x14; // now only a UCHAR, not a ULONG
|
||||
}
|
||||
// Windows 8, Windows Server 2012
|
||||
else if (majorVersion == 6 && minorVersion == 2)
|
||||
{
|
||||
Package->ResultingNtVersion = PHNT_WIN8;
|
||||
|
||||
if (servicePack == 0)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
Package->StructData.EgeGuid = 0xc;
|
||||
Package->StructData.EpObjectTable = 0x150;
|
||||
Package->StructData.EreGuidEntry = 0x8;
|
||||
Package->StructData.OtName = 0x8;
|
||||
Package->StructData.OtIndex = 0x14;
|
||||
}
|
||||
// Windows 8.1, Windows Server 2012 R2
|
||||
else if (majorVersion == 6 && minorVersion == 3)
|
||||
{
|
||||
Package->ResultingNtVersion = PHNT_WINBLUE;
|
||||
|
||||
if (servicePack == 0)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
Package->StructData.EgeGuid = 0xc;
|
||||
Package->StructData.EpObjectTable = 0x150;
|
||||
Package->StructData.EreGuidEntry = 0x8;
|
||||
Package->StructData.OtName = 0x8;
|
||||
Package->StructData.OtIndex = 0x14;
|
||||
}
|
||||
// Windows 10
|
||||
else if (majorVersion == 10 && minorVersion == 0 && buildNumber == 10240)
|
||||
{
|
||||
Package->BuildNumber = 10240;
|
||||
Package->ResultingNtVersion = PHNT_THRESHOLD;
|
||||
|
||||
Package->StructData.EgeGuid = 0xc;
|
||||
Package->StructData.EpObjectTable = 0x154;
|
||||
Package->StructData.EreGuidEntry = 0x10;
|
||||
Package->StructData.OtName = 0x8;
|
||||
Package->StructData.OtIndex = 0x14;
|
||||
}
|
||||
else if (majorVersion == 10 && minorVersion == 0 && buildNumber == 10586)
|
||||
{
|
||||
Package->BuildNumber = 10586;
|
||||
Package->ResultingNtVersion = PHNT_THRESHOLD2;
|
||||
|
||||
Package->StructData.EgeGuid = 0xc;
|
||||
Package->StructData.EpObjectTable = 0x154;
|
||||
Package->StructData.EreGuidEntry = 0x10;
|
||||
Package->StructData.OtName = 0x8;
|
||||
Package->StructData.OtIndex = 0x14;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
480
phlib/lsasup.c
Normal file
480
phlib/lsasup.c
Normal file
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* LSA support functions
|
||||
*
|
||||
* Copyright (C) 2010-2011 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These are functions which communicate with LSA or are support functions. They replace certain
|
||||
* Win32 security-related functions such as LookupAccountName, LookupAccountSid and
|
||||
* LookupPrivilege*, which are badly designed. (LSA already allocates the return values for the
|
||||
* caller, yet the Win32 functions insist on their callers providing their own buffers.)
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <lsasup.h>
|
||||
|
||||
static LSA_HANDLE PhLookupPolicyHandle = NULL;
|
||||
|
||||
NTSTATUS PhOpenLsaPolicy(
|
||||
_Out_ PLSA_HANDLE PolicyHandle,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_In_opt_ PUNICODE_STRING SystemName
|
||||
)
|
||||
{
|
||||
OBJECT_ATTRIBUTES oa = { 0 };
|
||||
|
||||
return LsaOpenPolicy(
|
||||
SystemName,
|
||||
&oa,
|
||||
DesiredAccess,
|
||||
PolicyHandle
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a handle to the local LSA policy with POLICY_LOOKUP_NAMES access.
|
||||
*
|
||||
* \remarks Do not close the handle; it is cached.
|
||||
*/
|
||||
LSA_HANDLE PhGetLookupPolicyHandle(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
LSA_HANDLE lookupPolicyHandle;
|
||||
LSA_HANDLE newLookupPolicyHandle;
|
||||
|
||||
lookupPolicyHandle = PhLookupPolicyHandle;
|
||||
|
||||
// If there is no cached handle, open one.
|
||||
|
||||
if (!lookupPolicyHandle)
|
||||
{
|
||||
if (NT_SUCCESS(PhOpenLsaPolicy(
|
||||
&newLookupPolicyHandle,
|
||||
POLICY_LOOKUP_NAMES,
|
||||
NULL
|
||||
)))
|
||||
{
|
||||
// We succeeded in opening a policy handle, and since we did not have a cached handle
|
||||
// before, we will now store it.
|
||||
|
||||
lookupPolicyHandle = _InterlockedCompareExchangePointer(
|
||||
&PhLookupPolicyHandle,
|
||||
newLookupPolicyHandle,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!lookupPolicyHandle)
|
||||
{
|
||||
// Success. Use our handle.
|
||||
lookupPolicyHandle = newLookupPolicyHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Someone already placed a handle in the cache. Close our handle and use their
|
||||
// handle.
|
||||
LsaClose(newLookupPolicyHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lookupPolicyHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of a privilege from its LUID.
|
||||
*
|
||||
* \param PrivilegeValue The LUID of a privilege.
|
||||
* \param PrivilegeName A variable which receives a pointer to a string containing the privilege
|
||||
* name. You must free the string using PhDereferenceObject() when you no longer need it.
|
||||
*/
|
||||
BOOLEAN PhLookupPrivilegeName(
|
||||
_In_ PLUID PrivilegeValue,
|
||||
_Out_ PPH_STRING *PrivilegeName
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PUNICODE_STRING name;
|
||||
|
||||
status = LsaLookupPrivilegeName(
|
||||
PhGetLookupPolicyHandle(),
|
||||
PrivilegeValue,
|
||||
&name
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return FALSE;
|
||||
|
||||
*PrivilegeName = PhCreateStringFromUnicodeString(name);
|
||||
LsaFreeMemory(name);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display name of a privilege from its name.
|
||||
*
|
||||
* \param PrivilegeName The name of a privilege.
|
||||
* \param PrivilegeDisplayName A variable which receives a pointer to a string containing the
|
||||
* privilege's display name. You must free the string using PhDereferenceObject() when you no longer
|
||||
* need it.
|
||||
*/
|
||||
BOOLEAN PhLookupPrivilegeDisplayName(
|
||||
_In_ PPH_STRINGREF PrivilegeName,
|
||||
_Out_ PPH_STRING *PrivilegeDisplayName
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING privilegeName;
|
||||
PUNICODE_STRING displayName;
|
||||
SHORT language;
|
||||
|
||||
if (!PhStringRefToUnicodeString(PrivilegeName, &privilegeName))
|
||||
return FALSE;
|
||||
|
||||
status = LsaLookupPrivilegeDisplayName(
|
||||
PhGetLookupPolicyHandle(),
|
||||
&privilegeName,
|
||||
&displayName,
|
||||
&language
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return FALSE;
|
||||
|
||||
*PrivilegeDisplayName = PhCreateStringFromUnicodeString(displayName);
|
||||
LsaFreeMemory(displayName);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the LUID of a privilege from its name.
|
||||
*
|
||||
* \param PrivilegeName The name of a privilege.
|
||||
* \param PrivilegeValue A variable which receives the LUID of the privilege.
|
||||
*/
|
||||
BOOLEAN PhLookupPrivilegeValue(
|
||||
_In_ PPH_STRINGREF PrivilegeName,
|
||||
_Out_ PLUID PrivilegeValue
|
||||
)
|
||||
{
|
||||
UNICODE_STRING privilegeName;
|
||||
|
||||
if (!PhStringRefToUnicodeString(PrivilegeName, &privilegeName))
|
||||
return FALSE;
|
||||
|
||||
return NT_SUCCESS(LsaLookupPrivilegeValue(
|
||||
PhGetLookupPolicyHandle(),
|
||||
&privilegeName,
|
||||
PrivilegeValue
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about a SID.
|
||||
*
|
||||
* \param Sid A SID to query.
|
||||
* \param Name A variable which receives a pointer to a string containing the SID's name. You must
|
||||
* free the string using PhDereferenceObject() when you no longer need it.
|
||||
* \param DomainName A variable which receives a pointer to a string containing the SID's domain
|
||||
* name. You must free the string using PhDereferenceObject() when you no longer need it.
|
||||
* \param NameUse A variable which receives the SID's usage.
|
||||
*/
|
||||
NTSTATUS PhLookupSid(
|
||||
_In_ PSID Sid,
|
||||
_Out_opt_ PPH_STRING *Name,
|
||||
_Out_opt_ PPH_STRING *DomainName,
|
||||
_Out_opt_ PSID_NAME_USE NameUse
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
LSA_HANDLE policyHandle;
|
||||
PLSA_REFERENCED_DOMAIN_LIST referencedDomains;
|
||||
PLSA_TRANSLATED_NAME names;
|
||||
|
||||
policyHandle = PhGetLookupPolicyHandle();
|
||||
|
||||
referencedDomains = NULL;
|
||||
names = NULL;
|
||||
|
||||
if (NT_SUCCESS(status = LsaLookupSids(
|
||||
policyHandle,
|
||||
1,
|
||||
&Sid,
|
||||
&referencedDomains,
|
||||
&names
|
||||
)))
|
||||
{
|
||||
if (names[0].Use != SidTypeInvalid && names[0].Use != SidTypeUnknown)
|
||||
{
|
||||
if (Name)
|
||||
{
|
||||
*Name = PhCreateStringFromUnicodeString(&names[0].Name);
|
||||
}
|
||||
|
||||
if (DomainName)
|
||||
{
|
||||
if (names[0].DomainIndex >= 0)
|
||||
{
|
||||
PLSA_TRUST_INFORMATION trustInfo;
|
||||
|
||||
trustInfo = &referencedDomains->Domains[names[0].DomainIndex];
|
||||
*DomainName = PhCreateStringFromUnicodeString(&trustInfo->Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
*DomainName = PhReferenceEmptyString();
|
||||
}
|
||||
}
|
||||
|
||||
if (NameUse)
|
||||
{
|
||||
*NameUse = names[0].Use;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_NONE_MAPPED;
|
||||
}
|
||||
}
|
||||
|
||||
// LsaLookupSids allocates memory even if it returns STATUS_NONE_MAPPED.
|
||||
if (referencedDomains)
|
||||
LsaFreeMemory(referencedDomains);
|
||||
if (names)
|
||||
LsaFreeMemory(names);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about a name.
|
||||
*
|
||||
* \param Name A name to query.
|
||||
* \param Sid A variable which receives a pointer to a SID. You must free the SID using PhFree()
|
||||
* when you no longer need it.
|
||||
* \param DomainName A variable which receives a pointer to a string containing the SID's domain
|
||||
* name. You must free the string using PhDereferenceObject() when you no longer need it.
|
||||
* \param NameUse A variable which receives the SID's usage.
|
||||
*/
|
||||
NTSTATUS PhLookupName(
|
||||
_In_ PPH_STRINGREF Name,
|
||||
_Out_opt_ PSID *Sid,
|
||||
_Out_opt_ PPH_STRING *DomainName,
|
||||
_Out_opt_ PSID_NAME_USE NameUse
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
LSA_HANDLE policyHandle;
|
||||
UNICODE_STRING name;
|
||||
PLSA_REFERENCED_DOMAIN_LIST referencedDomains;
|
||||
PLSA_TRANSLATED_SID2 sids;
|
||||
|
||||
if (!PhStringRefToUnicodeString(Name, &name))
|
||||
return STATUS_NAME_TOO_LONG;
|
||||
|
||||
policyHandle = PhGetLookupPolicyHandle();
|
||||
referencedDomains = NULL;
|
||||
sids = NULL;
|
||||
|
||||
if (NT_SUCCESS(status = LsaLookupNames2(
|
||||
policyHandle,
|
||||
0,
|
||||
1,
|
||||
&name,
|
||||
&referencedDomains,
|
||||
&sids
|
||||
)))
|
||||
{
|
||||
if (sids[0].Use != SidTypeInvalid && sids[0].Use != SidTypeUnknown)
|
||||
{
|
||||
if (Sid)
|
||||
{
|
||||
PSID sid;
|
||||
ULONG sidLength;
|
||||
|
||||
sidLength = RtlLengthSid(sids[0].Sid);
|
||||
sid = PhAllocate(sidLength);
|
||||
memcpy(sid, sids[0].Sid, sidLength);
|
||||
|
||||
*Sid = sid;
|
||||
}
|
||||
|
||||
if (DomainName)
|
||||
{
|
||||
if (sids[0].DomainIndex >= 0)
|
||||
{
|
||||
PLSA_TRUST_INFORMATION trustInfo;
|
||||
|
||||
trustInfo = &referencedDomains->Domains[sids[0].DomainIndex];
|
||||
*DomainName = PhCreateStringFromUnicodeString(&trustInfo->Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
*DomainName = PhReferenceEmptyString();
|
||||
}
|
||||
}
|
||||
|
||||
if (NameUse)
|
||||
{
|
||||
*NameUse = sids[0].Use;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_NONE_MAPPED;
|
||||
}
|
||||
}
|
||||
|
||||
// LsaLookupNames2 allocates memory even if it returns STATUS_NONE_MAPPED.
|
||||
if (referencedDomains)
|
||||
LsaFreeMemory(referencedDomains);
|
||||
if (sids)
|
||||
LsaFreeMemory(sids);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of a SID.
|
||||
*
|
||||
* \param Sid A SID to query.
|
||||
* \param IncludeDomain TRUE to include the domain name, otherwise FALSE.
|
||||
* \param NameUse A variable which receives the SID's usage.
|
||||
*
|
||||
* \return A pointer to a string containing the name of the SID in the following format:
|
||||
* domain\\name. You must free the string using PhDereferenceObject() when you no longer need it. If
|
||||
* an error occurs, the function returns NULL.
|
||||
*/
|
||||
PPH_STRING PhGetSidFullName(
|
||||
_In_ PSID Sid,
|
||||
_In_ BOOLEAN IncludeDomain,
|
||||
_Out_opt_ PSID_NAME_USE NameUse
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PPH_STRING fullName;
|
||||
LSA_HANDLE policyHandle;
|
||||
PLSA_REFERENCED_DOMAIN_LIST referencedDomains;
|
||||
PLSA_TRANSLATED_NAME names;
|
||||
|
||||
policyHandle = PhGetLookupPolicyHandle();
|
||||
|
||||
referencedDomains = NULL;
|
||||
names = NULL;
|
||||
|
||||
if (NT_SUCCESS(status = LsaLookupSids(
|
||||
policyHandle,
|
||||
1,
|
||||
&Sid,
|
||||
&referencedDomains,
|
||||
&names
|
||||
)))
|
||||
{
|
||||
if (names[0].Use != SidTypeInvalid && names[0].Use != SidTypeUnknown)
|
||||
{
|
||||
PWSTR domainNameBuffer;
|
||||
ULONG domainNameLength;
|
||||
|
||||
if (IncludeDomain && names[0].DomainIndex >= 0)
|
||||
{
|
||||
PLSA_TRUST_INFORMATION trustInfo;
|
||||
|
||||
trustInfo = &referencedDomains->Domains[names[0].DomainIndex];
|
||||
domainNameBuffer = trustInfo->Name.Buffer;
|
||||
domainNameLength = trustInfo->Name.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
domainNameBuffer = NULL;
|
||||
domainNameLength = 0;
|
||||
}
|
||||
|
||||
if (domainNameBuffer && domainNameLength != 0)
|
||||
{
|
||||
fullName = PhCreateStringEx(NULL, domainNameLength + sizeof(WCHAR) + names[0].Name.Length);
|
||||
memcpy(&fullName->Buffer[0], domainNameBuffer, domainNameLength);
|
||||
fullName->Buffer[domainNameLength / sizeof(WCHAR)] = '\\';
|
||||
memcpy(&fullName->Buffer[domainNameLength / sizeof(WCHAR) + 1], names[0].Name.Buffer, names[0].Name.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
fullName = PhCreateStringFromUnicodeString(&names[0].Name);
|
||||
}
|
||||
|
||||
if (NameUse)
|
||||
{
|
||||
*NameUse = names[0].Use;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fullName = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fullName = NULL;
|
||||
}
|
||||
|
||||
if (referencedDomains)
|
||||
LsaFreeMemory(referencedDomains);
|
||||
if (names)
|
||||
LsaFreeMemory(names);
|
||||
|
||||
return fullName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a SDDL string representation of a SID.
|
||||
*
|
||||
* \param Sid A SID to query.
|
||||
*
|
||||
* \return A pointer to a string containing the SDDL representation of the SID. You must free the
|
||||
* string using PhDereferenceObject() when you no longer need it. If an error occurs, the function
|
||||
* returns NULL.
|
||||
*/
|
||||
PPH_STRING PhSidToStringSid(
|
||||
_In_ PSID Sid
|
||||
)
|
||||
{
|
||||
PPH_STRING string;
|
||||
UNICODE_STRING us;
|
||||
|
||||
string = PhCreateStringEx(NULL, MAX_UNICODE_STACK_BUFFER_LENGTH * sizeof(WCHAR));
|
||||
PhStringRefToUnicodeString(&string->sr, &us);
|
||||
|
||||
if (NT_SUCCESS(RtlConvertSidToUnicodeString(
|
||||
&us,
|
||||
Sid,
|
||||
FALSE
|
||||
)))
|
||||
{
|
||||
string->Length = us.Length;
|
||||
string->Buffer[us.Length / sizeof(WCHAR)] = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
1218
phlib/mapimg.c
Normal file
1218
phlib/mapimg.c
Normal file
File diff suppressed because it is too large
Load Diff
402
phlib/maplib.c
Normal file
402
phlib/maplib.c
Normal file
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* mapped library
|
||||
*
|
||||
* Copyright (C) 2010 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains functions to load and retrieve information for library/archive files (lib).
|
||||
* The file format for archive files is explained in the PE/COFF specification located at:
|
||||
*
|
||||
* http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <mapimg.h>
|
||||
|
||||
VOID PhpMappedArchiveProbe(
|
||||
_In_ PPH_MAPPED_ARCHIVE MappedArchive,
|
||||
_In_ PVOID Address,
|
||||
_In_ SIZE_T Length
|
||||
);
|
||||
|
||||
NTSTATUS PhpGetMappedArchiveMemberFromHeader(
|
||||
_In_ PPH_MAPPED_ARCHIVE MappedArchive,
|
||||
_In_ PIMAGE_ARCHIVE_MEMBER_HEADER Header,
|
||||
_Out_ PPH_MAPPED_ARCHIVE_MEMBER Member
|
||||
);
|
||||
|
||||
NTSTATUS PhInitializeMappedArchive(
|
||||
_Out_ PPH_MAPPED_ARCHIVE MappedArchive,
|
||||
_In_ PVOID ViewBase,
|
||||
_In_ SIZE_T Size
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PCHAR start;
|
||||
|
||||
start = (PCHAR)ViewBase;
|
||||
|
||||
memset(MappedArchive, 0, sizeof(PH_MAPPED_ARCHIVE));
|
||||
MappedArchive->ViewBase = ViewBase;
|
||||
MappedArchive->Size = Size;
|
||||
|
||||
__try
|
||||
{
|
||||
// Verify the file signature.
|
||||
|
||||
PhpMappedArchiveProbe(MappedArchive, start, IMAGE_ARCHIVE_START_SIZE);
|
||||
|
||||
if (memcmp(start, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE) != 0)
|
||||
PhRaiseStatus(STATUS_INVALID_IMAGE_FORMAT);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
return GetExceptionCode();
|
||||
}
|
||||
|
||||
// Get the members.
|
||||
// Note: the names are checked.
|
||||
|
||||
// First linker member
|
||||
|
||||
status = PhpGetMappedArchiveMemberFromHeader(
|
||||
MappedArchive,
|
||||
(PIMAGE_ARCHIVE_MEMBER_HEADER)(start + IMAGE_ARCHIVE_START_SIZE),
|
||||
&MappedArchive->FirstLinkerMember
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
if (MappedArchive->FirstLinkerMember.Type != LinkerArchiveMemberType)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
MappedArchive->FirstStandardMember = &MappedArchive->FirstLinkerMember;
|
||||
|
||||
// Second linker member
|
||||
|
||||
status = PhGetNextMappedArchiveMember(
|
||||
&MappedArchive->FirstLinkerMember,
|
||||
&MappedArchive->SecondLinkerMember
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
if (MappedArchive->SecondLinkerMember.Type != LinkerArchiveMemberType)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
// Longnames member
|
||||
// This member doesn't seem to be mandatory, contrary to the specification.
|
||||
// So we'll check if it's actually a longnames member, and if not, ignore it.
|
||||
|
||||
status = PhGetNextMappedArchiveMember(
|
||||
&MappedArchive->SecondLinkerMember,
|
||||
&MappedArchive->LongnamesMember
|
||||
);
|
||||
|
||||
if (
|
||||
NT_SUCCESS(status) &&
|
||||
MappedArchive->LongnamesMember.Type == LongnamesArchiveMemberType
|
||||
)
|
||||
{
|
||||
MappedArchive->HasLongnamesMember = TRUE;
|
||||
MappedArchive->LastStandardMember = &MappedArchive->LongnamesMember;
|
||||
}
|
||||
else
|
||||
{
|
||||
MappedArchive->LastStandardMember = &MappedArchive->SecondLinkerMember;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS PhLoadMappedArchive(
|
||||
_In_opt_ PWSTR FileName,
|
||||
_In_opt_ HANDLE FileHandle,
|
||||
_In_ BOOLEAN ReadOnly,
|
||||
_Out_ PPH_MAPPED_ARCHIVE MappedArchive
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
status = PhMapViewOfEntireFile(
|
||||
FileName,
|
||||
FileHandle,
|
||||
ReadOnly,
|
||||
&MappedArchive->ViewBase,
|
||||
&MappedArchive->Size
|
||||
);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
status = PhInitializeMappedArchive(
|
||||
MappedArchive,
|
||||
MappedArchive->ViewBase,
|
||||
MappedArchive->Size
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), MappedArchive->ViewBase);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhUnloadMappedArchive(
|
||||
_Inout_ PPH_MAPPED_ARCHIVE MappedArchive
|
||||
)
|
||||
{
|
||||
return NtUnmapViewOfSection(
|
||||
NtCurrentProcess(),
|
||||
MappedArchive->ViewBase
|
||||
);
|
||||
}
|
||||
|
||||
VOID PhpMappedArchiveProbe(
|
||||
_In_ PPH_MAPPED_ARCHIVE MappedArchive,
|
||||
_In_ PVOID Address,
|
||||
_In_ SIZE_T Length
|
||||
)
|
||||
{
|
||||
PhProbeAddress(Address, Length, MappedArchive->ViewBase, MappedArchive->Size, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next archive member.
|
||||
*
|
||||
* \param Member An archive member structure.
|
||||
* \param NextMember A variable which receives a structure describing the next archive member. This
|
||||
* pointer may be the same as the pointer specified in \a Member.
|
||||
*/
|
||||
NTSTATUS PhGetNextMappedArchiveMember(
|
||||
_In_ PPH_MAPPED_ARCHIVE_MEMBER Member,
|
||||
_Out_ PPH_MAPPED_ARCHIVE_MEMBER NextMember
|
||||
)
|
||||
{
|
||||
PIMAGE_ARCHIVE_MEMBER_HEADER nextHeader;
|
||||
|
||||
nextHeader = (PIMAGE_ARCHIVE_MEMBER_HEADER)PTR_ADD_OFFSET(
|
||||
Member->Data,
|
||||
Member->Size
|
||||
);
|
||||
|
||||
// 2 byte alignment.
|
||||
if ((ULONG_PTR)nextHeader & 0x1)
|
||||
nextHeader = (PIMAGE_ARCHIVE_MEMBER_HEADER)PTR_ADD_OFFSET(nextHeader, 1);
|
||||
|
||||
return PhpGetMappedArchiveMemberFromHeader(
|
||||
Member->MappedArchive,
|
||||
nextHeader,
|
||||
NextMember
|
||||
);
|
||||
}
|
||||
|
||||
NTSTATUS PhpGetMappedArchiveMemberFromHeader(
|
||||
_In_ PPH_MAPPED_ARCHIVE MappedArchive,
|
||||
_In_ PIMAGE_ARCHIVE_MEMBER_HEADER Header,
|
||||
_Out_ PPH_MAPPED_ARCHIVE_MEMBER Member
|
||||
)
|
||||
{
|
||||
WCHAR integerString[11];
|
||||
ULONG64 size;
|
||||
PH_STRINGREF string;
|
||||
PWSTR digit;
|
||||
PSTR slash;
|
||||
|
||||
if ((ULONG_PTR)Header >= (ULONG_PTR)MappedArchive->ViewBase + MappedArchive->Size)
|
||||
return STATUS_NO_MORE_ENTRIES;
|
||||
|
||||
__try
|
||||
{
|
||||
PhpMappedArchiveProbe(MappedArchive, Header, sizeof(IMAGE_ARCHIVE_MEMBER_HEADER));
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
return GetExceptionCode();
|
||||
}
|
||||
|
||||
Member->MappedArchive = MappedArchive;
|
||||
Member->Header = Header;
|
||||
Member->Data = PTR_ADD_OFFSET(Header, sizeof(IMAGE_ARCHIVE_MEMBER_HEADER));
|
||||
Member->Type = NormalArchiveMemberType;
|
||||
|
||||
// Read the size string, terminate it after the last digit and parse it.
|
||||
|
||||
if (!PhCopyStringZFromBytes(Header->Size, 10, integerString, 11, NULL))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
string.Buffer = integerString;
|
||||
string.Length = 0;
|
||||
digit = string.Buffer;
|
||||
|
||||
while (iswdigit(*digit++))
|
||||
string.Length += sizeof(WCHAR);
|
||||
|
||||
if (!PhStringToInteger64(&string, 10, &size))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Member->Size = (ULONG)size;
|
||||
|
||||
__try
|
||||
{
|
||||
PhpMappedArchiveProbe(MappedArchive, Member->Data, Member->Size);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
return GetExceptionCode();
|
||||
}
|
||||
|
||||
// Parse the name.
|
||||
|
||||
if (!PhCopyBytesZ(Header->Name, 16, Member->NameBuffer, 20, NULL))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Member->Name = Member->NameBuffer;
|
||||
|
||||
slash = strchr(Member->NameBuffer, '/');
|
||||
|
||||
if (!slash)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
// Special names:
|
||||
// * If the slash is the first character, then this is a linker member.
|
||||
// * If there is a slash after the slash which is a first character, then this is the longnames
|
||||
// member.
|
||||
// * If there are digits after the slash, then the real name is stored in the longnames member.
|
||||
|
||||
if (slash == Member->NameBuffer)
|
||||
{
|
||||
if (Member->NameBuffer[1] == '/')
|
||||
{
|
||||
// Longnames member. Set the name to "/".
|
||||
Member->NameBuffer[0] = '/';
|
||||
Member->NameBuffer[1] = 0;
|
||||
|
||||
Member->Type = LongnamesArchiveMemberType;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Linker member. Set the name to "".
|
||||
Member->NameBuffer[0] = 0;
|
||||
|
||||
Member->Type = LinkerArchiveMemberType;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isdigit(slash[1]))
|
||||
{
|
||||
PSTR digita;
|
||||
ULONG64 offset64;
|
||||
ULONG offset;
|
||||
|
||||
// The name is stored in the longnames member.
|
||||
// Note: we make sure we have the longnames member first.
|
||||
|
||||
if (!MappedArchive->LongnamesMember.Header)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
// Find the last digit and null terminate the string there.
|
||||
|
||||
digita = slash + 2;
|
||||
|
||||
while (isdigit(*digita))
|
||||
digita++;
|
||||
|
||||
*digita = 0;
|
||||
|
||||
// Parse the offset and make sure it lies within the longnames member.
|
||||
|
||||
if (!PhCopyStringZFromBytes(slash + 1, -1, integerString, 11, NULL))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
PhInitializeStringRefLongHint(&string, integerString);
|
||||
if (!PhStringToInteger64(&string, 10, &offset64))
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
offset = (ULONG)offset64;
|
||||
|
||||
if (offset >= MappedArchive->LongnamesMember.Size)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
// TODO: Probe the name.
|
||||
Member->Name = (PSTR)PTR_ADD_OFFSET(MappedArchive->LongnamesMember.Data, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Null terminate the string.
|
||||
slash[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN PhIsMappedArchiveMemberShortFormat(
|
||||
_In_ PPH_MAPPED_ARCHIVE_MEMBER Member
|
||||
)
|
||||
{
|
||||
PIMAGE_FILE_HEADER header;
|
||||
|
||||
header = (PIMAGE_FILE_HEADER)Member->Data;
|
||||
|
||||
return header->Machine != IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
}
|
||||
|
||||
NTSTATUS PhGetMappedArchiveImportEntry(
|
||||
_In_ PPH_MAPPED_ARCHIVE_MEMBER Member,
|
||||
_Out_ PPH_MAPPED_ARCHIVE_IMPORT_ENTRY Entry
|
||||
)
|
||||
{
|
||||
IMPORT_OBJECT_HEADER *importHeader;
|
||||
|
||||
importHeader = (IMPORT_OBJECT_HEADER *)Member->Data;
|
||||
|
||||
if (Member->Type != NormalArchiveMemberType)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (
|
||||
importHeader->Sig1 != IMAGE_FILE_MACHINE_UNKNOWN ||
|
||||
importHeader->Sig2 != IMPORT_OBJECT_HDR_SIG2
|
||||
)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
Entry->Type = (BYTE)importHeader->Type;
|
||||
Entry->NameType = (BYTE)importHeader->NameType;
|
||||
Entry->Machine = importHeader->Machine;
|
||||
|
||||
// TODO: Probe the name.
|
||||
Entry->Name = (PSTR)PTR_ADD_OFFSET(importHeader, sizeof(IMPORT_OBJECT_HEADER));
|
||||
Entry->DllName = (PSTR)PTR_ADD_OFFSET(Entry->Name, strlen(Entry->Name) + 1);
|
||||
|
||||
// Ordinal/NameHint are union'ed, so these statements are exactly the same.
|
||||
// It's there in case this changes in the future.
|
||||
if (Entry->NameType == IMPORT_OBJECT_ORDINAL)
|
||||
{
|
||||
Entry->Ordinal = importHeader->Ordinal;
|
||||
}
|
||||
else
|
||||
{
|
||||
Entry->NameHint = importHeader->Hint;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
225
phlib/md5.c
Normal file
225
phlib/md5.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* MD5 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* This code was modified for Process Hacker. */
|
||||
|
||||
#include <phbase.h>
|
||||
#include "md5.h"
|
||||
|
||||
void MD5Transform(ULONG buf[4], ULONG in[16]);
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
VOID MD5Init(
|
||||
_Out_ MD5_CTX *Context
|
||||
)
|
||||
{
|
||||
Context->buf[0] = 0x67452301;
|
||||
Context->buf[1] = 0xefcdab89;
|
||||
Context->buf[2] = 0x98badcfe;
|
||||
Context->buf[3] = 0x10325476;
|
||||
|
||||
Context->i[0] = 0;
|
||||
Context->i[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
VOID MD5Update(
|
||||
_Inout_ MD5_CTX *Context,
|
||||
_In_reads_bytes_(Length) UCHAR *Input,
|
||||
_In_ ULONG Length
|
||||
)
|
||||
{
|
||||
ULONG t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = Context->i[0];
|
||||
if ((Context->i[0] = t + ((ULONG) Length << 3)) < t)
|
||||
Context->i[1]++; /* Carry from low to high */
|
||||
Context->i[1] += Length >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
unsigned char *p = (unsigned char *) Context->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (Length < t) {
|
||||
memcpy(p, Input, Length);
|
||||
return;
|
||||
}
|
||||
memcpy(p, Input, t);
|
||||
MD5Transform(Context->buf, (ULONG *) Context->in);
|
||||
Input += t;
|
||||
Length -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (Length >= 64) {
|
||||
memcpy(Context->in, Input, 64);
|
||||
MD5Transform(Context->buf, (ULONG *) Context->in);
|
||||
Input += 64;
|
||||
Length -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
memcpy(Context->in, Input, Length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
VOID MD5Final(
|
||||
_Inout_ MD5_CTX *Context
|
||||
)
|
||||
{
|
||||
unsigned int count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (Context->i[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = Context->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
MD5Transform(Context->buf, (ULONG *) Context->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(Context->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((ULONG *) Context->in)[14] = Context->i[0];
|
||||
((ULONG *) Context->in)[15] = Context->i[1];
|
||||
|
||||
MD5Transform(Context->buf, (ULONG *) Context->in);
|
||||
memcpy(Context->digest, Context->buf, 16);
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = _rotl(w, s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
void MD5Transform(ULONG buf[4], ULONG in[16])
|
||||
{
|
||||
register ULONG a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
26
phlib/md5.h
Normal file
26
phlib/md5.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _MD5_H
|
||||
#define _MD5_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG i[2];
|
||||
ULONG buf[4];
|
||||
UCHAR in[64];
|
||||
UCHAR digest[16];
|
||||
} MD5_CTX;
|
||||
|
||||
VOID MD5Init(
|
||||
_Out_ MD5_CTX *Context
|
||||
);
|
||||
|
||||
VOID MD5Update(
|
||||
_Inout_ MD5_CTX *Context,
|
||||
_In_reads_bytes_(Length) UCHAR *Input,
|
||||
_In_ ULONG Length
|
||||
);
|
||||
|
||||
VOID MD5Final(
|
||||
_Inout_ MD5_CTX *Context
|
||||
);
|
||||
|
||||
#endif
|
||||
6460
phlib/native.c
Normal file
6460
phlib/native.c
Normal file
File diff suppressed because it is too large
Load Diff
247
phlib/phlib.vcxproj
Normal file
247
phlib/phlib.vcxproj
Normal file
@@ -0,0 +1,247 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{477D0215-F252-41A1-874B-F27E3EA1ED17}</ProjectGuid>
|
||||
<RootNamespace>phlib</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)bin\$(Configuration)$(PlatformArchitecture)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)bin\$(Configuration)$(PlatformArchitecture)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)bin\$(Configuration)$(PlatformArchitecture)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)bin\$(Configuration)$(PlatformArchitecture)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\phnt\include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>DEBUG;_PHLIB_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\phnt\include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>DEBUG;_PHLIB_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\phnt\include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_PHLIB_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\phnt\include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_PHLIB_;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CallingConvention>StdCall</CallingConvention>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="apiimport.c" />
|
||||
<ClCompile Include="avltree.c" />
|
||||
<ClCompile Include="basesup.c" />
|
||||
<ClCompile Include="circbuf.c" />
|
||||
<ClCompile Include="colorbox.c" />
|
||||
<ClCompile Include="cpysave.c" />
|
||||
<ClCompile Include="data.c" />
|
||||
<ClCompile Include="dspick.c" />
|
||||
<ClCompile Include="emenu.c" />
|
||||
<ClCompile Include="error.c" />
|
||||
<ClCompile Include="extlv.c" />
|
||||
<ClCompile Include="fastlock.c" />
|
||||
<ClCompile Include="filepool.c" />
|
||||
<ClCompile Include="format.c" />
|
||||
<ClCompile Include="global.c" />
|
||||
<ClCompile Include="graph.c" />
|
||||
<ClCompile Include="guisup.c" />
|
||||
<ClCompile Include="handle.c" />
|
||||
<ClCompile Include="hexedit.c" />
|
||||
<ClCompile Include="hndlinfo.c" />
|
||||
<ClCompile Include="icotobmp.c" />
|
||||
<ClCompile Include="filestream.c" />
|
||||
<ClCompile Include="kph.c" />
|
||||
<ClCompile Include="kphdata.c" />
|
||||
<ClCompile Include="lsasup.c" />
|
||||
<ClCompile Include="mapimg.c" />
|
||||
<ClCompile Include="maplib.c" />
|
||||
<ClCompile Include="md5.c" />
|
||||
<ClCompile Include="native.c" />
|
||||
<ClCompile Include="provider.c" />
|
||||
<ClCompile Include="queuedlock.c" />
|
||||
<ClCompile Include="ref.c" />
|
||||
<ClCompile Include="secdata.c" />
|
||||
<ClCompile Include="secedit.c" />
|
||||
<ClCompile Include="sha.c" />
|
||||
<ClCompile Include="util.c" />
|
||||
<ClCompile Include="svcsup.c" />
|
||||
<ClCompile Include="symprv.c" />
|
||||
<ClCompile Include="sync.c" />
|
||||
<ClCompile Include="treenew.c" />
|
||||
<ClCompile Include="verify.c" />
|
||||
<ClCompile Include="workqueue.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\apiimport.h" />
|
||||
<ClInclude Include="include\cpysave.h" />
|
||||
<ClInclude Include="include\filepool.h" />
|
||||
<ClInclude Include="include\filepoolp.h" />
|
||||
<ClInclude Include="include\filestream.h" />
|
||||
<ClInclude Include="include\handle.h" />
|
||||
<ClInclude Include="include\hndlinfo.h" />
|
||||
<ClInclude Include="include\kphapi.h" />
|
||||
<ClInclude Include="include\kphuserp.h" />
|
||||
<ClInclude Include="include\lsasup.h" />
|
||||
<ClInclude Include="include\mapimg.h" />
|
||||
<ClInclude Include="include\phbasesup.h" />
|
||||
<ClInclude Include="include\phconfig.h" />
|
||||
<ClInclude Include="include\phdata.h" />
|
||||
<ClInclude Include="include\phintrnl.h" />
|
||||
<ClInclude Include="include\phnative.h" />
|
||||
<ClInclude Include="include\phnativeinl.h" />
|
||||
<ClInclude Include="include\circbuf.h" />
|
||||
<ClInclude Include="include\circbuf_h.h" />
|
||||
<ClInclude Include="circbuf_i.h" />
|
||||
<ClInclude Include="include\colorbox.h" />
|
||||
<ClInclude Include="include\phutil.h" />
|
||||
<ClInclude Include="include\provider.h" />
|
||||
<ClInclude Include="include\secedit.h" />
|
||||
<ClInclude Include="include\svcsup.h" />
|
||||
<ClInclude Include="include\symprvp.h" />
|
||||
<ClInclude Include="include\treenew.h" />
|
||||
<ClInclude Include="include\treenewp.h" />
|
||||
<ClInclude Include="include\verify.h" />
|
||||
<ClInclude Include="include\dltmgr.h" />
|
||||
<ClInclude Include="include\dspick.h" />
|
||||
<ClInclude Include="include\emenu.h" />
|
||||
<ClInclude Include="include\fastlock.h" />
|
||||
<ClInclude Include="format_i.h" />
|
||||
<ClInclude Include="include\graph.h" />
|
||||
<ClInclude Include="include\guisupp.h" />
|
||||
<ClInclude Include="include\handlep.h" />
|
||||
<ClInclude Include="include\hexedit.h" />
|
||||
<ClInclude Include="include\hexeditp.h" />
|
||||
<ClInclude Include="include\filestreamp.h" />
|
||||
<ClInclude Include="include\kphuser.h" />
|
||||
<ClInclude Include="md5.h" />
|
||||
<ClInclude Include="include\ph.h" />
|
||||
<ClInclude Include="include\phbase.h" />
|
||||
<ClInclude Include="include\guisup.h" />
|
||||
<ClInclude Include="include\phnet.h" />
|
||||
<ClInclude Include="include\phsup.h" />
|
||||
<ClInclude Include="include\queuedlock.h" />
|
||||
<ClInclude Include="include\ref.h" />
|
||||
<ClInclude Include="include\refp.h" />
|
||||
<ClInclude Include="include\seceditp.h" />
|
||||
<ClInclude Include="sha.h" />
|
||||
<ClInclude Include="include\symprv.h" />
|
||||
<ClInclude Include="include\templ.h" />
|
||||
<ClInclude Include="include\verifyp.h" />
|
||||
<ClInclude Include="include\workqueue.h" />
|
||||
<ClInclude Include="include\workqueuep.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
314
phlib/phlib.vcxproj.filters
Normal file
314
phlib/phlib.vcxproj.filters
Normal file
@@ -0,0 +1,314 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="basesup.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="circbuf.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="colorbox.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="data.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dspick.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="emenu.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="error.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="extlv.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="fastlock.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="format.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="global.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="graph.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="guisup.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="handle.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hexedit.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hndlinfo.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="icotobmp.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="kph.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mapimg.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="maplib.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="md5.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="native.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="provider.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="queuedlock.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ref.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="secdata.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="secedit.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sha.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="svcsup.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="symprv.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sync.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="verify.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="workqueue.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cpysave.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="filepool.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="treenew.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="kphdata.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="apiimport.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="avltree.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="filestream.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="lsasup.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\circbuf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\circbuf_h.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="circbuf_i.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\colorbox.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\dltmgr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\dspick.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\emenu.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\fastlock.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="format_i.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\graph.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\guisupp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\handlep.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\hexedit.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\hexeditp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\ph.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phbase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phnet.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phsup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\queuedlock.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\ref.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\refp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\seceditp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\symprv.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\templ.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\verifyp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phintrnl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\kphapi.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\kphuser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\cpysave.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\filepool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\filepoolp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\treenew.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\treenewp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\verify.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\secedit.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\symprvp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\apiimport.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\handle.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\workqueue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\mapimg.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\workqueuep.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\filestreamp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\filestream.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\hndlinfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\provider.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phdata.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phconfig.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phbasesup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\lsasup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phnativeinl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phnative.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\svcsup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\phutil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="md5.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sha.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\guisup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\kphuserp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
470
phlib/provider.c
Normal file
470
phlib/provider.c
Normal file
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* provider system
|
||||
*
|
||||
* Copyright (C) 2009-2016 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Provider objects allow a function to be executed periodically. This is managed by a
|
||||
* synchronization timer object which is signaled periodically. The use of a timer object as opposed
|
||||
* to a simple sleep call means that the length of time a provider function takes to execute has no
|
||||
* effect on the interval between runs.
|
||||
*
|
||||
* In contrast to callback objects, the context passed to provider functions must be
|
||||
* reference-counted objects. This means that it is not guaranteed that the function will not be in
|
||||
* execution after the unregister operation is complete. However, the since the context object is
|
||||
* reference-counted, there are no safety issues.
|
||||
*
|
||||
* Providers can be boosted, which causes them to be run immediately ignoring the interval. This is
|
||||
* separate to the periodic runs, and does not cause the next periodic run to be missed. Providers,
|
||||
* even when boosted, always run on the same provider thread. The other option would be to have the
|
||||
* boosting thread run the provider function directly, which would involve unnecessary blocking and
|
||||
* synchronization.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <provider.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
PPH_LIST PhDbgProviderList;
|
||||
PH_QUEUED_LOCK PhDbgProviderListLock = PH_QUEUED_LOCK_INIT;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initializes a provider thread.
|
||||
*
|
||||
* \param ProviderThread A pointer to a provider thread object.
|
||||
* \param Interval The interval between each run, in milliseconds.
|
||||
*/
|
||||
VOID PhInitializeProviderThread(
|
||||
_Out_ PPH_PROVIDER_THREAD ProviderThread,
|
||||
_In_ ULONG Interval
|
||||
)
|
||||
{
|
||||
ProviderThread->ThreadHandle = NULL;
|
||||
ProviderThread->TimerHandle = NULL;
|
||||
ProviderThread->Interval = Interval;
|
||||
ProviderThread->State = ProviderThreadStopped;
|
||||
|
||||
PhInitializeQueuedLock(&ProviderThread->Lock);
|
||||
InitializeListHead(&ProviderThread->ListHead);
|
||||
ProviderThread->BoostCount = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
PhAcquireQueuedLockExclusive(&PhDbgProviderListLock);
|
||||
if (!PhDbgProviderList)
|
||||
PhDbgProviderList = PhCreateList(4);
|
||||
PhAddItemList(PhDbgProviderList, ProviderThread);
|
||||
PhReleaseQueuedLockExclusive(&PhDbgProviderListLock);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees resources used by a provider thread.
|
||||
*
|
||||
* \param ProviderThread A pointer to a provider thread object.
|
||||
*/
|
||||
VOID PhDeleteProviderThread(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread
|
||||
)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
ULONG index;
|
||||
#endif
|
||||
// Nothing
|
||||
|
||||
#ifdef DEBUG
|
||||
PhAcquireQueuedLockExclusive(&PhDbgProviderListLock);
|
||||
if ((index = PhFindItemList(PhDbgProviderList, ProviderThread)) != -1)
|
||||
PhRemoveItemList(PhDbgProviderList, index);
|
||||
PhReleaseQueuedLockExclusive(&PhDbgProviderListLock);
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI PhpProviderThreadStart(
|
||||
_In_ PVOID Parameter
|
||||
)
|
||||
{
|
||||
PH_AUTO_POOL autoPool;
|
||||
PPH_PROVIDER_THREAD providerThread = (PPH_PROVIDER_THREAD)Parameter;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
PLIST_ENTRY listEntry;
|
||||
PPH_PROVIDER_REGISTRATION registration;
|
||||
PPH_PROVIDER_FUNCTION providerFunction;
|
||||
PVOID object;
|
||||
LIST_ENTRY tempListHead;
|
||||
|
||||
PhInitializeAutoPool(&autoPool);
|
||||
|
||||
while (providerThread->State != ProviderThreadStopping)
|
||||
{
|
||||
// Keep removing and executing providers from the list until there are no more. Each removed
|
||||
// provider will be placed on the temporary list. After this is done, all providers on the
|
||||
// temporary list will be re-added to the list again.
|
||||
//
|
||||
// The key to this working safely with the other functions (boost, register, unregister) is
|
||||
// that at all times when the mutex is not acquired every single provider must be in a list
|
||||
// (main list or the temp list).
|
||||
|
||||
InitializeListHead(&tempListHead);
|
||||
|
||||
PhAcquireQueuedLockExclusive(&providerThread->Lock);
|
||||
|
||||
// Main loop.
|
||||
|
||||
// We check the status variable for STATUS_ALERTED, which means that someone is requesting
|
||||
// that a provider be boosted. Note that if they alert this thread while we are not waiting
|
||||
// on the timer, when we do perform the wait it will return immediately with STATUS_ALERTED.
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (status == STATUS_ALERTED)
|
||||
{
|
||||
// Check if we have any more providers to boost. Note that this always works because
|
||||
// boosted providers are always in front of normal providers. Therefore we will
|
||||
// never mistakenly boost normal providers.
|
||||
|
||||
if (providerThread->BoostCount == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
listEntry = RemoveHeadList(&providerThread->ListHead);
|
||||
|
||||
if (listEntry == &providerThread->ListHead)
|
||||
break;
|
||||
|
||||
registration = CONTAINING_RECORD(listEntry, PH_PROVIDER_REGISTRATION, ListEntry);
|
||||
|
||||
// Add the provider to the temp list.
|
||||
InsertTailList(&tempListHead, listEntry);
|
||||
|
||||
if (status != STATUS_ALERTED)
|
||||
{
|
||||
if (!registration->Enabled || registration->Unregistering)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we're boosting providers, we don't care if they are enabled or not. However,
|
||||
// we have to make sure any providers which are being unregistered get a chance to
|
||||
// fix the boost count.
|
||||
|
||||
if (registration->Unregistering)
|
||||
{
|
||||
PhReleaseQueuedLockExclusive(&providerThread->Lock);
|
||||
PhAcquireQueuedLockExclusive(&providerThread->Lock);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == STATUS_ALERTED)
|
||||
{
|
||||
assert(registration->Boosting);
|
||||
registration->Boosting = FALSE;
|
||||
providerThread->BoostCount--;
|
||||
}
|
||||
|
||||
providerFunction = registration->Function;
|
||||
object = registration->Object;
|
||||
|
||||
if (object)
|
||||
PhReferenceObject(object);
|
||||
|
||||
registration->RunId++;
|
||||
|
||||
PhReleaseQueuedLockExclusive(&providerThread->Lock);
|
||||
providerFunction(object);
|
||||
PhDrainAutoPool(&autoPool);
|
||||
PhAcquireQueuedLockExclusive(&providerThread->Lock);
|
||||
|
||||
if (object)
|
||||
PhDereferenceObject(object);
|
||||
}
|
||||
|
||||
// Re-add the items in the temp list to the main list.
|
||||
|
||||
while ((listEntry = RemoveHeadList(&tempListHead)) != &tempListHead)
|
||||
{
|
||||
registration = CONTAINING_RECORD(listEntry, PH_PROVIDER_REGISTRATION, ListEntry);
|
||||
|
||||
// We must insert boosted providers at the front of the list in order to maintain the
|
||||
// condition that boosted providers are always in front of normal providers. This occurs
|
||||
// when the timer is signaled just before a boosting provider alerts our thread.
|
||||
if (!registration->Boosting)
|
||||
InsertTailList(&providerThread->ListHead, listEntry);
|
||||
else
|
||||
InsertHeadList(&providerThread->ListHead, listEntry);
|
||||
}
|
||||
|
||||
PhReleaseQueuedLockExclusive(&providerThread->Lock);
|
||||
|
||||
// Perform an alertable wait so we can be woken up by someone telling us to boost providers,
|
||||
// or to terminate.
|
||||
status = NtWaitForSingleObject(
|
||||
providerThread->TimerHandle,
|
||||
TRUE,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
PhDeleteAutoPool(&autoPool);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a provider thread.
|
||||
*
|
||||
* \param ProviderThread A pointer to a provider thread object.
|
||||
*/
|
||||
VOID PhStartProviderThread(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread
|
||||
)
|
||||
{
|
||||
if (ProviderThread->State != ProviderThreadStopped)
|
||||
return;
|
||||
|
||||
// Create and set the timer.
|
||||
NtCreateTimer(&ProviderThread->TimerHandle, TIMER_ALL_ACCESS, NULL, SynchronizationTimer);
|
||||
PhSetIntervalProviderThread(ProviderThread, ProviderThread->Interval);
|
||||
|
||||
// Create and start the thread.
|
||||
ProviderThread->ThreadHandle = PhCreateThread(
|
||||
0,
|
||||
PhpProviderThreadStart,
|
||||
ProviderThread
|
||||
);
|
||||
|
||||
ProviderThread->State = ProviderThreadRunning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops a provider thread.
|
||||
*
|
||||
* \param ProviderThread A pointer to a provider thread object.
|
||||
*/
|
||||
VOID PhStopProviderThread(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread
|
||||
)
|
||||
{
|
||||
if (ProviderThread->State != ProviderThreadRunning)
|
||||
return;
|
||||
|
||||
// Signal to the thread that we are shutting down, and wait for it to exit.
|
||||
ProviderThread->State = ProviderThreadStopping;
|
||||
NtAlertThread(ProviderThread->ThreadHandle); // wake it up
|
||||
NtWaitForSingleObject(ProviderThread->ThreadHandle, FALSE, NULL);
|
||||
|
||||
// Free resources.
|
||||
NtClose(ProviderThread->ThreadHandle);
|
||||
NtClose(ProviderThread->TimerHandle);
|
||||
ProviderThread->ThreadHandle = NULL;
|
||||
ProviderThread->TimerHandle = NULL;
|
||||
|
||||
ProviderThread->State = ProviderThreadStopped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the run interval for a provider thread.
|
||||
*
|
||||
* \param ProviderThread A pointer to a provider thread object.
|
||||
* \param Interval The interval between each run, in milliseconds.
|
||||
*/
|
||||
VOID PhSetIntervalProviderThread(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread,
|
||||
_In_ ULONG Interval
|
||||
)
|
||||
{
|
||||
ProviderThread->Interval = Interval;
|
||||
|
||||
if (ProviderThread->TimerHandle)
|
||||
{
|
||||
LARGE_INTEGER interval;
|
||||
|
||||
interval.QuadPart = -(LONGLONG)Interval * PH_TIMEOUT_MS;
|
||||
NtSetTimer(ProviderThread->TimerHandle, &interval, NULL, NULL, FALSE, Interval, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a provider with a provider thread.
|
||||
*
|
||||
* \param ProviderThread A pointer to a provider thread object.
|
||||
* \param Function The provider function.
|
||||
* \param Object A pointer to an object to pass to the provider function. The object must be managed
|
||||
* by the reference-counting system.
|
||||
* \param Registration A variable which receives registration information for the provider.
|
||||
*
|
||||
* \remarks The provider is initially disabled. Call PhSetEnabledProvider() to enable it.
|
||||
*/
|
||||
VOID PhRegisterProvider(
|
||||
_Inout_ PPH_PROVIDER_THREAD ProviderThread,
|
||||
_In_ PPH_PROVIDER_FUNCTION Function,
|
||||
_In_opt_ PVOID Object,
|
||||
_Out_ PPH_PROVIDER_REGISTRATION Registration
|
||||
)
|
||||
{
|
||||
Registration->ProviderThread = ProviderThread;
|
||||
Registration->Function = Function;
|
||||
Registration->Object = Object;
|
||||
Registration->RunId = 0;
|
||||
Registration->Enabled = FALSE;
|
||||
Registration->Unregistering = FALSE;
|
||||
Registration->Boosting = FALSE;
|
||||
|
||||
if (Object)
|
||||
PhReferenceObject(Object);
|
||||
|
||||
PhAcquireQueuedLockExclusive(&ProviderThread->Lock);
|
||||
InsertTailList(&ProviderThread->ListHead, &Registration->ListEntry);
|
||||
PhReleaseQueuedLockExclusive(&ProviderThread->Lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a provider.
|
||||
*
|
||||
* \param Registration A pointer to the registration object for a provider.
|
||||
*
|
||||
* \remarks The provider function may still be in execution once this function returns.
|
||||
*/
|
||||
VOID PhUnregisterProvider(
|
||||
_Inout_ PPH_PROVIDER_REGISTRATION Registration
|
||||
)
|
||||
{
|
||||
PPH_PROVIDER_THREAD providerThread;
|
||||
|
||||
providerThread = Registration->ProviderThread;
|
||||
|
||||
Registration->Unregistering = TRUE;
|
||||
|
||||
// There are two possibilities for removal:
|
||||
// 1. The provider is removed while the thread is not in the main loop. This is the normal case.
|
||||
// 2. The provider is removed while the thread is in the main loop. In that case the provider
|
||||
// will be removed from the temp list and so it won't be re-added to the main list.
|
||||
|
||||
PhAcquireQueuedLockExclusive(&providerThread->Lock);
|
||||
|
||||
RemoveEntryList(&Registration->ListEntry);
|
||||
|
||||
// Fix the boost count.
|
||||
if (Registration->Boosting)
|
||||
providerThread->BoostCount--;
|
||||
|
||||
// The user-supplied object must be dereferenced
|
||||
// while the mutex is held.
|
||||
if (Registration->Object)
|
||||
PhDereferenceObject(Registration->Object);
|
||||
|
||||
PhReleaseQueuedLockExclusive(&providerThread->Lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes a provider to be queued for immediate execution.
|
||||
*
|
||||
* \param Registration A pointer to the registration object for a provider.
|
||||
* \param FutureRunId A variable which receives the run ID of the future run.
|
||||
*
|
||||
* \return TRUE if the operation was successful; FALSE if the provider is being unregistered, the
|
||||
* provider is already being boosted, or the provider thread is not running.
|
||||
*
|
||||
* \remarks Boosted providers will be run immediately, ignoring the run interval. Boosting will not
|
||||
* however affect the normal runs.
|
||||
*/
|
||||
BOOLEAN PhBoostProvider(
|
||||
_Inout_ PPH_PROVIDER_REGISTRATION Registration,
|
||||
_Out_opt_ PULONG FutureRunId
|
||||
)
|
||||
{
|
||||
PPH_PROVIDER_THREAD providerThread;
|
||||
ULONG futureRunId;
|
||||
|
||||
if (Registration->Unregistering)
|
||||
return FALSE;
|
||||
|
||||
providerThread = Registration->ProviderThread;
|
||||
|
||||
// Simply move to the provider to the front of the list. This works even if the provider is
|
||||
// currently in the temp list.
|
||||
|
||||
PhAcquireQueuedLockExclusive(&providerThread->Lock);
|
||||
|
||||
// Abort if the provider is already being boosted or the provider thread is stopping/stopped.
|
||||
if (Registration->Boosting || providerThread->State != ProviderThreadRunning)
|
||||
{
|
||||
PhReleaseQueuedLockExclusive(&providerThread->Lock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RemoveEntryList(&Registration->ListEntry);
|
||||
InsertHeadList(&providerThread->ListHead, &Registration->ListEntry);
|
||||
|
||||
Registration->Boosting = TRUE;
|
||||
providerThread->BoostCount++;
|
||||
|
||||
futureRunId = Registration->RunId + 1;
|
||||
|
||||
PhReleaseQueuedLockExclusive(&providerThread->Lock);
|
||||
|
||||
// Wake up the thread.
|
||||
NtAlertThread(providerThread->ThreadHandle);
|
||||
|
||||
if (FutureRunId)
|
||||
*FutureRunId = futureRunId;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current run ID of a provider.
|
||||
*
|
||||
* \param Registration A pointer to the registration object for a provider.
|
||||
*/
|
||||
ULONG PhGetRunIdProvider(
|
||||
_In_ PPH_PROVIDER_REGISTRATION Registration
|
||||
)
|
||||
{
|
||||
return Registration->RunId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether a provider is enabled.
|
||||
*
|
||||
* \param Registration A pointer to the registration object for a provider.
|
||||
*/
|
||||
BOOLEAN PhGetEnabledProvider(
|
||||
_In_ PPH_PROVIDER_REGISTRATION Registration
|
||||
)
|
||||
{
|
||||
return Registration->Enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether a provider is enabled.
|
||||
*
|
||||
* \param Registration A pointer to the registration object for a provider.
|
||||
* \param Enabled TRUE if the provider is enabled, otherwise FALSE.
|
||||
*/
|
||||
VOID PhSetEnabledProvider(
|
||||
_Inout_ PPH_PROVIDER_REGISTRATION Registration,
|
||||
_In_ BOOLEAN Enabled
|
||||
)
|
||||
{
|
||||
Registration->Enabled = Enabled;
|
||||
}
|
||||
1201
phlib/queuedlock.c
Normal file
1201
phlib/queuedlock.c
Normal file
File diff suppressed because it is too large
Load Diff
753
phlib/ref.c
Normal file
753
phlib/ref.c
Normal file
@@ -0,0 +1,753 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* object manager
|
||||
*
|
||||
* Copyright (C) 2009-2016 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <phbase.h>
|
||||
#include <phintrnl.h>
|
||||
#include <workqueue.h>
|
||||
#include <refp.h>
|
||||
|
||||
PPH_OBJECT_TYPE PhObjectTypeObject = NULL;
|
||||
SLIST_HEADER PhObjectDeferDeleteListHead;
|
||||
PH_FREE_LIST PhObjectSmallFreeList;
|
||||
PPH_OBJECT_TYPE PhAllocType = NULL;
|
||||
|
||||
ULONG PhObjectTypeCount = 0;
|
||||
PPH_OBJECT_TYPE PhObjectTypeTable[PH_OBJECT_TYPE_TABLE_SIZE];
|
||||
|
||||
static ULONG PhpAutoPoolTlsIndex;
|
||||
|
||||
#ifdef DEBUG
|
||||
LIST_ENTRY PhDbgObjectListHead;
|
||||
PH_QUEUED_LOCK PhDbgObjectListLock = PH_QUEUED_LOCK_INIT;
|
||||
PPH_CREATE_OBJECT_HOOK PhDbgCreateObjectHook = NULL;
|
||||
#endif
|
||||
|
||||
#define REF_STAT_UP(Name) PHLIB_INC_STATISTIC(Name)
|
||||
|
||||
/**
|
||||
* Initializes the object manager module.
|
||||
*/
|
||||
NTSTATUS PhRefInitialization(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
PH_OBJECT_TYPE dummyObjectType;
|
||||
|
||||
#ifdef DEBUG
|
||||
InitializeListHead(&PhDbgObjectListHead);
|
||||
#endif
|
||||
|
||||
RtlInitializeSListHead(&PhObjectDeferDeleteListHead);
|
||||
PhInitializeFreeList(
|
||||
&PhObjectSmallFreeList,
|
||||
PhAddObjectHeaderSize(PH_OBJECT_SMALL_OBJECT_SIZE),
|
||||
PH_OBJECT_SMALL_OBJECT_COUNT
|
||||
);
|
||||
|
||||
// Create the fundamental object type.
|
||||
|
||||
memset(&dummyObjectType, 0, sizeof(PH_OBJECT_TYPE));
|
||||
PhObjectTypeObject = &dummyObjectType; // PhCreateObject expects an object type.
|
||||
PhObjectTypeTable[0] = &dummyObjectType; // PhCreateObject also expects PhObjectTypeTable[0] to be filled in.
|
||||
PhObjectTypeObject = PhCreateObjectType(L"Type", 0, NULL);
|
||||
|
||||
// Now that the fundamental object type exists, fix it up.
|
||||
PhObjectToObjectHeader(PhObjectTypeObject)->TypeIndex = PhObjectTypeObject->TypeIndex;
|
||||
PhObjectTypeObject->NumberOfObjects = 1;
|
||||
|
||||
// Create the allocated memory object type.
|
||||
PhAllocType = PhCreateObjectType(L"Alloc", 0, NULL);
|
||||
|
||||
// Reserve a slot for the auto pool.
|
||||
PhpAutoPoolTlsIndex = TlsAlloc();
|
||||
|
||||
if (PhpAutoPoolTlsIndex == TLS_OUT_OF_INDEXES)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a object.
|
||||
*
|
||||
* \param ObjectSize The size of the object.
|
||||
* \param ObjectType The type of the object.
|
||||
*
|
||||
* \return A pointer to the newly allocated object.
|
||||
*/
|
||||
_May_raise_ PVOID PhCreateObject(
|
||||
_In_ SIZE_T ObjectSize,
|
||||
_In_ PPH_OBJECT_TYPE ObjectType
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
PPH_OBJECT_HEADER objectHeader;
|
||||
|
||||
// Allocate storage for the object. Note that this includes the object header followed by the
|
||||
// object body.
|
||||
objectHeader = PhpAllocateObject(ObjectType, ObjectSize);
|
||||
|
||||
// Object type statistics.
|
||||
_InterlockedIncrement((PLONG)&ObjectType->NumberOfObjects);
|
||||
|
||||
// Initialize the object header.
|
||||
objectHeader->RefCount = 1;
|
||||
objectHeader->TypeIndex = ObjectType->TypeIndex;
|
||||
// objectHeader->Flags is set by PhpAllocateObject.
|
||||
|
||||
REF_STAT_UP(RefObjectsCreated);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
USHORT capturedFrames;
|
||||
|
||||
capturedFrames = RtlCaptureStackBackTrace(1, 16, objectHeader->StackBackTrace, NULL);
|
||||
memset(
|
||||
&objectHeader->StackBackTrace[capturedFrames],
|
||||
0,
|
||||
sizeof(objectHeader->StackBackTrace) - capturedFrames * sizeof(PVOID)
|
||||
);
|
||||
}
|
||||
|
||||
PhAcquireQueuedLockExclusive(&PhDbgObjectListLock);
|
||||
InsertTailList(&PhDbgObjectListHead, &objectHeader->ObjectListEntry);
|
||||
PhReleaseQueuedLockExclusive(&PhDbgObjectListLock);
|
||||
|
||||
{
|
||||
PPH_CREATE_OBJECT_HOOK dbgCreateObjectHook;
|
||||
|
||||
dbgCreateObjectHook = PhDbgCreateObjectHook;
|
||||
|
||||
if (dbgCreateObjectHook)
|
||||
{
|
||||
dbgCreateObjectHook(
|
||||
PhObjectHeaderToObject(objectHeader),
|
||||
ObjectSize,
|
||||
0,
|
||||
ObjectType
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return PhObjectHeaderToObject(objectHeader);
|
||||
}
|
||||
|
||||
/**
|
||||
* References the specified object.
|
||||
*
|
||||
* \param Object A pointer to the object to reference.
|
||||
*
|
||||
* \return The object.
|
||||
*/
|
||||
PVOID PhReferenceObject(
|
||||
_In_ PVOID Object
|
||||
)
|
||||
{
|
||||
PPH_OBJECT_HEADER objectHeader;
|
||||
|
||||
objectHeader = PhObjectToObjectHeader(Object);
|
||||
// Increment the reference count.
|
||||
_InterlockedIncrement(&objectHeader->RefCount);
|
||||
|
||||
return Object;
|
||||
}
|
||||
|
||||
/**
|
||||
* References the specified object.
|
||||
*
|
||||
* \param Object A pointer to the object to reference.
|
||||
* \param RefCount The number of references to add.
|
||||
*
|
||||
* \return The object.
|
||||
*/
|
||||
_May_raise_ PVOID PhReferenceObjectEx(
|
||||
_In_ PVOID Object,
|
||||
_In_ LONG RefCount
|
||||
)
|
||||
{
|
||||
PPH_OBJECT_HEADER objectHeader;
|
||||
LONG oldRefCount;
|
||||
|
||||
assert(!(RefCount < 0));
|
||||
|
||||
objectHeader = PhObjectToObjectHeader(Object);
|
||||
// Increase the reference count.
|
||||
oldRefCount = _InterlockedExchangeAdd(&objectHeader->RefCount, RefCount);
|
||||
|
||||
return Object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to reference an object and fails if it is being destroyed.
|
||||
*
|
||||
* \param Object The object to reference if it is not being deleted.
|
||||
*
|
||||
* \return The object itself if the object was referenced, NULL if it was being deleted and was not
|
||||
* referenced.
|
||||
*
|
||||
* \remarks This function is useful if a reference to an object is held, protected by a mutex, and
|
||||
* the delete procedure of the object's type attempts to acquire the mutex. If this function is
|
||||
* called while the mutex is owned, you can avoid referencing an object that is being destroyed.
|
||||
*/
|
||||
PVOID PhReferenceObjectSafe(
|
||||
_In_ PVOID Object
|
||||
)
|
||||
{
|
||||
PPH_OBJECT_HEADER objectHeader;
|
||||
|
||||
objectHeader = PhObjectToObjectHeader(Object);
|
||||
|
||||
// Increase the reference count only if it positive already (atomically).
|
||||
if (PhpInterlockedIncrementSafe(&objectHeader->RefCount))
|
||||
return Object;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereferences the specified object.
|
||||
* The object will be freed if its reference count reaches 0.
|
||||
*
|
||||
* \param Object A pointer to the object to dereference.
|
||||
*/
|
||||
VOID PhDereferenceObject(
|
||||
_In_ PVOID Object
|
||||
)
|
||||
{
|
||||
PPH_OBJECT_HEADER objectHeader;
|
||||
LONG newRefCount;
|
||||
|
||||
objectHeader = PhObjectToObjectHeader(Object);
|
||||
// Decrement the reference count.
|
||||
newRefCount = _InterlockedDecrement(&objectHeader->RefCount);
|
||||
ASSUME_ASSERT(newRefCount >= 0);
|
||||
|
||||
// Free the object if it has 0 references.
|
||||
if (newRefCount == 0)
|
||||
{
|
||||
PhpFreeObject(objectHeader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereferences the specified object.
|
||||
* The object will be freed in a worker thread if its reference count reaches 0.
|
||||
*
|
||||
* \param Object A pointer to the object to dereference.
|
||||
*/
|
||||
VOID PhDereferenceObjectDeferDelete(
|
||||
_In_ PVOID Object
|
||||
)
|
||||
{
|
||||
PhDereferenceObjectEx(Object, 1, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereferences the specified object.
|
||||
* The object will be freed if its reference count reaches 0.
|
||||
*
|
||||
* \param Object A pointer to the object to dereference.
|
||||
* \param RefCount The number of references to remove.
|
||||
* \param DeferDelete Whether to defer deletion of the object.
|
||||
*/
|
||||
_May_raise_ VOID PhDereferenceObjectEx(
|
||||
_In_ PVOID Object,
|
||||
_In_ LONG RefCount,
|
||||
_In_ BOOLEAN DeferDelete
|
||||
)
|
||||
{
|
||||
PPH_OBJECT_HEADER objectHeader;
|
||||
LONG oldRefCount;
|
||||
LONG newRefCount;
|
||||
|
||||
assert(!(RefCount < 0));
|
||||
|
||||
objectHeader = PhObjectToObjectHeader(Object);
|
||||
|
||||
// Decrease the reference count.
|
||||
oldRefCount = _InterlockedExchangeAdd(&objectHeader->RefCount, -RefCount);
|
||||
newRefCount = oldRefCount - RefCount;
|
||||
|
||||
// Free the object if it has 0 references.
|
||||
if (newRefCount == 0)
|
||||
{
|
||||
if (DeferDelete)
|
||||
{
|
||||
PhpDeferDeleteObject(objectHeader);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Free the object.
|
||||
PhpFreeObject(objectHeader);
|
||||
}
|
||||
}
|
||||
else if (newRefCount < 0)
|
||||
{
|
||||
PhRaiseStatus(STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object's type.
|
||||
*
|
||||
* \param Object A pointer to an object.
|
||||
*
|
||||
* \return A pointer to a type object.
|
||||
*/
|
||||
PPH_OBJECT_TYPE PhGetObjectType(
|
||||
_In_ PVOID Object
|
||||
)
|
||||
{
|
||||
return PhObjectTypeTable[PhObjectToObjectHeader(Object)->TypeIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object type.
|
||||
*
|
||||
* \param Name The name of the type.
|
||||
* \param Flags A combination of flags affecting the behaviour of the object type.
|
||||
* \param DeleteProcedure A callback function that is executed when an object of this type is about
|
||||
* to be freed (i.e. when its reference count is 0).
|
||||
*
|
||||
* \return A pointer to the newly created object type.
|
||||
*
|
||||
* \remarks Do not reference or dereference the object type once it is created.
|
||||
*/
|
||||
PPH_OBJECT_TYPE PhCreateObjectType(
|
||||
_In_ PWSTR Name,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ PPH_TYPE_DELETE_PROCEDURE DeleteProcedure
|
||||
)
|
||||
{
|
||||
return PhCreateObjectTypeEx(
|
||||
Name,
|
||||
Flags,
|
||||
DeleteProcedure,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object type.
|
||||
*
|
||||
* \param Name The name of the type.
|
||||
* \param Flags A combination of flags affecting the behaviour of the object type.
|
||||
* \param DeleteProcedure A callback function that is executed when an object of this type is about
|
||||
* to be freed (i.e. when its reference count is 0).
|
||||
* \param Parameters A structure containing additional parameters for the object type.
|
||||
*
|
||||
* \return A pointer to the newly created object type.
|
||||
*
|
||||
* \remarks Do not reference or dereference the object type once it is created.
|
||||
*/
|
||||
PPH_OBJECT_TYPE PhCreateObjectTypeEx(
|
||||
_In_ PWSTR Name,
|
||||
_In_ ULONG Flags,
|
||||
_In_opt_ PPH_TYPE_DELETE_PROCEDURE DeleteProcedure,
|
||||
_In_opt_ PPH_OBJECT_TYPE_PARAMETERS Parameters
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
PPH_OBJECT_TYPE objectType;
|
||||
|
||||
// Check the flags.
|
||||
if ((Flags & PH_OBJECT_TYPE_VALID_FLAGS) != Flags) /* Valid flag mask */
|
||||
PhRaiseStatus(STATUS_INVALID_PARAMETER_3);
|
||||
if ((Flags & PH_OBJECT_TYPE_USE_FREE_LIST) && !Parameters)
|
||||
PhRaiseStatus(STATUS_INVALID_PARAMETER_MIX);
|
||||
|
||||
// Create the type object.
|
||||
objectType = PhCreateObject(sizeof(PH_OBJECT_TYPE), PhObjectTypeObject);
|
||||
|
||||
// Initialize the type object.
|
||||
objectType->Flags = (USHORT)Flags;
|
||||
objectType->TypeIndex = (USHORT)_InterlockedIncrement(&PhObjectTypeCount) - 1;
|
||||
objectType->NumberOfObjects = 0;
|
||||
objectType->DeleteProcedure = DeleteProcedure;
|
||||
objectType->Name = Name;
|
||||
|
||||
if (objectType->TypeIndex < PH_OBJECT_TYPE_TABLE_SIZE)
|
||||
PhObjectTypeTable[objectType->TypeIndex] = objectType;
|
||||
else
|
||||
PhRaiseStatus(STATUS_UNSUCCESSFUL);
|
||||
|
||||
if (Parameters)
|
||||
{
|
||||
if (Flags & PH_OBJECT_TYPE_USE_FREE_LIST)
|
||||
{
|
||||
PhInitializeFreeList(
|
||||
&objectType->FreeList,
|
||||
PhAddObjectHeaderSize(Parameters->FreeListSize),
|
||||
Parameters->FreeListCount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return objectType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about an object type.
|
||||
*
|
||||
* \param ObjectType A pointer to an object type.
|
||||
* \param Information A variable which receives information about the object type.
|
||||
*/
|
||||
VOID PhGetObjectTypeInformation(
|
||||
_In_ PPH_OBJECT_TYPE ObjectType,
|
||||
_Out_ PPH_OBJECT_TYPE_INFORMATION Information
|
||||
)
|
||||
{
|
||||
Information->Name = ObjectType->Name;
|
||||
Information->NumberOfObjects = ObjectType->NumberOfObjects;
|
||||
Information->Flags = ObjectType->Flags;
|
||||
Information->TypeIndex = ObjectType->TypeIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates storage for an object.
|
||||
*
|
||||
* \param ObjectType The type of the object.
|
||||
* \param ObjectSize The size of the object, excluding the header.
|
||||
*/
|
||||
PPH_OBJECT_HEADER PhpAllocateObject(
|
||||
_In_ PPH_OBJECT_TYPE ObjectType,
|
||||
_In_ SIZE_T ObjectSize
|
||||
)
|
||||
{
|
||||
PPH_OBJECT_HEADER objectHeader;
|
||||
|
||||
if (ObjectType->Flags & PH_OBJECT_TYPE_USE_FREE_LIST)
|
||||
{
|
||||
assert(ObjectType->FreeList.Size == PhAddObjectHeaderSize(ObjectSize));
|
||||
|
||||
objectHeader = PhAllocateFromFreeList(&ObjectType->FreeList);
|
||||
objectHeader->Flags = PH_OBJECT_FROM_TYPE_FREE_LIST;
|
||||
REF_STAT_UP(RefObjectsAllocatedFromTypeFreeList);
|
||||
}
|
||||
else if (ObjectSize <= PH_OBJECT_SMALL_OBJECT_SIZE)
|
||||
{
|
||||
objectHeader = PhAllocateFromFreeList(&PhObjectSmallFreeList);
|
||||
objectHeader->Flags = PH_OBJECT_FROM_SMALL_FREE_LIST;
|
||||
REF_STAT_UP(RefObjectsAllocatedFromSmallFreeList);
|
||||
}
|
||||
else
|
||||
{
|
||||
objectHeader = PhAllocate(PhAddObjectHeaderSize(ObjectSize));
|
||||
objectHeader->Flags = 0;
|
||||
REF_STAT_UP(RefObjectsAllocated);
|
||||
}
|
||||
|
||||
return objectHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the delete procedure for an object and frees its allocated storage.
|
||||
*
|
||||
* \param ObjectHeader A pointer to the object header of an allocated object.
|
||||
*/
|
||||
VOID PhpFreeObject(
|
||||
_In_ PPH_OBJECT_HEADER ObjectHeader
|
||||
)
|
||||
{
|
||||
PPH_OBJECT_TYPE objectType;
|
||||
|
||||
objectType = PhObjectTypeTable[ObjectHeader->TypeIndex];
|
||||
|
||||
// Object type statistics.
|
||||
_InterlockedDecrement(&objectType->NumberOfObjects);
|
||||
|
||||
#ifdef DEBUG
|
||||
PhAcquireQueuedLockExclusive(&PhDbgObjectListLock);
|
||||
RemoveEntryList(&ObjectHeader->ObjectListEntry);
|
||||
PhReleaseQueuedLockExclusive(&PhDbgObjectListLock);
|
||||
#endif
|
||||
|
||||
REF_STAT_UP(RefObjectsDestroyed);
|
||||
|
||||
// Call the delete procedure if we have one.
|
||||
if (objectType->DeleteProcedure)
|
||||
{
|
||||
objectType->DeleteProcedure(PhObjectHeaderToObject(ObjectHeader), 0);
|
||||
}
|
||||
|
||||
if (ObjectHeader->Flags & PH_OBJECT_FROM_TYPE_FREE_LIST)
|
||||
{
|
||||
PhFreeToFreeList(&objectType->FreeList, ObjectHeader);
|
||||
REF_STAT_UP(RefObjectsFreedToTypeFreeList);
|
||||
}
|
||||
else if (ObjectHeader->Flags & PH_OBJECT_FROM_SMALL_FREE_LIST)
|
||||
{
|
||||
PhFreeToFreeList(&PhObjectSmallFreeList, ObjectHeader);
|
||||
REF_STAT_UP(RefObjectsFreedToSmallFreeList);
|
||||
}
|
||||
else
|
||||
{
|
||||
PhFree(ObjectHeader);
|
||||
REF_STAT_UP(RefObjectsFreed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues an object for deletion.
|
||||
*
|
||||
* \param ObjectHeader A pointer to the object header of the object to delete.
|
||||
*/
|
||||
VOID PhpDeferDeleteObject(
|
||||
_In_ PPH_OBJECT_HEADER ObjectHeader
|
||||
)
|
||||
{
|
||||
PSLIST_ENTRY oldFirstEntry;
|
||||
|
||||
// Save TypeIndex and Flags since they get overwritten when we push the object onto the defer
|
||||
// delete list.
|
||||
ObjectHeader->DeferDelete = 1;
|
||||
MemoryBarrier();
|
||||
ObjectHeader->SavedTypeIndex = ObjectHeader->TypeIndex;
|
||||
ObjectHeader->SavedFlags = ObjectHeader->Flags;
|
||||
|
||||
oldFirstEntry = RtlFirstEntrySList(&PhObjectDeferDeleteListHead);
|
||||
RtlInterlockedPushEntrySList(&PhObjectDeferDeleteListHead, &ObjectHeader->DeferDeleteListEntry);
|
||||
REF_STAT_UP(RefObjectsDeleteDeferred);
|
||||
|
||||
// Was the to-free list empty before? If so, we need to queue a work item.
|
||||
if (!oldFirstEntry)
|
||||
{
|
||||
PhQueueItemWorkQueue(PhGetGlobalWorkQueue(), PhpDeferDeleteObjectRoutine, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and frees objects from the to-free list.
|
||||
*/
|
||||
NTSTATUS PhpDeferDeleteObjectRoutine(
|
||||
_In_ PVOID Parameter
|
||||
)
|
||||
{
|
||||
PSLIST_ENTRY listEntry;
|
||||
PPH_OBJECT_HEADER objectHeader;
|
||||
|
||||
// Clear the list and obtain the first object to free.
|
||||
listEntry = RtlInterlockedFlushSList(&PhObjectDeferDeleteListHead);
|
||||
|
||||
while (listEntry)
|
||||
{
|
||||
objectHeader = CONTAINING_RECORD(listEntry, PH_OBJECT_HEADER, DeferDeleteListEntry);
|
||||
listEntry = listEntry->Next;
|
||||
|
||||
// Restore TypeIndex and Flags.
|
||||
objectHeader->TypeIndex = (USHORT)objectHeader->SavedTypeIndex;
|
||||
objectHeader->Flags = (UCHAR)objectHeader->SavedFlags;
|
||||
|
||||
PhpFreeObject(objectHeader);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a reference-counted memory block.
|
||||
*
|
||||
* \param Size The number of bytes to allocate.
|
||||
*
|
||||
* \return A pointer to the memory block.
|
||||
*/
|
||||
PVOID PhCreateAlloc(
|
||||
_In_ SIZE_T Size
|
||||
)
|
||||
{
|
||||
return PhCreateObject(Size, PhAllocType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current auto-dereference pool for the current thread.
|
||||
*/
|
||||
FORCEINLINE PPH_AUTO_POOL PhpGetCurrentAutoPool(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (PPH_AUTO_POOL)TlsGetValue(PhpAutoPoolTlsIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current auto-dereference pool for the current thread.
|
||||
*/
|
||||
_May_raise_ FORCEINLINE VOID PhpSetCurrentAutoPool(
|
||||
_In_ PPH_AUTO_POOL AutoPool
|
||||
)
|
||||
{
|
||||
if (!TlsSetValue(PhpAutoPoolTlsIndex, AutoPool))
|
||||
PhRaiseStatus(STATUS_UNSUCCESSFUL);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
PPHP_BASE_THREAD_DBG dbg;
|
||||
|
||||
dbg = (PPHP_BASE_THREAD_DBG)TlsGetValue(PhDbgThreadDbgTlsIndex);
|
||||
|
||||
if (dbg)
|
||||
{
|
||||
dbg->CurrentAutoPool = AutoPool;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an auto-dereference pool and sets it as the current pool for the current thread. You
|
||||
* must call PhDeleteAutoPool() before storage for the auto-dereference pool is freed.
|
||||
*
|
||||
* \remarks Always store auto-dereference pools in local variables, and do not share the pool with
|
||||
* any other functions.
|
||||
*/
|
||||
VOID PhInitializeAutoPool(
|
||||
_Out_ PPH_AUTO_POOL AutoPool
|
||||
)
|
||||
{
|
||||
AutoPool->StaticCount = 0;
|
||||
AutoPool->DynamicCount = 0;
|
||||
AutoPool->DynamicAllocated = 0;
|
||||
AutoPool->DynamicObjects = NULL;
|
||||
|
||||
// Add the pool to the stack.
|
||||
AutoPool->NextPool = PhpGetCurrentAutoPool();
|
||||
PhpSetCurrentAutoPool(AutoPool);
|
||||
|
||||
REF_STAT_UP(RefAutoPoolsCreated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an auto-dereference pool. The function will dereference any objects currently in the
|
||||
* pool. If a pool other than the current pool is passed to the function, an exception is raised.
|
||||
*
|
||||
* \param AutoPool The auto-dereference pool to delete.
|
||||
*/
|
||||
_May_raise_ VOID PhDeleteAutoPool(
|
||||
_Inout_ PPH_AUTO_POOL AutoPool
|
||||
)
|
||||
{
|
||||
PhDrainAutoPool(AutoPool);
|
||||
|
||||
if (PhpGetCurrentAutoPool() != AutoPool)
|
||||
PhRaiseStatus(STATUS_UNSUCCESSFUL);
|
||||
|
||||
// Remove the pool from the stack.
|
||||
PhpSetCurrentAutoPool(AutoPool->NextPool);
|
||||
|
||||
// Free the dynamic array if it hasn't been freed yet.
|
||||
if (AutoPool->DynamicObjects)
|
||||
PhFree(AutoPool->DynamicObjects);
|
||||
|
||||
REF_STAT_UP(RefAutoPoolsDestroyed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereferences and removes all objects in an auto-release pool.
|
||||
*
|
||||
* \param AutoPool The auto-release pool to drain.
|
||||
*/
|
||||
VOID PhDrainAutoPool(
|
||||
_In_ PPH_AUTO_POOL AutoPool
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < AutoPool->StaticCount; i++)
|
||||
PhDereferenceObject(AutoPool->StaticObjects[i]);
|
||||
|
||||
AutoPool->StaticCount = 0;
|
||||
|
||||
if (AutoPool->DynamicObjects)
|
||||
{
|
||||
for (i = 0; i < AutoPool->DynamicCount; i++)
|
||||
{
|
||||
PhDereferenceObject(AutoPool->DynamicObjects[i]);
|
||||
}
|
||||
|
||||
AutoPool->DynamicCount = 0;
|
||||
|
||||
if (AutoPool->DynamicAllocated > PH_AUTO_POOL_DYNAMIC_BIG_SIZE)
|
||||
{
|
||||
AutoPool->DynamicAllocated = 0;
|
||||
PhFree(AutoPool->DynamicObjects);
|
||||
AutoPool->DynamicObjects = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an object to the current auto-dereference pool for the current thread. If the current thread
|
||||
* does not have an auto-dereference pool, the function raises an exception.
|
||||
*
|
||||
* \param Object A pointer to an object. The object will be dereferenced when the current
|
||||
* auto-dereference pool is drained or freed.
|
||||
*/
|
||||
_May_raise_ PVOID PhAutoDereferenceObject(
|
||||
_In_opt_ PVOID Object
|
||||
)
|
||||
{
|
||||
PPH_AUTO_POOL autoPool = PhpGetCurrentAutoPool();
|
||||
|
||||
#ifdef DEBUG
|
||||
// If we don't have an auto-dereference pool, we don't want to leak the object (unlike what
|
||||
// Apple does with NSAutoreleasePool).
|
||||
if (!autoPool)
|
||||
PhRaiseStatus(STATUS_UNSUCCESSFUL);
|
||||
#endif
|
||||
|
||||
if (!Object)
|
||||
return NULL;
|
||||
|
||||
// See if we can use the static array.
|
||||
if (autoPool->StaticCount < PH_AUTO_POOL_STATIC_SIZE)
|
||||
{
|
||||
autoPool->StaticObjects[autoPool->StaticCount++] = Object;
|
||||
return Object;
|
||||
}
|
||||
|
||||
// Use the dynamic array.
|
||||
|
||||
// Allocate the array if we haven't already.
|
||||
if (!autoPool->DynamicObjects)
|
||||
{
|
||||
autoPool->DynamicAllocated = 64;
|
||||
autoPool->DynamicObjects = PhAllocate(
|
||||
sizeof(PVOID) * autoPool->DynamicAllocated
|
||||
);
|
||||
REF_STAT_UP(RefAutoPoolsDynamicAllocated);
|
||||
}
|
||||
|
||||
// See if we need to resize the array.
|
||||
if (autoPool->DynamicCount == autoPool->DynamicAllocated)
|
||||
{
|
||||
autoPool->DynamicAllocated *= 2;
|
||||
autoPool->DynamicObjects = PhReAllocate(
|
||||
autoPool->DynamicObjects,
|
||||
sizeof(PVOID) * autoPool->DynamicAllocated
|
||||
);
|
||||
REF_STAT_UP(RefAutoPoolsDynamicResized);
|
||||
}
|
||||
|
||||
autoPool->DynamicObjects[autoPool->DynamicCount++] = Object;
|
||||
|
||||
return Object;
|
||||
}
|
||||
786
phlib/secdata.c
Normal file
786
phlib/secdata.c
Normal file
@@ -0,0 +1,786 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* object security data
|
||||
*
|
||||
* Copyright (C) 2010-2016 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <guisup.h>
|
||||
#include <secedit.h>
|
||||
#include <wmistr.h>
|
||||
|
||||
#define ACCESS_ENTRIES(Type) static PH_ACCESS_ENTRY Ph##Type##AccessEntries[] =
|
||||
#define ACCESS_ENTRY(Type, HasSynchronize) \
|
||||
{ L#Type, Ph##Type##AccessEntries, sizeof(Ph##Type##AccessEntries), HasSynchronize }
|
||||
|
||||
typedef struct _PH_SPECIFIC_TYPE
|
||||
{
|
||||
PWSTR Type;
|
||||
PPH_ACCESS_ENTRY AccessEntries;
|
||||
ULONG SizeOfAccessEntries;
|
||||
BOOLEAN HasSynchronize;
|
||||
} PH_SPECIFIC_TYPE, *PPH_SPECIFIC_TYPE;
|
||||
|
||||
ACCESS_ENTRIES(Standard)
|
||||
{
|
||||
{ L"Synchronize", SYNCHRONIZE, FALSE, TRUE },
|
||||
{ L"Delete", DELETE, FALSE, TRUE },
|
||||
{ L"Read permissions", READ_CONTROL, FALSE, TRUE, L"Read control" },
|
||||
{ L"Change permissions", WRITE_DAC, FALSE, TRUE, L"Write DAC" },
|
||||
{ L"Take ownership", WRITE_OWNER, FALSE, TRUE, L"Write owner" }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(AlpcPort)
|
||||
{
|
||||
{ L"Full control", PORT_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Connect", PORT_CONNECT, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(DebugObject)
|
||||
{
|
||||
{ L"Full control", DEBUG_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read events", DEBUG_READ_EVENT, TRUE, TRUE },
|
||||
{ L"Assign processes", DEBUG_PROCESS_ASSIGN, TRUE, TRUE },
|
||||
{ L"Query information", DEBUG_QUERY_INFORMATION, TRUE, TRUE },
|
||||
{ L"Set information", DEBUG_SET_INFORMATION, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Desktop)
|
||||
{
|
||||
{ L"Full control", DESKTOP_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", DESKTOP_GENERIC_READ, TRUE, FALSE },
|
||||
{ L"Write", DESKTOP_GENERIC_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", DESKTOP_GENERIC_EXECUTE, TRUE, FALSE },
|
||||
{ L"Enumerate", DESKTOP_ENUMERATE, FALSE, TRUE },
|
||||
{ L"Read objects", DESKTOP_READOBJECTS, FALSE, TRUE },
|
||||
{ L"Playback journals", DESKTOP_JOURNALPLAYBACK, FALSE, TRUE },
|
||||
{ L"Write objects", DESKTOP_WRITEOBJECTS, FALSE, TRUE },
|
||||
{ L"Create windows", DESKTOP_CREATEWINDOW, FALSE, TRUE },
|
||||
{ L"Create menus", DESKTOP_CREATEMENU, FALSE, TRUE },
|
||||
{ L"Create window hooks", DESKTOP_HOOKCONTROL, FALSE, TRUE },
|
||||
{ L"Record journals", DESKTOP_JOURNALRECORD, FALSE, TRUE },
|
||||
{ L"Switch desktop", DESKTOP_SWITCHDESKTOP, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Directory)
|
||||
{
|
||||
{ L"Full control", DIRECTORY_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", DIRECTORY_QUERY, TRUE, TRUE},
|
||||
{ L"Traverse", DIRECTORY_TRAVERSE, TRUE, TRUE},
|
||||
{ L"Create objects", DIRECTORY_CREATE_OBJECT, TRUE, TRUE},
|
||||
{ L"Create subdirectories", DIRECTORY_CREATE_SUBDIRECTORY, TRUE, TRUE}
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Event)
|
||||
{
|
||||
{ L"Full control", EVENT_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", EVENT_QUERY_STATE, TRUE, TRUE },
|
||||
{ L"Modify", EVENT_MODIFY_STATE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(EventPair)
|
||||
{
|
||||
{ L"Full control", EVENT_PAIR_ALL_ACCESS, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(File)
|
||||
{
|
||||
{ L"Full control", FILE_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read & execute", FILE_GENERIC_READ | FILE_GENERIC_EXECUTE, TRUE, FALSE },
|
||||
{ L"Read", FILE_GENERIC_READ, TRUE, FALSE },
|
||||
{ L"Write", FILE_GENERIC_WRITE, TRUE, FALSE },
|
||||
{ L"Traverse folder / execute file", FILE_EXECUTE, FALSE, TRUE, L"Execute" },
|
||||
{ L"List folder / read data", FILE_READ_DATA, FALSE, TRUE, L"Read data" },
|
||||
{ L"Read attributes", FILE_READ_ATTRIBUTES, FALSE, TRUE },
|
||||
{ L"Read extended attributes", FILE_READ_EA, FALSE, TRUE, L"Read EA" },
|
||||
{ L"Create files / write data", FILE_WRITE_DATA, FALSE, TRUE, L"Write data" },
|
||||
{ L"Create folders / append data", FILE_APPEND_DATA, FALSE, TRUE, L"Append data" },
|
||||
{ L"Write attributes", FILE_WRITE_ATTRIBUTES, FALSE, TRUE },
|
||||
{ L"Write extended attributes", FILE_WRITE_EA, FALSE, TRUE, L"Write EA" },
|
||||
{ L"Delete subfolders and files", FILE_DELETE_CHILD, FALSE, TRUE, L"Delete child" }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(FilterConnectionPort)
|
||||
{
|
||||
{ L"Full control", FLT_PORT_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Connect", FLT_PORT_CONNECT, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(IoCompletion)
|
||||
{
|
||||
{ L"Full control", IO_COMPLETION_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", IO_COMPLETION_QUERY_STATE, TRUE, TRUE },
|
||||
{ L"Modify", IO_COMPLETION_MODIFY_STATE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Job)
|
||||
{
|
||||
{ L"Full control", JOB_OBJECT_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", JOB_OBJECT_QUERY, TRUE, TRUE },
|
||||
{ L"Assign processes", JOB_OBJECT_ASSIGN_PROCESS, TRUE, TRUE },
|
||||
{ L"Set attributes", JOB_OBJECT_SET_ATTRIBUTES, TRUE, TRUE },
|
||||
{ L"Set security attributes", JOB_OBJECT_SET_SECURITY_ATTRIBUTES, TRUE, TRUE },
|
||||
{ L"Terminate", JOB_OBJECT_TERMINATE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Key)
|
||||
{
|
||||
{ L"Full control", KEY_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", KEY_READ, TRUE, FALSE },
|
||||
{ L"Write", KEY_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", KEY_EXECUTE, TRUE, FALSE },
|
||||
{ L"Enumerate subkeys", KEY_ENUMERATE_SUB_KEYS, FALSE, TRUE },
|
||||
{ L"Query values", KEY_QUERY_VALUE, FALSE, TRUE },
|
||||
{ L"Notify", KEY_NOTIFY, FALSE, TRUE },
|
||||
{ L"Set values", KEY_SET_VALUE, FALSE, TRUE },
|
||||
{ L"Create subkeys", KEY_CREATE_SUB_KEY, FALSE, TRUE },
|
||||
{ L"Create links", KEY_CREATE_LINK, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(KeyedEvent)
|
||||
{
|
||||
{ L"Full control", KEYEDEVENT_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Wait", KEYEDEVENT_WAIT, TRUE, TRUE },
|
||||
{ L"Wake", KEYEDEVENT_WAKE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(LsaAccount)
|
||||
{
|
||||
{ L"Full control", ACCOUNT_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", ACCOUNT_READ, TRUE, FALSE },
|
||||
{ L"Write", ACCOUNT_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", ACCOUNT_EXECUTE, TRUE, FALSE },
|
||||
{ L"View", ACCOUNT_VIEW, FALSE, TRUE },
|
||||
{ L"Adjust privileges", ACCOUNT_ADJUST_PRIVILEGES, FALSE, TRUE },
|
||||
{ L"Adjust quotas", ACCOUNT_ADJUST_QUOTAS, FALSE, TRUE },
|
||||
{ L"Adjust system access", ACCOUNT_ADJUST_SYSTEM_ACCESS, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(LsaPolicy)
|
||||
{
|
||||
{ L"Full control", POLICY_ALL_ACCESS | POLICY_NOTIFICATION, TRUE, TRUE },
|
||||
{ L"Read", POLICY_READ, TRUE, FALSE },
|
||||
{ L"Write", POLICY_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", POLICY_EXECUTE | POLICY_NOTIFICATION, TRUE, FALSE },
|
||||
{ L"View local information", POLICY_VIEW_LOCAL_INFORMATION, FALSE, TRUE },
|
||||
{ L"View audit information", POLICY_VIEW_AUDIT_INFORMATION, FALSE, TRUE },
|
||||
{ L"Get private information", POLICY_GET_PRIVATE_INFORMATION, FALSE, TRUE },
|
||||
{ L"Administer trust", POLICY_TRUST_ADMIN, FALSE, TRUE },
|
||||
{ L"Create account", POLICY_CREATE_ACCOUNT, FALSE, TRUE },
|
||||
{ L"Create secret", POLICY_CREATE_SECRET, FALSE, TRUE },
|
||||
{ L"Create privilege", POLICY_CREATE_PRIVILEGE, FALSE, TRUE },
|
||||
{ L"Set default quota limits", POLICY_SET_DEFAULT_QUOTA_LIMITS, FALSE, TRUE },
|
||||
{ L"Set audit requirements", POLICY_SET_AUDIT_REQUIREMENTS, FALSE, TRUE },
|
||||
{ L"Administer audit log", POLICY_AUDIT_LOG_ADMIN, FALSE, TRUE },
|
||||
{ L"Administer server", POLICY_SERVER_ADMIN, FALSE, TRUE },
|
||||
{ L"Lookup names", POLICY_LOOKUP_NAMES, FALSE, TRUE },
|
||||
{ L"Get notifications", POLICY_NOTIFICATION, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(LsaSecret)
|
||||
{
|
||||
{ L"Full control", SECRET_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", SECRET_READ, TRUE, FALSE },
|
||||
{ L"Write", SECRET_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", SECRET_EXECUTE, TRUE, FALSE },
|
||||
{ L"Set value", SECRET_SET_VALUE, FALSE, TRUE },
|
||||
{ L"Query value", SECRET_QUERY_VALUE, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(LsaTrusted)
|
||||
{
|
||||
{ L"Full control", TRUSTED_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", TRUSTED_READ, TRUE, FALSE },
|
||||
{ L"Write", TRUSTED_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", TRUSTED_EXECUTE, TRUE, FALSE },
|
||||
{ L"Query domain name", TRUSTED_QUERY_DOMAIN_NAME, FALSE, TRUE },
|
||||
{ L"Query controllers", TRUSTED_QUERY_CONTROLLERS, FALSE, TRUE },
|
||||
{ L"Set controllers", TRUSTED_SET_CONTROLLERS, FALSE, TRUE },
|
||||
{ L"Query POSIX", TRUSTED_QUERY_POSIX, FALSE, TRUE },
|
||||
{ L"Set POSIX", TRUSTED_SET_POSIX, FALSE, TRUE },
|
||||
{ L"Query authentication", TRUSTED_QUERY_AUTH, FALSE, TRUE },
|
||||
{ L"Set authentication", TRUSTED_SET_AUTH, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Mutant)
|
||||
{
|
||||
{ L"Full control", MUTANT_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", MUTANT_QUERY_STATE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Partition)
|
||||
{
|
||||
{ L"Full control", MEMORY_PARTITION_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", MEMORY_PARTITION_QUERY_ACCESS, TRUE, TRUE },
|
||||
{ L"Modify", MEMORY_PARTITION_MODIFY_ACCESS, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Process)
|
||||
{
|
||||
{ L"Full control", STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xfff, TRUE, TRUE },
|
||||
{ L"Query information", PROCESS_QUERY_INFORMATION, TRUE, TRUE },
|
||||
{ L"Set information", PROCESS_SET_INFORMATION, TRUE, TRUE },
|
||||
{ L"Set quotas", PROCESS_SET_QUOTA, TRUE, TRUE },
|
||||
{ L"Set session ID", PROCESS_SET_SESSIONID, TRUE, TRUE },
|
||||
{ L"Create threads", PROCESS_CREATE_THREAD, TRUE, TRUE },
|
||||
{ L"Create processes", PROCESS_CREATE_PROCESS, TRUE, TRUE },
|
||||
{ L"Modify memory", PROCESS_VM_OPERATION, TRUE, TRUE, L"VM operation" },
|
||||
{ L"Read memory", PROCESS_VM_READ, TRUE, TRUE, L"VM read" },
|
||||
{ L"Write memory", PROCESS_VM_WRITE, TRUE, TRUE, L"VM write" },
|
||||
{ L"Duplicate handles", PROCESS_DUP_HANDLE, TRUE, TRUE },
|
||||
{ L"Suspend / resume / set port", PROCESS_SUSPEND_RESUME, TRUE, TRUE, L"Suspend/resume" },
|
||||
{ L"Terminate", PROCESS_TERMINATE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Process60)
|
||||
{
|
||||
{ L"Full control", STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff, TRUE, TRUE }, // PROCESS_ALL_ACCESS
|
||||
{ L"Query limited information", PROCESS_QUERY_LIMITED_INFORMATION, TRUE, TRUE },
|
||||
{ L"Query information", PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION, TRUE, TRUE },
|
||||
{ L"Set information", PROCESS_SET_INFORMATION, TRUE, TRUE },
|
||||
{ L"Set quotas", PROCESS_SET_QUOTA, TRUE, TRUE },
|
||||
{ L"Set session ID", PROCESS_SET_SESSIONID, TRUE, TRUE },
|
||||
{ L"Create threads", PROCESS_CREATE_THREAD, TRUE, TRUE },
|
||||
{ L"Create processes", PROCESS_CREATE_PROCESS, TRUE, TRUE },
|
||||
{ L"Modify memory", PROCESS_VM_OPERATION, TRUE, TRUE, L"VM operation" },
|
||||
{ L"Read memory", PROCESS_VM_READ, TRUE, TRUE, L"VM read" },
|
||||
{ L"Write memory", PROCESS_VM_WRITE, TRUE, TRUE, L"VM write" },
|
||||
{ L"Duplicate handles", PROCESS_DUP_HANDLE, TRUE, TRUE },
|
||||
{ L"Suspend / resume / set port", PROCESS_SUSPEND_RESUME, TRUE, TRUE, L"Suspend/resume" },
|
||||
{ L"Terminate", PROCESS_TERMINATE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Profile)
|
||||
{
|
||||
{ L"Full control", PROFILE_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Control", PROFILE_CONTROL, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(SamAlias)
|
||||
{
|
||||
{ L"Full control", ALIAS_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", ALIAS_READ, TRUE, FALSE },
|
||||
{ L"Write", ALIAS_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", ALIAS_EXECUTE, TRUE, FALSE },
|
||||
{ L"Read information", ALIAS_READ_INFORMATION, FALSE, TRUE },
|
||||
{ L"Write account", ALIAS_WRITE_ACCOUNT, FALSE, TRUE },
|
||||
{ L"Add member", ALIAS_ADD_MEMBER, FALSE, TRUE },
|
||||
{ L"Remove member", ALIAS_REMOVE_MEMBER, FALSE, TRUE },
|
||||
{ L"List members", ALIAS_LIST_MEMBERS, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(SamDomain)
|
||||
{
|
||||
{ L"Full control", DOMAIN_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", DOMAIN_READ, TRUE, FALSE },
|
||||
{ L"Write", DOMAIN_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", DOMAIN_EXECUTE, TRUE, FALSE },
|
||||
{ L"Read password parameters", DOMAIN_READ_PASSWORD_PARAMETERS, FALSE, TRUE },
|
||||
{ L"Write password parameters", DOMAIN_WRITE_PASSWORD_PARAMS, FALSE, TRUE },
|
||||
{ L"Read other parameters", DOMAIN_READ_OTHER_PARAMETERS, FALSE, TRUE },
|
||||
{ L"Write other parameters", DOMAIN_WRITE_OTHER_PARAMETERS, FALSE, TRUE },
|
||||
{ L"Create user", DOMAIN_CREATE_USER, FALSE, TRUE },
|
||||
{ L"Create group", DOMAIN_CREATE_GROUP, FALSE, TRUE },
|
||||
{ L"Create alias", DOMAIN_CREATE_ALIAS, FALSE, TRUE },
|
||||
{ L"Get alias membership", DOMAIN_GET_ALIAS_MEMBERSHIP, FALSE, TRUE },
|
||||
{ L"List accounts", DOMAIN_LIST_ACCOUNTS, FALSE, TRUE },
|
||||
{ L"Lookup", DOMAIN_LOOKUP, FALSE, TRUE },
|
||||
{ L"Administer server", DOMAIN_ADMINISTER_SERVER, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(SamGroup)
|
||||
{
|
||||
{ L"Full control", GROUP_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", GROUP_READ, TRUE, FALSE },
|
||||
{ L"Write", GROUP_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", GROUP_EXECUTE, TRUE, FALSE },
|
||||
{ L"Read information", GROUP_READ_INFORMATION, FALSE, TRUE },
|
||||
{ L"Write account", GROUP_WRITE_ACCOUNT, FALSE, TRUE },
|
||||
{ L"Add member", GROUP_ADD_MEMBER, FALSE, TRUE },
|
||||
{ L"Remove member", GROUP_REMOVE_MEMBER, FALSE, TRUE },
|
||||
{ L"List members", GROUP_LIST_MEMBERS, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(SamServer)
|
||||
{
|
||||
{ L"Full control", SAM_SERVER_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", SAM_SERVER_READ, TRUE, FALSE },
|
||||
{ L"Write", SAM_SERVER_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", SAM_SERVER_EXECUTE, TRUE, FALSE },
|
||||
{ L"Connect", SAM_SERVER_CONNECT, FALSE, TRUE },
|
||||
{ L"Shutdown", SAM_SERVER_SHUTDOWN, FALSE, TRUE },
|
||||
{ L"Initialize", SAM_SERVER_INITIALIZE, FALSE, TRUE },
|
||||
{ L"Create domain", SAM_SERVER_CREATE_DOMAIN, FALSE, TRUE },
|
||||
{ L"Enumerate domains", SAM_SERVER_ENUMERATE_DOMAINS, FALSE, TRUE },
|
||||
{ L"Lookup domain", SAM_SERVER_LOOKUP_DOMAIN, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(SamUser)
|
||||
{
|
||||
{ L"Full control", USER_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", USER_READ, TRUE, FALSE },
|
||||
{ L"Write", USER_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", USER_EXECUTE, TRUE, FALSE },
|
||||
{ L"Read general", USER_READ_GENERAL, FALSE, TRUE },
|
||||
{ L"Read preferences", USER_READ_PREFERENCES, FALSE, TRUE },
|
||||
{ L"Write preferences", USER_WRITE_PREFERENCES, FALSE, TRUE },
|
||||
{ L"Read logon", USER_READ_LOGON, FALSE, TRUE },
|
||||
{ L"Read account", USER_READ_ACCOUNT, FALSE, TRUE },
|
||||
{ L"Write account", USER_WRITE_ACCOUNT, FALSE, TRUE },
|
||||
{ L"Change password", USER_CHANGE_PASSWORD, FALSE, TRUE },
|
||||
{ L"Force password change", USER_FORCE_PASSWORD_CHANGE, FALSE, TRUE },
|
||||
{ L"List groups", USER_LIST_GROUPS, FALSE, TRUE },
|
||||
{ L"Read group information", USER_READ_GROUP_INFORMATION, FALSE, TRUE },
|
||||
{ L"Write group information", USER_WRITE_GROUP_INFORMATION, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Section)
|
||||
{
|
||||
{ L"Full control", SECTION_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", SECTION_QUERY, TRUE, TRUE },
|
||||
{ L"Map for read", SECTION_MAP_READ, TRUE, TRUE, L"Map read" },
|
||||
{ L"Map for write", SECTION_MAP_WRITE, TRUE, TRUE, L"Map write" },
|
||||
{ L"Map for execute", SECTION_MAP_EXECUTE, TRUE, TRUE, L"Map execute" },
|
||||
{ L"Map for execute (explicit)", SECTION_MAP_EXECUTE_EXPLICIT, TRUE, TRUE, L"Map execute explicit" },
|
||||
{ L"Extend size", SECTION_EXTEND_SIZE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Semaphore)
|
||||
{
|
||||
{ L"Full control", SEMAPHORE_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", SEMAPHORE_QUERY_STATE, TRUE, TRUE },
|
||||
{ L"Modify", SEMAPHORE_MODIFY_STATE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Service)
|
||||
{
|
||||
{ L"Full control", SERVICE_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query status", SERVICE_QUERY_STATUS, TRUE, TRUE },
|
||||
{ L"Query configuration", SERVICE_QUERY_CONFIG, TRUE, TRUE },
|
||||
{ L"Modify configuration", SERVICE_CHANGE_CONFIG, TRUE, TRUE },
|
||||
{ L"Enumerate dependents", SERVICE_ENUMERATE_DEPENDENTS, TRUE, TRUE },
|
||||
{ L"Start", SERVICE_START, TRUE, TRUE },
|
||||
{ L"Stop", SERVICE_STOP, TRUE, TRUE },
|
||||
{ L"Pause / continue", SERVICE_PAUSE_CONTINUE, TRUE, TRUE, L"Pause/continue" },
|
||||
{ L"Interrogate", SERVICE_INTERROGATE, TRUE, TRUE },
|
||||
{ L"User-defined control", SERVICE_USER_DEFINED_CONTROL, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Session)
|
||||
{
|
||||
{ L"Full control", SESSION_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", SESSION_QUERY_ACCESS, TRUE, TRUE },
|
||||
{ L"Modify", SESSION_MODIFY_ACCESS, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(SymbolicLink)
|
||||
{
|
||||
{ L"Full control", SYMBOLIC_LINK_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", SYMBOLIC_LINK_QUERY, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Thread)
|
||||
{
|
||||
{ L"Full control", STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff, TRUE, TRUE },
|
||||
{ L"Query information", THREAD_QUERY_INFORMATION, TRUE, TRUE },
|
||||
{ L"Set information", THREAD_SET_INFORMATION, TRUE, TRUE },
|
||||
{ L"Get context", THREAD_GET_CONTEXT, TRUE, TRUE },
|
||||
{ L"Set context", THREAD_SET_CONTEXT, TRUE, TRUE },
|
||||
{ L"Set token", THREAD_SET_THREAD_TOKEN, TRUE, TRUE },
|
||||
{ L"Alert", THREAD_ALERT, TRUE, TRUE },
|
||||
{ L"Impersonate", THREAD_IMPERSONATE, TRUE, TRUE },
|
||||
{ L"Direct impersonate", THREAD_DIRECT_IMPERSONATION, TRUE, TRUE },
|
||||
{ L"Suspend / resume", THREAD_SUSPEND_RESUME, TRUE, TRUE, L"Suspend/resume" },
|
||||
{ L"Terminate", THREAD_TERMINATE, TRUE, TRUE },
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Thread60)
|
||||
{
|
||||
{ L"Full control", STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff, TRUE, TRUE }, // THREAD_ALL_ACCESS
|
||||
{ L"Query limited information", THREAD_QUERY_LIMITED_INFORMATION, TRUE, TRUE },
|
||||
{ L"Query information", THREAD_QUERY_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION, TRUE, TRUE },
|
||||
{ L"Set limited information", THREAD_SET_LIMITED_INFORMATION, TRUE, TRUE },
|
||||
{ L"Set information", THREAD_SET_INFORMATION | THREAD_SET_LIMITED_INFORMATION, TRUE, TRUE },
|
||||
{ L"Get context", THREAD_GET_CONTEXT, TRUE, TRUE },
|
||||
{ L"Set context", THREAD_SET_CONTEXT, TRUE, TRUE },
|
||||
{ L"Set token", THREAD_SET_THREAD_TOKEN, TRUE, TRUE },
|
||||
{ L"Alert", THREAD_ALERT, TRUE, TRUE },
|
||||
{ L"Impersonate", THREAD_IMPERSONATE, TRUE, TRUE },
|
||||
{ L"Direct impersonate", THREAD_DIRECT_IMPERSONATION, TRUE, TRUE },
|
||||
{ L"Suspend / resume", THREAD_SUSPEND_RESUME, TRUE, TRUE, L"Suspend/resume" },
|
||||
{ L"Terminate", THREAD_TERMINATE, TRUE, TRUE },
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Timer)
|
||||
{
|
||||
{ L"Full control", TIMER_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Query", TIMER_QUERY_STATE, TRUE, TRUE },
|
||||
{ L"Modify", TIMER_MODIFY_STATE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(TmEn)
|
||||
{
|
||||
{ L"Full control", ENLISTMENT_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", ENLISTMENT_GENERIC_READ, TRUE, FALSE },
|
||||
{ L"Write", ENLISTMENT_GENERIC_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", ENLISTMENT_GENERIC_EXECUTE, TRUE, FALSE },
|
||||
{ L"Query information", ENLISTMENT_QUERY_INFORMATION, FALSE, TRUE },
|
||||
{ L"Set information", ENLISTMENT_SET_INFORMATION, FALSE, TRUE },
|
||||
{ L"Recover", ENLISTMENT_RECOVER, FALSE, TRUE },
|
||||
{ L"Subordinate rights", ENLISTMENT_SUBORDINATE_RIGHTS, FALSE, TRUE },
|
||||
{ L"Superior rights", ENLISTMENT_SUPERIOR_RIGHTS, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(TmRm)
|
||||
{
|
||||
{ L"Full control", RESOURCEMANAGER_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", RESOURCEMANAGER_GENERIC_READ, TRUE, FALSE },
|
||||
{ L"Write", RESOURCEMANAGER_GENERIC_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", RESOURCEMANAGER_GENERIC_EXECUTE, TRUE, FALSE },
|
||||
{ L"Query information", RESOURCEMANAGER_QUERY_INFORMATION, FALSE, TRUE },
|
||||
{ L"Set information", RESOURCEMANAGER_SET_INFORMATION, FALSE, TRUE },
|
||||
{ L"Get notifications", RESOURCEMANAGER_GET_NOTIFICATION, FALSE, TRUE },
|
||||
{ L"Enlist", RESOURCEMANAGER_ENLIST, FALSE, TRUE },
|
||||
{ L"Recover", RESOURCEMANAGER_RECOVER, FALSE, TRUE },
|
||||
{ L"Register protocols", RESOURCEMANAGER_REGISTER_PROTOCOL, FALSE, TRUE },
|
||||
{ L"Complete propagation", RESOURCEMANAGER_COMPLETE_PROPAGATION, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(TmTm)
|
||||
{
|
||||
{ L"Full control", TRANSACTIONMANAGER_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", TRANSACTIONMANAGER_GENERIC_READ, TRUE, FALSE },
|
||||
{ L"Write", TRANSACTIONMANAGER_GENERIC_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", TRANSACTIONMANAGER_GENERIC_EXECUTE, TRUE, FALSE },
|
||||
{ L"Query information", TRANSACTIONMANAGER_QUERY_INFORMATION, FALSE, TRUE },
|
||||
{ L"Set information", TRANSACTIONMANAGER_SET_INFORMATION, FALSE, TRUE },
|
||||
{ L"Recover", TRANSACTIONMANAGER_RECOVER, FALSE, TRUE },
|
||||
{ L"Rename", TRANSACTIONMANAGER_RENAME, FALSE, TRUE },
|
||||
{ L"Create resource manager", TRANSACTIONMANAGER_CREATE_RM, FALSE, TRUE },
|
||||
{ L"Bind transactions", TRANSACTIONMANAGER_BIND_TRANSACTION, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(TmTx)
|
||||
{
|
||||
{ L"Full control", TRANSACTION_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", TRANSACTION_GENERIC_READ, TRUE, FALSE },
|
||||
{ L"Write", TRANSACTION_GENERIC_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", TRANSACTION_GENERIC_EXECUTE, TRUE, FALSE },
|
||||
{ L"Query information", TRANSACTION_QUERY_INFORMATION, FALSE, TRUE },
|
||||
{ L"Set information", TRANSACTION_SET_INFORMATION, FALSE, TRUE },
|
||||
{ L"Enlist", TRANSACTION_ENLIST, FALSE, TRUE },
|
||||
{ L"Commit", TRANSACTION_COMMIT, FALSE, TRUE },
|
||||
{ L"Rollback", TRANSACTION_ROLLBACK, FALSE, TRUE },
|
||||
{ L"Propagate", TRANSACTION_PROPAGATE, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Token)
|
||||
{
|
||||
{ L"Full control", TOKEN_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", TOKEN_READ, TRUE, FALSE },
|
||||
{ L"Write", TOKEN_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", TOKEN_EXECUTE, TRUE, FALSE },
|
||||
{ L"Adjust privileges", TOKEN_ADJUST_PRIVILEGES, FALSE, TRUE },
|
||||
{ L"Adjust groups", TOKEN_ADJUST_GROUPS, FALSE, TRUE },
|
||||
{ L"Adjust defaults", TOKEN_ADJUST_DEFAULT, FALSE, TRUE },
|
||||
{ L"Adjust session ID", TOKEN_ADJUST_SESSIONID, FALSE, TRUE },
|
||||
{ L"Assign as primary token", TOKEN_ASSIGN_PRIMARY, FALSE, TRUE, L"Assign primary" },
|
||||
{ L"Duplicate", TOKEN_DUPLICATE, FALSE, TRUE },
|
||||
{ L"Impersonate", TOKEN_IMPERSONATE, FALSE, TRUE },
|
||||
{ L"Query", TOKEN_QUERY, FALSE, TRUE },
|
||||
{ L"Query source", TOKEN_QUERY_SOURCE, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(TpWorkerFactory)
|
||||
{
|
||||
{ L"Full control", WORKER_FACTORY_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Release worker", WORKER_FACTORY_RELEASE_WORKER, FALSE, TRUE },
|
||||
{ L"Ready worker", WORKER_FACTORY_READY_WORKER, FALSE, TRUE },
|
||||
{ L"Wait", WORKER_FACTORY_WAIT, FALSE, TRUE },
|
||||
{ L"Set information", WORKER_FACTORY_SET_INFORMATION, FALSE, TRUE },
|
||||
{ L"Query information", WORKER_FACTORY_QUERY_INFORMATION, FALSE, TRUE },
|
||||
{ L"Shutdown", WORKER_FACTORY_SHUTDOWN, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(Type)
|
||||
{
|
||||
{ L"Full control", OBJECT_TYPE_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Create", OBJECT_TYPE_CREATE, TRUE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(WindowStation)
|
||||
{
|
||||
{ L"Full control", WINSTA_ALL_ACCESS | STANDARD_RIGHTS_REQUIRED, TRUE, TRUE },
|
||||
{ L"Read", WINSTA_GENERIC_READ, TRUE, FALSE },
|
||||
{ L"Write", WINSTA_GENERIC_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", WINSTA_GENERIC_EXECUTE, TRUE, FALSE },
|
||||
{ L"Enumerate", WINSTA_ENUMERATE, FALSE, TRUE },
|
||||
{ L"Enumerate desktops", WINSTA_ENUMDESKTOPS, FALSE, TRUE },
|
||||
{ L"Read attributes", WINSTA_READATTRIBUTES, FALSE, TRUE },
|
||||
{ L"Read screen", WINSTA_READSCREEN, FALSE, TRUE },
|
||||
{ L"Access clipboard", WINSTA_ACCESSCLIPBOARD, FALSE, TRUE },
|
||||
{ L"Access global atoms", WINSTA_ACCESSGLOBALATOMS, FALSE, TRUE },
|
||||
{ L"Create desktop", WINSTA_CREATEDESKTOP, FALSE, TRUE },
|
||||
{ L"Write attributes", WINSTA_WRITEATTRIBUTES, FALSE, TRUE },
|
||||
{ L"Exit windows", WINSTA_EXITWINDOWS, FALSE, TRUE }
|
||||
};
|
||||
|
||||
ACCESS_ENTRIES(WmiGuid)
|
||||
{
|
||||
{ L"Full control", WMIGUID_ALL_ACCESS, TRUE, TRUE },
|
||||
{ L"Read", WMIGUID_GENERIC_READ, TRUE, FALSE },
|
||||
{ L"Write", WMIGUID_GENERIC_WRITE, TRUE, FALSE },
|
||||
{ L"Execute", WMIGUID_GENERIC_EXECUTE, TRUE, FALSE },
|
||||
{ L"Query information", WMIGUID_QUERY, FALSE, TRUE },
|
||||
{ L"Set information", WMIGUID_SET, FALSE, TRUE },
|
||||
{ L"Get notifications", WMIGUID_NOTIFICATION, FALSE, TRUE },
|
||||
{ L"Read description", WMIGUID_READ_DESCRIPTION, FALSE, TRUE },
|
||||
{ L"Execute", WMIGUID_EXECUTE, FALSE, TRUE },
|
||||
{ L"Create real-time logs", TRACELOG_CREATE_REALTIME, FALSE, TRUE, L"Create real-time" },
|
||||
{ L"Create on disk logs", TRACELOG_CREATE_ONDISK, FALSE, TRUE, L"Create on disk" },
|
||||
{ L"Enable provider GUIDs", TRACELOG_GUID_ENABLE, FALSE, TRUE, L"Enable GUIDs" },
|
||||
{ L"Access kernel logger", TRACELOG_ACCESS_KERNEL_LOGGER, FALSE, TRUE },
|
||||
{ L"Log events", TRACELOG_LOG_EVENT, FALSE, TRUE },
|
||||
{ L"Access real-time events", TRACELOG_ACCESS_REALTIME, FALSE, TRUE, L"Access real-time" },
|
||||
{ L"Register provider GUIDs", TRACELOG_REGISTER_GUIDS, FALSE, TRUE, L"Register GUIDs" }
|
||||
};
|
||||
|
||||
static PH_SPECIFIC_TYPE PhSpecificTypes[] =
|
||||
{
|
||||
ACCESS_ENTRY(AlpcPort, TRUE),
|
||||
ACCESS_ENTRY(DebugObject, TRUE),
|
||||
ACCESS_ENTRY(Desktop, FALSE),
|
||||
ACCESS_ENTRY(Directory, FALSE),
|
||||
ACCESS_ENTRY(Event, TRUE),
|
||||
ACCESS_ENTRY(EventPair, TRUE),
|
||||
ACCESS_ENTRY(File, TRUE),
|
||||
ACCESS_ENTRY(FilterConnectionPort, FALSE),
|
||||
ACCESS_ENTRY(IoCompletion, TRUE),
|
||||
ACCESS_ENTRY(Job, TRUE),
|
||||
ACCESS_ENTRY(Key, FALSE),
|
||||
ACCESS_ENTRY(KeyedEvent, FALSE),
|
||||
ACCESS_ENTRY(LsaAccount, FALSE),
|
||||
ACCESS_ENTRY(LsaPolicy, FALSE),
|
||||
ACCESS_ENTRY(LsaSecret, FALSE),
|
||||
ACCESS_ENTRY(LsaTrusted, FALSE),
|
||||
ACCESS_ENTRY(Mutant, TRUE),
|
||||
ACCESS_ENTRY(Partition, TRUE),
|
||||
ACCESS_ENTRY(Process, TRUE),
|
||||
ACCESS_ENTRY(Process60, TRUE),
|
||||
ACCESS_ENTRY(Profile, FALSE),
|
||||
ACCESS_ENTRY(SamAlias, FALSE),
|
||||
ACCESS_ENTRY(SamDomain, FALSE),
|
||||
ACCESS_ENTRY(SamGroup, FALSE),
|
||||
ACCESS_ENTRY(SamServer, FALSE),
|
||||
ACCESS_ENTRY(SamUser, FALSE),
|
||||
ACCESS_ENTRY(Section, FALSE),
|
||||
ACCESS_ENTRY(Semaphore, TRUE),
|
||||
ACCESS_ENTRY(Service, FALSE),
|
||||
ACCESS_ENTRY(Session, FALSE),
|
||||
ACCESS_ENTRY(SymbolicLink, FALSE),
|
||||
ACCESS_ENTRY(Thread, TRUE),
|
||||
ACCESS_ENTRY(Thread60, TRUE),
|
||||
ACCESS_ENTRY(Timer, TRUE),
|
||||
ACCESS_ENTRY(TmEn, FALSE),
|
||||
ACCESS_ENTRY(TmRm, FALSE),
|
||||
ACCESS_ENTRY(TmTm, FALSE),
|
||||
ACCESS_ENTRY(TmTx, FALSE),
|
||||
ACCESS_ENTRY(Token, FALSE),
|
||||
ACCESS_ENTRY(TpWorkerFactory, FALSE),
|
||||
ACCESS_ENTRY(Type, FALSE),
|
||||
ACCESS_ENTRY(WindowStation, FALSE),
|
||||
ACCESS_ENTRY(WmiGuid, TRUE)
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets access entries for an object type.
|
||||
*
|
||||
* \param Type The name of the object type.
|
||||
* \param AccessEntries A variable which receives an array of access entry structures. You must free
|
||||
* the buffer with PhFree() when you no longer need it.
|
||||
* \param NumberOfAccessEntries A variable which receives the number of access entry structures
|
||||
* returned in
|
||||
* \a AccessEntries.
|
||||
*/
|
||||
BOOLEAN PhGetAccessEntries(
|
||||
_In_ PWSTR Type,
|
||||
_Out_ PPH_ACCESS_ENTRY *AccessEntries,
|
||||
_Out_ PULONG NumberOfAccessEntries
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
PPH_SPECIFIC_TYPE specificType = NULL;
|
||||
PPH_ACCESS_ENTRY accessEntries;
|
||||
|
||||
if (PhEqualStringZ(Type, L"ALPC Port", TRUE))
|
||||
{
|
||||
Type = L"AlpcPort";
|
||||
}
|
||||
else if (PhEqualStringZ(Type, L"Port", TRUE))
|
||||
{
|
||||
Type = L"AlpcPort";
|
||||
}
|
||||
else if (PhEqualStringZ(Type, L"WaitablePort", TRUE))
|
||||
{
|
||||
Type = L"AlpcPort";
|
||||
}
|
||||
else if (PhEqualStringZ(Type, L"Process", TRUE))
|
||||
{
|
||||
if (WindowsVersion >= WINDOWS_VISTA)
|
||||
Type = L"Process60";
|
||||
}
|
||||
else if (PhEqualStringZ(Type, L"Thread", TRUE))
|
||||
{
|
||||
if (WindowsVersion >= WINDOWS_VISTA)
|
||||
Type = L"Thread60";
|
||||
}
|
||||
|
||||
// Find the specific type.
|
||||
for (i = 0; i < sizeof(PhSpecificTypes) / sizeof(PH_SPECIFIC_TYPE); i++)
|
||||
{
|
||||
if (PhEqualStringZ(PhSpecificTypes[i].Type, Type, TRUE))
|
||||
{
|
||||
specificType = &PhSpecificTypes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (specificType)
|
||||
{
|
||||
ULONG sizeOfEntries;
|
||||
|
||||
// Copy the specific access entries and append the standard access entries.
|
||||
|
||||
if (specificType->HasSynchronize)
|
||||
sizeOfEntries = specificType->SizeOfAccessEntries + sizeof(PhStandardAccessEntries);
|
||||
else
|
||||
sizeOfEntries = specificType->SizeOfAccessEntries + sizeof(PhStandardAccessEntries) - sizeof(PH_ACCESS_ENTRY);
|
||||
|
||||
accessEntries = PhAllocate(sizeOfEntries);
|
||||
memcpy(accessEntries, specificType->AccessEntries, specificType->SizeOfAccessEntries);
|
||||
|
||||
if (specificType->HasSynchronize)
|
||||
{
|
||||
memcpy(
|
||||
PTR_ADD_OFFSET(accessEntries, specificType->SizeOfAccessEntries),
|
||||
PhStandardAccessEntries,
|
||||
sizeof(PhStandardAccessEntries)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(
|
||||
PTR_ADD_OFFSET(accessEntries, specificType->SizeOfAccessEntries),
|
||||
&PhStandardAccessEntries[1],
|
||||
sizeof(PhStandardAccessEntries) - sizeof(PH_ACCESS_ENTRY)
|
||||
);
|
||||
}
|
||||
|
||||
*AccessEntries = accessEntries;
|
||||
*NumberOfAccessEntries = sizeOfEntries / sizeof(PH_ACCESS_ENTRY);
|
||||
}
|
||||
else
|
||||
{
|
||||
accessEntries = PhAllocate(sizeof(PhStandardAccessEntries));
|
||||
memcpy(accessEntries, PhStandardAccessEntries, sizeof(PhStandardAccessEntries));
|
||||
|
||||
*AccessEntries = accessEntries;
|
||||
*NumberOfAccessEntries = sizeof(PhStandardAccessEntries) / sizeof(PH_ACCESS_ENTRY);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int __cdecl PhpAccessEntryCompare(
|
||||
_In_ const void *elem1,
|
||||
_In_ const void *elem2
|
||||
)
|
||||
{
|
||||
PPH_ACCESS_ENTRY entry1 = (PPH_ACCESS_ENTRY)elem1;
|
||||
PPH_ACCESS_ENTRY entry2 = (PPH_ACCESS_ENTRY)elem2;
|
||||
|
||||
return intcmp(PhCountBits(entry2->Access), PhCountBits(entry1->Access));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string representation of an access mask.
|
||||
*
|
||||
* \param Access The access mask.
|
||||
* \param AccessEntries An array of access entry structures. You can call PhGetAccessEntries() to
|
||||
* retrieve the access entry structures for a standard object type.
|
||||
* \param NumberOfAccessEntries The number of elements in \a AccessEntries.
|
||||
*
|
||||
* \return The string representation of \a Access.
|
||||
*/
|
||||
PPH_STRING PhGetAccessString(
|
||||
_In_ ACCESS_MASK Access,
|
||||
_In_ PPH_ACCESS_ENTRY AccessEntries,
|
||||
_In_ ULONG NumberOfAccessEntries
|
||||
)
|
||||
{
|
||||
PH_STRING_BUILDER stringBuilder;
|
||||
PPH_ACCESS_ENTRY accessEntries;
|
||||
PBOOLEAN matched;
|
||||
ULONG i;
|
||||
ULONG j;
|
||||
|
||||
PhInitializeStringBuilder(&stringBuilder, 32);
|
||||
|
||||
// Sort the access entries according to how many access rights they include.
|
||||
accessEntries = PhAllocateCopy(AccessEntries, NumberOfAccessEntries * sizeof(PH_ACCESS_ENTRY));
|
||||
qsort(accessEntries, NumberOfAccessEntries, sizeof(PH_ACCESS_ENTRY), PhpAccessEntryCompare);
|
||||
|
||||
matched = PhAllocate(NumberOfAccessEntries * sizeof(BOOLEAN));
|
||||
memset(matched, 0, NumberOfAccessEntries * sizeof(BOOLEAN));
|
||||
|
||||
for (i = 0; i < NumberOfAccessEntries; i++)
|
||||
{
|
||||
// We make sure we haven't matched this access entry yet. This ensures that we won't get
|
||||
// duplicates, e.g. FILE_GENERIC_READ includes FILE_READ_DATA, and we don't want to display
|
||||
// both to the user.
|
||||
if (
|
||||
!matched[i] &&
|
||||
((Access & accessEntries[i].Access) == accessEntries[i].Access)
|
||||
)
|
||||
{
|
||||
if (accessEntries[i].ShortName)
|
||||
PhAppendStringBuilder2(&stringBuilder, accessEntries[i].ShortName);
|
||||
else
|
||||
PhAppendStringBuilder2(&stringBuilder, accessEntries[i].Name);
|
||||
|
||||
PhAppendStringBuilder2(&stringBuilder, L", ");
|
||||
|
||||
// Disable equal or more specific entries.
|
||||
for (j = i; j < NumberOfAccessEntries; j++)
|
||||
{
|
||||
if ((accessEntries[i].Access | accessEntries[j].Access) == accessEntries[i].Access)
|
||||
matched[j] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the trailing ", ".
|
||||
if (PhEndsWithString2(stringBuilder.String, L", ", FALSE))
|
||||
PhRemoveEndStringBuilder(&stringBuilder, 2);
|
||||
|
||||
PhFree(matched);
|
||||
PhFree(accessEntries);
|
||||
|
||||
return PhFinalStringBuilderString(&stringBuilder);
|
||||
}
|
||||
593
phlib/secedit.c
Normal file
593
phlib/secedit.c
Normal file
@@ -0,0 +1,593 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* object security editor
|
||||
*
|
||||
* Copyright (C) 2010 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <guisup.h>
|
||||
#include <secedit.h>
|
||||
#include <seceditp.h>
|
||||
#include <hndlinfo.h>
|
||||
|
||||
static ISecurityInformationVtbl PhSecurityInformation_VTable =
|
||||
{
|
||||
PhSecurityInformation_QueryInterface,
|
||||
PhSecurityInformation_AddRef,
|
||||
PhSecurityInformation_Release,
|
||||
PhSecurityInformation_GetObjectInformation,
|
||||
PhSecurityInformation_GetSecurity,
|
||||
PhSecurityInformation_SetSecurity,
|
||||
PhSecurityInformation_GetAccessRights,
|
||||
PhSecurityInformation_MapGeneric,
|
||||
PhSecurityInformation_GetInheritTypes,
|
||||
PhSecurityInformation_PropertySheetPageCallback
|
||||
};
|
||||
|
||||
static PH_INITONCE SecurityEditorInitOnce = PH_INITONCE_INIT;
|
||||
static _CreateSecurityPage CreateSecurityPage_I;
|
||||
static _EditSecurity EditSecurity_I;
|
||||
|
||||
FORCEINLINE VOID PhpSecurityEditorInitialization(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (PhBeginInitOnce(&SecurityEditorInitOnce))
|
||||
{
|
||||
HMODULE aclui;
|
||||
|
||||
aclui = LoadLibrary(L"aclui.dll");
|
||||
CreateSecurityPage_I = (PVOID)GetProcAddress(aclui, "CreateSecurityPage");
|
||||
EditSecurity_I = (PVOID)GetProcAddress(aclui, "EditSecurity");
|
||||
|
||||
PhEndInitOnce(&SecurityEditorInitOnce);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a security editor page.
|
||||
*
|
||||
* \param ObjectName The name of the object.
|
||||
* \param GetObjectSecurity A callback function executed to retrieve the security descriptor of the
|
||||
* object.
|
||||
* \param SetObjectSecurity A callback function executed to modify the security descriptor of the
|
||||
* object.
|
||||
* \param Context A user-defined value to pass to the callback functions.
|
||||
* \param AccessEntries An array of access mask descriptors.
|
||||
* \param NumberOfAccessEntries The number of elements in \a AccessEntries.
|
||||
*/
|
||||
HPROPSHEETPAGE PhCreateSecurityPage(
|
||||
_In_ PWSTR ObjectName,
|
||||
_In_ PPH_GET_OBJECT_SECURITY GetObjectSecurity,
|
||||
_In_ PPH_SET_OBJECT_SECURITY SetObjectSecurity,
|
||||
_In_opt_ PVOID Context,
|
||||
_In_ PPH_ACCESS_ENTRY AccessEntries,
|
||||
_In_ ULONG NumberOfAccessEntries
|
||||
)
|
||||
{
|
||||
ISecurityInformation *info;
|
||||
HPROPSHEETPAGE page;
|
||||
|
||||
PhpSecurityEditorInitialization();
|
||||
|
||||
if (!CreateSecurityPage_I)
|
||||
return NULL;
|
||||
|
||||
info = PhSecurityInformation_Create(
|
||||
ObjectName,
|
||||
GetObjectSecurity,
|
||||
SetObjectSecurity,
|
||||
Context,
|
||||
AccessEntries,
|
||||
NumberOfAccessEntries
|
||||
);
|
||||
|
||||
page = CreateSecurityPage_I(info);
|
||||
|
||||
PhSecurityInformation_Release(info);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a security editor dialog.
|
||||
*
|
||||
* \param hWnd The parent window of the dialog.
|
||||
* \param ObjectName The name of the object.
|
||||
* \param GetObjectSecurity A callback function executed to retrieve the security descriptor of the
|
||||
* object.
|
||||
* \param SetObjectSecurity A callback function executed to modify the security descriptor of the
|
||||
* object.
|
||||
* \param Context A user-defined value to pass to the callback functions.
|
||||
* \param AccessEntries An array of access mask descriptors.
|
||||
* \param NumberOfAccessEntries The number of elements in \a AccessEntries.
|
||||
*/
|
||||
VOID PhEditSecurity(
|
||||
_In_ HWND hWnd,
|
||||
_In_ PWSTR ObjectName,
|
||||
_In_ PPH_GET_OBJECT_SECURITY GetObjectSecurity,
|
||||
_In_ PPH_SET_OBJECT_SECURITY SetObjectSecurity,
|
||||
_In_opt_ PVOID Context,
|
||||
_In_ PPH_ACCESS_ENTRY AccessEntries,
|
||||
_In_ ULONG NumberOfAccessEntries
|
||||
)
|
||||
{
|
||||
ISecurityInformation *info;
|
||||
|
||||
PhpSecurityEditorInitialization();
|
||||
|
||||
if (!EditSecurity_I)
|
||||
return;
|
||||
|
||||
info = PhSecurityInformation_Create(
|
||||
ObjectName,
|
||||
GetObjectSecurity,
|
||||
SetObjectSecurity,
|
||||
Context,
|
||||
AccessEntries,
|
||||
NumberOfAccessEntries
|
||||
);
|
||||
|
||||
EditSecurity_I(hWnd, info);
|
||||
|
||||
PhSecurityInformation_Release(info);
|
||||
}
|
||||
|
||||
ISecurityInformation *PhSecurityInformation_Create(
|
||||
_In_ PWSTR ObjectName,
|
||||
_In_ PPH_GET_OBJECT_SECURITY GetObjectSecurity,
|
||||
_In_ PPH_SET_OBJECT_SECURITY SetObjectSecurity,
|
||||
_In_opt_ PVOID Context,
|
||||
_In_ PPH_ACCESS_ENTRY AccessEntries,
|
||||
_In_ ULONG NumberOfAccessEntries
|
||||
)
|
||||
{
|
||||
PhSecurityInformation *info;
|
||||
ULONG i;
|
||||
|
||||
info = PhAllocate(sizeof(PhSecurityInformation));
|
||||
info->VTable = &PhSecurityInformation_VTable;
|
||||
info->RefCount = 1;
|
||||
|
||||
info->ObjectName = PhCreateString(ObjectName);
|
||||
info->GetObjectSecurity = GetObjectSecurity;
|
||||
info->SetObjectSecurity = SetObjectSecurity;
|
||||
info->Context = Context;
|
||||
info->AccessEntries = PhAllocate(sizeof(SI_ACCESS) * NumberOfAccessEntries);
|
||||
info->NumberOfAccessEntries = NumberOfAccessEntries;
|
||||
|
||||
for (i = 0; i < NumberOfAccessEntries; i++)
|
||||
{
|
||||
memset(&info->AccessEntries[i], 0, sizeof(SI_ACCESS));
|
||||
info->AccessEntries[i].pszName = AccessEntries[i].Name;
|
||||
info->AccessEntries[i].mask = AccessEntries[i].Access;
|
||||
|
||||
if (AccessEntries[i].General)
|
||||
info->AccessEntries[i].dwFlags |= SI_ACCESS_GENERAL;
|
||||
if (AccessEntries[i].Specific)
|
||||
info->AccessEntries[i].dwFlags |= SI_ACCESS_SPECIFIC;
|
||||
}
|
||||
|
||||
return (ISecurityInformation *)info;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_QueryInterface(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ REFIID Riid,
|
||||
_Out_ PVOID *Object
|
||||
)
|
||||
{
|
||||
if (
|
||||
IsEqualIID(Riid, &IID_IUnknown) ||
|
||||
IsEqualIID(Riid, &IID_ISecurityInformation)
|
||||
)
|
||||
{
|
||||
PhSecurityInformation_AddRef(This);
|
||||
*Object = This;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*Object = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE PhSecurityInformation_AddRef(
|
||||
_In_ ISecurityInformation *This
|
||||
)
|
||||
{
|
||||
PhSecurityInformation *this = (PhSecurityInformation *)This;
|
||||
|
||||
this->RefCount++;
|
||||
|
||||
return this->RefCount;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE PhSecurityInformation_Release(
|
||||
_In_ ISecurityInformation *This
|
||||
)
|
||||
{
|
||||
PhSecurityInformation *this = (PhSecurityInformation *)This;
|
||||
|
||||
this->RefCount--;
|
||||
|
||||
if (this->RefCount == 0)
|
||||
{
|
||||
if (this->ObjectName) PhDereferenceObject(this->ObjectName);
|
||||
PhFree(this->AccessEntries);
|
||||
|
||||
PhFree(this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this->RefCount;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetObjectInformation(
|
||||
_In_ ISecurityInformation *This,
|
||||
_Out_ PSI_OBJECT_INFO ObjectInfo
|
||||
)
|
||||
{
|
||||
PhSecurityInformation *this = (PhSecurityInformation *)This;
|
||||
|
||||
memset(ObjectInfo, 0, sizeof(SI_OBJECT_INFO));
|
||||
ObjectInfo->dwFlags =
|
||||
SI_EDIT_AUDITS |
|
||||
SI_EDIT_OWNER |
|
||||
SI_EDIT_PERMS |
|
||||
SI_ADVANCED |
|
||||
SI_NO_ACL_PROTECT |
|
||||
SI_NO_TREE_APPLY;
|
||||
ObjectInfo->hInstance = NULL;
|
||||
ObjectInfo->pszObjectName = this->ObjectName->Buffer;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetSecurity(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ SECURITY_INFORMATION RequestedInformation,
|
||||
_Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor,
|
||||
_In_ BOOL Default
|
||||
)
|
||||
{
|
||||
PhSecurityInformation *this = (PhSecurityInformation *)This;
|
||||
NTSTATUS status;
|
||||
PSECURITY_DESCRIPTOR securityDescriptor;
|
||||
ULONG sdLength;
|
||||
PSECURITY_DESCRIPTOR newSd;
|
||||
|
||||
status = this->GetObjectSecurity(
|
||||
&securityDescriptor,
|
||||
RequestedInformation,
|
||||
this->Context
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return HRESULT_FROM_WIN32(PhNtStatusToDosError(status));
|
||||
|
||||
sdLength = RtlLengthSecurityDescriptor(securityDescriptor);
|
||||
newSd = LocalAlloc(0, sdLength);
|
||||
memcpy(newSd, securityDescriptor, sdLength);
|
||||
PhFree(securityDescriptor);
|
||||
|
||||
*SecurityDescriptor = newSd;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_SetSecurity(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor
|
||||
)
|
||||
{
|
||||
PhSecurityInformation *this = (PhSecurityInformation *)This;
|
||||
NTSTATUS status;
|
||||
|
||||
status = this->SetObjectSecurity(
|
||||
SecurityDescriptor,
|
||||
SecurityInformation,
|
||||
this->Context
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return HRESULT_FROM_WIN32(PhNtStatusToDosError(status));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetAccessRights(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ const GUID *ObjectType,
|
||||
_In_ ULONG Flags,
|
||||
_Out_ PSI_ACCESS *Access,
|
||||
_Out_ PULONG Accesses,
|
||||
_Out_ PULONG DefaultAccess
|
||||
)
|
||||
{
|
||||
PhSecurityInformation *this = (PhSecurityInformation *)This;
|
||||
|
||||
*Access = this->AccessEntries;
|
||||
*Accesses = this->NumberOfAccessEntries;
|
||||
*DefaultAccess = 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_MapGeneric(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ const GUID *ObjectType,
|
||||
_In_ PUCHAR AceFlags,
|
||||
_Inout_ PACCESS_MASK Mask
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetInheritTypes(
|
||||
_In_ ISecurityInformation *This,
|
||||
_Out_ PSI_INHERIT_TYPE *InheritTypes,
|
||||
_Out_ PULONG InheritTypesCount
|
||||
)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE PhSecurityInformation_PropertySheetPageCallback(
|
||||
_In_ ISecurityInformation *This,
|
||||
_In_ HWND hwnd,
|
||||
_In_ UINT uMsg,
|
||||
_In_ SI_PAGE_TYPE uPage
|
||||
)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
NTSTATUS PhpGetObjectSecurityWithTimeout(
|
||||
_In_ HANDLE Handle,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG bufferSize;
|
||||
PVOID buffer;
|
||||
|
||||
bufferSize = 0x100;
|
||||
buffer = PhAllocate(bufferSize);
|
||||
// This is required (especially for File objects) because some drivers don't seem to handle
|
||||
// QuerySecurity properly.
|
||||
memset(buffer, 0, bufferSize);
|
||||
|
||||
status = PhCallNtQuerySecurityObjectWithTimeout(
|
||||
Handle,
|
||||
SecurityInformation,
|
||||
buffer,
|
||||
bufferSize,
|
||||
&bufferSize
|
||||
);
|
||||
|
||||
if (status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
PhFree(buffer);
|
||||
buffer = PhAllocate(bufferSize);
|
||||
memset(buffer, 0, bufferSize);
|
||||
|
||||
status = PhCallNtQuerySecurityObjectWithTimeout(
|
||||
Handle,
|
||||
SecurityInformation,
|
||||
buffer,
|
||||
bufferSize,
|
||||
&bufferSize
|
||||
);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
PhFree(buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
*SecurityDescriptor = (PSECURITY_DESCRIPTOR)buffer;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the security descriptor of an object.
|
||||
*
|
||||
* \param SecurityDescriptor A variable which receives a pointer to the security descriptor of the
|
||||
* object. The security descriptor must be freed using PhFree() when no longer needed.
|
||||
* \param SecurityInformation The security information to retrieve.
|
||||
* \param Context A pointer to a PH_STD_OBJECT_SECURITY structure describing the object.
|
||||
*
|
||||
* \remarks This function may be used for the \a GetObjectSecurity callback in
|
||||
* PhCreateSecurityPage() or PhEditSecurity().
|
||||
*/
|
||||
_Callback_ NTSTATUS PhStdGetObjectSecurity(
|
||||
_Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PPH_STD_OBJECT_SECURITY stdObjectSecurity;
|
||||
HANDLE handle;
|
||||
|
||||
stdObjectSecurity = (PPH_STD_OBJECT_SECURITY)Context;
|
||||
|
||||
status = stdObjectSecurity->OpenObject(
|
||||
&handle,
|
||||
PhGetAccessForGetSecurity(SecurityInformation),
|
||||
stdObjectSecurity->Context
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
if (PhEqualStringZ(stdObjectSecurity->ObjectType, L"Service", TRUE))
|
||||
{
|
||||
status = PhGetSeObjectSecurity(handle, SE_SERVICE, SecurityInformation, SecurityDescriptor);
|
||||
CloseServiceHandle(handle);
|
||||
}
|
||||
else if (PhEqualStringZ(stdObjectSecurity->ObjectType, L"File", TRUE))
|
||||
{
|
||||
status = PhpGetObjectSecurityWithTimeout(handle, SecurityInformation, SecurityDescriptor);
|
||||
NtClose(handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = PhGetObjectSecurity(handle, SecurityInformation, SecurityDescriptor);
|
||||
NtClose(handle);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the security descriptor of an object.
|
||||
*
|
||||
* \param SecurityDescriptor A security descriptor containing security information to set.
|
||||
* \param SecurityInformation The security information to retrieve.
|
||||
* \param Context A pointer to a PH_STD_OBJECT_SECURITY structure describing the object.
|
||||
*
|
||||
* \remarks This function may be used for the \a SetObjectSecurity callback in
|
||||
* PhCreateSecurityPage() or PhEditSecurity().
|
||||
*/
|
||||
_Callback_ NTSTATUS PhStdSetObjectSecurity(
|
||||
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PPH_STD_OBJECT_SECURITY stdObjectSecurity;
|
||||
HANDLE handle;
|
||||
|
||||
stdObjectSecurity = (PPH_STD_OBJECT_SECURITY)Context;
|
||||
|
||||
status = stdObjectSecurity->OpenObject(
|
||||
&handle,
|
||||
PhGetAccessForSetSecurity(SecurityInformation),
|
||||
stdObjectSecurity->Context
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
if (PhEqualStringZ(stdObjectSecurity->ObjectType, L"Service", TRUE))
|
||||
{
|
||||
status = PhSetSeObjectSecurity(handle, SE_SERVICE, SecurityInformation, SecurityDescriptor);
|
||||
CloseServiceHandle(handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = PhSetObjectSecurity(handle, SecurityInformation, SecurityDescriptor);
|
||||
NtClose(handle);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhGetSeObjectSecurity(
|
||||
_In_ HANDLE Handle,
|
||||
_In_ ULONG ObjectType,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor
|
||||
)
|
||||
{
|
||||
ULONG win32Result;
|
||||
PSECURITY_DESCRIPTOR securityDescriptor;
|
||||
|
||||
win32Result = GetSecurityInfo(
|
||||
Handle,
|
||||
ObjectType,
|
||||
SecurityInformation,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&securityDescriptor
|
||||
);
|
||||
|
||||
if (win32Result != ERROR_SUCCESS)
|
||||
return NTSTATUS_FROM_WIN32(win32Result);
|
||||
|
||||
*SecurityDescriptor = PhAllocateCopy(securityDescriptor, RtlLengthSecurityDescriptor(securityDescriptor));
|
||||
LocalFree(securityDescriptor);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS PhSetSeObjectSecurity(
|
||||
_In_ HANDLE Handle,
|
||||
_In_ ULONG ObjectType,
|
||||
_In_ SECURITY_INFORMATION SecurityInformation,
|
||||
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor
|
||||
)
|
||||
{
|
||||
ULONG win32Result;
|
||||
SECURITY_INFORMATION securityInformation = 0;
|
||||
BOOLEAN present;
|
||||
BOOLEAN defaulted;
|
||||
PSID owner = NULL;
|
||||
PSID group = NULL;
|
||||
PACL dacl = NULL;
|
||||
PACL sacl = NULL;
|
||||
|
||||
if (SecurityInformation & OWNER_SECURITY_INFORMATION)
|
||||
{
|
||||
if (NT_SUCCESS(RtlGetOwnerSecurityDescriptor(SecurityDescriptor, &owner, &defaulted)))
|
||||
securityInformation |= OWNER_SECURITY_INFORMATION;
|
||||
}
|
||||
|
||||
if (SecurityInformation & GROUP_SECURITY_INFORMATION)
|
||||
{
|
||||
if (NT_SUCCESS(RtlGetGroupSecurityDescriptor(SecurityDescriptor, &group, &defaulted)))
|
||||
securityInformation |= GROUP_SECURITY_INFORMATION;
|
||||
}
|
||||
|
||||
if (SecurityInformation & DACL_SECURITY_INFORMATION)
|
||||
{
|
||||
if (NT_SUCCESS(RtlGetDaclSecurityDescriptor(SecurityDescriptor, &present, &dacl, &defaulted)) && present)
|
||||
securityInformation |= DACL_SECURITY_INFORMATION;
|
||||
}
|
||||
|
||||
if (SecurityInformation & SACL_SECURITY_INFORMATION)
|
||||
{
|
||||
if (NT_SUCCESS(RtlGetSaclSecurityDescriptor(SecurityDescriptor, &present, &sacl, &defaulted)) && present)
|
||||
securityInformation |= SACL_SECURITY_INFORMATION;
|
||||
}
|
||||
|
||||
win32Result = SetSecurityInfo(
|
||||
Handle,
|
||||
ObjectType,
|
||||
SecurityInformation,
|
||||
owner,
|
||||
group,
|
||||
dacl,
|
||||
sacl
|
||||
);
|
||||
|
||||
if (win32Result != ERROR_SUCCESS)
|
||||
return NTSTATUS_FROM_WIN32(win32Result);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
172
phlib/sha.c
Normal file
172
phlib/sha.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2004 Filip Navara
|
||||
* Based on public domain SHA code by Steve Reid <steve@edmweb.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* This code was modified for Process Hacker. */
|
||||
|
||||
#include <phbase.h>
|
||||
#include "sha.h"
|
||||
|
||||
/* SHA1 Helper Macros */
|
||||
|
||||
//#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
#define rol(value, bits) (_rotl((value), (bits)))
|
||||
#define DWORD2BE(x) (((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000);
|
||||
#define blk0(i) (Block[i] = (rol(Block[i],24)&0xFF00FF00)|(rol(Block[i],8)&0x00FF00FF))
|
||||
#define blk1(i) (Block[i&15] = rol(Block[(i+13)&15]^Block[(i+8)&15]^Block[(i+2)&15]^Block[i&15],1))
|
||||
#define f1(x,y,z) (z^(x&(y^z)))
|
||||
#define f2(x,y,z) (x^y^z)
|
||||
#define f3(x,y,z) ((x&y)|(z&(x|y)))
|
||||
#define f4(x,y,z) (x^y^z)
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
static void SHATransform(ULONG State[5], UCHAR Buffer[64])
|
||||
{
|
||||
ULONG a, b, c, d, e;
|
||||
ULONG *Block;
|
||||
|
||||
Block = (ULONG*)Buffer;
|
||||
|
||||
/* Copy Context->State[] to working variables */
|
||||
a = State[0];
|
||||
b = State[1];
|
||||
c = State[2];
|
||||
d = State[3];
|
||||
e = State[4];
|
||||
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
|
||||
/* Add the working variables back into Context->State[] */
|
||||
State[0] += a;
|
||||
State[1] += b;
|
||||
State[2] += c;
|
||||
State[3] += d;
|
||||
State[4] += e;
|
||||
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
}
|
||||
|
||||
VOID A_SHAInit(
|
||||
_Out_ A_SHA_CTX *Context
|
||||
)
|
||||
{
|
||||
/* SHA1 initialization constants */
|
||||
Context->state[0] = 0x67452301;
|
||||
Context->state[1] = 0xEFCDAB89;
|
||||
Context->state[2] = 0x98BADCFE;
|
||||
Context->state[3] = 0x10325476;
|
||||
Context->state[4] = 0xC3D2E1F0;
|
||||
Context->count[0] = 0;
|
||||
Context->count[1] = 0;
|
||||
}
|
||||
|
||||
VOID A_SHAUpdate(
|
||||
_Inout_ A_SHA_CTX *Context,
|
||||
_In_reads_bytes_(Length) UCHAR *Input,
|
||||
_In_ ULONG Length
|
||||
)
|
||||
{
|
||||
ULONG InputContentSize;
|
||||
|
||||
InputContentSize = Context->count[1] & 63;
|
||||
Context->count[1] += Length;
|
||||
if (Context->count[1] < Length)
|
||||
Context->count[0]++;
|
||||
Context->count[0] += (Length >> 29);
|
||||
|
||||
if (InputContentSize + Length < 64)
|
||||
{
|
||||
RtlCopyMemory(&Context->buffer[InputContentSize], Input,
|
||||
Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (InputContentSize + Length >= 64)
|
||||
{
|
||||
RtlCopyMemory(Context->buffer + InputContentSize, Input,
|
||||
64 - InputContentSize);
|
||||
Input += 64 - InputContentSize;
|
||||
Length -= 64 - InputContentSize;
|
||||
SHATransform(Context->state, Context->buffer);
|
||||
InputContentSize = 0;
|
||||
}
|
||||
RtlCopyMemory(Context->buffer + InputContentSize, Input, Length);
|
||||
}
|
||||
}
|
||||
|
||||
VOID A_SHAFinal(
|
||||
_Inout_ A_SHA_CTX *Context,
|
||||
_Out_writes_bytes_(20) UCHAR *Hash
|
||||
)
|
||||
{
|
||||
INT Pad, Index;
|
||||
UCHAR Buffer[72];
|
||||
ULONG *Count;
|
||||
ULONG BufferContentSize, LengthHi, LengthLo;
|
||||
ULONG *Result;
|
||||
|
||||
BufferContentSize = Context->count[1] & 63;
|
||||
if (BufferContentSize >= 56)
|
||||
Pad = 56 + 64 - BufferContentSize;
|
||||
else
|
||||
Pad = 56 - BufferContentSize;
|
||||
|
||||
LengthHi = (Context->count[0] << 3) | (Context->count[1] >> (32 - 3));
|
||||
LengthLo = (Context->count[1] << 3);
|
||||
|
||||
RtlZeroMemory(Buffer + 1, Pad - 1);
|
||||
Buffer[0] = 0x80;
|
||||
Count = (ULONG*)(Buffer + Pad);
|
||||
Count[0] = DWORD2BE(LengthHi);
|
||||
Count[1] = DWORD2BE(LengthLo);
|
||||
A_SHAUpdate(Context, Buffer, Pad + 8);
|
||||
|
||||
Result = (ULONG *)Hash;
|
||||
|
||||
for (Index = 0; Index < 5; Index++)
|
||||
Result[Index] = DWORD2BE(Context->state[Index]);
|
||||
|
||||
A_SHAInit(Context);
|
||||
}
|
||||
28
phlib/sha.h
Normal file
28
phlib/sha.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _SHA_H
|
||||
#define _SHA_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG flag;
|
||||
UCHAR hash[20];
|
||||
ULONG state[5];
|
||||
ULONG count[2];
|
||||
UCHAR buffer[64];
|
||||
} A_SHA_CTX;
|
||||
|
||||
VOID A_SHAInit(
|
||||
_Out_ A_SHA_CTX *Context
|
||||
);
|
||||
|
||||
VOID A_SHAUpdate(
|
||||
_Inout_ A_SHA_CTX *Context,
|
||||
_In_reads_bytes_(Length) UCHAR *Input,
|
||||
_In_ ULONG Length
|
||||
);
|
||||
|
||||
VOID A_SHAFinal(
|
||||
_Inout_ A_SHA_CTX *Context,
|
||||
_Out_writes_bytes_(20) UCHAR *Hash
|
||||
);
|
||||
|
||||
#endif
|
||||
530
phlib/svcsup.c
Normal file
530
phlib/svcsup.c
Normal file
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* service support functions
|
||||
*
|
||||
* Copyright (C) 2010-2012 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <svcsup.h>
|
||||
#include <subprocesstag.h>
|
||||
|
||||
#define SIP(String, Integer) { (String), (PVOID)(Integer) }
|
||||
|
||||
static PH_KEY_VALUE_PAIR PhpServiceStatePairs[] =
|
||||
{
|
||||
SIP(L"Stopped", SERVICE_STOPPED),
|
||||
SIP(L"Start pending", SERVICE_START_PENDING),
|
||||
SIP(L"Stop pending", SERVICE_STOP_PENDING),
|
||||
SIP(L"Running", SERVICE_RUNNING),
|
||||
SIP(L"Continue pending", SERVICE_CONTINUE_PENDING),
|
||||
SIP(L"Pause pending", SERVICE_PAUSE_PENDING),
|
||||
SIP(L"Paused", SERVICE_PAUSED)
|
||||
};
|
||||
|
||||
static PH_KEY_VALUE_PAIR PhpServiceTypePairs[] =
|
||||
{
|
||||
SIP(L"Driver", SERVICE_KERNEL_DRIVER),
|
||||
SIP(L"FS driver", SERVICE_FILE_SYSTEM_DRIVER),
|
||||
SIP(L"Own process", SERVICE_WIN32_OWN_PROCESS),
|
||||
SIP(L"Share process", SERVICE_WIN32_SHARE_PROCESS),
|
||||
SIP(L"Own interactive process", SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS),
|
||||
SIP(L"Share interactive process", SERVICE_WIN32_SHARE_PROCESS | SERVICE_INTERACTIVE_PROCESS),
|
||||
SIP(L"User own process", SERVICE_USER_OWN_PROCESS),
|
||||
SIP(L"User own process (instance)", SERVICE_USER_OWN_PROCESS | SERVICE_USERSERVICE_INSTANCE),
|
||||
SIP(L"User share process", SERVICE_USER_SHARE_PROCESS),
|
||||
SIP(L"User share process (instance)", SERVICE_USER_SHARE_PROCESS | SERVICE_USERSERVICE_INSTANCE),
|
||||
};
|
||||
|
||||
static PH_KEY_VALUE_PAIR PhpServiceStartTypePairs[] =
|
||||
{
|
||||
SIP(L"Disabled", SERVICE_DISABLED),
|
||||
SIP(L"Boot start", SERVICE_BOOT_START),
|
||||
SIP(L"System start", SERVICE_SYSTEM_START),
|
||||
SIP(L"Auto start", SERVICE_AUTO_START),
|
||||
SIP(L"Demand start", SERVICE_DEMAND_START)
|
||||
};
|
||||
|
||||
static PH_KEY_VALUE_PAIR PhpServiceErrorControlPairs[] =
|
||||
{
|
||||
SIP(L"Ignore", SERVICE_ERROR_IGNORE),
|
||||
SIP(L"Normal", SERVICE_ERROR_NORMAL),
|
||||
SIP(L"Severe", SERVICE_ERROR_SEVERE),
|
||||
SIP(L"Critical", SERVICE_ERROR_CRITICAL)
|
||||
};
|
||||
|
||||
WCHAR *PhServiceTypeStrings[10] = { L"Driver", L"FS driver", L"Own process", L"Share process",
|
||||
L"Own interactive process", L"Share interactive process", L"User own process", L"User own process (instance)",
|
||||
L"User share process", L"User share process (instance)" };
|
||||
WCHAR *PhServiceStartTypeStrings[5] = { L"Disabled", L"Boot start", L"System start",
|
||||
L"Auto start", L"Demand start" };
|
||||
WCHAR *PhServiceErrorControlStrings[4] = { L"Ignore", L"Normal", L"Severe", L"Critical" };
|
||||
|
||||
PVOID PhEnumServices(
|
||||
_In_ SC_HANDLE ScManagerHandle,
|
||||
_In_opt_ ULONG Type,
|
||||
_In_opt_ ULONG State,
|
||||
_Out_ PULONG Count
|
||||
)
|
||||
{
|
||||
static ULONG initialBufferSize = 0x8000;
|
||||
LOGICAL result;
|
||||
PVOID buffer;
|
||||
ULONG bufferSize;
|
||||
ULONG returnLength;
|
||||
ULONG servicesReturned;
|
||||
|
||||
if (!Type)
|
||||
Type = WindowsVersion >= WINDOWS_10 ? SERVICE_TYPE_ALL : (SERVICE_DRIVER | SERVICE_WIN32);
|
||||
if (!State)
|
||||
State = SERVICE_STATE_ALL;
|
||||
|
||||
bufferSize = initialBufferSize;
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
if (!(result = EnumServicesStatusEx(
|
||||
ScManagerHandle,
|
||||
SC_ENUM_PROCESS_INFO,
|
||||
Type,
|
||||
State,
|
||||
buffer,
|
||||
bufferSize,
|
||||
&returnLength,
|
||||
&servicesReturned,
|
||||
NULL,
|
||||
NULL
|
||||
)))
|
||||
{
|
||||
if (GetLastError() == ERROR_MORE_DATA)
|
||||
{
|
||||
PhFree(buffer);
|
||||
bufferSize += returnLength;
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
result = EnumServicesStatusEx(
|
||||
ScManagerHandle,
|
||||
SC_ENUM_PROCESS_INFO,
|
||||
Type,
|
||||
State,
|
||||
buffer,
|
||||
bufferSize,
|
||||
&returnLength,
|
||||
&servicesReturned,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
PhFree(buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufferSize <= 0x20000) initialBufferSize = bufferSize;
|
||||
*Count = servicesReturned;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
SC_HANDLE PhOpenService(
|
||||
_In_ PWSTR ServiceName,
|
||||
_In_ ACCESS_MASK DesiredAccess
|
||||
)
|
||||
{
|
||||
SC_HANDLE scManagerHandle;
|
||||
SC_HANDLE serviceHandle;
|
||||
|
||||
scManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
||||
|
||||
if (!scManagerHandle)
|
||||
return NULL;
|
||||
|
||||
serviceHandle = OpenService(scManagerHandle, ServiceName, DesiredAccess);
|
||||
CloseServiceHandle(scManagerHandle);
|
||||
|
||||
return serviceHandle;
|
||||
}
|
||||
|
||||
PVOID PhGetServiceConfig(
|
||||
_In_ SC_HANDLE ServiceHandle
|
||||
)
|
||||
{
|
||||
PVOID buffer;
|
||||
ULONG bufferSize = 0x200;
|
||||
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
if (!QueryServiceConfig(ServiceHandle, buffer, bufferSize, &bufferSize))
|
||||
{
|
||||
PhFree(buffer);
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
if (!QueryServiceConfig(ServiceHandle, buffer, bufferSize, &bufferSize))
|
||||
{
|
||||
PhFree(buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
PVOID PhQueryServiceVariableSize(
|
||||
_In_ SC_HANDLE ServiceHandle,
|
||||
_In_ ULONG InfoLevel
|
||||
)
|
||||
{
|
||||
PVOID buffer;
|
||||
ULONG bufferSize = 0x100;
|
||||
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
if (!QueryServiceConfig2(
|
||||
ServiceHandle,
|
||||
InfoLevel,
|
||||
(BYTE *)buffer,
|
||||
bufferSize,
|
||||
&bufferSize
|
||||
))
|
||||
{
|
||||
PhFree(buffer);
|
||||
buffer = PhAllocate(bufferSize);
|
||||
|
||||
if (!QueryServiceConfig2(
|
||||
ServiceHandle,
|
||||
InfoLevel,
|
||||
(BYTE *)buffer,
|
||||
bufferSize,
|
||||
&bufferSize
|
||||
))
|
||||
{
|
||||
PhFree(buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
PPH_STRING PhGetServiceDescription(
|
||||
_In_ SC_HANDLE ServiceHandle
|
||||
)
|
||||
{
|
||||
PPH_STRING description = NULL;
|
||||
LPSERVICE_DESCRIPTION serviceDescription;
|
||||
|
||||
serviceDescription = PhQueryServiceVariableSize(ServiceHandle, SERVICE_CONFIG_DESCRIPTION);
|
||||
|
||||
if (serviceDescription)
|
||||
{
|
||||
if (serviceDescription->lpDescription)
|
||||
description = PhCreateString(serviceDescription->lpDescription);
|
||||
|
||||
PhFree(serviceDescription);
|
||||
|
||||
return description;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN PhGetServiceDelayedAutoStart(
|
||||
_In_ SC_HANDLE ServiceHandle,
|
||||
_Out_ PBOOLEAN DelayedAutoStart
|
||||
)
|
||||
{
|
||||
SERVICE_DELAYED_AUTO_START_INFO delayedAutoStartInfo;
|
||||
ULONG returnLength;
|
||||
|
||||
if (QueryServiceConfig2(
|
||||
ServiceHandle,
|
||||
SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
|
||||
(BYTE *)&delayedAutoStartInfo,
|
||||
sizeof(SERVICE_DELAYED_AUTO_START_INFO),
|
||||
&returnLength
|
||||
))
|
||||
{
|
||||
*DelayedAutoStart = !!delayedAutoStartInfo.fDelayedAutostart;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN PhSetServiceDelayedAutoStart(
|
||||
_In_ SC_HANDLE ServiceHandle,
|
||||
_In_ BOOLEAN DelayedAutoStart
|
||||
)
|
||||
{
|
||||
SERVICE_DELAYED_AUTO_START_INFO delayedAutoStartInfo;
|
||||
|
||||
delayedAutoStartInfo.fDelayedAutostart = DelayedAutoStart;
|
||||
|
||||
return !!ChangeServiceConfig2(
|
||||
ServiceHandle,
|
||||
SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
|
||||
&delayedAutoStartInfo
|
||||
);
|
||||
}
|
||||
|
||||
PWSTR PhGetServiceStateString(
|
||||
_In_ ULONG ServiceState
|
||||
)
|
||||
{
|
||||
PWSTR string;
|
||||
|
||||
if (PhFindStringSiKeyValuePairs(
|
||||
PhpServiceStatePairs,
|
||||
sizeof(PhpServiceStatePairs),
|
||||
ServiceState,
|
||||
&string
|
||||
))
|
||||
return string;
|
||||
else
|
||||
return L"Unknown";
|
||||
}
|
||||
|
||||
PWSTR PhGetServiceTypeString(
|
||||
_In_ ULONG ServiceType
|
||||
)
|
||||
{
|
||||
PWSTR string;
|
||||
|
||||
if (PhFindStringSiKeyValuePairs(
|
||||
PhpServiceTypePairs,
|
||||
sizeof(PhpServiceTypePairs),
|
||||
ServiceType,
|
||||
&string
|
||||
))
|
||||
return string;
|
||||
else
|
||||
return L"Unknown";
|
||||
}
|
||||
|
||||
ULONG PhGetServiceTypeInteger(
|
||||
_In_ PWSTR ServiceType
|
||||
)
|
||||
{
|
||||
ULONG integer;
|
||||
|
||||
if (PhFindIntegerSiKeyValuePairs(
|
||||
PhpServiceTypePairs,
|
||||
sizeof(PhpServiceTypePairs),
|
||||
ServiceType,
|
||||
&integer
|
||||
))
|
||||
return integer;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
PWSTR PhGetServiceStartTypeString(
|
||||
_In_ ULONG ServiceStartType
|
||||
)
|
||||
{
|
||||
PWSTR string;
|
||||
|
||||
if (PhFindStringSiKeyValuePairs(
|
||||
PhpServiceStartTypePairs,
|
||||
sizeof(PhpServiceStartTypePairs),
|
||||
ServiceStartType,
|
||||
&string
|
||||
))
|
||||
return string;
|
||||
else
|
||||
return L"Unknown";
|
||||
}
|
||||
|
||||
ULONG PhGetServiceStartTypeInteger(
|
||||
_In_ PWSTR ServiceStartType
|
||||
)
|
||||
{
|
||||
ULONG integer;
|
||||
|
||||
if (PhFindIntegerSiKeyValuePairs(
|
||||
PhpServiceStartTypePairs,
|
||||
sizeof(PhpServiceStartTypePairs),
|
||||
ServiceStartType,
|
||||
&integer
|
||||
))
|
||||
return integer;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
PWSTR PhGetServiceErrorControlString(
|
||||
_In_ ULONG ServiceErrorControl
|
||||
)
|
||||
{
|
||||
PWSTR string;
|
||||
|
||||
if (PhFindStringSiKeyValuePairs(
|
||||
PhpServiceErrorControlPairs,
|
||||
sizeof(PhpServiceErrorControlPairs),
|
||||
ServiceErrorControl,
|
||||
&string
|
||||
))
|
||||
return string;
|
||||
else
|
||||
return L"Unknown";
|
||||
}
|
||||
|
||||
ULONG PhGetServiceErrorControlInteger(
|
||||
_In_ PWSTR ServiceErrorControl
|
||||
)
|
||||
{
|
||||
ULONG integer;
|
||||
|
||||
if (PhFindIntegerSiKeyValuePairs(
|
||||
PhpServiceErrorControlPairs,
|
||||
sizeof(PhpServiceErrorControlPairs),
|
||||
ServiceErrorControl,
|
||||
&integer
|
||||
))
|
||||
return integer;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
PPH_STRING PhGetServiceNameFromTag(
|
||||
_In_ HANDLE ProcessId,
|
||||
_In_ PVOID ServiceTag
|
||||
)
|
||||
{
|
||||
static PQUERY_TAG_INFORMATION I_QueryTagInformation = NULL;
|
||||
PPH_STRING serviceName = NULL;
|
||||
TAG_INFO_NAME_FROM_TAG nameFromTag;
|
||||
|
||||
if (!I_QueryTagInformation)
|
||||
{
|
||||
I_QueryTagInformation = PhGetModuleProcAddress(L"advapi32.dll", "I_QueryTagInformation");
|
||||
|
||||
if (!I_QueryTagInformation)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(&nameFromTag, 0, sizeof(TAG_INFO_NAME_FROM_TAG));
|
||||
nameFromTag.InParams.dwPid = HandleToUlong(ProcessId);
|
||||
nameFromTag.InParams.dwTag = PtrToUlong(ServiceTag);
|
||||
|
||||
I_QueryTagInformation(NULL, eTagInfoLevelNameFromTag, &nameFromTag);
|
||||
|
||||
if (nameFromTag.OutParams.pszName)
|
||||
{
|
||||
serviceName = PhCreateString(nameFromTag.OutParams.pszName);
|
||||
LocalFree(nameFromTag.OutParams.pszName);
|
||||
}
|
||||
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
NTSTATUS PhGetThreadServiceTag(
|
||||
_In_ HANDLE ThreadHandle,
|
||||
_In_opt_ HANDLE ProcessHandle,
|
||||
_Out_ PVOID *ServiceTag
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
THREAD_BASIC_INFORMATION basicInfo;
|
||||
BOOLEAN openedProcessHandle = FALSE;
|
||||
|
||||
if (!NT_SUCCESS(status = PhGetThreadBasicInformation(ThreadHandle, &basicInfo)))
|
||||
return status;
|
||||
|
||||
if (!ProcessHandle)
|
||||
{
|
||||
if (!NT_SUCCESS(status = PhOpenThreadProcess(
|
||||
ThreadHandle,
|
||||
PROCESS_VM_READ,
|
||||
&ProcessHandle
|
||||
)))
|
||||
return status;
|
||||
|
||||
openedProcessHandle = TRUE;
|
||||
}
|
||||
|
||||
status = NtReadVirtualMemory(
|
||||
ProcessHandle,
|
||||
PTR_ADD_OFFSET(basicInfo.TebBaseAddress, FIELD_OFFSET(TEB, SubProcessTag)),
|
||||
ServiceTag,
|
||||
sizeof(PVOID),
|
||||
NULL
|
||||
);
|
||||
|
||||
if (openedProcessHandle)
|
||||
NtClose(ProcessHandle);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS PhGetServiceDllParameter(
|
||||
_In_ PPH_STRINGREF ServiceName,
|
||||
_Out_ PPH_STRING *ServiceDll
|
||||
)
|
||||
{
|
||||
static PH_STRINGREF servicesKeyName = PH_STRINGREF_INIT(L"System\\CurrentControlSet\\Services\\");
|
||||
static PH_STRINGREF parameters = PH_STRINGREF_INIT(L"\\Parameters");
|
||||
|
||||
NTSTATUS status;
|
||||
HANDLE keyHandle;
|
||||
PPH_STRING keyName;
|
||||
|
||||
keyName = PhConcatStringRef3(&servicesKeyName, ServiceName, ¶meters);
|
||||
|
||||
if (NT_SUCCESS(status = PhOpenKey(
|
||||
&keyHandle,
|
||||
KEY_READ,
|
||||
PH_KEY_LOCAL_MACHINE,
|
||||
&keyName->sr,
|
||||
0
|
||||
)))
|
||||
{
|
||||
PPH_STRING serviceDllString;
|
||||
|
||||
if (serviceDllString = PhQueryRegistryString(keyHandle, L"ServiceDll"))
|
||||
{
|
||||
PPH_STRING expandedString;
|
||||
|
||||
if (expandedString = PhExpandEnvironmentStrings(&serviceDllString->sr))
|
||||
{
|
||||
*ServiceDll = expandedString;
|
||||
PhDereferenceObject(serviceDllString);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ServiceDll = serviceDllString;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
NtClose(keyHandle);
|
||||
}
|
||||
|
||||
PhDereferenceObject(keyName);
|
||||
|
||||
return status;
|
||||
}
|
||||
1762
phlib/symprv.c
Normal file
1762
phlib/symprv.c
Normal file
File diff suppressed because it is too large
Load Diff
496
phlib/sync.c
Normal file
496
phlib/sync.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* misc. synchronization utilities
|
||||
*
|
||||
* Copyright (C) 2010-2015 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains code for several synchronization objects.
|
||||
*
|
||||
* Event. This is a lightweight notification event object that does not create a kernel event object
|
||||
* until needed. Additionally the kernel event object is automatically freed when no longer needed.
|
||||
* Note that PhfResetEvent is NOT thread-safe.
|
||||
*
|
||||
* Barrier. This is a non-traditional implementation of a barrier, built on the wake event object. I
|
||||
* have identified three types of participants in this process:
|
||||
* 1. The slaves, who wait for the master to release them. This is the main mechanism through which
|
||||
* the threads are synchronized.
|
||||
* 2. The master, who is the last thread to wait on the barrier. This thread triggers the waking
|
||||
* process, and waits until all slaves have woken.
|
||||
* 3. The observers, who are simply threads which were slaves before, were woken, and have tried to
|
||||
* wait on the barrier again before all other slaves have woken.
|
||||
*
|
||||
* Rundown protection. This object allows a thread to wait until all other threads have finished
|
||||
* using a particular resource before freeing the resource.
|
||||
*
|
||||
* Init-once. This is a lightweight one-time initialization mechanism which uses the event object
|
||||
* for any required blocking. The overhead is very small - only a single inlined comparison.
|
||||
*/
|
||||
|
||||
#include <phbase.h>
|
||||
|
||||
/**
|
||||
* Initializes an event object.
|
||||
*
|
||||
* \param Event A pointer to an event object.
|
||||
*/
|
||||
VOID FASTCALL PhfInitializeEvent(
|
||||
_Out_ PPH_EVENT Event
|
||||
)
|
||||
{
|
||||
Event->Value = PH_EVENT_REFCOUNT_INC;
|
||||
Event->EventHandle = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereferences the event object used by an event.
|
||||
*
|
||||
* \param Event A pointer to an event object.
|
||||
* \param EventHandle The current value of the event object.
|
||||
*/
|
||||
FORCEINLINE VOID PhpDereferenceEvent(
|
||||
_Inout_ PPH_EVENT Event,
|
||||
_In_opt_ HANDLE EventHandle
|
||||
)
|
||||
{
|
||||
ULONG_PTR value;
|
||||
|
||||
value = _InterlockedExchangeAddPointer((PLONG_PTR)&Event->Value, -PH_EVENT_REFCOUNT_INC);
|
||||
|
||||
// See if the reference count has become 0.
|
||||
if (((value >> PH_EVENT_REFCOUNT_SHIFT) & PH_EVENT_REFCOUNT_MASK) - 1 == 0)
|
||||
{
|
||||
if (EventHandle)
|
||||
{
|
||||
NtClose(EventHandle);
|
||||
Event->EventHandle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* References the event object used by an event.
|
||||
*
|
||||
* \param Event A pointer to an event object.
|
||||
*/
|
||||
FORCEINLINE VOID PhpReferenceEvent(
|
||||
_Inout_ PPH_EVENT Event
|
||||
)
|
||||
{
|
||||
_InterlockedExchangeAddPointer((PLONG_PTR)&Event->Value, PH_EVENT_REFCOUNT_INC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an event object. Any threads waiting on the event will be released.
|
||||
*
|
||||
* \param Event A pointer to an event object.
|
||||
*/
|
||||
VOID FASTCALL PhfSetEvent(
|
||||
_Inout_ PPH_EVENT Event
|
||||
)
|
||||
{
|
||||
HANDLE eventHandle;
|
||||
|
||||
// Only proceed if the event isn't set already.
|
||||
if (!_InterlockedBitTestAndSetPointer((PLONG_PTR)&Event->Value, PH_EVENT_SET_SHIFT))
|
||||
{
|
||||
eventHandle = Event->EventHandle;
|
||||
|
||||
if (eventHandle)
|
||||
{
|
||||
NtSetEvent(eventHandle, NULL);
|
||||
}
|
||||
|
||||
PhpDereferenceEvent(Event, eventHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for an event object to be set.
|
||||
*
|
||||
* \param Event A pointer to an event object.
|
||||
* \param Timeout The timeout value.
|
||||
*
|
||||
* \return TRUE if the event object was set before the timeout period expired, otherwise FALSE.
|
||||
*
|
||||
* \remarks To test the event, use PhTestEvent() instead of using a timeout of zero.
|
||||
*/
|
||||
BOOLEAN FASTCALL PhfWaitForEvent(
|
||||
_Inout_ PPH_EVENT Event,
|
||||
_In_opt_ PLARGE_INTEGER Timeout
|
||||
)
|
||||
{
|
||||
BOOLEAN result;
|
||||
ULONG_PTR value;
|
||||
HANDLE eventHandle;
|
||||
|
||||
value = Event->Value;
|
||||
|
||||
// Shortcut: if the event is set, return immediately.
|
||||
if (value & PH_EVENT_SET)
|
||||
return TRUE;
|
||||
|
||||
// Shortcut: if the timeout is 0, return immediately if the event isn't set.
|
||||
if (Timeout && Timeout->QuadPart == 0)
|
||||
return FALSE;
|
||||
|
||||
// Prevent the event from being invalidated.
|
||||
PhpReferenceEvent(Event);
|
||||
|
||||
eventHandle = Event->EventHandle;
|
||||
|
||||
if (!eventHandle)
|
||||
{
|
||||
NtCreateEvent(&eventHandle, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE);
|
||||
assert(eventHandle);
|
||||
|
||||
// Try to set the event handle to our event.
|
||||
if (_InterlockedCompareExchangePointer(
|
||||
&Event->EventHandle,
|
||||
eventHandle,
|
||||
NULL
|
||||
) != NULL)
|
||||
{
|
||||
// Someone else set the event before we did.
|
||||
NtClose(eventHandle);
|
||||
eventHandle = Event->EventHandle;
|
||||
}
|
||||
}
|
||||
|
||||
// Essential: check the event one last time to see if it is set.
|
||||
if (!(Event->Value & PH_EVENT_SET))
|
||||
{
|
||||
result = NtWaitForSingleObject(eventHandle, FALSE, Timeout) == STATUS_WAIT_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
PhpDereferenceEvent(Event, eventHandle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets an event's state.
|
||||
*
|
||||
* \param Event A pointer to an event object.
|
||||
*
|
||||
* \remarks This function is not thread-safe. Make sure no other threads are using the event when
|
||||
* you call this function.
|
||||
*/
|
||||
VOID FASTCALL PhfResetEvent(
|
||||
_Inout_ PPH_EVENT Event
|
||||
)
|
||||
{
|
||||
assert(!Event->EventHandle);
|
||||
|
||||
if (PhTestEvent(Event))
|
||||
Event->Value = PH_EVENT_REFCOUNT_INC;
|
||||
}
|
||||
|
||||
VOID FASTCALL PhfInitializeBarrier(
|
||||
_Out_ PPH_BARRIER Barrier,
|
||||
_In_ ULONG_PTR Target
|
||||
)
|
||||
{
|
||||
Barrier->Value = Target << PH_BARRIER_TARGET_SHIFT;
|
||||
PhInitializeWakeEvent(&Barrier->WakeEvent);
|
||||
}
|
||||
|
||||
FORCEINLINE VOID PhpBlockOnBarrier(
|
||||
_Inout_ PPH_BARRIER Barrier,
|
||||
_In_ ULONG Role,
|
||||
_In_ BOOLEAN Spin
|
||||
)
|
||||
{
|
||||
PH_QUEUED_WAIT_BLOCK waitBlock;
|
||||
ULONG_PTR cancel;
|
||||
|
||||
PhQueueWakeEvent(&Barrier->WakeEvent, &waitBlock);
|
||||
|
||||
cancel = 0;
|
||||
|
||||
switch (Role)
|
||||
{
|
||||
case PH_BARRIER_MASTER:
|
||||
cancel = ((Barrier->Value >> PH_BARRIER_COUNT_SHIFT) & PH_BARRIER_COUNT_MASK) == 1;
|
||||
break;
|
||||
case PH_BARRIER_SLAVE:
|
||||
cancel = Barrier->Value & PH_BARRIER_WAKING;
|
||||
break;
|
||||
case PH_BARRIER_OBSERVER:
|
||||
cancel = !(Barrier->Value & PH_BARRIER_WAKING);
|
||||
break;
|
||||
default:
|
||||
ASSUME_NO_DEFAULT;
|
||||
}
|
||||
|
||||
if (cancel)
|
||||
{
|
||||
PhSetWakeEvent(&Barrier->WakeEvent, &waitBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
PhWaitForWakeEvent(&Barrier->WakeEvent, &waitBlock, Spin, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until all threads are blocking on the barrier, and resets the state of the barrier.
|
||||
*
|
||||
* \param Barrier A barrier.
|
||||
* \param Spin TRUE to spin on the barrier before blocking, FALSE to block immediately.
|
||||
*
|
||||
* \return TRUE for an unspecified thread after each phase, and FALSE for all other threads.
|
||||
*
|
||||
* \remarks By checking the return value of the function, in each phase an action can be performed
|
||||
* exactly once. This could, for example, involve merging the results of calculations.
|
||||
*/
|
||||
BOOLEAN FASTCALL PhfWaitForBarrier(
|
||||
_Inout_ PPH_BARRIER Barrier,
|
||||
_In_ BOOLEAN Spin
|
||||
)
|
||||
{
|
||||
ULONG_PTR value;
|
||||
ULONG_PTR newValue;
|
||||
ULONG_PTR count;
|
||||
ULONG_PTR target;
|
||||
|
||||
value = Barrier->Value;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (!(value & PH_BARRIER_WAKING))
|
||||
{
|
||||
count = (value >> PH_BARRIER_COUNT_SHIFT) & PH_BARRIER_COUNT_MASK;
|
||||
target = (value >> PH_BARRIER_TARGET_SHIFT) & PH_BARRIER_TARGET_MASK;
|
||||
assert(count != target);
|
||||
|
||||
count++;
|
||||
|
||||
if (count != target)
|
||||
newValue = value + PH_BARRIER_COUNT_INC;
|
||||
else
|
||||
newValue = value + PH_BARRIER_COUNT_INC + PH_BARRIER_WAKING;
|
||||
|
||||
if ((newValue = (ULONG_PTR)_InterlockedCompareExchangePointer(
|
||||
(PVOID *)&Barrier->Value,
|
||||
(PVOID)newValue,
|
||||
(PVOID)value
|
||||
)) == value)
|
||||
{
|
||||
if (count != target)
|
||||
{
|
||||
// Wait for the master signal (the last thread to reach the barrier).
|
||||
// Once we get it, decrement the count to allow the master to continue.
|
||||
|
||||
do
|
||||
{
|
||||
PhpBlockOnBarrier(Barrier, PH_BARRIER_SLAVE, Spin);
|
||||
} while (!(Barrier->Value & PH_BARRIER_WAKING));
|
||||
|
||||
value = _InterlockedExchangeAddPointer((PLONG_PTR)&Barrier->Value, -PH_BARRIER_COUNT_INC);
|
||||
|
||||
if (((value >> PH_BARRIER_COUNT_SHIFT) & PH_BARRIER_COUNT_MASK) - 1 == 1)
|
||||
{
|
||||
PhSetWakeEvent(&Barrier->WakeEvent, NULL); // for the master
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're the last one to reach the barrier, so we become the master.
|
||||
// Wake the slaves and wait for them to decrease the count to 1. This is so that
|
||||
// we know the slaves have woken and we don't clear the waking bit before they
|
||||
// wake.
|
||||
|
||||
PhSetWakeEvent(&Barrier->WakeEvent, NULL); // for slaves
|
||||
|
||||
do
|
||||
{
|
||||
PhpBlockOnBarrier(Barrier, PH_BARRIER_MASTER, Spin);
|
||||
} while (((Barrier->Value >> PH_BARRIER_COUNT_SHIFT) & PH_BARRIER_COUNT_MASK) != 1);
|
||||
|
||||
_InterlockedExchangeAddPointer((PLONG_PTR)&Barrier->Value, -(PH_BARRIER_WAKING + PH_BARRIER_COUNT_INC));
|
||||
PhSetWakeEvent(&Barrier->WakeEvent, NULL); // for observers
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're too early; other threads are still waking. Wait for them to finish.
|
||||
|
||||
PhpBlockOnBarrier(Barrier, PH_BARRIER_OBSERVER, Spin);
|
||||
newValue = Barrier->Value;
|
||||
}
|
||||
|
||||
value = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
VOID FASTCALL PhfInitializeRundownProtection(
|
||||
_Out_ PPH_RUNDOWN_PROTECT Protection
|
||||
)
|
||||
{
|
||||
Protection->Value = 0;
|
||||
}
|
||||
|
||||
BOOLEAN FASTCALL PhfAcquireRundownProtection(
|
||||
_Inout_ PPH_RUNDOWN_PROTECT Protection
|
||||
)
|
||||
{
|
||||
ULONG_PTR value;
|
||||
|
||||
// Increment the reference count only if rundown has not started.
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
value = Protection->Value;
|
||||
|
||||
if (value & PH_RUNDOWN_ACTIVE)
|
||||
return FALSE;
|
||||
|
||||
if ((ULONG_PTR)_InterlockedCompareExchangePointer(
|
||||
(PVOID *)&Protection->Value,
|
||||
(PVOID)(value + PH_RUNDOWN_REF_INC),
|
||||
(PVOID)value
|
||||
) == value)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
VOID FASTCALL PhfReleaseRundownProtection(
|
||||
_Inout_ PPH_RUNDOWN_PROTECT Protection
|
||||
)
|
||||
{
|
||||
ULONG_PTR value;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
value = Protection->Value;
|
||||
|
||||
if (value & PH_RUNDOWN_ACTIVE)
|
||||
{
|
||||
PPH_RUNDOWN_WAIT_BLOCK waitBlock;
|
||||
|
||||
// Since rundown is active, the reference count has been moved to the waiter's wait
|
||||
// block. If we are the last user, we must wake up the waiter.
|
||||
|
||||
waitBlock = (PPH_RUNDOWN_WAIT_BLOCK)(value & ~PH_RUNDOWN_ACTIVE);
|
||||
|
||||
if (_InterlockedDecrementPointer(&waitBlock->Count) == 0)
|
||||
{
|
||||
PhSetEvent(&waitBlock->WakeEvent);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decrement the reference count normally.
|
||||
|
||||
if ((ULONG_PTR)_InterlockedCompareExchangePointer(
|
||||
(PVOID *)&Protection->Value,
|
||||
(PVOID)(value - PH_RUNDOWN_REF_INC),
|
||||
(PVOID)value
|
||||
) == value)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID FASTCALL PhfWaitForRundownProtection(
|
||||
_Inout_ PPH_RUNDOWN_PROTECT Protection
|
||||
)
|
||||
{
|
||||
ULONG_PTR value;
|
||||
ULONG_PTR count;
|
||||
PH_RUNDOWN_WAIT_BLOCK waitBlock;
|
||||
BOOLEAN waitBlockInitialized;
|
||||
|
||||
// Fast path. If the reference count is 0 or rundown has already been completed, return.
|
||||
value = (ULONG_PTR)_InterlockedCompareExchangePointer(
|
||||
(PVOID *)&Protection->Value,
|
||||
(PVOID)PH_RUNDOWN_ACTIVE,
|
||||
(PVOID)0
|
||||
);
|
||||
|
||||
if (value == 0 || value == PH_RUNDOWN_ACTIVE)
|
||||
return;
|
||||
|
||||
waitBlockInitialized = FALSE;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
value = Protection->Value;
|
||||
count = value >> PH_RUNDOWN_REF_SHIFT;
|
||||
|
||||
// Initialize the wait block if necessary.
|
||||
if (count != 0 && !waitBlockInitialized)
|
||||
{
|
||||
PhInitializeEvent(&waitBlock.WakeEvent);
|
||||
waitBlockInitialized = TRUE;
|
||||
}
|
||||
|
||||
// Save the existing reference count.
|
||||
waitBlock.Count = count;
|
||||
|
||||
if ((ULONG_PTR)_InterlockedCompareExchangePointer(
|
||||
(PVOID *)&Protection->Value,
|
||||
(PVOID)((ULONG_PTR)&waitBlock | PH_RUNDOWN_ACTIVE),
|
||||
(PVOID)value
|
||||
) == value)
|
||||
{
|
||||
if (count != 0)
|
||||
PhWaitForEvent(&waitBlock.WakeEvent, NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID FASTCALL PhfInitializeInitOnce(
|
||||
_Out_ PPH_INITONCE InitOnce
|
||||
)
|
||||
{
|
||||
PhInitializeEvent(&InitOnce->Event);
|
||||
}
|
||||
|
||||
BOOLEAN FASTCALL PhfBeginInitOnce(
|
||||
_Inout_ PPH_INITONCE InitOnce
|
||||
)
|
||||
{
|
||||
if (!_InterlockedBitTestAndSetPointer(&InitOnce->Event.Value, PH_INITONCE_INITIALIZING_SHIFT))
|
||||
return TRUE;
|
||||
|
||||
PhWaitForEvent(&InitOnce->Event, NULL);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID FASTCALL PhfEndInitOnce(
|
||||
_Inout_ PPH_INITONCE InitOnce
|
||||
)
|
||||
{
|
||||
PhSetEvent(&InitOnce->Event);
|
||||
}
|
||||
6662
phlib/treenew.c
Normal file
6662
phlib/treenew.c
Normal file
File diff suppressed because it is too large
Load Diff
4970
phlib/util.c
Normal file
4970
phlib/util.c
Normal file
File diff suppressed because it is too large
Load Diff
671
phlib/verify.c
Normal file
671
phlib/verify.c
Normal file
@@ -0,0 +1,671 @@
|
||||
/*
|
||||
* Process Hacker -
|
||||
* image verification
|
||||
*
|
||||
* Copyright (C) 2009-2013 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
* Process Hacker 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.
|
||||
*
|
||||
* Process Hacker 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 Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ph.h>
|
||||
#include <verify.h>
|
||||
#include <verifyp.h>
|
||||
|
||||
_CryptCATAdminCalcHashFromFileHandle CryptCATAdminCalcHashFromFileHandle;
|
||||
_CryptCATAdminCalcHashFromFileHandle2 CryptCATAdminCalcHashFromFileHandle2;
|
||||
_CryptCATAdminAcquireContext CryptCATAdminAcquireContext;
|
||||
_CryptCATAdminAcquireContext2 CryptCATAdminAcquireContext2;
|
||||
_CryptCATAdminEnumCatalogFromHash CryptCATAdminEnumCatalogFromHash;
|
||||
_CryptCATCatalogInfoFromContext CryptCATCatalogInfoFromContext;
|
||||
_CryptCATAdminReleaseCatalogContext CryptCATAdminReleaseCatalogContext;
|
||||
_CryptCATAdminReleaseContext CryptCATAdminReleaseContext;
|
||||
_WTHelperProvDataFromStateData WTHelperProvDataFromStateData_I;
|
||||
_WTHelperGetProvSignerFromChain WTHelperGetProvSignerFromChain_I;
|
||||
_WinVerifyTrust WinVerifyTrust_I;
|
||||
_CertNameToStr CertNameToStr_I;
|
||||
_CertDuplicateCertificateContext CertDuplicateCertificateContext_I;
|
||||
_CertFreeCertificateContext CertFreeCertificateContext_I;
|
||||
static PH_INITONCE PhpVerifyInitOnce = PH_INITONCE_INIT;
|
||||
|
||||
static GUID WinTrustActionGenericVerifyV2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
|
||||
static GUID DriverActionVerify = DRIVER_ACTION_VERIFY;
|
||||
|
||||
static VOID PhpVerifyInitialization(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HMODULE wintrust;
|
||||
HMODULE crypt32;
|
||||
|
||||
wintrust = LoadLibrary(L"wintrust.dll");
|
||||
crypt32 = LoadLibrary(L"crypt32.dll");
|
||||
|
||||
CryptCATAdminCalcHashFromFileHandle = (PVOID)GetProcAddress(wintrust, "CryptCATAdminCalcHashFromFileHandle");
|
||||
CryptCATAdminCalcHashFromFileHandle2 = (PVOID)GetProcAddress(wintrust, "CryptCATAdminCalcHashFromFileHandle2");
|
||||
CryptCATAdminAcquireContext = (PVOID)GetProcAddress(wintrust, "CryptCATAdminAcquireContext");
|
||||
CryptCATAdminAcquireContext2 = (PVOID)GetProcAddress(wintrust, "CryptCATAdminAcquireContext2");
|
||||
CryptCATAdminEnumCatalogFromHash = (PVOID)GetProcAddress(wintrust, "CryptCATAdminEnumCatalogFromHash");
|
||||
CryptCATCatalogInfoFromContext = (PVOID)GetProcAddress(wintrust, "CryptCATCatalogInfoFromContext");
|
||||
CryptCATAdminReleaseCatalogContext = (PVOID)GetProcAddress(wintrust, "CryptCATAdminReleaseCatalogContext");
|
||||
CryptCATAdminReleaseContext = (PVOID)GetProcAddress(wintrust, "CryptCATAdminReleaseContext");
|
||||
WTHelperProvDataFromStateData_I = (PVOID)GetProcAddress(wintrust, "WTHelperProvDataFromStateData");
|
||||
WTHelperGetProvSignerFromChain_I = (PVOID)GetProcAddress(wintrust, "WTHelperGetProvSignerFromChain");
|
||||
WinVerifyTrust_I = (PVOID)GetProcAddress(wintrust, "WinVerifyTrust");
|
||||
CertNameToStr_I = (PVOID)GetProcAddress(crypt32, "CertNameToStrW");
|
||||
CertDuplicateCertificateContext_I = (PVOID)GetProcAddress(crypt32, "CertDuplicateCertificateContext");
|
||||
CertFreeCertificateContext_I = (PVOID)GetProcAddress(crypt32, "CertFreeCertificateContext");
|
||||
}
|
||||
|
||||
VERIFY_RESULT PhpStatusToVerifyResult(
|
||||
_In_ LONG Status
|
||||
)
|
||||
{
|
||||
switch (Status)
|
||||
{
|
||||
case 0:
|
||||
return VrTrusted;
|
||||
case TRUST_E_NOSIGNATURE:
|
||||
return VrNoSignature;
|
||||
case CERT_E_EXPIRED:
|
||||
return VrExpired;
|
||||
case CERT_E_REVOKED:
|
||||
return VrRevoked;
|
||||
case TRUST_E_EXPLICIT_DISTRUST:
|
||||
return VrDistrust;
|
||||
case CRYPT_E_SECURITY_SETTINGS:
|
||||
return VrSecuritySettings;
|
||||
case TRUST_E_BAD_DIGEST:
|
||||
return VrBadSignature;
|
||||
default:
|
||||
return VrSecuritySettings;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN PhpGetSignaturesFromStateData(
|
||||
_In_ HANDLE StateData,
|
||||
_Out_ PCERT_CONTEXT **Signatures,
|
||||
_Out_ PULONG NumberOfSignatures
|
||||
)
|
||||
{
|
||||
PCRYPT_PROVIDER_DATA provData;
|
||||
PCRYPT_PROVIDER_SGNR sgnr;
|
||||
PCERT_CONTEXT *signatures;
|
||||
ULONG i;
|
||||
ULONG numberOfSignatures;
|
||||
ULONG index;
|
||||
|
||||
provData = WTHelperProvDataFromStateData_I(StateData);
|
||||
|
||||
if (!provData)
|
||||
{
|
||||
*Signatures = NULL;
|
||||
*NumberOfSignatures = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
numberOfSignatures = 0;
|
||||
|
||||
while (sgnr = WTHelperGetProvSignerFromChain_I(provData, i, FALSE, 0))
|
||||
{
|
||||
if (sgnr->csCertChain != 0)
|
||||
numberOfSignatures++;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (numberOfSignatures != 0)
|
||||
{
|
||||
signatures = PhAllocate(numberOfSignatures * sizeof(PCERT_CONTEXT));
|
||||
i = 0;
|
||||
index = 0;
|
||||
|
||||
while (sgnr = WTHelperGetProvSignerFromChain_I(provData, i, FALSE, 0))
|
||||
{
|
||||
if (sgnr->csCertChain != 0)
|
||||
signatures[index++] = (PCERT_CONTEXT)CertDuplicateCertificateContext_I(sgnr->pasCertChain[0].pCert);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
signatures = NULL;
|
||||
}
|
||||
|
||||
*Signatures = signatures;
|
||||
*NumberOfSignatures = numberOfSignatures;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID PhpViewSignerInfo(
|
||||
_In_ PPH_VERIFY_FILE_INFO Information,
|
||||
_In_ HANDLE StateData
|
||||
)
|
||||
{
|
||||
static PH_INITONCE initOnce = PH_INITONCE_INIT;
|
||||
static _CryptUIDlgViewSignerInfo cryptUIDlgViewSignerInfo;
|
||||
|
||||
if (PhBeginInitOnce(&initOnce))
|
||||
{
|
||||
HMODULE cryptui = LoadLibrary(L"cryptui.dll");
|
||||
|
||||
cryptUIDlgViewSignerInfo = (PVOID)GetProcAddress(cryptui, "CryptUIDlgViewSignerInfoW");
|
||||
PhEndInitOnce(&initOnce);
|
||||
}
|
||||
|
||||
if (cryptUIDlgViewSignerInfo)
|
||||
{
|
||||
CRYPTUI_VIEWSIGNERINFO_STRUCT viewSignerInfo = { sizeof(CRYPTUI_VIEWSIGNERINFO_STRUCT) };
|
||||
PCRYPT_PROVIDER_DATA provData;
|
||||
PCRYPT_PROVIDER_SGNR sgnr;
|
||||
|
||||
if (!(provData = WTHelperProvDataFromStateData_I(StateData)))
|
||||
return;
|
||||
if (!(sgnr = WTHelperGetProvSignerFromChain_I(provData, 0, FALSE, 0)))
|
||||
return;
|
||||
|
||||
viewSignerInfo.hwndParent = Information->hWnd;
|
||||
viewSignerInfo.pSignerInfo = sgnr->psSigner;
|
||||
viewSignerInfo.hMsg = provData->hMsg;
|
||||
viewSignerInfo.pszOID = szOID_PKIX_KP_CODE_SIGNING;
|
||||
cryptUIDlgViewSignerInfo(&viewSignerInfo);
|
||||
}
|
||||
}
|
||||
|
||||
VERIFY_RESULT PhpVerifyFile(
|
||||
_In_ PPH_VERIFY_FILE_INFO Information,
|
||||
_In_ HANDLE FileHandle,
|
||||
_In_ ULONG UnionChoice,
|
||||
_In_ PVOID UnionData,
|
||||
_In_ PGUID ActionId,
|
||||
_In_opt_ PVOID PolicyCallbackData,
|
||||
_Out_ PCERT_CONTEXT **Signatures,
|
||||
_Out_ PULONG NumberOfSignatures
|
||||
)
|
||||
{
|
||||
LONG status;
|
||||
WINTRUST_DATA trustData = { 0 };
|
||||
|
||||
trustData.cbStruct = sizeof(WINTRUST_DATA);
|
||||
trustData.pPolicyCallbackData = PolicyCallbackData;
|
||||
trustData.dwUIChoice = WTD_UI_NONE;
|
||||
trustData.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
|
||||
trustData.dwUnionChoice = UnionChoice;
|
||||
trustData.dwStateAction = WTD_STATEACTION_VERIFY;
|
||||
trustData.dwProvFlags = WTD_SAFER_FLAG;
|
||||
|
||||
trustData.pFile = UnionData;
|
||||
|
||||
if (UnionChoice == WTD_CHOICE_CATALOG)
|
||||
trustData.pCatalog = UnionData;
|
||||
|
||||
if (Information->Flags & PH_VERIFY_PREVENT_NETWORK_ACCESS)
|
||||
{
|
||||
trustData.fdwRevocationChecks = WTD_REVOKE_NONE;
|
||||
|
||||
if (WindowsVersion >= WINDOWS_VISTA)
|
||||
trustData.dwProvFlags |= WTD_CACHE_ONLY_URL_RETRIEVAL;
|
||||
else
|
||||
trustData.dwProvFlags |= WTD_REVOCATION_CHECK_NONE;
|
||||
}
|
||||
|
||||
status = WinVerifyTrust_I(NULL, ActionId, &trustData);
|
||||
PhpGetSignaturesFromStateData(trustData.hWVTStateData, Signatures, NumberOfSignatures);
|
||||
|
||||
if (status == 0 && (Information->Flags & PH_VERIFY_VIEW_PROPERTIES))
|
||||
PhpViewSignerInfo(Information, trustData.hWVTStateData);
|
||||
|
||||
// Close the state data.
|
||||
trustData.dwStateAction = WTD_STATEACTION_CLOSE;
|
||||
WinVerifyTrust_I(NULL, ActionId, &trustData);
|
||||
|
||||
return PhpStatusToVerifyResult(status);
|
||||
}
|
||||
|
||||
BOOLEAN PhpCalculateFileHash(
|
||||
_In_ HANDLE FileHandle,
|
||||
_In_ PWSTR HashAlgorithm,
|
||||
_Out_ PUCHAR *FileHash,
|
||||
_Out_ PULONG FileHashLength,
|
||||
_Out_ HANDLE *CatAdminHandle
|
||||
)
|
||||
{
|
||||
HANDLE catAdminHandle;
|
||||
PUCHAR fileHash;
|
||||
ULONG fileHashLength;
|
||||
|
||||
if (CryptCATAdminAcquireContext2)
|
||||
{
|
||||
if (!CryptCATAdminAcquireContext2(&catAdminHandle, &DriverActionVerify, HashAlgorithm, NULL, 0))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CryptCATAdminAcquireContext(&catAdminHandle, &DriverActionVerify, 0))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fileHashLength = 32;
|
||||
fileHash = PhAllocate(fileHashLength);
|
||||
|
||||
if (CryptCATAdminCalcHashFromFileHandle2)
|
||||
{
|
||||
if (!CryptCATAdminCalcHashFromFileHandle2(catAdminHandle, FileHandle, &fileHashLength, fileHash, 0))
|
||||
{
|
||||
PhFree(fileHash);
|
||||
fileHash = PhAllocate(fileHashLength);
|
||||
|
||||
if (!CryptCATAdminCalcHashFromFileHandle2(catAdminHandle, FileHandle, &fileHashLength, fileHash, 0))
|
||||
{
|
||||
CryptCATAdminReleaseContext(catAdminHandle, 0);
|
||||
PhFree(fileHash);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CryptCATAdminCalcHashFromFileHandle(FileHandle, &fileHashLength, fileHash, 0))
|
||||
{
|
||||
PhFree(fileHash);
|
||||
fileHash = PhAllocate(fileHashLength);
|
||||
|
||||
if (!CryptCATAdminCalcHashFromFileHandle(FileHandle, &fileHashLength, fileHash, 0))
|
||||
{
|
||||
CryptCATAdminReleaseContext(catAdminHandle, 0);
|
||||
PhFree(fileHash);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*FileHash = fileHash;
|
||||
*FileHashLength = fileHashLength;
|
||||
*CatAdminHandle = catAdminHandle;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VERIFY_RESULT PhpVerifyFileFromCatalog(
|
||||
_In_ PPH_VERIFY_FILE_INFO Information,
|
||||
_In_ HANDLE FileHandle,
|
||||
_In_opt_ PWSTR HashAlgorithm,
|
||||
_Out_ PCERT_CONTEXT **Signatures,
|
||||
_Out_ PULONG NumberOfSignatures
|
||||
)
|
||||
{
|
||||
VERIFY_RESULT verifyResult = VrNoSignature;
|
||||
PCERT_CONTEXT *signatures;
|
||||
ULONG numberOfSignatures;
|
||||
WINTRUST_CATALOG_INFO catalogInfo = { 0 };
|
||||
LARGE_INTEGER fileSize;
|
||||
ULONG fileSizeLimit;
|
||||
PUCHAR fileHash;
|
||||
ULONG fileHashLength;
|
||||
PPH_STRING fileHashTag;
|
||||
HANDLE catAdminHandle;
|
||||
HANDLE catInfoHandle;
|
||||
ULONG i;
|
||||
|
||||
*Signatures = NULL;
|
||||
*NumberOfSignatures = 0;
|
||||
|
||||
if (!NT_SUCCESS(PhGetFileSize(FileHandle, &fileSize)))
|
||||
return VrNoSignature;
|
||||
|
||||
signatures = NULL;
|
||||
numberOfSignatures = 0;
|
||||
|
||||
if (Information->FileSizeLimitForHash != -1)
|
||||
{
|
||||
fileSizeLimit = PH_VERIFY_DEFAULT_SIZE_LIMIT;
|
||||
|
||||
if (Information->FileSizeLimitForHash != 0)
|
||||
fileSizeLimit = Information->FileSizeLimitForHash;
|
||||
|
||||
if (fileSize.QuadPart > fileSizeLimit)
|
||||
return VrNoSignature;
|
||||
}
|
||||
|
||||
if (PhpCalculateFileHash(FileHandle, HashAlgorithm, &fileHash, &fileHashLength, &catAdminHandle))
|
||||
{
|
||||
fileHashTag = PhBufferToHexStringEx(fileHash, fileHashLength, TRUE);
|
||||
|
||||
// Search the system catalogs.
|
||||
|
||||
catInfoHandle = CryptCATAdminEnumCatalogFromHash(
|
||||
catAdminHandle,
|
||||
fileHash,
|
||||
fileHashLength,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (catInfoHandle)
|
||||
{
|
||||
CATALOG_INFO ci = { 0 };
|
||||
DRIVER_VER_INFO verInfo = { 0 };
|
||||
|
||||
if (CryptCATCatalogInfoFromContext(catInfoHandle, &ci, 0))
|
||||
{
|
||||
// Disable OS version checking by passing in a DRIVER_VER_INFO structure.
|
||||
verInfo.cbStruct = sizeof(DRIVER_VER_INFO);
|
||||
|
||||
catalogInfo.cbStruct = sizeof(catalogInfo);
|
||||
catalogInfo.pcwszCatalogFilePath = ci.wszCatalogFile;
|
||||
catalogInfo.pcwszMemberFilePath = Information->FileName;
|
||||
catalogInfo.pcwszMemberTag = fileHashTag->Buffer;
|
||||
catalogInfo.pbCalculatedFileHash = fileHash;
|
||||
catalogInfo.cbCalculatedFileHash = fileHashLength;
|
||||
catalogInfo.hCatAdmin = catAdminHandle;
|
||||
verifyResult = PhpVerifyFile(Information, FileHandle, WTD_CHOICE_CATALOG, &catalogInfo, &DriverActionVerify, &verInfo, &signatures, &numberOfSignatures);
|
||||
|
||||
if (verInfo.pcSignerCertContext)
|
||||
CertFreeCertificateContext_I(verInfo.pcSignerCertContext);
|
||||
}
|
||||
|
||||
CryptCATAdminReleaseCatalogContext(catAdminHandle, catInfoHandle, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search any user-supplied catalogs.
|
||||
|
||||
for (i = 0; i < Information->NumberOfCatalogFileNames; i++)
|
||||
{
|
||||
PhFreeVerifySignatures(signatures, numberOfSignatures);
|
||||
|
||||
catalogInfo.cbStruct = sizeof(catalogInfo);
|
||||
catalogInfo.pcwszCatalogFilePath = Information->CatalogFileNames[i];
|
||||
catalogInfo.pcwszMemberFilePath = Information->FileName;
|
||||
catalogInfo.pcwszMemberTag = fileHashTag->Buffer;
|
||||
catalogInfo.pbCalculatedFileHash = fileHash;
|
||||
catalogInfo.cbCalculatedFileHash = fileHashLength;
|
||||
catalogInfo.hCatAdmin = catAdminHandle;
|
||||
verifyResult = PhpVerifyFile(Information, FileHandle, WTD_CHOICE_CATALOG, &catalogInfo, &WinTrustActionGenericVerifyV2, NULL, &signatures, &numberOfSignatures);
|
||||
|
||||
if (verifyResult == VrTrusted)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PhDereferenceObject(fileHashTag);
|
||||
PhFree(fileHash);
|
||||
CryptCATAdminReleaseContext(catAdminHandle, 0);
|
||||
}
|
||||
|
||||
*Signatures = signatures;
|
||||
*NumberOfSignatures = numberOfSignatures;
|
||||
|
||||
return verifyResult;
|
||||
}
|
||||
|
||||
NTSTATUS PhVerifyFileEx(
|
||||
_In_ PPH_VERIFY_FILE_INFO Information,
|
||||
_Out_ VERIFY_RESULT *VerifyResult,
|
||||
_Out_opt_ PCERT_CONTEXT **Signatures,
|
||||
_Out_opt_ PULONG NumberOfSignatures
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
HANDLE fileHandle;
|
||||
VERIFY_RESULT verifyResult;
|
||||
PCERT_CONTEXT *signatures;
|
||||
ULONG numberOfSignatures;
|
||||
WINTRUST_FILE_INFO fileInfo = { 0 };
|
||||
|
||||
if (PhBeginInitOnce(&PhpVerifyInitOnce))
|
||||
{
|
||||
PhpVerifyInitialization();
|
||||
PhEndInitOnce(&PhpVerifyInitOnce);
|
||||
}
|
||||
|
||||
// Make sure we have successfully imported the required functions.
|
||||
if (
|
||||
!CryptCATAdminCalcHashFromFileHandle ||
|
||||
!CryptCATAdminAcquireContext ||
|
||||
!CryptCATAdminEnumCatalogFromHash ||
|
||||
!CryptCATCatalogInfoFromContext ||
|
||||
!CryptCATAdminReleaseCatalogContext ||
|
||||
!CryptCATAdminReleaseContext ||
|
||||
!WinVerifyTrust_I ||
|
||||
!WTHelperProvDataFromStateData_I ||
|
||||
!WTHelperGetProvSignerFromChain_I ||
|
||||
!CertNameToStr_I ||
|
||||
!CertDuplicateCertificateContext_I ||
|
||||
!CertFreeCertificateContext_I
|
||||
)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
|
||||
if (!NT_SUCCESS(status = PhCreateFileWin32(
|
||||
&fileHandle,
|
||||
Information->FileName,
|
||||
FILE_GENERIC_READ,
|
||||
0,
|
||||
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
|
||||
)))
|
||||
return status;
|
||||
|
||||
fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
|
||||
fileInfo.pcwszFilePath = Information->FileName;
|
||||
fileInfo.hFile = fileHandle;
|
||||
|
||||
verifyResult = PhpVerifyFile(Information, fileHandle, WTD_CHOICE_FILE, &fileInfo, &WinTrustActionGenericVerifyV2, NULL, &signatures, &numberOfSignatures);
|
||||
|
||||
if (verifyResult == VrNoSignature)
|
||||
{
|
||||
if (CryptCATAdminAcquireContext2 && CryptCATAdminCalcHashFromFileHandle2)
|
||||
{
|
||||
PhFreeVerifySignatures(signatures, numberOfSignatures);
|
||||
verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, BCRYPT_SHA256_ALGORITHM, &signatures, &numberOfSignatures);
|
||||
}
|
||||
|
||||
if (verifyResult != VrTrusted)
|
||||
{
|
||||
PhFreeVerifySignatures(signatures, numberOfSignatures);
|
||||
verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, NULL, &signatures, &numberOfSignatures);
|
||||
}
|
||||
}
|
||||
|
||||
*VerifyResult = verifyResult;
|
||||
|
||||
if (Signatures)
|
||||
*Signatures = signatures;
|
||||
else
|
||||
PhFreeVerifySignatures(signatures, numberOfSignatures);
|
||||
|
||||
if (NumberOfSignatures)
|
||||
*NumberOfSignatures = numberOfSignatures;
|
||||
|
||||
NtClose(fileHandle);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID PhFreeVerifySignatures(
|
||||
_In_ PCERT_CONTEXT *Signatures,
|
||||
_In_ ULONG NumberOfSignatures
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (Signatures)
|
||||
{
|
||||
for (i = 0; i < NumberOfSignatures; i++)
|
||||
CertFreeCertificateContext_I(Signatures[i]);
|
||||
|
||||
PhFree(Signatures);
|
||||
}
|
||||
}
|
||||
|
||||
PPH_STRING PhpGetCertNameString(
|
||||
_In_ PCERT_NAME_BLOB Blob
|
||||
)
|
||||
{
|
||||
PPH_STRING string;
|
||||
ULONG bufferSize;
|
||||
|
||||
// CertNameToStr doesn't give us the correct buffer size unless we don't provide a buffer at
|
||||
// all.
|
||||
bufferSize = CertNameToStr_I(
|
||||
X509_ASN_ENCODING,
|
||||
Blob,
|
||||
CERT_X500_NAME_STR,
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
|
||||
string = PhCreateStringEx(NULL, bufferSize * sizeof(WCHAR));
|
||||
CertNameToStr_I(
|
||||
X509_ASN_ENCODING,
|
||||
Blob,
|
||||
CERT_X500_NAME_STR,
|
||||
string->Buffer,
|
||||
bufferSize
|
||||
);
|
||||
|
||||
PhTrimToNullTerminatorString(string);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
PPH_STRING PhpGetX500Value(
|
||||
_In_ PPH_STRINGREF String,
|
||||
_In_ PPH_STRINGREF KeyName
|
||||
)
|
||||
{
|
||||
WCHAR keyNamePlusEqualsBuffer[10];
|
||||
PH_STRINGREF keyNamePlusEquals;
|
||||
SIZE_T keyNameLength;
|
||||
PH_STRINGREF firstPart;
|
||||
PH_STRINGREF remainingPart;
|
||||
|
||||
keyNameLength = KeyName->Length / sizeof(WCHAR);
|
||||
assert(!(keyNameLength > sizeof(keyNamePlusEquals) / sizeof(WCHAR) - 1));
|
||||
keyNamePlusEquals.Buffer = keyNamePlusEqualsBuffer;
|
||||
keyNamePlusEquals.Length = (keyNameLength + 1) * sizeof(WCHAR);
|
||||
|
||||
memcpy(keyNamePlusEquals.Buffer, KeyName->Buffer, KeyName->Length);
|
||||
keyNamePlusEquals.Buffer[keyNameLength] = '=';
|
||||
|
||||
// Find "Key=".
|
||||
|
||||
if (!PhSplitStringRefAtString(String, &keyNamePlusEquals, FALSE, &firstPart, &remainingPart))
|
||||
return NULL;
|
||||
if (remainingPart.Length == 0)
|
||||
return NULL;
|
||||
|
||||
// Is the value quoted? If so, return the part inside the quotes.
|
||||
if (remainingPart.Buffer[0] == '"')
|
||||
{
|
||||
PhSkipStringRef(&remainingPart, sizeof(WCHAR));
|
||||
|
||||
if (!PhSplitStringRefAtChar(&remainingPart, '"', &firstPart, &remainingPart))
|
||||
return NULL;
|
||||
|
||||
return PhCreateString2(&firstPart);
|
||||
}
|
||||
else
|
||||
{
|
||||
PhSplitStringRefAtChar(&remainingPart, ',', &firstPart, &remainingPart);
|
||||
|
||||
return PhCreateString2(&firstPart);
|
||||
}
|
||||
}
|
||||
|
||||
PPH_STRING PhGetSignerNameFromCertificate(
|
||||
_In_ PCERT_CONTEXT Certificate
|
||||
)
|
||||
{
|
||||
PCERT_INFO certInfo;
|
||||
PH_STRINGREF keyName;
|
||||
PPH_STRING name;
|
||||
PPH_STRING value;
|
||||
|
||||
// Cert context -> Cert info
|
||||
|
||||
certInfo = Certificate->pCertInfo;
|
||||
|
||||
if (!certInfo)
|
||||
return NULL;
|
||||
|
||||
// Cert info subject -> Subject X.500 string
|
||||
|
||||
name = PhpGetCertNameString(&certInfo->Subject);
|
||||
|
||||
// Subject X.500 string -> CN or OU value
|
||||
|
||||
PhInitializeStringRef(&keyName, L"CN");
|
||||
value = PhpGetX500Value(&name->sr, &keyName);
|
||||
|
||||
if (!value)
|
||||
{
|
||||
PhInitializeStringRef(&keyName, L"OU");
|
||||
value = PhpGetX500Value(&name->sr, &keyName);
|
||||
}
|
||||
|
||||
PhDereferenceObject(name);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a file's digital signature.
|
||||
*
|
||||
* \param FileName A file name.
|
||||
* \param SignerName A variable which receives a pointer to a string containing the signer name. You
|
||||
* must free the string using PhDereferenceObject() when you no longer need it. Note that the signer
|
||||
* name may be NULL if it is not valid.
|
||||
*
|
||||
* \return A VERIFY_RESULT value.
|
||||
*/
|
||||
VERIFY_RESULT PhVerifyFile(
|
||||
_In_ PWSTR FileName,
|
||||
_Out_opt_ PPH_STRING *SignerName
|
||||
)
|
||||
{
|
||||
PH_VERIFY_FILE_INFO info = { 0 };
|
||||
VERIFY_RESULT verifyResult;
|
||||
PCERT_CONTEXT *signatures;
|
||||
ULONG numberOfSignatures;
|
||||
|
||||
info.FileName = FileName;
|
||||
info.Flags = PH_VERIFY_PREVENT_NETWORK_ACCESS;
|
||||
|
||||
if (NT_SUCCESS(PhVerifyFileEx(&info, &verifyResult, &signatures, &numberOfSignatures)))
|
||||
{
|
||||
if (SignerName)
|
||||
{
|
||||
*SignerName = NULL;
|
||||
|
||||
if (numberOfSignatures != 0)
|
||||
*SignerName = PhGetSignerNameFromCertificate(signatures[0]);
|
||||
}
|
||||
|
||||
PhFreeVerifySignatures(signatures, numberOfSignatures);
|
||||
return verifyResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SignerName)
|
||||
*SignerName = NULL;
|
||||
|
||||
return VrNoSignature;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user