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.
 
 
 
 
 
 

915 lines
21 KiB

// Utils.cpp: implementation of the CGenericClass class.
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
//////////////////////////////////////////////////////////////////////
#include "precomp.h"
char * WcharToTchar(WCHAR * wcPtr, char * tcTmp)
{
WideCharToMultiByte(CP_OEMCP, WC_COMPOSITECHECK, wcPtr, (-1), tcTmp, BUFF_SIZE, NULL, NULL);
return tcTmp;
}
WCHAR * TcharToWchar(char * tcPtr, WCHAR * wcTmp)
{
MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, tcPtr, (-1), wcTmp, BUFF_SIZE);
return wcTmp;
}
WCHAR * TcharToWchar(const char * tcPtr, WCHAR * wcTmp)
{
MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, tcPtr, (-1), wcTmp, BUFF_SIZE);
return wcTmp;
}
HRESULT ConvertError(UINT uiStatus)
{
switch(uiStatus){
case ERROR_INSTALL_ALREADY_RUNNING:
return WBEM_E_ACCESS_DENIED;
case ERROR_ACCESS_DENIED:
return WBEM_E_PRIVILEGE_NOT_HELD;
case E_OUTOFMEMORY:
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
return WBEM_E_OUT_OF_MEMORY;
default:
return WBEM_E_FAILED;
}
}
WCHAR * EscapeStringW(WCHAR * wcIn, WCHAR * wcOut)
{
wcOut [ 0 ] = 0;
DWORD dwLenghtIn = 0L;
dwLenghtIn = lstrlenW ( wcIn );
WCHAR wcTmp[BUFF_SIZE] = { L'\0' };
wcscpy(wcTmp, wcIn);
WCHAR * wcp = wcTmp;
DWORD dwNumber = 0L;
while ( *wcp )
{
if ( *wcp == L'\\' || *wcp == L'\"' )
{
dwNumber++;
}
wcp++;
}
if ( BUFF_SIZE > ( dwLenghtIn + dwNumber * 2 ) )
{
wcp = wcTmp;
while ( *wcp )
{
switch ( *wcp )
{
case L'\\':
*wcp = NULL;
wcscpy(wcOut, wcTmp);
wcscat(wcOut, L"\\\\");
wcscat(wcOut, (wcp + 1));
wcscpy(wcTmp, wcOut);
wcp++;
break;
case L'\"':
*wcp = NULL;
wcscpy(wcOut, wcTmp);
wcscat(wcOut, L"\\\"");
wcscat(wcOut, (wcp + 1));
wcscpy(wcTmp, wcOut);
wcp++;
break;
default:
break;
}
wcp++;
}
}
return wcOut;
}
void SoftwareElementState(INSTALLSTATE piInstalled, int *iState)
{
switch(piInstalled){
case INSTALLSTATE_ABSENT:
*iState = 0;
break;
case INSTALLSTATE_BADCONFIG:
*iState = 0;
break;
case INSTALLSTATE_INVALIDARG:
*iState = 0;
break;
case INSTALLSTATE_LOCAL:
*iState = 2;
break;
case INSTALLSTATE_SOURCE:
*iState = 1;
break;
case INSTALLSTATE_SOURCEABSENT:
*iState = 0;
break;
case INSTALLSTATE_UNKNOWN:
*iState = 0;
break;
default:
*iState = 0;
}
}
// string am getting is BUF_SIZE ( statically allocated )
bool CreateProductString(WCHAR *wcProductCode, WCHAR *wcProductPath)
{
DWORD dwBufSize;
WCHAR wcBuf[BUFF_SIZE];
#if !defined(_UNICODE)
WCHAR wcTmp[BUFF_SIZE];
#endif
bool bResult = false;
// safe operation
wcscpy(wcProductPath, L"Win32_Product.IdentifyingNumber=\"");
if ( wcslen ( wcProductPath ) +
wcslen ( L"\",Name=\"" )
< BUFF_SIZE
)
{
wcscat(wcProductPath, wcProductCode);
wcscat(wcProductPath, L"\",Name=\"");
dwBufSize = BUFF_SIZE;
#if defined(_UNICODE)
if(g_fpMsiGetProductInfoW(wcProductCode, INSTALLPROPERTY_PRODUCTNAME,
#else
if(g_fpMsiGetProductInfoW(wcProductCode, TcharToWchar(INSTALLPROPERTY_PRODUCTNAME, wcTmp),
#endif
wcBuf, &dwBufSize) == ERROR_SUCCESS)
{
if ( wcslen (wcProductPath) +
wcslen (wcBuf) +
wcslen (L"\",Version=\"")
< BUFF_SIZE
)
{
wcscat(wcProductPath, wcBuf);
wcscat(wcProductPath, L"\",Version=\"");
dwBufSize = BUFF_SIZE;
#if defined(_UNICODE)
if(g_fpMsiGetProductInfoW(wcProductCode, INSTALLPROPERTY_VERSIONSTRING,
#else
if(g_fpMsiGetProductInfoW(wcProductCode, TcharToWchar(INSTALLPROPERTY_VERSIONSTRING, wcTmp),
#endif
wcBuf, &dwBufSize) == ERROR_SUCCESS)
{
if ( wcslen (wcProductPath) +
wcslen (wcBuf) +
1
< BUFF_SIZE
)
{
wcscat(wcProductPath, wcBuf);
wcscat(wcProductPath, L"\"");
bResult = true;
}
}
else
{
dwBufSize = BUFF_SIZE;
if(ERROR_SUCCESS == g_fpMsiGetProductInfoW(wcProductCode,
#if defined(_UNICODE)
INSTALLPROPERTY_VERSION, wcBuf, &dwBufSize))
{
#else
TcharToWchar(INSTALLPROPERTY_VERSION, wcTmp), wcBuf, &dwBufSize))
{
#endif
if ( wcslen (wcProductPath) +
wcslen (wcBuf) +
1
< BUFF_SIZE
)
{
wcscat(wcProductPath, wcBuf);
wcscat(wcProductPath, L"\"");
bResult = true;
}
}
}
}
}
}
return bResult;
}
DWORD CreateSoftwareElementString ( MSIHANDLE hDatabase, WCHAR *wcComponent, WCHAR *wcProductCode, WCHAR *wcPath, DWORD * dwPath )
{
DWORD dwResult = static_cast < DWORD > ( E_INVALIDARG );
DWORD dwResultHelp = static_cast < DWORD > ( S_FALSE );
#if !defined(_UNICODE)
WCHAR wcTmp[BUFF_SIZE];
#endif
if ( wcComponent != NULL && wcComponent [ 0 ] != 0 )
{
MSIHANDLE hView = NULL;
MSIHANDLE hRecord = NULL;
DWORD dwBufSize = BUFF_SIZE;
LPWSTR wcBuf = NULL;
LPWSTR wcID = NULL;
LPWSTR wcQuery = NULL;
int iState = 0L;
DWORD dwPathSize = 0;
dwPathSize = * dwPath;
DWORD dwUsed = 1; // last null
try
{
if ( ( wcBuf = new WCHAR [ dwBufSize ] ) == NULL )
{
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
if ( ( wcID = new WCHAR [ dwBufSize ] ) == NULL )
{
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
LPCWSTR wszQuery = L"select distinct `ComponentId` from Component where `Component`=\'";
DWORD dwQuery = 0L;
dwQuery = lstrlenW ( wszQuery ) + lstrlenW ( wcComponent ) + 1 + 1;
if ( ( wcQuery = new WCHAR [ dwQuery ] ) == NULL )
{
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
wcscpy ( wcQuery, wszQuery );
wcscat ( wcQuery, wcComponent );
wcscat ( wcQuery, L"\'" );
if ( ( dwResult = g_fpMsiDatabaseOpenViewW ( hDatabase, wcQuery, &hView ) ) == ERROR_SUCCESS )
{
if ( g_fpMsiViewExecute ( hView, 0 ) == ERROR_SUCCESS )
{
if ( g_fpMsiViewFetch ( hView, &hRecord ) != ERROR_NO_MORE_ITEMS )
{
dwBufSize = BUFF_SIZE;
BOOL bContinue = TRUE;
DWORD dwContinue= 2;
do
{
if ( ( dwResult = g_fpMsiRecordGetStringW ( hRecord, 1, wcID, &dwBufSize ) ) == ERROR_MORE_DATA )
{
delete [] wcID;
wcID = NULL;
if ( ( wcID = new WCHAR [ dwBufSize ] ) == NULL )
{
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
}
else
{
bContinue = FALSE;
}
}
while ( bContinue && dwContinue-- );
if ( dwResult == ERROR_MORE_DATA )
{
dwResult = static_cast < DWORD > ( E_FAIL );
}
if ( dwResult == ERROR_SUCCESS && wcProductCode != NULL && wcProductCode [ 0 ] != 0 )
{
//Check to make sure it's on the system
if ( ValidateComponentID ( wcID, wcProductCode ) )
{
dwUsed = dwUsed +
lstrlenW ( L"Win32_SoftwareElement.Name=\"" ) +
lstrlenW ( wcComponent ) +
lstrlenW ( L"\",SoftwareElementID=\"" ) +
lstrlenW ( wcID ) +
lstrlenW ( L"\",SoftwareElementState=" );
if ( dwUsed > dwPathSize )
{
dwResultHelp = ERROR_MORE_DATA;
}
else
{
wcscpy(wcPath, L"Win32_SoftwareElement.Name=\"");
wcscat(wcPath, wcComponent);
wcscat(wcPath, L"\",SoftwareElementID=\"");
wcscat(wcPath, wcID);
wcscat(wcPath, L"\",SoftwareElementState=");
}
SoftwareElementState ( g_fpMsiGetComponentPathW (
wcProductCode,
wcID,
NULL,
NULL
),
&iState
);
_itow(iState, wcBuf, 10);
dwUsed = dwUsed +
lstrlenW ( wcBuf ) +
lstrlenW ( L"\",SoftwareElementState=\"" );
if ( dwUsed > dwPathSize )
{
dwResultHelp = ERROR_MORE_DATA;
}
else
{
wcscat(wcPath, wcBuf);
wcscat(wcPath, L",TargetOperatingSystem=");
}
_itow(GetOS(), wcBuf, 10);
dwUsed = dwUsed +
lstrlenW ( wcBuf ) +
lstrlenW ( L"\",SoftwareElementState=\"" );
if ( dwUsed > dwPathSize )
{
dwResultHelp = ERROR_MORE_DATA;
}
else
{
wcscat(wcPath, wcBuf);
wcscat(wcPath, L",Version=\"");
}
dwBufSize = BUFF_SIZE;
wcBuf [0] = 0;
bContinue = TRUE;
dwContinue = 2;
do
{
if ( ( dwResult = g_fpMsiGetProductInfoW ( wcProductCode,
#ifdef _UNICODE
INSTALLPROPERTY_VERSIONSTRING,
#else _UNICODE
TcharToWchar(INSTALLPROPERTY_VERSIONSTRING, wcTmp),
#endif _UNICODE
wcBuf,
&dwBufSize
)
) == ERROR_MORE_DATA
)
{
delete [] wcBuf;
wcBuf = NULL;
if ( ( wcBuf = new WCHAR [ dwBufSize + 1 ] ) == NULL )
{
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
dwBufSize = dwBufSize + 1;
}
else
{
bContinue = FALSE;
}
}
while ( bContinue && dwContinue-- );
if ( dwResult == ERROR_MORE_DATA )
{
dwResult = static_cast < DWORD > ( E_FAIL );
}
if ( dwResult == ERROR_SUCCESS )
{
dwUsed = dwUsed +
lstrlenW ( wcBuf ) +
lstrlenW ( L"\"" );
if ( dwUsed > dwPathSize )
{
dwResultHelp = ERROR_MORE_DATA;
}
else
{
wcscat(wcPath, wcBuf);
wcscat(wcPath, L"\"");
dwResult = ERROR_SUCCESS;
}
}
}
else
{
dwResult = static_cast < DWORD > ( E_FAIL );
}
}
}
}
}
else
{
if ( dwResult == E_OUTOFMEMORY )
{
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
}
}
catch ( ... )
{
if ( wcBuf )
{
delete [] wcBuf;
wcBuf = NULL;
}
if ( wcID )
{
delete [] wcID;
wcID = NULL;
}
if ( wcQuery )
{
delete [] wcQuery;
wcQuery = NULL;
}
throw;
}
if ( wcBuf )
{
delete [] wcBuf;
wcBuf = NULL;
}
if ( wcID )
{
delete [] wcID;
wcID = NULL;
}
if ( wcQuery )
{
delete [] wcQuery;
wcQuery = NULL;
}
g_fpMsiCloseHandle(hRecord);
g_fpMsiViewClose(hView);
g_fpMsiCloseHandle(hView);
if ( dwResult == ERROR_SUCCESS && dwResultHelp == ERROR_MORE_DATA )
{
( * dwPath ) = ( * dwPath ) + ( dwUsed - dwPathSize );
wcPath [ 0 ] = 0;
dwResult = dwResultHelp;
}
}
return dwResult;
}
// string am getting is BUF_SIZE ( statically allocated )
bool CreateSoftwareFeatureString(WCHAR *wcName, WCHAR *wcProductCode, WCHAR * wcString, bool bValidate)
{
bool bResult = false;
DWORD dwBufSize;
WCHAR wcBuf[BUFF_SIZE];
#if !defined(_UNICODE)
WCHAR wcTmp[BUFF_SIZE];
#endif
if((bValidate) && (!ValidateFeatureName(wcName, wcProductCode))) return bResult;
// safe operation
wcscpy(wcString, L"Win32_SoftwareFeature.IdentifyingNumber=\"");
if ( wcslen ( wcString ) +
wcslen ( L"\",Name=\"" ) +
wcslen ( wcName ) +
wcslen ( L"\",ProductName=\"" )
< BUFF_SIZE
)
{
wcscat(wcString, wcProductCode);
wcscat(wcString, L"\",Name=\"");
wcscat(wcString, wcName);
wcscat(wcString, L"\",ProductName=\"");
dwBufSize = BUFF_SIZE;
if(g_fpMsiGetProductInfoW(wcProductCode,
#if defined(_UNICODE)
INSTALLPROPERTY_PRODUCTNAME,
#else
TcharToWchar(INSTALLPROPERTY_PRODUCTNAME, wcTmp),
#endif
wcBuf, &dwBufSize) == ERROR_SUCCESS)
{
if ( wcslen (wcString) +
wcslen (wcBuf) +
wcslen (L"\",Version=\"")
< BUFF_SIZE
)
{
wcscat(wcString, wcBuf);
wcscat(wcString, L"\",Version=\"");
dwBufSize = BUFF_SIZE;
if(g_fpMsiGetProductInfoW(wcProductCode,
#if defined(_UNICODE)
INSTALLPROPERTY_VERSIONSTRING,
#else
TcharToWchar(INSTALLPROPERTY_VERSIONSTRING, wcTmp),
#endif
wcBuf, &dwBufSize) == ERROR_SUCCESS)
{
if ( wcslen (wcString) +
wcslen (wcBuf) +
1
< BUFF_SIZE
)
{
wcscat(wcString, wcBuf);
wcscat(wcString, L"\"");
bResult = true;
}
}
else
{
dwBufSize = BUFF_SIZE;
if(ERROR_SUCCESS == g_fpMsiGetProductInfoW(wcProductCode,
#if defined(_UNICODE)
INSTALLPROPERTY_VERSION
#else
TcharToWchar(INSTALLPROPERTY_VERSION, wcTmp)
#endif
, wcBuf, &dwBufSize))
{
if ( wcslen (wcString) +
wcslen (wcBuf) +
1
< BUFF_SIZE
)
{
wcscat(wcString, wcBuf);
wcscat(wcString, L"\"");
bResult = true;
}
}
}
}
}
}
return bResult;
}
// simple helper to ask the age old question
// of what OS are we running on, anyway?
bool AreWeOnNT()
{
OSVERSIONINFO osversion;
osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osversion);
return (osversion.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
int GetOS()
{
OSVERSIONINFO osversion;
int iOS = 19;
osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osversion);
if(osversion.dwPlatformId == VER_PLATFORM_WIN32s) iOS = 16;
else if(osversion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS){
if(osversion.dwMinorVersion == 0) iOS = 17;
else iOS = 18;
}
return iOS;
}
bool IsNT4()
{
OSVERSIONINFO osversion;
int iOS = 19;
osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osversion);
return osversion.dwMajorVersion == 4;
}
bool IsNT5()
{
OSVERSIONINFO osversion;
int iOS = 19;
osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osversion);
return osversion.dwMajorVersion == 5;
}
// checks impersonation level
// impersonates client if allowed
HRESULT CheckImpersonationLevel()
{
HRESULT hr = WBEM_E_ACCESS_DENIED;
if(AreWeOnNT()){
if(SUCCEEDED(CoImpersonateClient())){
// Now, let's check the impersonation level. First, get the thread token
HANDLE hThreadTok;
DWORD dwImp, dwBytesReturned;
if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hThreadTok )){
DWORD dwLastError = GetLastError();
if (dwLastError == ERROR_NO_TOKEN){
// If the CoImpersonate works, but the OpenThreadToken fails due to ERROR_NO_TOKEN, we
// are running under the process token (either local system, or if we are running
// with /exe, the rights of the logged in user). In either case, impersonation rights
// don't apply. We have the full rights of that user.
hr = WBEM_S_NO_ERROR;
}else{
// If we failed to get the thread token for any other reason, an error.
hr = WBEM_E_ACCESS_DENIED;
}
}else{
if(GetTokenInformation(hThreadTok, TokenImpersonationLevel, &dwImp,
sizeof(DWORD), &dwBytesReturned)){
// Is the impersonation level Impersonate?
if (dwImp >= SecurityImpersonation) hr = WBEM_S_NO_ERROR;
else hr = WBEM_E_ACCESS_DENIED;
}else hr = WBEM_E_FAILED;
CloseHandle(hThreadTok);
}
if (FAILED(hr))
{
CoRevertToSelf();
}
}
}else
// let win9X in...
hr = WBEM_S_NO_ERROR;
return hr;
}
bool ValidateComponentID(WCHAR *wcID, WCHAR *wcProductCode)
{
int i = 0;
WCHAR * wcBuf = (WCHAR *)malloc(BUFF_SIZE * sizeof(WCHAR));
if(!wcBuf)
{
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
DWORD dwBufSize;
UINT uiStatus;
INSTALLSTATE isInstalled;
bool bRetVal = false;
dwBufSize = BUFF_SIZE;
isInstalled = g_fpMsiGetComponentPathW(wcProductCode, wcID, wcBuf, &dwBufSize);
// this lines are added for backward compatability ( ! INSTALLSTATE_NOTUSED )
if( isInstalled == INSTALLSTATE_LOCAL ||
isInstalled == INSTALLSTATE_SOURCE ||
isInstalled == INSTALLSTATE_SOURCEABSENT ||
isInstalled == INSTALLSTATE_UNKNOWN ||
isInstalled == INSTALLSTATE_ABSENT
)
{
bRetVal = true;
}
free((void *)wcBuf);
return bRetVal;
}
bool ValidateComponentName ( MSIHANDLE hDatabase, WCHAR *wcProductCode, WCHAR *wcName )
{
bool bResult = false;
if ( wcName != NULL )
{
MSIHANDLE hView = NULL;
MSIHANDLE hRecord = NULL;
LPWSTR wcQuery = NULL;
LPWSTR wcBuf = NULL;
LPCWSTR wszQuery = L"select distinct `ComponentId` from Component where `Component`=\'";
DWORD dwBuf = BUFF_SIZE;
DWORD dwQuery = 0L;
dwQuery = wcslen ( wszQuery ) + wcslen ( wcName ) + 1 + 1;
if ( ( wcQuery = new WCHAR [ dwQuery ] ) == NULL )
{
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
try
{
wcscpy ( wcQuery, wszQuery );
wcscat ( wcQuery, wcName );
wcscat ( wcQuery, L"\'" );
}
catch ( ... )
{
delete [] wcQuery;
wcQuery = NULL;
throw;
}
try
{
if ( ( wcBuf = new WCHAR [ dwBuf ] ) == NULL )
{
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
}
catch ( ... )
{
delete [] wcQuery;
wcQuery = NULL;
throw;
}
HRESULT hRes = S_OK;
if ( ERROR_SUCCESS == ( hRes = g_fpMsiDatabaseOpenViewW ( hDatabase, wcQuery, &hView ) ) )
{
if ( ERROR_SUCCESS == g_fpMsiViewExecute ( hView, 0 ) )
{
if ( ERROR_NO_MORE_ITEMS != ( hRes = g_fpMsiViewFetch ( hView, &hRecord ) ) )
{
if ( E_OUTOFMEMORY == hRes )
{
g_fpMsiCloseHandle(hRecord);
g_fpMsiViewClose(hView);
g_fpMsiCloseHandle(hView);
delete [] wcBuf;
delete [] wcQuery;
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
if ( ERROR_SUCCESS == g_fpMsiRecordGetStringW ( hRecord, 1, wcBuf, &dwBuf ) )
{
//Check to make sure it's on the system
bResult = ValidateComponentID ( wcBuf, wcProductCode );
}
g_fpMsiCloseHandle(hRecord);
}
}
g_fpMsiViewClose(hView);
g_fpMsiCloseHandle(hView);
}
else
{
if ( E_OUTOFMEMORY == hRes )
{
delete [] wcBuf;
delete [] wcQuery;
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
}
delete [] wcBuf;
delete [] wcQuery;
}
return bResult;
}
bool ValidateFeatureName(WCHAR *wcName, WCHAR *wcProduct)
{
int i = 0;
bool bRetVal = false;
WCHAR * wcBuf = (WCHAR *)malloc(BUFF_SIZE * sizeof(WCHAR));
if(!wcBuf)
{
wcBuf = NULL;
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
WCHAR * wcParent = (WCHAR *)malloc(BUFF_SIZE * sizeof(WCHAR));
if(!wcParent)
{
free ( wcBuf );
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
UINT uiStatus;
while((uiStatus = g_fpMsiEnumFeaturesW(wcProduct, i++, wcBuf, wcParent)) != ERROR_NO_MORE_ITEMS){
if(uiStatus != S_OK){
bRetVal = false;
break;
}
if(wcscmp(wcName, wcBuf) == 0){
bRetVal = true;
break;
}
}
free((void *)wcBuf);
free((void *)wcParent);
return bRetVal;
}
bool SafeLeaveCriticalSection(CRITICAL_SECTION *pcs)
{
void * vpOwner = pcs->OwningThread;
DWORD dwOwner = PtrToUlong(vpOwner);
if((pcs->LockCount > -1) && (dwOwner == GetCurrentThreadId()))
LeaveCriticalSection(pcs);
return true;
}