Leaked source code of windows server 2003
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

//=================================================================
//
// 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(&reg, '\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(&reg, 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(&reg, '\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(&reg, 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(&reg, '\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(&reg, 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(&reg, '\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(&reg, 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;
}