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.
2178 lines
55 KiB
2178 lines
55 KiB
//=================================================================
|
|
|
|
//
|
|
|
|
// DllUtils.cpp
|
|
|
|
//
|
|
|
|
// Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
//=================================================================
|
|
#include "precomp.h"
|
|
#include <cregcls.h>
|
|
#include <assertbreak.h>
|
|
#include <lockwrap.h>
|
|
#include <lmerr.h>
|
|
|
|
#include <CCriticalSec.h>
|
|
#include <CAutoLock.h>
|
|
#include "dllmain.h"
|
|
|
|
#ifdef WIN9XONLY
|
|
#include <win32thk.h>
|
|
#endif
|
|
|
|
#include <CRegCls.h>
|
|
#include <delayimp.h>
|
|
|
|
#define UNRECOGNIZED_VARIANT_TYPE FALSE
|
|
|
|
DWORD g_dwMajorVersion,
|
|
g_dwMinorVersion,
|
|
g_dwBuildNumber;
|
|
|
|
CCriticalSec g_CSFlakyFileVersionAPI;
|
|
|
|
// There is a problem with loading Cim32Net.dll over and over, so this code
|
|
// makes sure we only load it once, then unloads it at exit.
|
|
// these are used with GetCim32NetHandle
|
|
|
|
#ifdef WIN9XONLY
|
|
HoldSingleCim32NetPtr::HoldSingleCim32NetPtr()
|
|
{
|
|
}
|
|
|
|
// Initialize the static members
|
|
HINSTANCE HoldSingleCim32NetPtr::m_spCim32NetApiHandle = NULL;
|
|
CCritSec HoldSingleCim32NetPtr::m_csCim32Net;
|
|
|
|
HoldSingleCim32NetPtr::~HoldSingleCim32NetPtr()
|
|
{
|
|
// FreeCim32NetApiPtr();
|
|
}
|
|
|
|
void HoldSingleCim32NetPtr::FreeCim32NetApiPtr()
|
|
{
|
|
CLockWrapper Cim32NetLock( m_csCim32Net ) ;
|
|
if (m_spCim32NetApiHandle)
|
|
{
|
|
FreeLibrary ( m_spCim32NetApiHandle );
|
|
m_spCim32NetApiHandle = NULL;
|
|
}
|
|
}
|
|
|
|
CCim32NetApi* HoldSingleCim32NetPtr::GetCim32NetApiPtr()
|
|
{
|
|
CCim32NetApi* pNewCim32NetApi = NULL ;
|
|
{
|
|
// Avoid contention on static
|
|
CLockWrapper Cim32NetLock( m_csCim32Net ) ;
|
|
|
|
// Check for race condition
|
|
if (m_spCim32NetApiHandle == NULL)
|
|
{
|
|
m_spCim32NetApiHandle = LoadLibrary ( "Cim32Net.dll" ) ;
|
|
}
|
|
|
|
if (m_spCim32NetApiHandle != NULL)
|
|
{
|
|
pNewCim32NetApi = (CCim32NetApi*) CResourceManager::sm_TheResourceManager.GetResource(g_guidCim32NetApi, NULL);
|
|
}
|
|
else
|
|
{
|
|
LogErrorMessage2(L"Failed to loadlibrary Cim32Net.dll (0x%x)", GetLastError());
|
|
}
|
|
}
|
|
|
|
return pNewCim32NetApi;
|
|
}
|
|
|
|
HoldSingleCim32NetPtr g_GlobalInstOfHoldSingleCim32NetPtr;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
class CInitDllUtilsData
|
|
{
|
|
public:
|
|
CInitDllUtilsData();
|
|
};
|
|
|
|
CInitDllUtilsData::CInitDllUtilsData()
|
|
{
|
|
OSVERSIONINFO version = { sizeof(version) };
|
|
|
|
GetVersionEx((LPOSVERSIONINFO) &version);
|
|
|
|
g_dwMajorVersion = version.dwMajorVersion;
|
|
g_dwMinorVersion = version.dwMinorVersion;
|
|
g_dwBuildNumber = version.dwBuildNumber;
|
|
}
|
|
|
|
// So we can cache OS info automatically.
|
|
static CInitDllUtilsData dllUtilsData;
|
|
|
|
#ifdef NTONLY
|
|
// sets a status object with one single missing privilege
|
|
void WINAPI 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)
|
|
{
|
|
try
|
|
{
|
|
long index = 0;
|
|
bstr_t privilege(pPrivilege);
|
|
if(SUCCEEDED(SafeArrayPutElement(psaPrivilegesReqd, &index, (void*)(BSTR)privilege)))
|
|
if(SUCCEEDED(SafeArrayPutElement(psaPrivilegesNotHeld, &index, (void*)(BSTR)privilege)))
|
|
{
|
|
CWbemProviderGlue::SetStatusObject(pContext, IDS_CimWin32Namespace,
|
|
L"Required privilege not enabled", WBEM_E_FAILED, psaPrivilegesNotHeld, psaPrivilegesReqd);
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
SafeArrayDestroy(psaPrivilegesNotHeld);
|
|
SafeArrayDestroy(psaPrivilegesReqd);
|
|
throw ;
|
|
}
|
|
|
|
SafeArrayDestroy(psaPrivilegesNotHeld);
|
|
SafeArrayDestroy(psaPrivilegesReqd);
|
|
}
|
|
else
|
|
{
|
|
if (psaPrivilegesNotHeld)
|
|
SafeArrayDestroy(psaPrivilegesNotHeld);
|
|
if (psaPrivilegesReqd)
|
|
SafeArrayDestroy(psaPrivilegesReqd);
|
|
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
DWORD WINAPI GetPlatformBuildNumber(void)
|
|
{
|
|
return g_dwBuildNumber;
|
|
}
|
|
|
|
// 3 for NT 3.51
|
|
// 4 for NT 4.0, W95 & W98
|
|
DWORD WINAPI GetPlatformMajorVersion(void)
|
|
{
|
|
return g_dwMajorVersion;
|
|
}
|
|
|
|
// 0 for W95, 10 for 98
|
|
DWORD WINAPI GetPlatformMinorVersion(void)
|
|
{
|
|
return g_dwMajorVersion;
|
|
}
|
|
|
|
#ifdef WIN9XONLY
|
|
// returns TRUE iff the current OS is Win 98+
|
|
// false for NT or Win 95
|
|
bool WINAPI IsWin95(void)
|
|
{
|
|
return g_dwMinorVersion == 0;
|
|
}
|
|
|
|
bool WINAPI IsWin98(void)
|
|
{
|
|
return g_dwMinorVersion >= 10;
|
|
}
|
|
|
|
bool WINAPI IsMillennium(void)
|
|
{
|
|
return g_dwMinorVersion >= 90;
|
|
}
|
|
#endif
|
|
|
|
#ifdef NTONLY
|
|
bool WINAPI IsWinNT52(void)
|
|
{
|
|
return (g_dwMajorVersion >= 5 && g_dwMinorVersion == 2);
|
|
}
|
|
|
|
bool WINAPI IsWinNT51(void)
|
|
{
|
|
return (g_dwMajorVersion >= 5 && g_dwMinorVersion == 1);
|
|
}
|
|
|
|
bool WINAPI IsWinNT5(void)
|
|
{
|
|
return g_dwMajorVersion >= 5;
|
|
}
|
|
|
|
bool WINAPI IsWinNT4(void)
|
|
{
|
|
return g_dwMajorVersion == 4;
|
|
}
|
|
|
|
bool WINAPI IsWinNT351(void)
|
|
{
|
|
return g_dwMajorVersion == 3 && g_dwMinorVersion == 51;
|
|
}
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
void WINAPI LogEnumValueError( LPCWSTR szFile, DWORD dwLine, LPCWSTR szKey, LPCWSTR szId )
|
|
{
|
|
if (IsErrorLoggingEnabled())
|
|
{
|
|
CHString gazotta;
|
|
gazotta.Format(ERR_REGISTRY_ENUM_VALUE_FOR_KEY, szId, szKey);
|
|
LogErrorMessageEx(gazotta, szFile, dwLine);
|
|
}
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
void WINAPI LogOpenRegistryError( LPCWSTR szFile, DWORD dwLine, LPCWSTR szKey )
|
|
{
|
|
if (IsErrorLoggingEnabled())
|
|
{
|
|
CHString gazotta;
|
|
gazotta.Format(ERR_OPEN_REGISTRY, szKey);
|
|
|
|
LogErrorMessageEx(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 WINAPI LogLastError( LPCTSTR szFile, DWORD dwLine )
|
|
{
|
|
if (IsErrorLoggingEnabled())
|
|
{
|
|
DWORD duhWord = GetLastError();
|
|
CHString gazotta;
|
|
gazotta.Format(IDS_GETLASTERROR, duhWord, duhWord);
|
|
|
|
LogErrorMessageEx(gazotta, TOBSTRT(szFile), dwLine);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
BOOL WINAPI GetValue( CRegistry & Reg,
|
|
LPCWSTR szKey,
|
|
LPCWSTR ValueName,
|
|
CHString * pchsValueBuffer )
|
|
{
|
|
BOOL bRet = (Reg.GetCurrentKeyValue( ValueName, *pchsValueBuffer) == ERROR_SUCCESS);
|
|
|
|
if( !bRet )
|
|
LogEnumValueError(_T2(__FILE__), __LINE__, szKey, ValueName);
|
|
|
|
return bRet;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
BOOL WINAPI GetValue( CRegistry & Reg,
|
|
LPCWSTR szKey,
|
|
LPCWSTR ValueName,
|
|
DWORD * dwValueBuffer )
|
|
{
|
|
BOOL bRet = (Reg.GetCurrentKeyValue( ValueName, *dwValueBuffer) == ERROR_SUCCESS);
|
|
|
|
if( !bRet )
|
|
LogEnumValueError(_T2(__FILE__),__LINE__, TOBSTRT(szKey), TOBSTRT(ValueName));
|
|
|
|
return bRet;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
BOOL WINAPI OpenAndGetValue( CRegistry & Reg,
|
|
LPCWSTR szKey,
|
|
LPCWSTR ValueName,
|
|
CHString * pchsValueBuffer )
|
|
{
|
|
BOOL bRet = ( Reg.OpenLocalMachineKeyAndReadValue( szKey, ValueName, *pchsValueBuffer )== ERROR_SUCCESS);
|
|
|
|
if( !bRet )
|
|
LogEnumValueError(_T2(__FILE__),__LINE__, szKey, ValueName);
|
|
|
|
return bRet;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////
|
|
BOOL WINAPI GetBinaryValue( CRegistry & Reg, LPCWSTR szKey,
|
|
LPCWSTR ValueName, CHString * pchsValueBuffer )
|
|
{
|
|
BOOL bRet = ( Reg.GetCurrentBinaryKeyValue( ValueName, *pchsValueBuffer) == ERROR_SUCCESS);
|
|
|
|
if( !bRet )
|
|
(LogEnumValueError(_T2(__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 :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifdef WIN9XONLY
|
|
BOOL WINAPI 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;
|
|
|
|
// While the docs say failure will set carry, experience shows
|
|
// this isn't true. So, if carry is clear, and ax is zero, we'll
|
|
// assume that things are ok.
|
|
if (reg.reg_EAX == 0)
|
|
return TRUE;
|
|
|
|
// If they didn't change the value, we'll assume that they followed
|
|
// the spec and are correctly setting carry.
|
|
if (reg.reg_EAX == 0x440d)
|
|
return TRUE;
|
|
|
|
// Otherwise, assume they are incorrectly setting carry, and have returned
|
|
// a failure code.
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : GetDeviceParmsFat32
|
|
*
|
|
* DESCRIPTION : Gets drive characteristics (heads, tracks, cylinders, etc)
|
|
* for Fat32 drives.
|
|
*
|
|
* INPUTS : Pointer to a EA_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 :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifdef WIN9XONLY
|
|
BOOL WINAPI GetDeviceParmsFat32(PEA_DEVICEPARAMETERS 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 = 0x4860; /* Get Media ID command */
|
|
reg.reg_EDX = (DWORD) pstDeviceParms;
|
|
|
|
memset(pstDeviceParms, 0, sizeof(EA_DEVICEPARAMETERS));
|
|
|
|
if (!VWIN32IOCTL(®, VWIN32_DIOC_DOS_IOCTL))
|
|
return FALSE;
|
|
|
|
if (reg.reg_Flags & 0x8000) /* error if carry flag set */
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* 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 :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifdef WIN9XONLY
|
|
BOOL WINAPI 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;
|
|
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* 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 :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifdef WIN9XONLY
|
|
BOOL WINAPI 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;
|
|
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* 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 :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifdef WIN9XONLY
|
|
BOOL WINAPI VWIN32IOCTL(PDEVIOCTL_REGISTERS preg, DWORD dwCall)
|
|
{
|
|
|
|
BOOL fResult;
|
|
DWORD cb;
|
|
|
|
preg->reg_Flags = 0x8000; /* assume error (carry flag set) */
|
|
|
|
SmartCloseHandle hDevice = CreateFile(_T("\\\\.\\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);
|
|
}
|
|
|
|
if (!fResult)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
CHString WINAPI GetFileTypeDescription(LPCTSTR szExtension)
|
|
{
|
|
CRegistry RegInfo;
|
|
CHString sTemp, sType(szExtension);
|
|
|
|
if (RegInfo.Open(HKEY_CLASSES_ROOT, TOBSTRT(szExtension), KEY_READ) == ERROR_SUCCESS) {
|
|
RegInfo.GetCurrentKeyValue(L"", sTemp);
|
|
|
|
if (RegInfo.Open(HKEY_CLASSES_ROOT, sTemp, KEY_READ) == ERROR_SUCCESS) {
|
|
RegInfo.GetCurrentKeyValue(L"", sType);
|
|
}
|
|
}
|
|
|
|
return sType;
|
|
}
|
|
|
|
void WINAPI ConfigStatusToCimStatus ( DWORD a_Status , CHString &a_StringStatus )
|
|
{
|
|
if( a_Status & DN_ROOT_ENUMERATED ||
|
|
a_Status & DN_DRIVER_LOADED ||
|
|
a_Status & DN_ENUM_LOADED ||
|
|
a_Status & DN_STARTED )
|
|
{
|
|
a_StringStatus = IDS_STATUS_OK;
|
|
}
|
|
|
|
// we don't care about these:
|
|
// DN_MANUAL,DN_NOT_FIRST_TIME,DN_HARDWARE_ENUM,DN_FILTERED
|
|
// DN_DISABLEABLE, DN_REMOVABLE,DN_MF_PARENT,DN_MF_CHILD
|
|
// DN_NEED_TO_ENUM, DN_LIAR,DN_HAS_MARK
|
|
|
|
if( a_Status & DN_MOVED ||
|
|
a_Status & DN_WILL_BE_REMOVED)
|
|
{
|
|
a_StringStatus = IDS_STATUS_Degraded;
|
|
}
|
|
|
|
if( a_Status & DN_HAS_PROBLEM ||
|
|
a_Status & DN_PRIVATE_PROBLEM)
|
|
{
|
|
a_StringStatus = IDS_STATUS_Error;
|
|
}
|
|
}
|
|
|
|
#ifdef NTONLY
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 WINAPI 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;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
#ifdef NTONLY
|
|
bool WINAPI GetServiceStatus( CHString a_chsService, CHString &a_chsStatus )
|
|
{
|
|
bool t_bRet = false ;
|
|
SC_HANDLE t_hDBHandle = NULL ;
|
|
SC_HANDLE t_hSvcHandle = NULL ;
|
|
|
|
try
|
|
{
|
|
if( t_hDBHandle = OpenSCManager( NULL, NULL, GENERIC_READ ) )
|
|
{
|
|
t_bRet = true ;
|
|
|
|
if( t_hSvcHandle = OpenService (
|
|
t_hDBHandle,
|
|
a_chsService,
|
|
SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE ) )
|
|
{
|
|
SERVICE_STATUS t_StatusInfo ;
|
|
if ( ControlService( t_hSvcHandle, SERVICE_CONTROL_INTERROGATE, &t_StatusInfo ) )
|
|
{
|
|
switch( t_StatusInfo.dwCurrentState )
|
|
{
|
|
case SERVICE_STOPPED:
|
|
{
|
|
a_chsStatus = L"Degraded" ;
|
|
}
|
|
break ;
|
|
|
|
case SERVICE_START_PENDING:
|
|
{
|
|
a_chsStatus = L"Starting" ;
|
|
}
|
|
break ;
|
|
|
|
case SERVICE_STOP_PENDING:
|
|
{
|
|
a_chsStatus = L"Stopping" ;
|
|
}
|
|
break ;
|
|
|
|
case SERVICE_RUNNING:
|
|
case SERVICE_PAUSE_PENDING:
|
|
{
|
|
a_chsStatus = L"OK" ;
|
|
}
|
|
break ;
|
|
|
|
case SERVICE_PAUSED:
|
|
case SERVICE_CONTINUE_PENDING:
|
|
{
|
|
a_chsStatus = L"Degraded" ;
|
|
}
|
|
break ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
a_chsStatus = L"Unknown" ;
|
|
}
|
|
|
|
CloseServiceHandle( t_hSvcHandle ) ;
|
|
t_hSvcHandle = NULL ;
|
|
}
|
|
else
|
|
{
|
|
a_chsStatus = L"Unknown" ;
|
|
}
|
|
|
|
CloseServiceHandle( t_hDBHandle ) ;
|
|
t_hDBHandle = NULL ;
|
|
}
|
|
}
|
|
catch( ... )
|
|
{
|
|
if( t_hSvcHandle )
|
|
{
|
|
CloseServiceHandle( t_hSvcHandle ) ;
|
|
}
|
|
|
|
if( t_hDBHandle )
|
|
{
|
|
CloseServiceHandle( t_hDBHandle ) ;
|
|
}
|
|
|
|
throw ;
|
|
}
|
|
return t_bRet ;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
bool WINAPI GetFileInfoBlock(LPCTSTR szFile, LPVOID *pInfo)
|
|
{
|
|
BOOL fRet = false;
|
|
DWORD dwTemp,
|
|
dwBlockSize;
|
|
LPVOID pInfoTemp = NULL;
|
|
|
|
if(pInfo != NULL)
|
|
{
|
|
try
|
|
{
|
|
CAutoLock cs(g_CSFlakyFileVersionAPI);
|
|
dwBlockSize = GetFileVersionInfoSize((LPTSTR) szFile, &dwTemp);
|
|
if(dwBlockSize)
|
|
{
|
|
pInfoTemp = (LPVOID) new BYTE[dwBlockSize + 4];
|
|
if(pInfoTemp != NULL)
|
|
{
|
|
memset( pInfoTemp, NULL, dwBlockSize + 4);
|
|
if (GetFileVersionInfo((LPTSTR) szFile, 0, dwBlockSize, pInfoTemp))
|
|
{
|
|
*pInfo = pInfoTemp;
|
|
fRet = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
// We don't need to do anything else, just need to protect ourselves
|
|
// from the flaky version.dll calls.
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
bool WINAPI GetVarFromInfoBlock(LPVOID pInfo, LPCTSTR szVar, CHString &strValue)
|
|
{
|
|
bool fRet = false;
|
|
|
|
try
|
|
{
|
|
if(pInfo != NULL)
|
|
{
|
|
WORD wLang = 0;
|
|
WORD wCodePage = 0;
|
|
UINT len;
|
|
if(!GetVersionLanguage(pInfo, &wLang, &wCodePage) )
|
|
{
|
|
// on failure: default to English
|
|
// this returns a pointer to an array of WORDs
|
|
WORD *pArray;
|
|
if (VerQueryValue(pInfo, _T("\\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;
|
|
TCHAR szTemp[256];
|
|
StringCchPrintf(szTemp,LENGTH_OF(szTemp), _T("\\StringFileInfo\\%04X%04X\\%s"), wLang, wCodePage, szVar);
|
|
|
|
if( VerQueryValue(pInfo, szTemp, (void **)(&pMfg), &len))
|
|
{
|
|
strValue = pMfg;
|
|
fRet = true;
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
// We don't need to do anything else, just need to protect ourselves
|
|
// from the flaky version.dll calls.
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
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 WINAPI GetVersionLanguage(void *vpInfo, WORD *wpLang, WORD *wpCodePage)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
*wpLang = 0;
|
|
*wpCodePage = 0;
|
|
|
|
if ( vpInfo )
|
|
{
|
|
VERHEAD* pVerInfo = NULL;
|
|
pVerInfo = (VERHEAD*) vpInfo;
|
|
|
|
BYTE* ptr = NULL;
|
|
ptr = (BYTE*) &pVerInfo->vsf;
|
|
ptr = ptr + pVerInfo->wValLen;
|
|
|
|
if ( pVerInfo->wType == 0 || pVerInfo->wType == 1 )
|
|
{
|
|
StringFileInfo* pStringFileInfo = NULL;
|
|
pStringFileInfo = (StringFileInfo*) ptr;
|
|
|
|
if ( pStringFileInfo->wValueLength == 0 )
|
|
{
|
|
if ( wcscmp(L"StringFileInfo",pStringFileInfo->szKey) == 0 )
|
|
{
|
|
// OK! were aligned properly
|
|
StringTable* pStringTable = NULL;
|
|
pStringTable = (StringTable*) &pStringFileInfo->Children;
|
|
|
|
if ( pStringTable->wValueLength == 0 )
|
|
{
|
|
swscanf(pStringTable->szKey, L"%4x%4x", wpLang, wpCodePage);
|
|
|
|
if ( *wpLang && *wpCodePage )
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ptr = ptr+4;
|
|
|
|
if ( strcmp("StringFileInfo",reinterpret_cast < char* > (ptr) ) == 0 )
|
|
{
|
|
// OK! were aligned properly
|
|
ptr = ptr+20;
|
|
sscanf(reinterpret_cast < char* > (ptr), "%4x%4x", wpLang, wpCodePage);
|
|
|
|
if ( *wpLang && *wpCodePage )
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
bool WINAPI GetManufacturerFromFileName(LPCTSTR szFile, CHString &strMfg)
|
|
{
|
|
LPVOID lpv = NULL;
|
|
bool fRet = false;
|
|
try
|
|
{
|
|
if(GetFileInfoBlock(szFile, &lpv) && (lpv != NULL))
|
|
{
|
|
fRet = GetVarFromInfoBlock(lpv, _T("CompanyName"), strMfg);
|
|
delete lpv;
|
|
lpv = NULL;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
if(lpv != NULL)
|
|
{
|
|
delete lpv;
|
|
lpv = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
bool WINAPI GetVersionFromFileName(LPCTSTR szFile, CHString &strVersion)
|
|
{
|
|
LPVOID lpv = NULL;
|
|
bool fRet = false;
|
|
try
|
|
{
|
|
if(GetFileInfoBlock(szFile, &lpv) && (lpv != NULL))
|
|
{
|
|
fRet = GetVarFromInfoBlock(lpv, _T("ProductVersion"), strVersion);
|
|
delete lpv;
|
|
lpv = NULL;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
if(lpv != NULL)
|
|
{
|
|
delete lpv;
|
|
lpv = NULL;
|
|
}
|
|
throw;
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
void WINAPI ReplaceString(CHString &str, LPCWSTR szFind, LPCWSTR szReplace)
|
|
{
|
|
int iWhere,
|
|
nLen = lstrlenW(szFind);
|
|
|
|
while ((iWhere = str.Find(szFind)) != -1)
|
|
{
|
|
str.Format(
|
|
L"%s%s%s",
|
|
(LPCWSTR) str.Left(iWhere),
|
|
szReplace,
|
|
(LPCWSTR) str.Mid(iWhere + nLen));
|
|
}
|
|
}
|
|
|
|
#ifdef NTONLY
|
|
BOOL WINAPI GetServiceFileName(LPCTSTR szService, CHString &strFileName)
|
|
{
|
|
SmartCloseServiceHandle 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(_T("\\SYSTEMROOT\\")) == 0)
|
|
ReplaceString(strFileName, _T("\\SYSTEMROOT\\"), _T("%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(_T("%%SystemRoot%%\\%s"), (LPCTSTR) strFileName);
|
|
strFileName = strTemp;
|
|
}
|
|
|
|
TCHAR szOut[MAX_PATH * 2];
|
|
|
|
ExpandEnvironmentStrings(strFileName, szOut, sizeof(szOut) / sizeof(TCHAR));
|
|
strFileName = szOut;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// 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 WINAPI 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(UNRECOGNIZED_VARIANT_TYPE);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// map standard API return values (defined WinError.h)
|
|
// to WBEMish hresults (defined in WbemCli.h)
|
|
HRESULT WINAPI 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_INVALID_PRINTER_NAME:
|
|
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 WINAPI 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(IDS_ConfigManagerErrorCode, dwProblem);
|
|
|
|
pInstance->SetDWORD(IDS_ConfigManagerUserConfig,
|
|
pDevice->IsUsingForcedConfig());
|
|
}
|
|
|
|
#ifdef NTONLY
|
|
BOOL WINAPI 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 (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES |
|
|
TOKEN_QUERY, FALSE, &hToken))
|
|
{
|
|
|
|
{
|
|
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);
|
|
}
|
|
else
|
|
{
|
|
dwLastError = ::GetLastError();
|
|
}
|
|
|
|
// We have to check GetLastError() because AdjustTokenPrivileges lies about
|
|
// its success but GetLastError() doesn't.
|
|
return bRet && dwLastError == ERROR_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
// 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");
|
|
#ifdef WIN9XONLY
|
|
BYTE WINAPI GetBiosUnitNumberFromPNPID(CHString strDeviceID)
|
|
{
|
|
CHString sTemp;
|
|
DRIVE_MAP_INFO stDMI;
|
|
CRegistry Reg1;
|
|
|
|
BYTE btBiosUnit = -1;
|
|
|
|
// Open the associated registry key
|
|
if (Reg1.Open(HKEY_LOCAL_MACHINE, _T("enum\\") + strDeviceID, KEY_QUERY_VALUE) == ERROR_SUCCESS)
|
|
{
|
|
|
|
// Get a drive letter for this pnp id
|
|
if ((Reg1.GetCurrentKeyValue(L"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.
|
|
CCim32NetApi* t_pCim32Net = HoldSingleCim32NetPtr::GetCim32NetApiPtr();
|
|
if (t_pCim32Net != NULL)
|
|
{
|
|
#ifndef UNICODE // This function only takes a LPSTR, and only works on 9x anyway.
|
|
btBiosUnit = t_pCim32Net->GetWin9XBiosUnit(TOBSTRT(strDeviceID));
|
|
CResourceManager::sm_TheResourceManager.ReleaseResource(g_guidCim32NetApi, t_pCim32Net);
|
|
t_pCim32Net = NULL;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GetDriveMapInfo(&stDMI, toupper(sTemp[0]) - 'A' + 1))
|
|
{
|
|
btBiosUnit = stDMI.btInt13Unit;
|
|
}
|
|
}
|
|
}
|
|
|
|
return btBiosUnit;
|
|
}
|
|
#endif
|
|
|
|
HRESULT WINAPI GetHKUserNames(CHStringList &list)
|
|
{
|
|
HRESULT hres;
|
|
|
|
// Empty the list.
|
|
list.clear();
|
|
|
|
#ifdef NTONLY
|
|
{
|
|
// 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);
|
|
}
|
|
#endif
|
|
#ifdef WIN9XONLY
|
|
{
|
|
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)
|
|
{
|
|
delete [] szBuff;
|
|
|
|
dwSize *= 2;
|
|
}
|
|
|
|
szBuff = new TCHAR [dwSize];
|
|
|
|
// Out of memory. Get out of loop.
|
|
if (!szBuff)
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
try
|
|
{
|
|
dwBytesRead =
|
|
GetPrivateProfileString(
|
|
_T("Password Lists"),
|
|
NULL,
|
|
_T(""),
|
|
szBuff,
|
|
dwSize / sizeof(TCHAR),
|
|
_T("system.ini"));
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] szBuff;
|
|
throw;
|
|
}
|
|
|
|
} while (dwBytesRead >= dwSize - 2);
|
|
|
|
if (szBuff)
|
|
{
|
|
try
|
|
{
|
|
// 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;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] szBuff;
|
|
throw;
|
|
}
|
|
|
|
// Free the buffer.
|
|
delete [] szBuff;
|
|
|
|
// Add the .DEFAULT name.
|
|
list.push_back(_T(".DEFAULT"));
|
|
}
|
|
else
|
|
// Failed to malloc, so set error code.
|
|
hres = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
#endif
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
VOID WINAPI 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 WINAPI 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 WINAPI RemoveDoubleBackslashes(const CHString& chstrIn, CHString& chstrOut)
|
|
{
|
|
CHString chstrBuildString;
|
|
CHString chstrInCopy = chstrIn;
|
|
BOOL fDone = FALSE;
|
|
LONG lPos = -1;
|
|
while(!fDone)
|
|
{
|
|
lPos = chstrInCopy.Find(L"\\\\");
|
|
if(lPos != -1)
|
|
{
|
|
chstrBuildString += chstrInCopy.Left(lPos);
|
|
chstrBuildString += _T("\\");
|
|
chstrInCopy = chstrInCopy.Mid(lPos+2);
|
|
}
|
|
else
|
|
{
|
|
chstrBuildString += chstrInCopy;
|
|
fDone = TRUE;
|
|
}
|
|
}
|
|
chstrOut = chstrBuildString;
|
|
}
|
|
|
|
CHString WINAPI RemoveDoubleBackslashes(const CHString& chstrIn)
|
|
{
|
|
CHString chstrBuildString;
|
|
CHString chstrInCopy = chstrIn;
|
|
BOOL fDone = FALSE;
|
|
LONG lPos = -1;
|
|
while(!fDone)
|
|
{
|
|
lPos = chstrInCopy.Find(L"\\\\");
|
|
if(lPos != -1)
|
|
{
|
|
chstrBuildString += chstrInCopy.Left(lPos);
|
|
chstrBuildString += _T("\\");
|
|
chstrInCopy = chstrInCopy.Mid(lPos+2);
|
|
}
|
|
else
|
|
{
|
|
chstrBuildString += chstrInCopy;
|
|
fDone = TRUE;
|
|
}
|
|
}
|
|
return chstrBuildString;
|
|
}
|
|
|
|
#ifdef NTONLY
|
|
// helper for StrToSID
|
|
// takes a string, converts to a SID_IDENTIFIER_AUTHORITY
|
|
// returns false if not a valid SID_IDENTIFIER_AUTHORITY
|
|
// contents of identifierAuthority are unrelieable on failure
|
|
bool WINAPI StrToIdentifierAuthority(const CHString& str, SID_IDENTIFIER_AUTHORITY& identifierAuthority)
|
|
{
|
|
bool bRet = false;
|
|
memset(&identifierAuthority, '\0', sizeof(SID_IDENTIFIER_AUTHORITY));
|
|
|
|
DWORD duhWord;
|
|
WCHAR* p = NULL;
|
|
CHString localStr(str);
|
|
|
|
// per KB article Q13132, if identifier authority is greater than 2**32, it's in hex
|
|
if ((localStr[0] == '0') && ((localStr[1] == 'x') || (localStr[1] == 'X')))
|
|
// if it looks hexidecimalish...
|
|
{
|
|
// going to parse this out backwards, chpping two chars off the end at a time
|
|
// first, whack off the 0x
|
|
localStr = localStr.Mid(2);
|
|
|
|
CHString token;
|
|
int nValue =5;
|
|
|
|
bRet = true;
|
|
while (bRet && localStr.GetLength() && (nValue > 0))
|
|
{
|
|
token = localStr.Right(2);
|
|
localStr = localStr.Left(localStr.GetLength() -2);
|
|
duhWord = wcstoul(token, &p, 16);
|
|
|
|
// if strtoul succeeds, the pointer is moved
|
|
if (p != (LPCTSTR)token)
|
|
identifierAuthority.Value[nValue--] = (BYTE)duhWord;
|
|
else
|
|
bRet = false;
|
|
}
|
|
}
|
|
else
|
|
// it looks decimalish
|
|
{
|
|
duhWord = wcstoul(localStr, &p, 10);
|
|
|
|
if (p != (LPCTSTR)localStr)
|
|
// conversion succeeded
|
|
{
|
|
bRet = true;
|
|
identifierAuthority.Value[5] = LOBYTE(LOWORD(duhWord));
|
|
identifierAuthority.Value[4] = HIBYTE(LOWORD(duhWord));
|
|
identifierAuthority.Value[3] = LOBYTE(HIWORD(duhWord));
|
|
identifierAuthority.Value[2] = HIBYTE(HIWORD(duhWord));
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// for input of the form AAA-BBB-CCC
|
|
// will return AAA in token
|
|
// and BBB-CCC in str
|
|
bool WINAPI WhackToken(CHString& str, CHString& token)
|
|
{
|
|
bool bRet = false;
|
|
if (bRet = !str.IsEmpty())
|
|
{
|
|
int index;
|
|
index = str.Find('-');
|
|
|
|
if (index == -1)
|
|
{
|
|
// all that's left is the token, we're done
|
|
token = str;
|
|
str.Empty();
|
|
}
|
|
else
|
|
{
|
|
token = str.Left(index);
|
|
str = str.Mid(index+1);
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
// a string representation of a SID is assumed to be:
|
|
// S-#-####-####-####-####-####-####
|
|
// we will enforce only the S ourselves,
|
|
// The version is not checked
|
|
// everything else will be handed off to the OS
|
|
// caller must free the SID returned
|
|
PSID WINAPI StrToSID(const CHString& sid)
|
|
{
|
|
PSID pSid = NULL;
|
|
if (!sid.IsEmpty() && ((sid[0] == 'S')||(sid[0] == 's')) && (sid[1] == '-'))
|
|
{
|
|
// get a local copy we can play with
|
|
// we'll parse this puppy the easy way
|
|
// by slicing off each token as we find it
|
|
// slow but sure
|
|
// start by slicing off the "S-"
|
|
CHString str(sid.Mid(2));
|
|
CHString token;
|
|
|
|
SID_IDENTIFIER_AUTHORITY identifierAuthority = {0,0,0,0,0,0};
|
|
BYTE nSubAuthorityCount =0; // count of subauthorities
|
|
DWORD dwSubAuthority[8] = {0,0,0,0,0,0,0,0}; // subauthorities
|
|
|
|
// skip version
|
|
WhackToken(str, token);
|
|
// Grab Authority
|
|
if (WhackToken(str, token))
|
|
{
|
|
DWORD duhWord;
|
|
WCHAR* p = NULL;
|
|
bool bDoIt = false;
|
|
|
|
if (StrToIdentifierAuthority(token, identifierAuthority))
|
|
// conversion succeeded
|
|
{
|
|
bDoIt = true;
|
|
|
|
// now fill up the subauthorities
|
|
while (bDoIt && WhackToken(str, token))
|
|
{
|
|
p = NULL;
|
|
duhWord = wcstoul(token, &p, 10);
|
|
|
|
if (p != (LPCTSTR)token)
|
|
{
|
|
dwSubAuthority[nSubAuthorityCount] = duhWord;
|
|
bDoIt = (++nSubAuthorityCount <= 8);
|
|
}
|
|
else
|
|
bDoIt = false;
|
|
} // end while WhackToken
|
|
|
|
if(bDoIt)
|
|
{
|
|
AllocateAndInitializeSid(&identifierAuthority,
|
|
nSubAuthorityCount,
|
|
dwSubAuthority[0],
|
|
dwSubAuthority[1],
|
|
dwSubAuthority[2],
|
|
dwSubAuthority[3],
|
|
dwSubAuthority[4],
|
|
dwSubAuthority[5],
|
|
dwSubAuthority[6],
|
|
dwSubAuthority[7],
|
|
&pSid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return pSid;
|
|
}
|
|
#endif // NTONLY defined
|
|
|
|
|
|
CHString WINAPI GetDateTimeViaFilenameFiletime(LPCTSTR szFilename, FILETIME *pFileTime)
|
|
{
|
|
CHString strDate,
|
|
strRootPath;
|
|
|
|
// UNC path?
|
|
if (szFilename[0] == '\\' && szFilename[1] == '\\')
|
|
{
|
|
LPTSTR szSlash = _tcschr(&szFilename[2], '\\');
|
|
|
|
// If szSlash, we're sitting on 3rd slash of \\server\share\myfile
|
|
if (szSlash)
|
|
{
|
|
szSlash = _tcschr(szSlash + 1, '\\');
|
|
|
|
// If no 4th slash, there's no filename.
|
|
if (szSlash)
|
|
{
|
|
strRootPath = szFilename;
|
|
strRootPath =
|
|
strRootPath.Left(szSlash - szFilename + 1);
|
|
}
|
|
}
|
|
}
|
|
// Drive path?
|
|
else if (szFilename[1] == ':')
|
|
{
|
|
strRootPath = szFilename;
|
|
strRootPath = strRootPath.Left(3);
|
|
}
|
|
|
|
if (!strRootPath.IsEmpty())
|
|
{
|
|
TCHAR szBuffer[MAX_PATH];
|
|
BOOL bNTFS = FALSE;
|
|
|
|
if (GetVolumeInformation(
|
|
TOBSTRT(strRootPath),
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
szBuffer,
|
|
sizeof(szBuffer) / sizeof(TCHAR)) &&
|
|
!lstrcmpi(szBuffer, _T("NTFS")))
|
|
{
|
|
bNTFS = TRUE;
|
|
}
|
|
|
|
strDate = GetDateTimeViaFilenameFiletime(bNTFS, pFileTime);
|
|
}
|
|
|
|
return strDate;
|
|
}
|
|
|
|
CHString WINAPI GetDateTimeViaFilenameFiletime(LPCTSTR szFilename, FT_ENUM ftWhich)
|
|
{
|
|
WIN32_FIND_DATA finddata;
|
|
SmartFindClose hFind = FindFirstFile(szFilename, &finddata);
|
|
CHString strDate;
|
|
|
|
if (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
FILETIME *pFileTime = NULL;
|
|
|
|
switch(ftWhich)
|
|
{
|
|
case FT_CREATION_DATE:
|
|
pFileTime = &finddata.ftCreationTime;
|
|
break;
|
|
|
|
case FT_ACCESSED_DATE:
|
|
pFileTime = &finddata.ftLastAccessTime;
|
|
break;
|
|
|
|
case FT_MODIFIED_DATE:
|
|
pFileTime = &finddata.ftLastWriteTime;
|
|
break;
|
|
|
|
default:
|
|
// Caller must send in a proper enum value.
|
|
ASSERT_BREAK(FALSE);
|
|
break;
|
|
}
|
|
|
|
if (pFileTime)
|
|
strDate = GetDateTimeViaFilenameFiletime(szFilename, pFileTime);
|
|
}
|
|
|
|
return strDate;
|
|
}
|
|
|
|
CHString WINAPI GetDateTimeViaFilenameFiletime(BOOL bNTFS, FILETIME *pFileTime)
|
|
{
|
|
WBEMTime wbemTime(*pFileTime);
|
|
// This is just used as a wrapper. It avoids a try/catch block.
|
|
bstr_t bstrDate(bNTFS ? wbemTime.GetDMTF() : wbemTime.GetDMTFNonNtfs(), false);
|
|
CHString strRet = (LPWSTR) bstrDate;
|
|
|
|
return strRet;
|
|
}
|
|
|
|
// Used to validate a numbered device ID is OK.
|
|
// Example: ValidateNumberedDeviceID("VideoController7", "VideoController", pdwWhich)
|
|
// returns TRUE, pdwWhich = 7.
|
|
// Example: ValidateNumberedDeviceID("BadDeviceID", "VideoController", pdwWhich)
|
|
// returns FALSE, pdwWhich unchanged
|
|
BOOL WINAPI ValidateNumberedDeviceID(LPCWSTR szDeviceID, LPCWSTR szTag, DWORD *pdwWhich)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
int nTagLen = wcslen(szTag);
|
|
|
|
if (wcslen(szDeviceID) > nTagLen)
|
|
{
|
|
CHString strDeviceID;
|
|
DWORD dwWhich = _wtoi(&szDeviceID[nTagLen]);
|
|
|
|
strDeviceID.Format(L"%s%d", szTag, dwWhich);
|
|
|
|
if (!_wcsicmp(szDeviceID, strDeviceID))
|
|
{
|
|
bRet = TRUE;
|
|
*pdwWhich = dwWhich;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// Critical sections used by various
|
|
CCritSec g_csPrinter;
|
|
CCritSec g_csSystemName;
|
|
#ifdef WIN9XONLY
|
|
CCritSec g_csVXD;
|
|
#endif
|
|
|
|
#define STR_BLK_SIZE 256
|
|
#define CHAR_FUDGE 1 // one WCHAR unused is good enough
|
|
BOOL LoadStringW(CHString &sString, UINT nID)
|
|
{
|
|
// try fixed buffer first (to avoid wasting space in the heap)
|
|
WCHAR szTemp[ STR_BLK_SIZE ];
|
|
|
|
int nLen = LoadStringW(nID, szTemp, STR_BLK_SIZE);
|
|
|
|
if (STR_BLK_SIZE - nLen > CHAR_FUDGE)
|
|
{
|
|
sString = szTemp;
|
|
}
|
|
else
|
|
{
|
|
// try buffer size of 512, then larger size until entire string is retrieved
|
|
int nSize = STR_BLK_SIZE;
|
|
|
|
do
|
|
{
|
|
nSize += STR_BLK_SIZE;
|
|
nLen = LoadStringW(nID, sString.GetBuffer(nSize-1), nSize);
|
|
|
|
}
|
|
while (nSize - nLen <= CHAR_FUDGE);
|
|
|
|
sString.ReleaseBuffer();
|
|
}
|
|
|
|
return nLen > 0;
|
|
}
|
|
|
|
void Format(CHString &sString, UINT nFormatID, ...)
|
|
{
|
|
va_list argList;
|
|
va_start(argList, nFormatID);
|
|
|
|
CHString strFormat;
|
|
|
|
LoadStringW(strFormat, nFormatID);
|
|
|
|
sString.FormatV(strFormat, argList);
|
|
va_end(argList);
|
|
}
|
|
|
|
void FormatMessageW(CHString &sString, UINT nFormatID, ...)
|
|
{
|
|
// get format string from string table
|
|
CHString strFormat;
|
|
|
|
LoadStringW(strFormat, nFormatID);
|
|
|
|
// format message into temporary buffer lpszTemp
|
|
va_list argList;
|
|
va_start(argList, nFormatID);
|
|
|
|
#ifdef NTONLY
|
|
LPWSTR lpszTemp;
|
|
|
|
if (::FormatMessageW(
|
|
FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
(LPCWSTR) strFormat,
|
|
0,
|
|
0,
|
|
(LPWSTR) &lpszTemp,
|
|
0,
|
|
&argList) == 0 || lpszTemp == NULL)
|
|
{
|
|
// Should throw memory exception here. Now we do.
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
else
|
|
{
|
|
// assign lpszTemp into the resulting string and free lpszTemp
|
|
sString = lpszTemp;
|
|
LocalFree(lpszTemp);
|
|
va_end(argList);
|
|
}
|
|
#else
|
|
#error Not written for win9x
|
|
#endif
|
|
}
|
|
|
|
int LoadStringW(UINT nID, LPWSTR lpszBuf, UINT nMaxBuf)
|
|
{
|
|
int nLen = 0;
|
|
|
|
#ifdef NTONLY
|
|
nLen = ::LoadStringW(ghModule, nID, lpszBuf, nMaxBuf);
|
|
if (nLen == 0)
|
|
{
|
|
lpszBuf[0] = '\0';
|
|
}
|
|
#else
|
|
#error Not written for win9x
|
|
#endif
|
|
|
|
return nLen; // excluding terminator
|
|
}
|
|
|
|
bool WINAPI DelayLoadDllExceptionFilter(PEXCEPTION_POINTERS pep)
|
|
{
|
|
// We might have thrown as a result of the
|
|
// delay load library mechanism. There are
|
|
// two types of such exceptions - those
|
|
// generated because the dll could not be
|
|
// loaded, and thos generated because the
|
|
// proc address of the function referred to
|
|
// could not be found. We want to log an
|
|
// error message in either case.
|
|
bool fRet = false;
|
|
if(pep &&
|
|
pep->ExceptionRecord)
|
|
{
|
|
// If this is a Delay-load problem, ExceptionInformation[0] points
|
|
// to a DelayLoadInfo structure that has detailed error info
|
|
PDelayLoadInfo pdli = PDelayLoadInfo(
|
|
pep->ExceptionRecord->ExceptionInformation[0]);
|
|
|
|
if(pdli)
|
|
{
|
|
switch(pep->ExceptionRecord->ExceptionCode)
|
|
{
|
|
case VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND):
|
|
{
|
|
// The DLL module was not found at runtime
|
|
LogErrorMessage2(L"Dll not found: %s", pdli->szDll);
|
|
fRet = true;
|
|
break;
|
|
}
|
|
case VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND):
|
|
{
|
|
// The DLL module was found but it doesn't contain the function
|
|
if(pdli->dlp.fImportByName)
|
|
{
|
|
LogErrorMessage3(
|
|
L"Function %s was not found in %s",
|
|
pdli->dlp.szProcName,
|
|
pdli->szDll);
|
|
}
|
|
else
|
|
{
|
|
LogErrorMessage3(
|
|
L"Function ordinal %d was not found in %s",
|
|
pdli->dlp.dwOrdinal,
|
|
pdli->szDll);
|
|
}
|
|
fRet = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
// This is here in common because
|
|
// at least the classes Pagefile and
|
|
// PageFileSetting use it, perhaps
|
|
// more in the future.
|
|
#ifdef NTONLY
|
|
HRESULT CreatePageFile(
|
|
LPCWSTR wstrPageFileName,
|
|
const LARGE_INTEGER liInitial,
|
|
const LARGE_INTEGER liMaximum,
|
|
const CInstance& Instance)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
UNICODE_STRING ustrFileName = { 0 };
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
if(!EnablePrivilegeOnCurrentThread(SE_CREATE_PAGEFILE_NAME))
|
|
{
|
|
SetSinglePrivilegeStatusObject(
|
|
Instance.GetMethodContext(),
|
|
SE_CREATE_PAGEFILE_NAME);
|
|
hr = WBEM_E_ACCESS_DENIED;
|
|
}
|
|
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(!::RtlDosPathNameToNtPathName_U(
|
|
wstrPageFileName,
|
|
&ustrFileName,
|
|
NULL,
|
|
NULL) && ustrFileName.Buffer)
|
|
{
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
LARGE_INTEGER liInit;
|
|
LARGE_INTEGER liMax;
|
|
|
|
liInit.QuadPart = liInitial.QuadPart * 1024 * 1024;
|
|
liMax.QuadPart = liMaximum.QuadPart * 1024 * 1024;
|
|
|
|
if(!NT_SUCCESS(
|
|
status = ::NtCreatePagingFile(
|
|
&ustrFileName,
|
|
&liInit,
|
|
&liMax,
|
|
0)))
|
|
{
|
|
if (STATUS_INVALID_PARAMETER_2 == status)
|
|
hr = WBEM_E_VALUE_OUT_OF_RANGE;
|
|
else
|
|
hr = WinErrorToWBEMhResult(RtlNtStatusToDosError(status));
|
|
}
|
|
}
|
|
|
|
|
|
RtlFreeUnicodeString(&ustrFileName);
|
|
ustrFileName.Buffer = NULL;
|
|
|
|
}
|
|
catch(...)
|
|
{
|
|
RtlFreeUnicodeString(&ustrFileName);
|
|
ustrFileName.Buffer = NULL;
|
|
throw;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
#endif
|
|
|
|
|
|
// Useful for obtaining the localized versions
|
|
// of "All Users" and "Default User".
|
|
#if NTONLY >= 5
|
|
bool GetAllUsersName(CHString& chstrAllUsersName)
|
|
{
|
|
bool fRet = false;
|
|
CRegistry reg;
|
|
CHString chstrTemp;
|
|
|
|
DWORD dwRet = reg.Open(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
|
|
KEY_READ);
|
|
|
|
if(dwRet == ERROR_SUCCESS)
|
|
{
|
|
if(reg.GetCurrentKeyValue(
|
|
L"AllUsersProfile",
|
|
chstrTemp) == ERROR_SUCCESS)
|
|
{
|
|
chstrAllUsersName = chstrTemp.SpanExcluding(L".");
|
|
fRet = true;
|
|
}
|
|
}
|
|
if(!fRet)
|
|
{
|
|
chstrAllUsersName = L"";
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
#endif
|
|
|
|
#if NTONLY >= 5
|
|
bool GetDefaultUsersName(CHString& chstrDefaultUsersName)
|
|
{
|
|
bool fRet = false;
|
|
CRegistry reg;
|
|
CHString chstrTemp;
|
|
|
|
DWORD dwRet = reg.Open(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
|
|
KEY_READ);
|
|
|
|
if(dwRet == ERROR_SUCCESS)
|
|
{
|
|
if(reg.GetCurrentKeyValue(
|
|
L"DefaultUserProfile",
|
|
chstrTemp) == ERROR_SUCCESS)
|
|
{
|
|
chstrDefaultUsersName = chstrTemp.SpanExcluding(L".");
|
|
fRet = true;
|
|
}
|
|
}
|
|
if(!fRet)
|
|
{
|
|
chstrDefaultUsersName = L"";
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if NTONLY >= 5
|
|
bool GetCommonStartup(CHString& chstrCommonStartup)
|
|
{
|
|
bool fRet = false;
|
|
CRegistry reg;
|
|
CHString chstrTemp;
|
|
|
|
DWORD dwRet = reg.Open(
|
|
HKEY_LOCAL_MACHINE,
|
|
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
|
|
KEY_READ);
|
|
|
|
if(dwRet == ERROR_SUCCESS)
|
|
{
|
|
if(reg.GetCurrentKeyValue(
|
|
L"Common Startup",
|
|
chstrTemp) == ERROR_SUCCESS)
|
|
{
|
|
int iPos = chstrTemp.ReverseFind(L'\\');
|
|
if(iPos != -1)
|
|
{
|
|
chstrCommonStartup = chstrTemp.Mid(iPos+1);
|
|
fRet = true;
|
|
}
|
|
}
|
|
}
|
|
if(!fRet)
|
|
{
|
|
chstrCommonStartup = L"";
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
#endif
|
|
|
|
BOOL GetLocalizedNTAuthorityString(
|
|
CHString& chstrNT_AUTHORITY)
|
|
{
|
|
BOOL fRet = false;
|
|
SID_IDENTIFIER_AUTHORITY siaNTSidAuthority = SECURITY_NT_AUTHORITY;
|
|
CSid csidAccountSid;
|
|
|
|
if(GetSysAccountNameAndDomain(
|
|
&siaNTSidAuthority,
|
|
csidAccountSid,
|
|
1,
|
|
SECURITY_NETWORK_SERVICE_RID))
|
|
{
|
|
chstrNT_AUTHORITY = csidAccountSid.GetDomainName();
|
|
fRet = TRUE;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL GetLocalizedBuiltInString(
|
|
CHString& chstrBuiltIn)
|
|
{
|
|
BOOL fRet = false;
|
|
SID_IDENTIFIER_AUTHORITY siaNTSidAuthority = SECURITY_NT_AUTHORITY;
|
|
CSid csidAccountSid;
|
|
|
|
if(GetSysAccountNameAndDomain(
|
|
&siaNTSidAuthority,
|
|
csidAccountSid,
|
|
1,
|
|
SECURITY_BUILTIN_DOMAIN_RID))
|
|
{
|
|
chstrBuiltIn = csidAccountSid.GetDomainName();
|
|
fRet = TRUE;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL GetSysAccountNameAndDomain(
|
|
PSID_IDENTIFIER_AUTHORITY a_pAuthority,
|
|
CSid& a_accountsid,
|
|
BYTE a_saCount /*=0*/,
|
|
DWORD a_dwSubAuthority1 /*=0*/,
|
|
DWORD a_dwSubAuthority2 /*=0*/ )
|
|
{
|
|
BOOL t_fReturn = FALSE;
|
|
PSID t_psid = NULL;
|
|
|
|
if ( AllocateAndInitializeSid( a_pAuthority,
|
|
a_saCount,
|
|
a_dwSubAuthority1,
|
|
a_dwSubAuthority2,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
&t_psid ) )
|
|
{
|
|
try
|
|
{
|
|
CSid t_sid( t_psid ) ;
|
|
|
|
// The SID may be valid in this case, however the Lookup may have failed
|
|
if ( t_sid.IsValid() && t_sid.IsOK() )
|
|
{
|
|
a_accountsid = t_sid;
|
|
t_fReturn = TRUE;
|
|
}
|
|
|
|
}
|
|
catch( ... )
|
|
{
|
|
if( t_psid )
|
|
{
|
|
FreeSid( t_psid ) ;
|
|
}
|
|
throw ;
|
|
}
|
|
|
|
// Cleanup the sid
|
|
FreeSid( t_psid ) ;
|
|
}
|
|
|
|
return t_fReturn;
|
|
}
|