2025-11-28 00:35:46 +09:00

841 lines
25 KiB
C++

//+-------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: utils.cpp
//
//--------------------------------------------------------------------------
#include "setup.h"
#include "resource.h"
#include "common.h"
#include "msi.h"
#include <assert.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <strsafe.h>
#define WIN // scope W32 API
/////////////////////////////////////////////////////////////////////////////
// VerifyFileSignature
//
DWORD VerifyFileSignature (LPCSTR lpszModule, __in_opt LPSTR lpszCmdLine)
{
LPCSTR pszFirstArgEnd;
LPCSTR pszFileName;
LPCSTR pszEnd;
DWORD Status;
//
// When this function is called, the first argument has already
// been verified. So skip the first argument.
//
GetNextArgument (lpszCmdLine, NULL, &pszFirstArgEnd, NULL);
// Now get the name of the file whose signature needs to be verified.
Status = GetNextArgument (CharNextA(pszFirstArgEnd), &pszFileName, &pszEnd, NULL);
// Must supply a filename
if (ERROR_NO_MORE_ITEMS == Status)
return ERROR_BAD_ARGUMENTS;
// Should not have any more arguments
if ('\0' != *(CharNextA(pszEnd)) &&
ERROR_NO_MORE_ITEMS != GetNextArgument (CharNextA(CharNextA(pszEnd)), NULL, NULL, NULL))
{
return ERROR_BAD_ARGUMENTS;
}
// We have the right arguments. Null terminate the filename.
*(CharNextA(pszEnd)) = '\0';
switch (IsPackageTrusted(lpszModule, pszFileName, NULL))
{
case itvWintrustNotOnMachine:
return TRUST_E_PROVIDER_UNKNOWN;
case itvTrusted:
return ERROR_SUCCESS;
case itvUnTrusted:
default:
return TRUST_E_SUBJECT_NOT_TRUSTED;
}
}
/////////////////////////////////////////////////////////////////////////////
// GetExecutionMode
//
emEnum GetExecutionMode (LPCSTR lpszCmdLine)
{
LPCSTR pszStart = NULL;
LPCSTR pszEnd = NULL;
DWORD dwStatus = ERROR_SUCCESS;
bool fQuoted = false;
//
// Check the first argument and set the execution mode accordingly.
// When run without arguments, it is assumed that the default install
// preset by the package publisher needs to be performed.
//
// In case an invalid option is provided, the help dialog describing the
// usage must be displayed.
//
dwStatus = GetNextArgument (lpszCmdLine, &pszStart, &pszEnd, &fQuoted);
if (ERROR_NO_MORE_ITEMS == dwStatus)
return emPreset;
// The only allowed values in the first argument are /a, /v and /?
if (pszEnd != CharNextA(pszStart) || fQuoted)
return emHelp;
if ('/' != (*pszStart) && '-' != (*pszStart))
return emHelp;
switch (*pszEnd)
{
case 'a':
case 'A':
return emAdminInstall;
case 'v':
case 'V':
return emVerify;
default:
return emHelp;
}
}
/////////////////////////////////////////////////////////////////////////////
// GetNextArgument
//
DWORD GetNextArgument (LPCSTR pszCmdLine, LPCSTR *ppszArgStart, LPCSTR *ppszArgEnd, bool * pfQuoted)
{
bool fInQuotes = false;
bool fFoundArgEnd = false;
LPCSTR pszChar = pszCmdLine;
LPCSTR pszFirst = NULL;
LPCSTR pszLast = NULL;
if (NULL == pszChar)
return ERROR_NO_MORE_ITEMS;
// Skip leading spaces.
while (' ' == *pszChar || '\t' == *pszChar)
pszChar = CharNextA(pszChar);
// Check if we have run out of arguments.
if ('\0' == (*pszChar))
return ERROR_NO_MORE_ITEMS;
// Check if we this argument has been enclosed in quotes
if ('\"' == (*pszChar))
{
fInQuotes = true;
pszChar = CharNextA (pszChar);
}
pszFirst = pszChar;
// Now look for the end of the argument
while (! fFoundArgEnd)
{
pszChar = CharNextA(pszChar);
if ('\0' == (*pszChar))
fFoundArgEnd = true;
if (fInQuotes && '\"' == (*pszChar))
fFoundArgEnd = true;
if (!fInQuotes && ' ' == (*pszChar))
fFoundArgEnd = true;
if (!fInQuotes && '\t' == (*pszChar))
fFoundArgEnd = true;
}
pszLast = CharPrevA (pszFirst, pszChar);
if (ppszArgStart)
*ppszArgStart = pszFirst;
if (ppszArgEnd)
*ppszArgEnd = pszLast;
if (pfQuoted)
*pfQuoted = fInQuotes;
return ERROR_SUCCESS;
}
/////////////////////////////////////////////////////////////////////////////
//
//
DWORD GetAdminInstallInfo (bool fPatch, __in_opt LPSTR lpszCmdLine, LPCSTR * ppszAdminImagePath)
{
LPCSTR pszFirstArgEnd;
LPCSTR pszFileName;
LPCSTR pszEnd;
DWORD Status;
//
// When this function is called, the first argument has already been
// verified. So skip the first argument.
//
GetNextArgument (lpszCmdLine, NULL, &pszFirstArgEnd, NULL);
// See if there is another argument
Status = GetNextArgument (CharNextA(pszFirstArgEnd), &pszFileName, &pszEnd, NULL);
// If it is not a patch, there should not be any more arguments.
if (!fPatch)
{
if (ERROR_NO_MORE_ITEMS != Status)
return ERROR_BAD_ARGUMENTS;
// If we are here, then we are done, because we have all the information we need.
if (ppszAdminImagePath)
*ppszAdminImagePath = NULL;
return ERROR_SUCCESS;
}
// If we are here, this is a patch. Get the path to the admin. install.
if (ERROR_NO_MORE_ITEMS == Status)
return ERROR_BAD_ARGUMENTS; // No path was supplied.
// Should not have any more arguments.
if ('\0' != *(CharNextA(pszEnd)) &&
ERROR_NO_MORE_ITEMS != GetNextArgument (CharNextA(CharNextA(pszEnd)), NULL, NULL, NULL))
{
return ERROR_BAD_ARGUMENTS;
}
// We have the right arguments. Null terminate the pathname.
*(CharNextA(pszEnd)) = '\0';
if (ppszAdminImagePath)
*ppszAdminImagePath = pszFileName;
return ERROR_SUCCESS;
}
/////////////////////////////////////////////////////////////////////////////
// LoadResourceString
//
UINT LoadResourceString(HINSTANCE hInst, LPCSTR lpType, LPCSTR lpName, __out_ecount(*pdwBufSize) LPSTR lpBuf, DWORD *pdwBufSize)
{
HRSRC hRsrc = 0;
HGLOBAL hGlobal = 0;
WCHAR *pch = 0;
if ((hRsrc = WIN::FindResource(hInst, lpName, lpType)) != 0
&& (hGlobal = WIN::LoadResource(hInst, hRsrc)) != 0)
{
// resource exists
if ((pch = (WCHAR*)LockResource(hGlobal)) != 0)
{
unsigned int cch = WideCharToMultiByte(CP_ACP, 0, pch, -1, NULL, 0, NULL, NULL);
if (cch > *pdwBufSize)
{
*pdwBufSize = cch;
return ERROR_MORE_DATA;
}
if (0 == WideCharToMultiByte(CP_ACP, 0, pch, -1, lpBuf, *pdwBufSize, NULL, NULL))
return ERROR_FUNCTION_FAILED;
*pdwBufSize = cch;
}
else
{
if (1 > *pdwBufSize)
{
*pdwBufSize = 1;
return ERROR_MORE_DATA;
}
*pdwBufSize = 1;
*lpBuf = 0;
}
DebugMsg("[Resource] lpName = %s, lpBuf = %s\n", lpName, lpBuf);
return ERROR_SUCCESS;
}
// resource does not exist
DebugMsg("[Resource] lpName = %s NOT FOUND\n", lpName);
return ERROR_RESOURCE_NAME_NOT_FOUND;
}
/////////////////////////////////////////////////////////////////////////////
// SetupLoadResourceString
//
UINT SetupLoadResourceString(HINSTANCE hInst, LPCSTR lpName, __deref_out LPSTR *lppBuf, DWORD dwBufSize)
{
UINT uiStat = 0;
if (!*lppBuf)
{
dwBufSize = (dwBufSize > 0) ? dwBufSize : 256;
*lppBuf = new char[dwBufSize];
if (!*lppBuf)
return ERROR_OUTOFMEMORY;
}
if (ERROR_SUCCESS != (uiStat = LoadResourceString(hInst, RT_INSTALL_PROPERTY, lpName, *lppBuf, &dwBufSize)))
{
if (uiStat != ERROR_MORE_DATA)
return uiStat;
// resize and try again
delete [] *lppBuf;
*lppBuf = new char[dwBufSize];
if (!*lppBuf)
return ERROR_OUTOFMEMORY;
uiStat = LoadResourceString(hInst, RT_INSTALL_PROPERTY, lpName, *lppBuf, &dwBufSize);
}
return uiStat;
}
/////////////////////////////////////////////////////////////////////////////
// PostResourceNotFoundError
//
void PostResourceNotFoundError(HINSTANCE hInst, HWND hwndOwner, LPCSTR szTitle, LPCSTR szName)
{
char szError[MAX_STR_LENGTH] = {0};
char szFormat[MAX_STR_LENGTH] = {0};
WIN::LoadString(hInst, IDS_MISSING_RESOURCE, szFormat, sizeof(szFormat)/sizeof(char));
StringCchPrintf(szError, sizeof(szError), szFormat, szName);
MessageBox(hwndOwner, szError, szTitle, MB_OK | MB_ICONEXCLAMATION);
}
/////////////////////////////////////////////////////////////////////////////
// ReportUserCancelled
//
void ReportUserCancelled(HINSTANCE hInst, HWND hwndOwner, LPCSTR szTitle)
{
char szError[MAX_STR_LENGTH] = {0};
WIN::LoadString(hInst, IDS_USER_CANCELLED, szError, sizeof(szError)/sizeof(char));
MessageBox(hwndOwner, szError, szTitle, MB_OK | MB_ICONEXCLAMATION);
}
/////////////////////////////////////////////////////////////////////////////
// PostError
//
void PostError(HINSTANCE hInst, HWND hwndOwner, LPCSTR szTitle, UINT uiErrorId)
{
char szError[MAX_STR_LENGTH] = {0};
WIN::LoadString(hInst, uiErrorId, szError, sizeof(szError)/sizeof(char));
MessageBox(hwndOwner, szError, szTitle, MB_OK | MB_ICONERROR);
}
/////////////////////////////////////////////////////////////////////////////
// PostError
//
void PostError(HINSTANCE hInst, HWND hwndOwner, LPCSTR szTitle, UINT uiErrorId, LPCSTR szValue)
{
char szError[MAX_STR_LENGTH] = {0};
char szFormat[MAX_STR_LENGTH] = {0};
WIN::LoadString(hInst, uiErrorId, szFormat, sizeof(szFormat)/sizeof(char));
StringCchPrintf(szError, sizeof(szError), szFormat, szValue);
MessageBox(hwndOwner, szError, szTitle, MB_OK | MB_ICONERROR);
}
/////////////////////////////////////////////////////////////////////////////
// PostError
//
void PostError(HINSTANCE hInst, HWND hwndOwner, LPCSTR szTitle, UINT uiErrorId, LPCSTR szValue, int iValue)
{
char szError[MAX_STR_LENGTH] = {0};
char szFormat[MAX_STR_LENGTH] = {0};
WIN::LoadString(hInst, uiErrorId, szFormat, sizeof(szFormat)/sizeof(char));
StringCchPrintf(szError, sizeof(szError), szFormat, szValue, iValue);
MessageBox(hwndOwner, szError, szTitle, MB_OK | MB_ICONERROR);
}
/////////////////////////////////////////////////////////////////////////////
// PostError
//
void PostError(HINSTANCE hInst, HWND hwndOwner, LPCSTR szTitle, UINT uiErrorId, int iValue)
{
char szError[MAX_STR_LENGTH] = {0};
char szFormat[MAX_STR_LENGTH] = {0};
WIN::LoadString(hInst, uiErrorId, szFormat, sizeof(szFormat)/sizeof(char));
StringCchPrintf(szError, sizeof(szError), szFormat, iValue);
MessageBox(hwndOwner, szError, szTitle, MB_OK | MB_ICONERROR);
}
/////////////////////////////////////////////////////////////////////////////
// PostFormattedError
//
void PostFormattedError(HINSTANCE hInst, HWND hwndOwner, LPCSTR szTitle, UINT uiErrorId, LPCSTR szValue)
{
char szFormat[MAX_STR_LENGTH] = {0};
const char* szArgs[1] = {szValue};
LPVOID lpMessage = 0;;
WIN::LoadString(hInst, uiErrorId, szFormat, sizeof(szFormat)/sizeof(char));
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, (LPVOID)szFormat, 0, 0, (LPSTR)&lpMessage, 0, (va_list*)szArgs);
if (!lpMessage)
{
ReportErrorOutOfMemory(hInst, hwndOwner, szTitle);
return;
}
MessageBox(hwndOwner, (LPCSTR)lpMessage, szTitle, MB_OK | MB_ICONERROR);
LocalFree(lpMessage);
}
/////////////////////////////////////////////////////////////////////////////
// PostMsiError
//
void PostMsiError(HINSTANCE hInst, HINSTANCE hMsi, HWND hwndOwner, LPCSTR szTitle, UINT uiErrorId)
{
switch (uiErrorId)
{
case ERROR_INSTALL_SUSPEND:
case ERROR_INSTALL_USEREXIT:
case ERROR_INSTALL_FAILURE:
case ERROR_SUCCESS_REBOOT_REQUIRED:
case ERROR_SUCCESS_REBOOT_INITIATED:
case ERROR_APPHELP_BLOCK:
break;
case ERROR_FILE_NOT_FOUND:
case ERROR_INVALID_NAME:
case ERROR_PATH_NOT_FOUND:
uiErrorId = ERROR_INSTALL_PACKAGE_OPEN_FAILED;
default:
{
char szError[MAX_STR_LENGTH] = {0};
if (0 == WIN::LoadString(hMsi, uiErrorId, szError, sizeof(szError)/sizeof(char)))
{
// error string does not exist, use default
PostError(hInst, hwndOwner, szTitle, IDS_INSTALL_ERROR, uiErrorId);
}
else
{
MessageBox(hwndOwner, szError, szTitle, MB_OK | MB_ICONERROR);
}
return;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// AlreadyInProgress
//
// Attempts to create the MSISETUP mutex. Returns TRUE
// if mutex already exists or failed to create mutex
//
bool AlreadyInProgress(HANDLE& hMutex)
{
const char *szMutexName = "Global\\_MSISETUP_{2956EBA1-9B5A-4679-8618-357136DA66CA}";
hMutex = WIN::CreateMutex(NULL /*default security descriptor*/, FALSE, szMutexName);
if (!hMutex || ERROR_ALREADY_EXISTS == GetLastError())
return true;
return false;
}
/////////////////////////////////////////////////////////////////////////////
// DisplayUsage
//
void DisplayUsage (HINSTANCE hInst, HWND hwndOwner, LPCSTR szCaption)
{
char szMessage[MAX_STR_LENGTH];
WIN::LoadString(hInst, IDS_USAGE, szMessage, sizeof(szMessage)/sizeof(char));
WIN::MessageBox(hwndOwner, szMessage, szCaption, MB_OK | MB_ICONINFORMATION);
}
/////////////////////////////////////////////////////////////////////////////
// ReportErrorOutOfMemory
//
void ReportErrorOutOfMemory(HINSTANCE hInst, HWND hwndOwner, LPCSTR szCaption)
{
char szError[MAX_STR_LENGTH];
WIN::LoadString(hInst, IDS_OUTOFMEM, szError, sizeof(szError)/sizeof(char));
WIN::MessageBox(hwndOwner, szError, szCaption, MB_OK | MB_ICONERROR);
}
/////////////////////////////////////////////////////////////////////////////
// GetFileVersionNumber
//
DWORD GetFileVersionNumber(__in LPSTR szFilename, DWORD * pdwMSVer, DWORD * pdwLSVer)
{
DWORD dwResult = NOERROR;
unsigned uiSize;
DWORD dwVerInfoSize;
DWORD dwHandle;
BYTE *prgbVersionInfo = NULL;
VS_FIXEDFILEINFO *lpVSFixedFileInfo = NULL;
DWORD dwMSVer = 0xffffffff;
DWORD dwLSVer = 0xffffffff;
dwVerInfoSize = GetFileVersionInfoSize(szFilename, &dwHandle);
if (0 != dwVerInfoSize)
{
prgbVersionInfo = (LPBYTE) WIN::GlobalAlloc(GPTR, dwVerInfoSize);
if (NULL == prgbVersionInfo)
{
dwResult = ERROR_NOT_ENOUGH_MEMORY;
goto Finish;
}
// Read version stamping info
if (GetFileVersionInfo(szFilename, dwHandle, dwVerInfoSize, prgbVersionInfo))
{
// get the value for Translation
if (VerQueryValue(prgbVersionInfo, "\\", (LPVOID*)&lpVSFixedFileInfo, &uiSize) && (uiSize != 0))
{
dwMSVer = lpVSFixedFileInfo->dwFileVersionMS;
dwLSVer = lpVSFixedFileInfo->dwFileVersionLS;
}
}
else
{
dwResult = GetLastError();
goto Finish;
}
}
else
{
dwResult = GetLastError();
}
#ifdef DEBUG
char szVersion[255];
StringCchPrintf(szVersion, sizeof(szVersion), "%s is version %d.%d.%d.%d\n", szFilename, HIWORD(dwMSVer), LOWORD(dwMSVer), HIWORD(dwLSVer), LOWORD(dwLSVer));
DebugMsg("[INFO] %s", szVersion);
#endif // DEBUG
Finish:
if (NULL != prgbVersionInfo)
WIN::GlobalFree(prgbVersionInfo);
if (pdwMSVer)
*pdwMSVer = dwMSVer;
if (pdwLSVer)
*pdwLSVer = dwLSVer;
return dwResult;
}
/////////////////////////////////////////////////////////////////////////////
// MimimumWindowsPlatform
//
// Returns true if running on a platform whose major version, minor version
// and service pack major are greater than or equal to the ones specifed
// while making this function call
//
bool MimimumWindowsPlatform(DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor)
{
OSVERSIONINFOEX osvi;
DWORDLONG dwlConditionMask = 0;
// Initialize the OSVERSIONINFOEX structure.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = dwMajorVersion;
osvi.dwMinorVersion = dwMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
// Initialize the condition mask.
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
// Perform the test.
return VerifyVersionInfo(&osvi,
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
dwlConditionMask) ? true : false;
}
/////////////////////////////////////////////////////////////////////////////
// IsOSSupported
//
// Returns true if running on Windows 2003, Windows XP or
// Windows 2000 SP3 and above. Else returns false
//
bool IsOSSupported()
{
OSVERSIONINFO sInfoOS;
memset((void*)&sInfoOS, 0x00, sizeof(OSVERSIONINFO));
sInfoOS.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
WIN::GetVersionEx(&sInfoOS);
// We do no support any platform prior to Windows 2000
if (5 > sInfoOS.dwMajorVersion)
return false;
// We support:
if(MimimumWindowsPlatform(5, 2, 0) || // Windows 2003 and above
MimimumWindowsPlatform(5, 1, 0) || // Windows XP and above
MimimumWindowsPlatform(5, 0, 3)) // Windows 2000 SP3 and above
return true;
else
return false;
}
//--------------------------------------------------------------------------------------
// ADVAPI32 API -- delay load
//--------------------------------------------------------------------------------------
#define ADVAPI32_DLL "advapi32.dll"
#define ADVAPI32API_CheckTokenMembership "CheckTokenMembership"
typedef BOOL (WINAPI* PFnCheckTokenMembership)(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember);
#define ADVAPI32API_AdjustTokenPrivileges "AdjustTokenPrivileges"
typedef BOOL (WINAPI* PFnAdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength);
#define ADVAPI32API_OpenProcessToken "OpenProcessToken"
typedef BOOL (WINAPI* PFnOpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
#define ADVAPI32API_LookupPrivilegeValue "LookupPrivilegeValueA"
typedef BOOL (WINAPI* PFnLookupPrivilegeValue)(LPCSTR lpSystemName, LPCSTR lpName, PLUID lpLuid);
/////////////////////////////////////////////////////////////////////////////
// IsAdmin
//
// Returns true if current user is an administrator (or if on Win9X)
// Returns false if current user is not an adminstrator
//
// implemented as per KB Q118626
//
bool IsAdmin()
{
// get the administrator sid
PSID psidAdministrators;
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
if(!AllocateAndInitializeSid(&siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdministrators))
return false;
// on NT5, use the CheckTokenMembershipAPI to correctly handle cases where
// the Adiminstrators group might be disabled. bIsAdmin is BOOL for
BOOL bIsAdmin = FALSE;
// CheckTokenMembership checks if the SID is enabled in the token. NULL for
// the token means the token of the current thread. Disabled groups, restricted
// SIDS, and SE_GROUP_USE_FOR_DENY_ONLY are all considered. If the function
// returns false, ignore the result.
HMODULE hAdvapi32 = LoadLibrary(ADVAPI32_DLL);
if (!hAdvapi32)
bIsAdmin = FALSE;
else
{
PFnCheckTokenMembership pfnCheckTokenMembership = (PFnCheckTokenMembership)GetProcAddress(hAdvapi32, ADVAPI32API_CheckTokenMembership);
if (!pfnCheckTokenMembership || !pfnCheckTokenMembership(NULL, psidAdministrators, &bIsAdmin))
bIsAdmin = FALSE;
}
FreeLibrary(hAdvapi32);
hAdvapi32 = 0;
WIN::FreeSid(psidAdministrators);
return bIsAdmin ? true : false;
}
/////////////////////////////////////////////////////////////////////////////
// AcquireShutdownPrivilege
//
// Attempts to enable the SE_SHUTDOWN_NAME privilege in the process token
//
bool AcquireShutdownPrivilege()
{
HANDLE hToken = 0;
TOKEN_PRIVILEGES tkp;
HMODULE hAdvapi32 = LoadLibrary(ADVAPI32_DLL);
if (!hAdvapi32)
return false;
PFnOpenProcessToken pfnOpenProcessToken = (PFnOpenProcessToken)GetProcAddress(hAdvapi32, ADVAPI32API_OpenProcessToken);
PFnLookupPrivilegeValue pfnLookupPrivilegeValue = (PFnLookupPrivilegeValue)GetProcAddress(hAdvapi32, ADVAPI32API_LookupPrivilegeValue);
PFnAdjustTokenPrivileges pfnAdjustTokenPrivileges = (PFnAdjustTokenPrivileges)GetProcAddress(hAdvapi32, ADVAPI32API_AdjustTokenPrivileges);
if (!pfnOpenProcessToken || !pfnLookupPrivilegeValue || !pfnAdjustTokenPrivileges)
{
FreeLibrary(hAdvapi32);
return false;
}
// grab this process's token
if (!pfnOpenProcessToken(WIN::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
FreeLibrary(hAdvapi32);
return false;
}
// get the LUID for the shutdown privilege
pfnLookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// get the shutdown privilege for this process
pfnAdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
// cannot test return value of AdjustTokenPrivileges
if (ERROR_SUCCESS != WIN::GetLastError())
{
FreeLibrary(hAdvapi32);
return false;
}
FreeLibrary(hAdvapi32);
return true;
}
/////////////////////////////////////////////////////////////////////////////
// SetDiagnosticMode
//
// Turns on debug output if first char of szDebugEnvVar is set to 1
//
int g_dmDiagnosticMode = -1; // -1 until set, then DebugMsg skips fn call if 0
void SetDiagnosticMode()
{
g_dmDiagnosticMode = 0; // disable DebugMsg to start
char rgchBuf[64] = {0};
if (0 != WIN::GetEnvironmentVariable(szDebugEnvVar, rgchBuf, sizeof(rgchBuf)/sizeof(char))
&& rgchBuf[0] == '1')
{
g_dmDiagnosticMode = 1; // enable DebugMsg output
}
}
/////////////////////////////////////////////////////////////////////////////
// DebugMsg
//
// Outputs debugging string to debugger if debug output is enabled
//
void DebugMsg(LPCSTR szFormat, int iArg1)
{
if (-1 == g_dmDiagnosticMode)
{
SetDiagnosticMode();
}
if (0 == g_dmDiagnosticMode || !szFormat)
return; // debug output is not enabled or nothing to output
const int INT_AS_STRING_SIZE = 12;
size_t cchFormat = lstrlen(szFormat);
size_t cchDebug = cchFormat + INT_AS_STRING_SIZE + 1;
char *szDebug = new char[cchDebug];
if (!szDebug)
return ; // out of memory
if (FAILED(StringCchPrintf(szDebug, cchDebug, szFormat, iArg1)))
{
delete[] szDebug;
return;
}
OutputDebugString(szDebug);
return;
}
void DebugMsg(LPCSTR szFormat, int iArg1, int iArg2)
{
if (-1 == g_dmDiagnosticMode)
{
SetDiagnosticMode();
}
if (0 == g_dmDiagnosticMode || !szFormat)
return; // debug output is not enabled or nothing to output
const int INT_AS_STRING_SIZE = 12;
size_t cchFormat = lstrlen(szFormat);
size_t cchDebug = cchFormat + 2 * INT_AS_STRING_SIZE + 1;
char *szDebug = new char[cchDebug];
if (!szDebug)
return ; // out of memory
if (FAILED(StringCchPrintf(szDebug, cchDebug, szFormat, iArg1, iArg2)))
{
delete[] szDebug;
return;
}
OutputDebugString(szDebug);
return;
}
void DebugMsg(LPCSTR szFormat, LPCSTR szArg1, LPCSTR szArg2)
{
if (-1 == g_dmDiagnosticMode)
{
SetDiagnosticMode();
}
if (0 == g_dmDiagnosticMode || !szFormat)
return; // debug output is not enabled or nothing to output
size_t cchFormat = lstrlen(szFormat);
size_t cchArg1 = (szArg1 != 0) ? lstrlen(szArg1) : 0;
size_t cchArg2 = (szArg2 != 0) ? lstrlen(szArg2) : 0;
if (0 == cchArg1)
{
OutputDebugString(szFormat);
}
else
{
size_t cchDebug = cchFormat + cchArg1 + cchArg2 + 1;
char *szDebug = new char[cchDebug];
if (!szDebug)
return ; // out of memory
if (0 == cchArg2)
{
if (FAILED(StringCchPrintf(szDebug, cchDebug, szFormat, szArg1)))
{
delete[] szDebug;
return;
}
OutputDebugString(szDebug);
}
else
{
if (FAILED(StringCchPrintf(szDebug, cchDebug, szFormat, szArg1, szArg2)))
{
delete[] szDebug;
return;
}
OutputDebugString(szDebug);
}
}
return;
}