mirror of https://github.com/tongzx/nt5src
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.
1040 lines
28 KiB
1040 lines
28 KiB
#include "pchealth.h"
|
|
#include <FWcommon.h>
|
|
#include <strings.h>
|
|
|
|
#include <DllUtils.h>
|
|
#include <BrodCast.h>
|
|
#include <lmerr.h>
|
|
#include <confgmgr.h>
|
|
#include <createmutexasprocess.h>
|
|
|
|
// sets a status object with one single missing privilege
|
|
void SetSinglePrivilegeStatusObject(MethodContext* pContext, const WCHAR* pPrivilege)
|
|
{
|
|
SAFEARRAY *psaPrivilegesReqd, *psaPrivilegesNotHeld;
|
|
SAFEARRAYBOUND rgsabound[1];
|
|
rgsabound[0].cElements = 1;
|
|
rgsabound[0].lLbound = 0;
|
|
psaPrivilegesReqd = SafeArrayCreate(VT_BSTR, 1, rgsabound);
|
|
psaPrivilegesNotHeld = SafeArrayCreate(VT_BSTR, 1, rgsabound);
|
|
|
|
if (psaPrivilegesReqd && psaPrivilegesNotHeld)
|
|
{
|
|
long index = 0;
|
|
bstr_t privilege(pPrivilege);
|
|
SafeArrayPutElement(psaPrivilegesReqd, &index, (void*)(BSTR)privilege);
|
|
SafeArrayPutElement(psaPrivilegesNotHeld, &index, (void*)(BSTR)privilege);
|
|
CWbemProviderGlue::SetStatusObject(pContext, IDS_CimWin32Namespace, "Required privilege not enabled", WBEM_E_FAILED, psaPrivilegesNotHeld, psaPrivilegesReqd);
|
|
}
|
|
|
|
if (psaPrivilegesNotHeld)
|
|
SafeArrayDestroy(psaPrivilegesNotHeld);
|
|
if (psaPrivilegesReqd)
|
|
SafeArrayDestroy(psaPrivilegesReqd);
|
|
}
|
|
|
|
// VER_PLATFORM_WIN32s Win32s on Windows 3.1
|
|
// VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95
|
|
// VER_PLATFORM_WIN32_NT Windows NT
|
|
DWORD GetPlatformID(void)
|
|
{
|
|
OSVERSIONINFO OsVersion;
|
|
|
|
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx((LPOSVERSIONINFO)&OsVersion);
|
|
|
|
return OsVersion.dwPlatformId;
|
|
}
|
|
|
|
// 3 for NT 3.51
|
|
// 4 for NT 4.0, W95 & W98
|
|
DWORD GetPlatformMajorVersion(void)
|
|
{
|
|
OSVERSIONINFO OsVersion;
|
|
|
|
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx((LPOSVERSIONINFO)&OsVersion);
|
|
|
|
return OsVersion.dwMajorVersion;
|
|
}
|
|
|
|
// 0 for W95, 10 for 98
|
|
DWORD GetPlatformMinorVersion(void)
|
|
{
|
|
OSVERSIONINFO OsVersion;
|
|
|
|
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx((LPOSVERSIONINFO)&OsVersion);
|
|
|
|
return OsVersion.dwMinorVersion;
|
|
}
|
|
|
|
// returns TRUE iff the current OS is Win 98+
|
|
// false for NT or Win 95
|
|
bool IsWin98(void)
|
|
{
|
|
OSVERSIONINFO OsVersion;
|
|
|
|
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx((LPOSVERSIONINFO)&OsVersion);
|
|
|
|
return (OsVersion.dwPlatformId == (VER_PLATFORM_WIN32_WINDOWS) && (OsVersion.dwMinorVersion >= 10));
|
|
}
|
|
|
|
bool IsWinNT5(void)
|
|
{
|
|
OSVERSIONINFO OsVersion;
|
|
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx((LPOSVERSIONINFO)&OsVersion);
|
|
|
|
return(OsVersion.dwPlatformId == (VER_PLATFORM_WIN32_NT) && (OsVersion.dwMajorVersion >= 5));
|
|
}
|
|
|
|
bool IsWinNT4(void)
|
|
{
|
|
OSVERSIONINFO OsVersion;
|
|
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx((LPOSVERSIONINFO)&OsVersion);
|
|
|
|
return(OsVersion.dwPlatformId == (VER_PLATFORM_WIN32_NT) && (OsVersion.dwMajorVersion == 4));
|
|
}
|
|
|
|
bool IsWinNT351(void)
|
|
{
|
|
OSVERSIONINFO OsVersion;
|
|
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx((LPOSVERSIONINFO)&OsVersion);
|
|
|
|
return ( OsVersion.dwPlatformId == VER_PLATFORM_WIN32_NT
|
|
&& OsVersion.dwMajorVersion == 3
|
|
&& OsVersion.dwMinorVersion == 51 );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
void LogEnumValueError( char * szFile, DWORD dwLine, char * szKey, char * szId )
|
|
{
|
|
if (IsErrorLoggingEnabled())
|
|
{
|
|
CHString gazotta;
|
|
gazotta.Format(ERR_REGISTRY_ENUM_VALUE_FOR_KEY, szId, szKey);
|
|
LogErrorMessageEx((const char *)gazotta, szFile, dwLine);
|
|
}
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
void LogOpenRegistryError( char * szFile, DWORD dwLine, char * szKey )
|
|
{
|
|
if (IsErrorLoggingEnabled())
|
|
{
|
|
CHString gazotta;
|
|
gazotta.Format(ERR_OPEN_REGISTRY, szKey);
|
|
|
|
LogErrorMessageEx((const char *)gazotta, szFile, dwLine);
|
|
}
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
// left in for hysterical purposes
|
|
// prefer to use LogMessage macro in BrodCast.h
|
|
void LogError( char * szFile, DWORD dwLine, char * szKey )
|
|
{
|
|
LogErrorMessageEx(szKey, szFile, dwLine);
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
void LogLastError( char * szFile, DWORD dwLine )
|
|
{
|
|
if (IsErrorLoggingEnabled())
|
|
{
|
|
DWORD duhWord = GetLastError();
|
|
CHString gazotta;
|
|
gazotta.Format(IDS_GETLASTERROR, duhWord, duhWord);
|
|
|
|
LogErrorMessageEx(gazotta, szFile, dwLine);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
BOOL GetValue( CRegistry & Reg,
|
|
char * szKey,
|
|
char * ValueName,
|
|
CHString * pchsValueBuffer )
|
|
{
|
|
BOOL bRet = (Reg.GetCurrentKeyValue( ValueName, *pchsValueBuffer) == ERROR_SUCCESS);
|
|
|
|
if( !bRet )
|
|
LogEnumValueError(__FILE__,__LINE__, szKey, ValueName);
|
|
|
|
return bRet;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
BOOL GetValue( CRegistry & Reg,
|
|
char * szKey,
|
|
char * ValueName,
|
|
DWORD * dwValueBuffer )
|
|
{
|
|
BOOL bRet = (Reg.GetCurrentKeyValue( ValueName, *dwValueBuffer) == ERROR_SUCCESS);
|
|
|
|
if( !bRet )
|
|
LogEnumValueError(__FILE__,__LINE__, szKey, ValueName);
|
|
|
|
return bRet;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
BOOL OpenAndGetValue( CRegistry & Reg,
|
|
char * szKey,
|
|
char * ValueName,
|
|
CHString * pchsValueBuffer )
|
|
{
|
|
BOOL bRet = ( Reg.OpenLocalMachineKeyAndReadValue( szKey, ValueName, *pchsValueBuffer )== ERROR_SUCCESS);
|
|
|
|
if( !bRet )
|
|
LogEnumValueError(__FILE__,__LINE__, szKey, ValueName);
|
|
|
|
return bRet;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
BOOL GetBinaryValue( CRegistry & Reg, char * szKey,
|
|
char * ValueName, CHString * pchsValueBuffer )
|
|
{
|
|
BOOL bRet = ( Reg.GetCurrentBinaryKeyValue( ValueName, *pchsValueBuffer) == ERROR_SUCCESS);
|
|
|
|
if( !bRet )
|
|
(LogEnumValueError(__FILE__,__LINE__, szKey, ValueName));
|
|
|
|
return bRet;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : GetDeviceParms
|
|
*
|
|
* DESCRIPTION : Gets drive characteristics (heads, tracks, cylinders, etc)
|
|
*
|
|
* INPUTS : Pointer to a DEVICEPARMS struct to receive the data
|
|
* Drive number of the drive to query (0 = default drive,
|
|
* 1 = A, 2 = B, and so on)
|
|
*
|
|
* OUTPUTS :
|
|
*
|
|
* RETURNS : TRUE if successful, FALSE otherwise
|
|
*
|
|
* COMMENTS :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL GetDeviceParms(PDEVICEPARMS pstDeviceParms, UINT nDrive)
|
|
{
|
|
DEVIOCTL_REGISTERS reg;
|
|
memset(®, '\0', sizeof(DEVIOCTL_REGISTERS));
|
|
|
|
reg.reg_EAX = 0x440D; /* IOCTL for block devices */
|
|
reg.reg_EBX = nDrive; /* zero-based drive ID */
|
|
reg.reg_ECX = 0x0860; /* Get Media ID command */
|
|
reg.reg_EDX = (DWORD) pstDeviceParms;
|
|
|
|
memset(pstDeviceParms, 0, sizeof(DEVICEPARMS));
|
|
|
|
if (!VWIN32IOCTL(®, VWIN32_DIOC_DOS_IOCTL))
|
|
return FALSE;
|
|
|
|
if (reg.reg_Flags & 0x8000) /* error if carry flag set */
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : GetDriveMapInfo
|
|
*
|
|
* DESCRIPTION : Gets logical to physical mapping info
|
|
*
|
|
* INPUTS : Pointer to a DRIVE_MAP_INFO struct to receive the data
|
|
* Drive number of the drive to query (0 = default drive,
|
|
* 1 = A, 2 = B, and so on)
|
|
*
|
|
* OUTPUTS :
|
|
*
|
|
* RETURNS : TRUE if successful, FALSE otherwise
|
|
*
|
|
* COMMENTS :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL GetDriveMapInfo(PDRIVE_MAP_INFO pDriveMapInfo, UINT nDrive)
|
|
{
|
|
DEVIOCTL_REGISTERS reg;
|
|
memset(®, '\0', sizeof(DEVIOCTL_REGISTERS));
|
|
|
|
reg.reg_EAX = 0x440d; /* IOCTL for block devices */
|
|
reg.reg_EBX = nDrive; /* zero-based drive ID */
|
|
reg.reg_ECX = 0x086f; /* Get Drive Map Info */
|
|
reg.reg_EDX = (DWORD) pDriveMapInfo;
|
|
|
|
// zero the struct
|
|
memset(pDriveMapInfo, 0, sizeof(DRIVE_MAP_INFO));
|
|
|
|
// Set the length byte
|
|
pDriveMapInfo->btAllocationLength = sizeof(DRIVE_MAP_INFO);
|
|
|
|
// Doit
|
|
if (!VWIN32IOCTL(®, VWIN32_DIOC_DOS_IOCTL))
|
|
return FALSE;
|
|
|
|
if (reg.reg_Flags & 0x8000) {/* error if carry flag set */
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : Get_ExtFreeSpace
|
|
*
|
|
* DESCRIPTION : Gets detailed info about a partition
|
|
*
|
|
* INPUTS : Drive number of the drive to query (0 = default drive,
|
|
* 1 = A, 2 = B, and so on)
|
|
* Pointer to ExtGetDskFreSpcStruct
|
|
*
|
|
* OUTPUTS :
|
|
*
|
|
* RETURNS : TRUE if successful, FALSE otherwise
|
|
*
|
|
* COMMENTS :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL Get_ExtFreeSpace(BYTE btDriveName, ExtGetDskFreSpcStruc *pstExtGetDskFreSpcStruc)
|
|
{
|
|
DEVIOCTL_REGISTERS reg;
|
|
memset(®, '\0', sizeof(DEVIOCTL_REGISTERS));
|
|
char szDrive[4];
|
|
|
|
szDrive[0] = btDriveName;
|
|
szDrive[1] = ':';
|
|
szDrive[2] = '\\';
|
|
szDrive[3] = '\0';
|
|
|
|
reg.reg_EAX = 0x7303; // Get_ExtFreeSpace
|
|
reg.reg_ECX = sizeof(ExtGetDskFreSpcStruc); // Size of the structure sent in
|
|
reg.reg_EDI = (DWORD)pstExtGetDskFreSpcStruc; // Structure
|
|
reg.reg_EDX = (DWORD)szDrive; // Drive to get info for
|
|
|
|
// zero the struct
|
|
memset(pstExtGetDskFreSpcStruc, 0, sizeof(ExtGetDskFreSpcStruc));
|
|
|
|
// Doit
|
|
if (!VWIN32IOCTL(®, VWIN32_DIOC_DOS_DRIVEINFO))
|
|
return FALSE;
|
|
|
|
if (reg.reg_Flags & 0x8000) {/* error if carry flag set */
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : VWIN32IOCTL
|
|
*
|
|
* DESCRIPTION : Calls IOControl against the vwin32 vxd
|
|
*
|
|
* INPUTS : Pointer to DEVIOCTL_REGISTERS structure
|
|
* IOControl call number.
|
|
*
|
|
* OUTPUTS :
|
|
*
|
|
* RETURNS : TRUE if successful, FALSE otherwise
|
|
*
|
|
* COMMENTS :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL VWIN32IOCTL(PDEVIOCTL_REGISTERS preg, DWORD dwCall)
|
|
{
|
|
HANDLE hDevice;
|
|
|
|
BOOL fResult;
|
|
DWORD cb;
|
|
|
|
preg->reg_Flags = 0x8000; /* assume error (carry flag set) */
|
|
|
|
hDevice = CreateFile("\\\\.\\VWIN32", 0, 0, 0, OPEN_EXISTING,
|
|
FILE_FLAG_DELETE_ON_CLOSE, 0);
|
|
|
|
if (hDevice == (HANDLE) INVALID_HANDLE_VALUE) {
|
|
return FALSE;
|
|
} else {
|
|
fResult = DeviceIoControl(hDevice, dwCall, preg, sizeof(*preg), preg, sizeof(*preg), &cb, 0);
|
|
}
|
|
|
|
CloseHandle(hDevice);
|
|
|
|
if (!fResult) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
CHString GetFileTypeDescription(char *szExtension)
|
|
{
|
|
CRegistry RegInfo;
|
|
CHString sTemp, sType(szExtension);
|
|
|
|
if (RegInfo.Open(HKEY_CLASSES_ROOT, szExtension, KEY_READ) == ERROR_SUCCESS) {
|
|
RegInfo.GetCurrentKeyValue("", sTemp);
|
|
|
|
if (RegInfo.Open(HKEY_CLASSES_ROOT, sTemp, KEY_READ) == ERROR_SUCCESS) {
|
|
RegInfo.GetCurrentKeyValue("", sType);
|
|
}
|
|
}
|
|
|
|
return sType;
|
|
}
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// Define the severity codes
|
|
//
|
|
// Sev - is the severity code
|
|
//
|
|
// 00 - Success
|
|
// 01 - Informational
|
|
// 10 - Warning
|
|
// 11 - Error
|
|
|
|
//
|
|
// Define the severity codes
|
|
//
|
|
//
|
|
// Define the severity codes
|
|
//
|
|
#define STATUS_SEVERITY_WARNING 0x2
|
|
#define STATUS_SEVERITY_SUCCESS 0x0
|
|
#define STATUS_SEVERITY_INFORMATIONAL 0x1
|
|
#define STATUS_SEVERITY_ERROR 0x3
|
|
#define SEV_MASK 0xC0000000
|
|
void TranslateNTStatus( DWORD dwStatus, CHString & chsValue)
|
|
{
|
|
|
|
switch((dwStatus & SEV_MASK) >> 30){
|
|
|
|
case STATUS_SEVERITY_WARNING:
|
|
chsValue = IDS_STATUS_Degraded;
|
|
break;
|
|
|
|
case STATUS_SEVERITY_SUCCESS:
|
|
chsValue = IDS_STATUS_OK;
|
|
break;
|
|
|
|
case STATUS_SEVERITY_ERROR:
|
|
chsValue = IDS_STATUS_Error;
|
|
break;
|
|
|
|
case STATUS_SEVERITY_INFORMATIONAL:
|
|
chsValue = IDS_STATUS_OK;
|
|
break;
|
|
|
|
default:
|
|
chsValue = IDS_STATUS_Unknown;
|
|
}
|
|
}
|
|
|
|
BOOL GetVarFromVersionInfo(LPCTSTR szFile, LPCTSTR szVar, CHString &strValue)
|
|
{
|
|
BOOL fRc = FALSE;
|
|
DWORD dwTemp,
|
|
dwBlockSize;
|
|
LPVOID pInfo = NULL;
|
|
|
|
try
|
|
{
|
|
dwBlockSize = GetFileVersionInfoSize((LPTSTR) szFile, &dwTemp);
|
|
if (dwBlockSize)
|
|
{
|
|
pInfo = (LPVOID) new BYTE[dwBlockSize + 4];
|
|
memset( pInfo, NULL, dwBlockSize + 4);
|
|
|
|
if (pInfo)
|
|
{
|
|
UINT len;
|
|
if (GetFileVersionInfo((LPTSTR) szFile, 0, dwBlockSize, pInfo))
|
|
{
|
|
WORD wLang = 0;
|
|
WORD wCodePage = 0;
|
|
if(!GetVersionLanguage(pInfo, &wLang, &wCodePage) )
|
|
{
|
|
// on failure: default to English
|
|
|
|
// this returns a pointer to an array of WORDs
|
|
WORD *pArray;
|
|
if (VerQueryValue(pInfo, "\\VarFileInfo\\Translation",(void **)(&pArray), &len))
|
|
{
|
|
len = len / sizeof(WORD);
|
|
|
|
// find the english one...
|
|
for (int i = 0; i < len; i += 2)
|
|
{
|
|
if( pArray[i] == 0x0409 ) {
|
|
wLang = pArray[i];
|
|
wCodePage = pArray[i + 1];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TCHAR *pMfg, szTemp[256];
|
|
wsprintf(szTemp, _T("\\StringFileInfo\\%04X%04X\\%s"), wLang, wCodePage, szVar);
|
|
|
|
if( VerQueryValue(pInfo, szTemp, (void **)(&pMfg), &len))
|
|
{
|
|
strValue = pMfg;
|
|
fRc = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
// We don't need to do anything, just need to protect ourselves
|
|
// from the flaky version.dll calls.
|
|
}
|
|
|
|
if (pInfo)
|
|
delete pInfo;
|
|
|
|
return fRc;
|
|
}
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
Function: BOOL GetVersionLanguage(void *vpInfo,
|
|
WORD *wpLang,
|
|
WORD *wpCodePage);
|
|
Description: This function extracts the language and codepage out of a passed GetFileVersionInfo()
|
|
result. Consideration is given to variation in the layout.
|
|
Arguments: vpInfo, wpLang, wpCodePage
|
|
Returns: Boolean
|
|
Inputs:
|
|
Outputs:
|
|
Caveats:
|
|
Courtesy of: SMS, Nick Dyer
|
|
Raid:
|
|
History: a-peterc 30-Oct-1998 Created
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
BOOL GetVersionLanguage(void *vpInfo, WORD *wpLang, WORD *wpCodePage)
|
|
{
|
|
WORD *wpTemp;
|
|
WORD wLength;
|
|
WCHAR *wcpTemp;
|
|
char *cpTemp;
|
|
BOOL bRet = FALSE;
|
|
|
|
wpTemp = (WORD *) vpInfo;
|
|
cpTemp = (char *) vpInfo;
|
|
|
|
wpTemp++; // jump past buffer length.
|
|
wLength = *wpTemp; // capture value length.
|
|
wpTemp++; // skip past value length to what should be type code in new format
|
|
if (*wpTemp == 0 || *wpTemp == 1) // new format expect unicode strings.
|
|
{
|
|
cpTemp = cpTemp + 38 + wLength + 8;
|
|
wcpTemp = (WCHAR *) cpTemp;
|
|
if (wcscmp(L"StringFileInfo", wcpTemp) == 0) // OK! were aligned properly.
|
|
{
|
|
bRet = TRUE;
|
|
|
|
cpTemp += 30; // skip over "StringFileInfo"
|
|
while ((DWORD) cpTemp % 4 > 0) // 32 bit align
|
|
cpTemp++;
|
|
|
|
cpTemp += 6; // skip over length and type fields.
|
|
|
|
wcpTemp = (WCHAR *) cpTemp;
|
|
swscanf(wcpTemp, L"%4x%4x", wpLang, wpCodePage);
|
|
}
|
|
}
|
|
else // old format, expect single byte character strings.
|
|
{
|
|
cpTemp += 20 + wLength + 4;
|
|
if (strcmp("StringFileInfo", cpTemp) == 0) // OK! were aligned properly.
|
|
{
|
|
bRet = TRUE;
|
|
|
|
cpTemp += 20; // skip over length fields.
|
|
sscanf(cpTemp, "%4x%4x", wpLang, wpCodePage);
|
|
}
|
|
}
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
BOOL GetManufacturerFromFileName(LPCTSTR szFile, CHString &strMfg)
|
|
{
|
|
return GetVarFromVersionInfo(szFile, "CompanyName", strMfg);
|
|
}
|
|
|
|
BOOL GetVersionFromFileName(LPCTSTR szFile, CHString &strVersion)
|
|
{
|
|
return GetVarFromVersionInfo(szFile, "ProductVersion", strVersion);
|
|
}
|
|
|
|
void ReplaceString(CHString &str, LPCTSTR szFind, LPCTSTR szReplace)
|
|
{
|
|
int iWhere,
|
|
nLen = lstrlen(szFind);
|
|
|
|
while ((iWhere = str.Find(szFind)) != -1)
|
|
{
|
|
str.Format(
|
|
"%s%s%s",
|
|
(LPCTSTR) str.Left(iWhere),
|
|
szReplace,
|
|
(LPCTSTR) str.Mid(iWhere + nLen));
|
|
}
|
|
}
|
|
|
|
BOOL GetServiceFileName(LPCTSTR szService, CHString &strFileName)
|
|
{
|
|
SC_HANDLE hSCManager,
|
|
hService;
|
|
TCHAR szBuffer[2048];
|
|
QUERY_SERVICE_CONFIG
|
|
*pConfig = (QUERY_SERVICE_CONFIG *) szBuffer;
|
|
DWORD dwNeeded;
|
|
BOOL bRet = FALSE;
|
|
|
|
hSCManager =
|
|
OpenSCManager(
|
|
NULL,
|
|
NULL,
|
|
STANDARD_RIGHTS_REQUIRED);
|
|
if (!hSCManager)
|
|
return FALSE;
|
|
|
|
hService =
|
|
OpenService(
|
|
hSCManager,
|
|
szService,
|
|
SERVICE_QUERY_CONFIG);
|
|
|
|
if (hService)
|
|
{
|
|
if (QueryServiceConfig(
|
|
hService,
|
|
pConfig,
|
|
sizeof(szBuffer),
|
|
&dwNeeded))
|
|
{
|
|
strFileName = pConfig->lpBinaryPathName;
|
|
|
|
// Now fix up the path so that it has a drive letter.
|
|
|
|
strFileName.MakeUpper();
|
|
|
|
// If the filename is using \SYSTEMROOT\, replace it with %SystemRoot%.
|
|
if (strFileName.Find("\\SYSTEMROOT\\") == 0)
|
|
ReplaceString(strFileName, "\\SYSTEMROOT\\", "%SystemRoot%\\");
|
|
// If the filename doesn't start with a replacement string, and if it
|
|
// doesn't have a drive letter, assume it should start with
|
|
// %SystemRoot%.
|
|
else if (strFileName.GetLength() >= 2 &&
|
|
strFileName[0] != '%' && strFileName[1] != ':')
|
|
{
|
|
CHString strTemp;
|
|
|
|
strTemp.Format("%%SystemRoot%%\\%s", (LPCTSTR) strFileName);
|
|
strFileName = strTemp;
|
|
}
|
|
|
|
TCHAR szOut[MAX_PATH * 2];
|
|
|
|
ExpandEnvironmentStrings(strFileName, szOut, sizeof(szOut));
|
|
strFileName = szOut;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
|
|
CloseServiceHandle(hService);
|
|
}
|
|
|
|
CloseServiceHandle(hSCManager);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// Performs a case insensitive compare (such as is required for keys)
|
|
// on two variants and returns true if they are the same type and
|
|
// the same value, else false. Note that arrays, VT_NULL, and
|
|
// embedded objects will assert, and return false.
|
|
///////////////////////////////////////////////////////////////////
|
|
bool CompareVariantsNoCase(const VARIANT *v1, const VARIANT *v2)
|
|
{
|
|
|
|
if (v1->vt == v2->vt) {
|
|
switch (v1->vt) {
|
|
case VT_BOOL: return (v1->boolVal == v2->boolVal);
|
|
case VT_UI1: return (v1->bVal == v2->bVal);
|
|
case VT_I2: return (v1->iVal == v2->iVal);
|
|
case VT_I4: return (v1->lVal == v2->lVal);
|
|
case VT_R4: return (v1->fltVal == v2->fltVal);
|
|
case VT_R8: return (v1->dblVal == v2->dblVal);
|
|
case VT_BSTR: return (0 == _wcsicmp(v1->bstrVal, v2->bstrVal));
|
|
default:
|
|
ASSERT_BREAK(0);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// map standard API return values (defined WinError.h)
|
|
// to WBEMish hresults (defined in WbemCli.h)
|
|
HRESULT WinErrorToWBEMhResult(LONG error)
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
switch (error)
|
|
{
|
|
case ERROR_SUCCESS:
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
case ERROR_ACCESS_DENIED:
|
|
hr = WBEM_E_ACCESS_DENIED;
|
|
break;
|
|
case ERROR_NOT_ENOUGH_MEMORY:
|
|
case ERROR_OUTOFMEMORY:
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
break;
|
|
case ERROR_ALREADY_EXISTS:
|
|
hr = WBEM_E_ALREADY_EXISTS;
|
|
break;
|
|
case ERROR_BAD_NETPATH:
|
|
case ERROR_INVALID_DATA:
|
|
case ERROR_BAD_PATHNAME:
|
|
case REGDB_E_INVALIDVALUE:
|
|
case ERROR_PATH_NOT_FOUND:
|
|
case ERROR_FILE_NOT_FOUND:
|
|
case ERROR_BAD_USERNAME:
|
|
case NERR_NetNameNotFound:
|
|
case ERROR_NOT_READY:
|
|
case ERROR_INVALID_NAME:
|
|
hr = WBEM_E_NOT_FOUND;
|
|
break;
|
|
default:
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
void SetConfigMgrProperties(CConfigMgrDevice *pDevice, CInstance *pInstance)
|
|
{
|
|
CHString strDeviceID;
|
|
DWORD dwStatus,
|
|
dwProblem;
|
|
|
|
if (pDevice->GetDeviceID(strDeviceID))
|
|
pInstance->SetCHString(IDS_PNPDeviceID, strDeviceID);
|
|
|
|
if (pDevice->GetStatus(&dwStatus, &dwProblem))
|
|
pInstance->SetDWORD("ConfigManagerErrorCode", dwProblem);
|
|
|
|
pInstance->SetDWORD("ConfigManagerUserConfig",
|
|
pDevice->IsUsingForcedConfig());
|
|
}
|
|
|
|
BOOL EnablePrivilegeOnCurrentThread(LPCTSTR szPriv)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
HANDLE hToken = NULL;
|
|
TOKEN_PRIVILEGES tkp;
|
|
BOOL bLookup = FALSE;
|
|
DWORD dwLastError = ERROR_SUCCESS;
|
|
|
|
// Try to open the thread token. If we fail, it's because no
|
|
// impersonation is going on, so call ImpersonateSelf to get a token.
|
|
// Then call OpenThreadToken again.
|
|
if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES |
|
|
TOKEN_QUERY, FALSE, &hToken) ||
|
|
(ImpersonateSelf(SecurityImpersonation) &&
|
|
OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES |
|
|
TOKEN_QUERY, FALSE, &hToken)))
|
|
{
|
|
|
|
{
|
|
CreateMutexAsProcess createMutexAsProcess(SECURITYAPIMUTEXNAME);
|
|
bLookup = LookupPrivilegeValue(NULL, szPriv, &tkp.Privileges[0].Luid);
|
|
}
|
|
if (bLookup)
|
|
{
|
|
tkp.PrivilegeCount = 1;
|
|
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
// Clear the last error.
|
|
SetLastError(0);
|
|
|
|
// Turn it on
|
|
bRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
|
|
(PTOKEN_PRIVILEGES) NULL, 0);
|
|
dwLastError = GetLastError();
|
|
}
|
|
|
|
CloseHandle(hToken);
|
|
}
|
|
|
|
// We have to check GetLastError() because AdjustTokenPrivileges lies about
|
|
// its success but GetLastError() doesn't.
|
|
return bRet && dwLastError == ERROR_SUCCESS;
|
|
}
|
|
|
|
// Takes a pnp id and returns a bios unit number
|
|
// To avoid frequent load/unload of a library, the pGetWin9XBiosUnit parameter comes from:
|
|
// HINSTANCE hInst = LoadLibrary("cim32net.dll");
|
|
// pGetWin9XBiosUnit = (fnGetWin9XBiosUnit)GetProcAddress(hInst, "GetWin9XBiosUnit");
|
|
BYTE GetBiosUnitNumberFromPNPID(fnGetWin9XBiosUnit pGetWin9XBiosUnit, CHString strDeviceID)
|
|
{
|
|
CHString sTemp;
|
|
DRIVE_MAP_INFO stDMI;
|
|
CRegistry Reg1;
|
|
|
|
BYTE btBiosUnit = -1;
|
|
|
|
// Open the associated registry key
|
|
if (Reg1.Open(HKEY_LOCAL_MACHINE, "enum\\" + strDeviceID, KEY_QUERY_VALUE) == ERROR_SUCCESS)
|
|
{
|
|
|
|
// Get a drive letter for this pnp id
|
|
if ((Reg1.GetCurrentKeyValue("CurrentDriveLetterAssignment", sTemp) != ERROR_SUCCESS) ||
|
|
(sTemp.GetLength() == 0)) {
|
|
// No drive letters, let's try one more thing. On memphis sp1, this call will also
|
|
// get us a unit number.
|
|
if (pGetWin9XBiosUnit != NULL)
|
|
{
|
|
btBiosUnit = pGetWin9XBiosUnit(strDeviceID.GetBuffer(0));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GetDriveMapInfo(&stDMI, toupper(sTemp[0]) - 'A' + 1))
|
|
{
|
|
btBiosUnit = stDMI.btInt13Unit;
|
|
}
|
|
}
|
|
}
|
|
|
|
return btBiosUnit;
|
|
}
|
|
|
|
HRESULT GetHKUserNames(CHStringList &list)
|
|
{
|
|
HRESULT hres;
|
|
|
|
// Empty the list.
|
|
list.clear();
|
|
|
|
if (GetPlatformID() == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
// Enum the profiles from the registry.
|
|
CRegistry regProfileList;
|
|
CHString strProfile;
|
|
DWORD dwErr;
|
|
|
|
// Open the ProfileList key so we know which profiles to load up.
|
|
if ((dwErr = regProfileList.OpenAndEnumerateSubKeys(
|
|
HKEY_LOCAL_MACHINE,
|
|
IDS_RegNTProfileList,
|
|
KEY_READ)) == ERROR_SUCCESS)
|
|
{
|
|
for (int i = 0; regProfileList.GetCurrentSubKeyName(strProfile) ==
|
|
ERROR_SUCCESS; i++)
|
|
{
|
|
list.push_back(strProfile);
|
|
regProfileList.NextSubKey();
|
|
}
|
|
}
|
|
|
|
// Add the .DEFAULT name.
|
|
list.push_back(_T(".DEFAULT"));
|
|
|
|
hres = WinErrorToWBEMhResult(dwErr);
|
|
}
|
|
else
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
#ifdef _DEBUG
|
|
DWORD dwSize = 10,
|
|
#else
|
|
DWORD dwSize = 1024,
|
|
#endif
|
|
dwBytesRead;
|
|
TCHAR *szBuff = NULL;
|
|
|
|
// Keep looping until we read the entire section.
|
|
// You know your buffer wasn't big enough if the returned number
|
|
// of bytes == (size passed in - 2).
|
|
do
|
|
{
|
|
if (szBuff)
|
|
{
|
|
free(szBuff);
|
|
|
|
dwSize *= 2;
|
|
}
|
|
|
|
szBuff = (TCHAR *) malloc(dwSize);
|
|
|
|
// Out of memory. Get out of loop.
|
|
if (!szBuff)
|
|
break;
|
|
|
|
dwBytesRead =
|
|
GetPrivateProfileString(
|
|
"Password Lists",
|
|
NULL,
|
|
"",
|
|
szBuff,
|
|
dwSize,
|
|
"system.ini");
|
|
|
|
} while (dwBytesRead >= dwSize - 2);
|
|
|
|
if (szBuff)
|
|
{
|
|
// Loop through the list of names. Each is null-terminated, and the
|
|
// list is terminated with a double null.
|
|
TCHAR *pszCurrent = szBuff;
|
|
|
|
while (*pszCurrent)
|
|
{
|
|
list.push_back(pszCurrent);
|
|
|
|
pszCurrent += lstrlen(pszCurrent) + 1;
|
|
}
|
|
|
|
hres = WBEM_S_NO_ERROR;
|
|
|
|
// Free the buffer.
|
|
free(szBuff);
|
|
|
|
// Add the .DEFAULT name.
|
|
list.push_back(_T(".DEFAULT"));
|
|
}
|
|
else
|
|
// Failed to malloc, so set error code.
|
|
hres = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
VOID EscapeBackslashes(CHString& chstrIn,
|
|
CHString& chstrOut)
|
|
{
|
|
CHString chstrCpyNormPathname = chstrIn;
|
|
LONG lNext = -1L;
|
|
chstrOut.Empty();
|
|
|
|
// Find the next '\'
|
|
lNext = chstrCpyNormPathname.Find(_T('\\'));
|
|
while(lNext != -1)
|
|
{
|
|
// Add on to the new string we are building:
|
|
chstrOut += chstrCpyNormPathname.Left(lNext + 1);
|
|
// Add on the second backslash:
|
|
chstrOut += _T('\\');
|
|
// Hack off from the input string the portion we just copied
|
|
chstrCpyNormPathname = chstrCpyNormPathname.Right(chstrCpyNormPathname.GetLength() - lNext - 1);
|
|
lNext = chstrCpyNormPathname.Find(_T('\\'));
|
|
}
|
|
// If the last character wasn't a '\', there may still be leftovers, so
|
|
// copy them here.
|
|
if(chstrCpyNormPathname.GetLength() != 0)
|
|
{
|
|
chstrOut += chstrCpyNormPathname;
|
|
}
|
|
}
|
|
|
|
VOID EscapeQuotes(CHString& chstrIn,
|
|
CHString& chstrOut)
|
|
{
|
|
CHString chstrCpyNormPathname = chstrIn;
|
|
LONG lNext = -1L;
|
|
chstrOut.Empty();
|
|
|
|
// Find the next '\'
|
|
lNext = chstrCpyNormPathname.Find(_T('\"'));
|
|
while(lNext != -1)
|
|
{
|
|
// Add on to the new string we are building:
|
|
chstrOut += chstrCpyNormPathname.Left(lNext);
|
|
// Escape the quote:
|
|
chstrOut += _T("\\\"");
|
|
// Hack off from the input string the portion we just copied
|
|
chstrCpyNormPathname = chstrCpyNormPathname.Right(chstrCpyNormPathname.GetLength() - lNext - 1);
|
|
lNext = chstrCpyNormPathname.Find(_T('\"'));
|
|
}
|
|
// If the last character wasn't a '\', there may still be leftovers, so
|
|
// copy them here.
|
|
if(chstrCpyNormPathname.GetLength() != 0)
|
|
{
|
|
chstrOut += chstrCpyNormPathname;
|
|
}
|
|
}
|
|
|
|
VOID RemoveDoubleBackslashes(const CHString& chstrIn, CHString& chstrOut)
|
|
{
|
|
CHString chstrBuildString;
|
|
CHString chstrInCopy = chstrIn;
|
|
BOOL fDone = FALSE;
|
|
LONG lPos = -1;
|
|
while(!fDone)
|
|
{
|
|
lPos = chstrInCopy.Find(_T("\\\\"));
|
|
if(lPos != -1)
|
|
{
|
|
chstrBuildString += chstrInCopy.Left(lPos);
|
|
chstrBuildString += _T("\\");
|
|
chstrInCopy = chstrInCopy.Mid(lPos+2);
|
|
}
|
|
else
|
|
{
|
|
chstrBuildString += chstrInCopy;
|
|
fDone = TRUE;
|
|
}
|
|
}
|
|
chstrOut = chstrBuildString;
|
|
}
|
|
|
|
CHString RemoveDoubleBackslashes(const CHString& chstrIn)
|
|
{
|
|
CHString chstrBuildString;
|
|
CHString chstrInCopy = chstrIn;
|
|
BOOL fDone = FALSE;
|
|
LONG lPos = -1;
|
|
while(!fDone)
|
|
{
|
|
lPos = chstrInCopy.Find(_T("\\\\"));
|
|
if(lPos != -1)
|
|
{
|
|
chstrBuildString += chstrInCopy.Left(lPos);
|
|
chstrBuildString += _T("\\");
|
|
chstrInCopy = chstrInCopy.Mid(lPos+2);
|
|
}
|
|
else
|
|
{
|
|
chstrBuildString += chstrInCopy;
|
|
fDone = TRUE;
|
|
}
|
|
}
|
|
return chstrBuildString;
|
|
}
|
|
|
|
|