You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
611 lines
19 KiB
611 lines
19 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
csrdbgmon.cpp
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
|
|
Michael Grier (MGrier) June 2002
|
|
|
|
Revision History:
|
|
|
|
Jay Krell (Jaykrell) June 2002
|
|
make it compile for 64bit
|
|
tabs to spaces
|
|
init some locals
|
|
make some tables const
|
|
|
|
--*/
|
|
#include <windows.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <dbghelp.h>
|
|
|
|
#define ASSERT(x) do { /* nothing */ } while(0)
|
|
|
|
#define NUMBER_OF(_x) (sizeof(_x) / sizeof((_x)[0]))
|
|
|
|
static const char g_szImage[] = "csrdbgmon";
|
|
static const char *g_pszImage = g_szImage;
|
|
|
|
static HANDLE g_hWorkerThread;
|
|
static DWORD g_tidWorkerThread;
|
|
static HANDLE g_hCompletionPort;
|
|
static HANDLE g_hCSRSS;
|
|
static DWORD g_pidCSRSS;
|
|
|
|
static bool g_fDebuggingCSRSS = false;
|
|
static DWORD64 g_dw64NtdllBaseAddress;
|
|
static DWORD g_dwOldKdFusionMask = 0;
|
|
static bool g_fKdFusionMaskSet = false;
|
|
|
|
void ReportFailure(const char szFormat[], ...);
|
|
DWORD WINAPI WorkerThreadThreadProc(LPVOID);
|
|
BOOL EnableDebugPrivilege();
|
|
|
|
FILE *fp;
|
|
|
|
void
|
|
ReportFailure(
|
|
const char szFormat[],
|
|
...
|
|
)
|
|
{
|
|
const DWORD dwLastError = ::GetLastError();
|
|
va_list ap;
|
|
char rgchBuffer[4096];
|
|
WCHAR rgchWin32Error[4096];
|
|
|
|
// Stop debugging csrss so that we can actually issue the error message.
|
|
if (g_fDebuggingCSRSS)
|
|
::DebugActiveProcessStop((DWORD) -1);
|
|
|
|
va_start(ap, szFormat);
|
|
::_vsnprintf(rgchBuffer, sizeof(rgchBuffer) / sizeof(rgchBuffer[0]), szFormat, ap);
|
|
va_end(ap);
|
|
|
|
if (!::FormatMessageW(
|
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
dwLastError,
|
|
0,
|
|
rgchWin32Error,
|
|
NUMBER_OF(rgchWin32Error),
|
|
&ap))
|
|
{
|
|
const DWORD dwLastError2 = ::GetLastError();
|
|
::_snwprintf(rgchWin32Error, sizeof(rgchWin32Error) / sizeof(rgchWin32Error[0]), L"Error formatting Win32 error %lu (0x%08lx)\nError from FormatMessage is %lu", dwLastError, dwLastError, dwLastError2);
|
|
}
|
|
|
|
::fprintf(stderr, "%ls: %s\n%ls\n", g_pszImage, rgchBuffer, rgchWin32Error);
|
|
}
|
|
|
|
BOOL
|
|
FormatAndQueueString(
|
|
const WCHAR szFormat[],
|
|
...
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
|
|
::SetLastError(ERROR_INTERNAL_ERROR);
|
|
|
|
WCHAR rgwchBuffer[2048];
|
|
SIZE_T cch;
|
|
LPOVERLAPPED lpo = NULL;
|
|
PWSTR psz = NULL;
|
|
const HANDLE Heap = ::GetProcessHeap();
|
|
|
|
va_list ap;
|
|
va_start(ap, szFormat);
|
|
cch = ::_vsnwprintf(rgwchBuffer, NUMBER_OF(rgwchBuffer), szFormat, ap);
|
|
va_end(ap);
|
|
|
|
lpo = (LPOVERLAPPED) ::HeapAlloc(Heap, 0, sizeof(OVERLAPPED) + ((cch + 1) * sizeof(WCHAR)));
|
|
if (lpo == NULL)
|
|
{
|
|
::SetLastError(ERROR_OUTOFMEMORY);
|
|
::ReportFailure("HeapAlloc(%p, 0, %lu) failed", Heap, sizeof(OVERLAPPED) + ((cch + 1) * sizeof(WCHAR)));
|
|
goto Exit;
|
|
}
|
|
|
|
::ZeroMemory(lpo, sizeof(OVERLAPPED));
|
|
|
|
psz = (PWSTR) (lpo + 1);
|
|
|
|
::wcscpy(psz, rgwchBuffer);
|
|
|
|
if (!::PostQueuedCompletionStatus(g_hCompletionPort, 0, NULL, lpo))
|
|
{
|
|
::ReportFailure("PostQueuedCompletionStatus(%p, 0, NULL, %p) failed", g_hCompletionPort, 0, NULL, lpo);
|
|
goto Exit;
|
|
}
|
|
|
|
lpo = NULL;
|
|
|
|
fSuccess = TRUE;
|
|
|
|
Exit:
|
|
if (lpo != NULL)
|
|
{
|
|
const DWORD dwLastError = ::GetLastError();
|
|
::HeapFree(Heap, 0, lpo);
|
|
::SetLastError(dwLastError);
|
|
}
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL CALLBACK EnumModules(
|
|
LPSTR ModuleName,
|
|
ULONG BaseOfDll,
|
|
PVOID UserContext )
|
|
{
|
|
::printf("%08X %s\n", BaseOfDll, ModuleName);
|
|
return TRUE;
|
|
}
|
|
|
|
typedef HANDLE (__stdcall * PCSR_GET_PROCESS_ID)();
|
|
|
|
extern "C" int __cdecl wmain(int argc, wchar_t** argv)
|
|
{
|
|
int iReturnStatus = EXIT_FAILURE;
|
|
DEBUG_EVENT de;
|
|
SYMBOL_INFO si = { sizeof(si) };
|
|
PCSR_GET_PROCESS_ID pfn = NULL;
|
|
DWORD dwNewKdMask = 0x40000000;
|
|
SIZE_T nBytesWritten = 0;
|
|
DWORD dwSymOptions = 0;
|
|
const HANDLE Heap = ::GetProcessHeap();
|
|
|
|
#if 0
|
|
fp = fopen("csrdbgmon.log", "w");
|
|
if (!fp)
|
|
{
|
|
perror("unable to create csrdbgmon.log");
|
|
goto Exit;
|
|
}
|
|
#endif // 0
|
|
|
|
if (!::EnableDebugPrivilege())
|
|
{
|
|
::ReportFailure("EnableDebugPrivilege() failed");
|
|
goto Exit;
|
|
}
|
|
|
|
if ((pfn = (PCSR_GET_PROCESS_ID) GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "CsrGetProcessId")) == NULL)
|
|
{
|
|
::ReportFailure("GetProcessAddress(GetModuleHandleW(L\"ntdll\"), \"CsrGetProcessId\") failed");
|
|
goto Exit;
|
|
}
|
|
|
|
g_pidCSRSS = (DWORD)(DWORD_PTR)(*pfn)();
|
|
|
|
if ((g_hCSRSS = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, g_pidCSRSS)) == NULL)
|
|
{
|
|
::ReportFailure("OpenProcess(PROCESS_ALL_ACCESS, FALSE, 0x%lx) failed", g_pidCSRSS);
|
|
goto Exit;
|
|
}
|
|
|
|
dwSymOptions = ::SymGetOptions();
|
|
if (!::SymSetOptions(dwSymOptions | SYMOPT_DEFERRED_LOADS))
|
|
{
|
|
::ReportFailure("SymSetOptions(dwSymOptions (= 0x%08lx) | SYMOPT_DEFERRED_LOADS (= 0x%08x)) failed", dwSymOptions, SYMOPT_DEFERRED_LOADS);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!::SymInitialize(g_hCSRSS, NULL, TRUE))
|
|
{
|
|
::ReportFailure("SymInitialize(%p, NULL, TRUE) failed", g_hCSRSS);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!::SymFromName(g_hCSRSS, "sxs!kd_fusion_mask", &si))
|
|
{
|
|
::ReportFailure("SymFromName(%p, \"sxs!kd_fusion_mask\", %p) failed", g_hCSRSS, &si);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!::ReadProcessMemory(g_hCSRSS, (PVOID) si.Address, &g_dwOldKdFusionMask, sizeof(g_dwOldKdFusionMask), &nBytesWritten))
|
|
{
|
|
::ReportFailure("ReadProcessMemory(%p, %p, %p, %lu, %p) failed", g_hCSRSS, (PVOID) si.Address, &g_dwOldKdFusionMask, sizeof(g_dwOldKdFusionMask), &nBytesWritten);
|
|
goto Exit;
|
|
}
|
|
|
|
dwNewKdMask = g_dwOldKdFusionMask | 0x40000000;
|
|
|
|
if (!::WriteProcessMemory(g_hCSRSS, (PVOID) si.Address, &dwNewKdMask, sizeof(dwNewKdMask), &nBytesWritten))
|
|
{
|
|
::ReportFailure("WriteProcessMemory(%p, %p, %p (-> %lx), %lu, %p) failed", g_hCSRSS, (PVOID) si.Address, &dwNewKdMask, dwNewKdMask, sizeof(dwNewKdMask), &nBytesWritten);
|
|
goto Exit;
|
|
}
|
|
|
|
g_fKdFusionMaskSet = true;
|
|
|
|
if ((g_hCompletionPort = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1)) == NULL)
|
|
{
|
|
::ReportFailure("CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1) failed");
|
|
goto Exit;
|
|
}
|
|
|
|
if ((g_hWorkerThread = ::CreateThread(NULL, 0, &WorkerThreadThreadProc, NULL, 0, &g_tidWorkerThread)) == NULL)
|
|
{
|
|
::ReportFailure("CreateThread(NULL, 0, %p (==&WorkerThreadThreadProc), NULL, 0, %p (== &g_tidWorkerThread))", &WorkerThreadThreadProc, &g_tidWorkerThread);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!::FormatAndQueueString(L"Found ntdll!kd_fusion_mask at %I64x\n", si.Address))
|
|
{
|
|
::ReportFailure("FormatAndQueueString() failed");
|
|
goto Exit;
|
|
}
|
|
|
|
if (!::DebugActiveProcess(g_pidCSRSS))
|
|
{
|
|
::ReportFailure("DebugActiveProcess(0x%lx) failed", g_pidCSRSS);
|
|
goto Exit;
|
|
}
|
|
|
|
// First, if we die, we don't want to take the system with us.
|
|
if (!::DebugSetProcessKillOnExit(FALSE))
|
|
{
|
|
const DWORD dwLastError = ::GetLastError();
|
|
::DebugActiveProcessStop(g_pidCSRSS);
|
|
::SetLastError(dwLastError);
|
|
::ReportFailure("DebugSetProcessKillOnExit(FALSE) failed");
|
|
goto Exit;
|
|
}
|
|
|
|
g_fDebuggingCSRSS = true;
|
|
|
|
for (;;)
|
|
{
|
|
SIZE_T t = 0;
|
|
PCSTR EventName = "<Event not in map>";
|
|
|
|
if (!::WaitForDebugEvent(&de, INFINITE))
|
|
{
|
|
::ReportFailure("WaitForDebugEvent(%p, INFINITE) failed", &de);
|
|
goto Exit;
|
|
}
|
|
|
|
if (fp != NULL)
|
|
{
|
|
const static struct { PCSTR psz; DWORD dwEventCode; } s_rgMap[] = {
|
|
#define ENTRY(x) { #x, x }
|
|
ENTRY(EXCEPTION_DEBUG_EVENT),
|
|
ENTRY(CREATE_THREAD_DEBUG_EVENT),
|
|
ENTRY(CREATE_PROCESS_DEBUG_EVENT),
|
|
ENTRY(EXIT_THREAD_DEBUG_EVENT),
|
|
ENTRY(EXIT_PROCESS_DEBUG_EVENT),
|
|
ENTRY(LOAD_DLL_DEBUG_EVENT),
|
|
ENTRY(UNLOAD_DLL_DEBUG_EVENT),
|
|
ENTRY(OUTPUT_DEBUG_STRING_EVENT),
|
|
ENTRY(RIP_EVENT),
|
|
#undef ENTRY
|
|
};
|
|
|
|
for (t=0; t<NUMBER_OF(s_rgMap); t++)
|
|
{
|
|
if (s_rgMap[t].dwEventCode == de.dwDebugEventCode)
|
|
{
|
|
EventName = s_rgMap[t].psz;
|
|
break;
|
|
}
|
|
}
|
|
|
|
::fprintf(fp, "%s { p: %lu; t: %lu } ", EventName, de.dwProcessId, de.dwThreadId);
|
|
}
|
|
|
|
switch (de.dwDebugEventCode)
|
|
{
|
|
case CREATE_PROCESS_DEBUG_EVENT:
|
|
g_hCSRSS = de.u.CreateProcessInfo.hProcess;
|
|
break;
|
|
|
|
case EXIT_PROCESS_DEBUG_EVENT:
|
|
break;
|
|
|
|
#if 0
|
|
case LOAD_DLL_DEBUG_EVENT:
|
|
{
|
|
LOAD_DLL_DEBUG_INFO &rlddi = de.u.LoadDll;
|
|
|
|
if (!::FormatAndQueueString(
|
|
L"Loaded:\n"
|
|
L" hFile: %p\n"
|
|
L" lpBaseOfDll: %p\n"
|
|
L" dwDebugInfoFileOffset: %lu (0x%lx)\n"
|
|
L" nDebugInfoSize: %lu (0x%lx)\n"
|
|
L" lpImageName: %p\n"
|
|
L" fUnicode: %u\n",
|
|
rlddi.hFile,
|
|
rlddi.lpBaseOfDll,
|
|
rlddi.dwDebugInfoFileOffset, rlddi.dwDebugInfoFileOffset,
|
|
rlddi.nDebugInfoSize, rlddi.nDebugInfoSize,
|
|
rlddi.lpImageName,
|
|
rlddi.fUnicode))
|
|
{
|
|
::ReportFailure("FormatAndQueueString() for LOAD_DLL_DEBUG_EVENT failed");
|
|
goto Exit;
|
|
}
|
|
|
|
break;
|
|
}
|
|
#endif // 0
|
|
|
|
case OUTPUT_DEBUG_STRING_EVENT:
|
|
{
|
|
DWORD BytesReadDword = 0;
|
|
SIZE_T BytesReadSizeT = 0;
|
|
OUTPUT_DEBUG_STRING_INFO &rodsi = de.u.DebugString;
|
|
PWSTR pszLocalString = NULL;
|
|
LPOVERLAPPED lpo = NULL;
|
|
SIZE_T len = rodsi.nDebugStringLength;
|
|
|
|
if (rodsi.nDebugStringLength != 0)
|
|
{
|
|
if (rodsi.fUnicode)
|
|
{
|
|
if ((lpo = (LPOVERLAPPED) ::HeapAlloc(Heap, 0, sizeof(OVERLAPPED) + ((len + 1) * sizeof(WCHAR)))) == NULL)
|
|
{
|
|
::ReportFailure("HeapAlloc(%p (== GetProcessHeap()), 0, %lu) failed", GetProcessHeap(), sizeof(OVERLAPPED) + (rodsi.nDebugStringLength * sizeof(WCHAR)));
|
|
goto Exit;
|
|
}
|
|
|
|
pszLocalString = (PWSTR) (lpo + 1);
|
|
|
|
BytesReadSizeT = BytesReadDword;
|
|
if (!::ReadProcessMemory(g_hCSRSS, rodsi.lpDebugStringData, pszLocalString, rodsi.nDebugStringLength * sizeof(WCHAR), &BytesReadSizeT))
|
|
{
|
|
::ReportFailure("ReadProcessMemory(%p, %p, %p, %lu, %p) failed", g_hCSRSS, rodsi.lpDebugStringData, pszLocalString, rodsi.nDebugStringLength * sizeof(WCHAR), &BytesReadSizeT);
|
|
goto Exit;
|
|
}
|
|
BytesReadDword = (DWORD)BytesReadSizeT;
|
|
ASSERT(BytesReadDword == BytesReadSizeT);
|
|
|
|
pszLocalString[rodsi.nDebugStringLength] = L'\0';
|
|
}
|
|
else
|
|
{
|
|
PSTR pszTempString = NULL;
|
|
INT i = 0;
|
|
INT j = 0;
|
|
|
|
if ((pszTempString = (PSTR) ::HeapAlloc(Heap, 0, rodsi.nDebugStringLength)) == NULL)
|
|
{
|
|
::ReportFailure("HeapAlloc(%p (== GetProcessHeap()), 0, %lu) failed", GetProcessHeap(), rodsi.nDebugStringLength);
|
|
goto Exit;
|
|
}
|
|
|
|
BytesReadSizeT = BytesReadDword;
|
|
if (!::ReadProcessMemory(g_hCSRSS, rodsi.lpDebugStringData, pszTempString, rodsi.nDebugStringLength, &BytesReadSizeT))
|
|
{
|
|
::ReportFailure("ReadProcessMemory(%p, %p, %p, %lu, %p) failed", g_hCSRSS, rodsi.lpDebugStringData, pszTempString, rodsi.nDebugStringLength, &BytesReadSizeT);
|
|
goto Exit;
|
|
}
|
|
BytesReadDword = (DWORD)BytesReadSizeT;
|
|
ASSERT(BytesReadDword == BytesReadSizeT);
|
|
|
|
if ((i = ::MultiByteToWideChar(CP_ACP, 0, pszTempString, BytesReadDword, NULL, 0)) == 0)
|
|
{
|
|
::ReportFailure("MultiByteToWideChar(CP_ACP, 0, %p, %lu, NULL, 0) failed", pszTempString, BytesReadDword);
|
|
goto Exit;
|
|
}
|
|
|
|
if ((lpo = (LPOVERLAPPED) ::HeapAlloc(Heap, 0, sizeof(OVERLAPPED) + ((i + 1) * sizeof(WCHAR)))) == NULL)
|
|
{
|
|
::ReportFailure("HeapAlloc(%p (== GetProcessHeap()), 0, %lu) failed", GetProcessHeap(), sizeof(OVERLAPPED) + ((i + 1) * sizeof(WCHAR)));
|
|
goto Exit;
|
|
}
|
|
|
|
pszLocalString = (PWSTR) (lpo + 1);
|
|
|
|
if ((j = ::MultiByteToWideChar(CP_ACP, 0, pszTempString, BytesReadDword, pszLocalString, i * sizeof(WCHAR))) == 0)
|
|
{
|
|
::ReportFailure("MultiByteToWideChar(CP_ACP, 0, %p, %lu, %p, %lu) failed", pszTempString, BytesReadDword, pszLocalString, i * sizeof(WCHAR));
|
|
goto Exit;
|
|
}
|
|
|
|
pszLocalString[j] = L'\0';
|
|
|
|
::HeapFree(Heap, 0, pszTempString);
|
|
}
|
|
|
|
::ZeroMemory(lpo, sizeof(OVERLAPPED));
|
|
|
|
if (!::PostQueuedCompletionStatus(g_hCompletionPort, 0, NULL, lpo))
|
|
{
|
|
::ReportFailure("PostQueuedCompletionStatus(%p, 0, NULL, %p) failed", g_hCompletionPort, 0, NULL, lpo);
|
|
goto Exit;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!::ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_EXCEPTION_NOT_HANDLED))
|
|
{
|
|
::ReportFailure("ContinueDebugEvent(%lu, %lu, DBG_EXCEPTION_NOT_HANDLED) failed", de.dwProcessId, de.dwThreadId);
|
|
goto Exit;
|
|
}
|
|
|
|
if (fp != NULL)
|
|
{
|
|
::fprintf(fp, "\n");
|
|
::fflush(fp);
|
|
}
|
|
}
|
|
|
|
iReturnStatus = EXIT_SUCCESS;
|
|
|
|
Exit:
|
|
if (g_fKdFusionMaskSet)
|
|
{
|
|
const DWORD dwLastError = ::GetLastError();
|
|
::WriteProcessMemory(g_hCSRSS, (PVOID) si.Address, &g_dwOldKdFusionMask, sizeof(g_dwOldKdFusionMask), &nBytesWritten);
|
|
::SetLastError(dwLastError);
|
|
}
|
|
|
|
return iReturnStatus;
|
|
}
|
|
|
|
DWORD
|
|
WINAPI
|
|
WorkerThreadThreadProc(
|
|
LPVOID
|
|
)
|
|
{
|
|
ULONG n = 0;
|
|
LPOVERLAPPED lpoPrevious = NULL;
|
|
ULONG nReps = 0;
|
|
DWORD dwMSTimeout = 100;
|
|
const HANDLE Heap = ::GetProcessHeap();
|
|
|
|
for (;;)
|
|
{
|
|
DWORD dwNumberOfBytes = 0;
|
|
ULONG_PTR ulpCompletionKey = 0;
|
|
LPOVERLAPPED lpOverlapped = NULL;
|
|
|
|
if (!::GetQueuedCompletionStatus(g_hCompletionPort, &dwNumberOfBytes, &ulpCompletionKey, &lpOverlapped, dwMSTimeout))
|
|
{
|
|
if (lpOverlapped == NULL)
|
|
{
|
|
if (lpoPrevious != NULL)
|
|
{
|
|
// timeout...
|
|
PCWSTR psz2 = (PCWSTR) (lpoPrevious + 1);
|
|
|
|
if (nReps != 0)
|
|
::printf("[%08lx:%lu] %ls", n++, nReps + 1, psz2);
|
|
else
|
|
::printf("[%08lx] %ls", n++, psz2);
|
|
|
|
::fflush(stdout);
|
|
|
|
::HeapFree(Heap, 0, lpoPrevious);
|
|
lpoPrevious = lpOverlapped;
|
|
nReps = 0;
|
|
dwMSTimeout = INFINITE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
::ReportFailure("GetQueuedCompletionStatus(%p, %p, %p, %p, INFINITE) failed", g_hCompletionPort, &dwNumberOfBytes, &ulpCompletionKey, &lpOverlapped);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PCWSTR psz = (PCWSTR) (lpOverlapped + 1);
|
|
|
|
dwMSTimeout = 100;
|
|
|
|
if (lpoPrevious != NULL)
|
|
{
|
|
PCWSTR psz2 = (PCWSTR) (lpoPrevious + 1);
|
|
|
|
if (::wcscmp(psz, psz2) == 0)
|
|
{
|
|
psz = NULL;
|
|
nReps++;
|
|
::HeapFree(Heap, 0, lpOverlapped);
|
|
}
|
|
else
|
|
{
|
|
if (nReps != 0)
|
|
::printf("[%08lx:%lu] %ls", n++, nReps + 1, psz2);
|
|
else
|
|
::printf("[%08lx] %ls", n++, psz2);
|
|
|
|
::fflush(stdout);
|
|
|
|
::HeapFree(Heap, 0, lpoPrevious);
|
|
lpoPrevious = lpOverlapped;
|
|
nReps = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// first one...
|
|
lpoPrevious = lpOverlapped;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
EnableDebugPrivilege()
|
|
{
|
|
LUID PrivilegeValue;
|
|
BOOL Result = FALSE;
|
|
TOKEN_PRIVILEGES TokenPrivileges;
|
|
TOKEN_PRIVILEGES OldTokenPrivileges;
|
|
DWORD ReturnLength = 0;
|
|
HANDLE TokenHandle = NULL;
|
|
|
|
//
|
|
// First, find out the LUID Value of the privilege
|
|
//
|
|
|
|
if(!::LookupPrivilegeValueW(NULL, L"SeDebugPrivilege", &PrivilegeValue)) {
|
|
::ReportFailure("LookupPrivilegeValueW(NULL, L\"SeDebugPrivilege\", %p) failed", &PrivilegeValue);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the token handle
|
|
//
|
|
if (!::OpenProcessToken (
|
|
::GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
|
&TokenHandle
|
|
))
|
|
{
|
|
::ReportFailure("OpenProcessToken() failed");
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Set up the privilege set we will need
|
|
//
|
|
|
|
TokenPrivileges.PrivilegeCount = 1;
|
|
TokenPrivileges.Privileges[0].Luid = PrivilegeValue;
|
|
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
ReturnLength = sizeof(TOKEN_PRIVILEGES);
|
|
if (!::AdjustTokenPrivileges (
|
|
TokenHandle,
|
|
FALSE,
|
|
&TokenPrivileges,
|
|
sizeof(OldTokenPrivileges),
|
|
&OldTokenPrivileges,
|
|
&ReturnLength
|
|
))
|
|
{
|
|
::ReportFailure("AdjustTokenPrivileges(%p, FALSE, %p, %lu, %p, %p) failed", TokenHandle, &TokenPrivileges, sizeof(OldTokenPrivileges), &OldTokenPrivileges, &ReturnLength);
|
|
goto Exit;
|
|
}
|
|
|
|
Result = TRUE;
|
|
Exit:
|
|
|
|
if (TokenHandle != NULL)
|
|
{
|
|
const DWORD dwLastError = ::GetLastError();
|
|
::CloseHandle(TokenHandle);
|
|
::SetLastError(dwLastError);
|
|
}
|
|
|
|
return Result;
|
|
}
|