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.
1257 lines
32 KiB
1257 lines
32 KiB
// GenericClass.cpp: implementation of the CGenericClass class.
|
|
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "precomp.h"
|
|
#include "GenericClass.h"
|
|
#include <wininet.h>
|
|
|
|
#define READ_HANDLE 0
|
|
#define WRITE_HANDLE 1
|
|
|
|
#include "ExtendString.h"
|
|
#include "ExtendQuery.h"
|
|
|
|
#include <scopeguard.h>
|
|
|
|
CRITICAL_SECTION CGenericClass::m_cs;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CGenericClass::CGenericClass(CRequestObject *pObj, IWbemServices *pNamespace, IWbemContext *pCtx)
|
|
{
|
|
m_pRequest = pObj;
|
|
m_pNamespace = pNamespace;
|
|
m_pCtx = pCtx;
|
|
m_pObj = NULL;
|
|
m_pClassForSpawning = NULL;
|
|
}
|
|
|
|
CGenericClass::~CGenericClass()
|
|
{
|
|
}
|
|
|
|
void CGenericClass::CleanUp()
|
|
{
|
|
if(m_pClassForSpawning){
|
|
|
|
m_pClassForSpawning->Release();
|
|
m_pClassForSpawning = NULL;
|
|
}
|
|
}
|
|
|
|
void CGenericClass::CheckMSI(UINT uiStatus)
|
|
{
|
|
if(uiStatus == E_OUTOFMEMORY){
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
}else if(uiStatus != ERROR_SUCCESS){
|
|
throw ConvertError(uiStatus);
|
|
}
|
|
}
|
|
|
|
HRESULT CGenericClass::CheckOpen(UINT uiStatus)
|
|
{
|
|
switch(uiStatus){
|
|
case ERROR_SUCCESS:
|
|
return WBEM_S_NO_ERROR;
|
|
case ERROR_ACCESS_DENIED:
|
|
return WBEM_E_PRIVILEGE_NOT_HELD;
|
|
default:
|
|
return WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
HRESULT CGenericClass::SetSinglePropertyPath(WCHAR wcProperty[])
|
|
{
|
|
|
|
if( m_pRequest->m_iPropCount >= MSI_KEY_LIST_SIZE) {
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
}
|
|
|
|
if(m_pRequest->m_iValCount > m_pRequest->m_iPropCount){
|
|
|
|
m_pRequest->m_Property[m_pRequest->m_iPropCount] = SysAllocString(wcProperty);
|
|
|
|
if(!m_pRequest->m_Property[(m_pRequest->m_iPropCount)++])
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
WCHAR * CGenericClass::GetFirstGUID(WCHAR wcIn[], WCHAR wcOut[])
|
|
{
|
|
// safe operation
|
|
// tested outside of that call
|
|
wcscpy(wcOut, wcIn);
|
|
wcOut[38] = NULL;
|
|
|
|
return wcOut;
|
|
}
|
|
|
|
WCHAR * CGenericClass::RemoveFinalGUID(WCHAR wcIn[], WCHAR wcOut[])
|
|
{
|
|
// safe operation
|
|
// tested outside of that call
|
|
wcscpy(wcOut, wcIn);
|
|
wcOut[wcslen(wcOut) - 38] = NULL;
|
|
|
|
return wcOut;
|
|
}
|
|
|
|
HRESULT CGenericClass::SpawnAnInstance(IWbemServices *pNamespace, IWbemContext *pCtx,
|
|
IWbemClassObject **pObj, BSTR bstrName)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if(!m_pClassForSpawning){
|
|
|
|
//Get ourselves an instance
|
|
if(FAILED(hr = m_pNamespace->GetObject(bstrName, 0, m_pCtx, &m_pClassForSpawning, NULL))){
|
|
|
|
*pObj = NULL;
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = m_pClassForSpawning->SpawnInstance(0, pObj);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CGenericClass::SpawnAnInstance(IWbemClassObject **pObj)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if(!m_pClassForSpawning){
|
|
|
|
//Get ourselves an instance
|
|
if(FAILED(hr = m_pNamespace->GetObject(m_pRequest->m_bstrClass, 0, m_pCtx,
|
|
&m_pClassForSpawning, NULL))){
|
|
|
|
*pObj = NULL;
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
hr = m_pClassForSpawning->SpawnInstance(0, pObj);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, WCHAR *wcValue)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
CHeap_Exception he(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
|
|
if(!wcTmp)
|
|
throw he;
|
|
|
|
mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
|
|
BSTR bstrName = SysAllocString(wcTmp);
|
|
free((void *)wcTmp);
|
|
if(!bstrName)
|
|
throw he;
|
|
|
|
VARIANT vp;
|
|
VariantInit(&vp);
|
|
V_VT(&vp) = VT_BSTR;
|
|
V_BSTR(&vp) = SysAllocString(wcValue);
|
|
if(!V_BSTR(&vp)){
|
|
|
|
SysFreeString(bstrName);
|
|
throw he;
|
|
}
|
|
|
|
if((wcValue == NULL) || (0 != _wcsicmp(wcValue, L""))){
|
|
|
|
hr = pObj->Put(bstrName, 0, &vp, NULL);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
SysFreeString(bstrName);
|
|
VariantClear(&vp);
|
|
throw hr;
|
|
}
|
|
|
|
}else hr = WBEM_E_FAILED;
|
|
|
|
SysFreeString(bstrName);
|
|
VariantClear(&vp);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, int iValue)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
|
|
if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
|
|
mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
|
|
BSTR bstrName = SysAllocString(wcTmp);
|
|
free((void *)wcTmp);
|
|
if(!bstrName)
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
|
|
|
|
if(iValue != MSI_NULL_INTEGER){
|
|
|
|
VARIANT pv;
|
|
VariantInit(&pv);
|
|
V_VT(&pv) = VT_I4;
|
|
V_I4(&pv) = iValue;
|
|
|
|
hr = pObj->Put(bstrName, 0, &pv, NULL);
|
|
|
|
VariantClear(&pv);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
SysFreeString(bstrName);
|
|
throw hr;
|
|
}
|
|
|
|
}else hr = WBEM_E_FAILED;
|
|
|
|
SysFreeString(bstrName);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, float dValue)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
|
|
if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
|
|
mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
|
|
BSTR bstrName = SysAllocString(wcTmp);
|
|
free((void *)wcTmp);
|
|
if(!bstrName)
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
|
|
|
|
VARIANT pv;
|
|
VariantInit(&pv);
|
|
V_VT(&pv) = VT_R4;
|
|
V_R4(&pv) = dValue;
|
|
|
|
hr = pObj->Put(bstrName, 0, &pv, NULL);
|
|
|
|
SysFreeString(bstrName);
|
|
VariantClear(&pv);
|
|
|
|
if(FAILED(hr))
|
|
throw hr;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, bool bValue)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
|
|
if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
|
|
mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
|
|
BSTR bstrName = SysAllocString(wcTmp);
|
|
free((void *)wcTmp);
|
|
if(!bstrName)
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
|
|
VARIANT pv;
|
|
VariantInit(&pv);
|
|
V_VT(&pv) = VT_BOOL;
|
|
if(bValue) V_BOOL(&pv) = VARIANT_TRUE;
|
|
else V_BOOL(&pv) = VARIANT_FALSE;
|
|
|
|
hr = pObj->Put(bstrName, 0, &pv, NULL);
|
|
|
|
SysFreeString(bstrName);
|
|
VariantClear(&pv);
|
|
|
|
if(FAILED(hr))
|
|
throw hr;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CGenericClass::PutKeyProperty(IWbemClassObject *pObj, const char *wcProperty, WCHAR *wcValue,
|
|
bool *bKey, CRequestObject *pRequest)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
|
|
if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
|
|
mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
|
|
BSTR bstrName = SysAllocString(wcTmp);
|
|
free((void *)wcTmp);
|
|
if(!bstrName)
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
|
|
|
|
VARIANT pv;
|
|
VariantInit(&pv);
|
|
V_VT(&pv) = VT_BSTR;
|
|
#ifdef _STRIP_ESCAPED_CHARS
|
|
V_BSTR(&pv) = SysAllocString(ConvertToASCII(wcValue));
|
|
#else
|
|
V_BSTR(&pv) = SysAllocString(wcValue);
|
|
#endif //_STRIP_ESCAPED_CHARS
|
|
|
|
if(!V_BSTR(&pv))
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
|
|
|
|
if((wcValue == NULL) || (0 != wcscmp(wcValue, L""))){
|
|
|
|
hr = pObj->Put(bstrName, 0, &pv, NULL);
|
|
|
|
if(FAILED(hr)){
|
|
|
|
SysFreeString(bstrName);
|
|
VariantClear(&pv);
|
|
throw hr;
|
|
}
|
|
|
|
// Find the keys
|
|
*bKey = false;
|
|
int iPos = -1;
|
|
if(FindIn(pRequest->m_Property, bstrName, &iPos) &&
|
|
FindIn(pRequest->m_Value, V_BSTR(&pv), &iPos)) *bKey = true;
|
|
|
|
}else hr = WBEM_E_FAILED;
|
|
|
|
SysFreeString(bstrName);
|
|
VariantClear(&pv);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CGenericClass::PutKeyProperty(IWbemClassObject *pObj, const char *wcProperty, int iValue,
|
|
bool *bKey, CRequestObject *pRequest)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
WCHAR * wcTmp = (WCHAR *)malloc((strlen(wcProperty) + 1) * sizeof(WCHAR));
|
|
if(!wcTmp) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
|
|
mbstowcs(wcTmp, wcProperty, (strlen(wcProperty) + 1));
|
|
BSTR bstrName = SysAllocString(wcTmp);
|
|
free((void *)wcTmp);
|
|
if(!bstrName)
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);;
|
|
|
|
VARIANT pv;
|
|
WCHAR wcBuf[BUFF_SIZE];
|
|
|
|
if(iValue != MSI_NULL_INTEGER){
|
|
|
|
VariantInit(&pv);
|
|
V_VT(&pv) = VT_I4;
|
|
V_I4(&pv) = iValue;
|
|
|
|
hr = pObj->Put(bstrName, 0, &pv, NULL);
|
|
|
|
VariantClear(&pv);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
SysFreeString(bstrName);
|
|
throw hr;
|
|
}
|
|
|
|
// Find the keys
|
|
_itow(iValue, wcBuf, 10);
|
|
BSTR bstrValue = SysAllocString(wcBuf);
|
|
if(!bstrValue)
|
|
{
|
|
SysFreeString(bstrName);
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
}
|
|
|
|
*bKey = false;
|
|
int iPos = -1;
|
|
if(FindIn(pRequest->m_Property, bstrName, &iPos) &&
|
|
FindIn(pRequest->m_Value, bstrValue, &iPos)) *bKey = true;
|
|
|
|
SysFreeString(bstrValue);
|
|
|
|
}else hr = WBEM_E_FAILED;
|
|
|
|
SysFreeString(bstrName);
|
|
|
|
return hr;
|
|
}
|
|
|
|
bool CGenericClass::FindIn(BSTR bstrProp[], BSTR bstrSearch, int *iPos)
|
|
{
|
|
int i = 0;
|
|
|
|
if(*iPos == (-1))
|
|
{
|
|
while(bstrProp[i] != NULL)
|
|
{
|
|
if(0 == _wcsicmp(bstrProp[i], bstrSearch))
|
|
{
|
|
*iPos = i;
|
|
return true;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(0 == _wcsicmp(bstrProp[*iPos], bstrSearch))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CGenericClass::GetView ( MSIHANDLE *phProduct,
|
|
WCHAR *wcPackage,
|
|
WCHAR *wcQuery,
|
|
WCHAR *wcTable,
|
|
BOOL bCloseProduct,
|
|
BOOL bCloseDatabase
|
|
)
|
|
{
|
|
return msidata.GetView ( phProduct, wcPackage, wcQuery, wcTable, bCloseProduct, bCloseDatabase );
|
|
}
|
|
|
|
HRESULT CGenericClass::GetProperty(IWbemClassObject *pObj, const char *cProperty, BSTR *wcValue)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
VARIANT v;
|
|
WCHAR wcTmp[BUFF_SIZE];
|
|
CHeap_Exception he(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
|
|
BSTR bstrProp = SysAllocString(TcharToWchar(cProperty, wcTmp));
|
|
if(!bstrProp)
|
|
throw he;
|
|
|
|
ON_BLOCK_EXIT ( SysFreeString, bstrProp ) ;
|
|
|
|
VariantInit(&v);
|
|
ON_BLOCK_EXIT ( VariantClear, &v ) ;
|
|
|
|
if(SUCCEEDED(hr = pObj->Get(bstrProp, 0, &v, NULL, NULL))){
|
|
|
|
if( V_VT( &v ) == VT_BSTR )
|
|
{
|
|
if ( wcslen ( V_BSTR ( &v ) ) > INTERNET_MAX_PATH_LENGTH )
|
|
{
|
|
return WBEM_E_INVALID_METHOD_PARAMETERS;
|
|
}
|
|
|
|
*wcValue = SysAllocString(V_BSTR(&v));
|
|
}
|
|
else
|
|
{
|
|
*wcValue = SysAllocString(L"");
|
|
}
|
|
|
|
if(!wcValue)
|
|
throw he;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CGenericClass::GetProperty(IWbemClassObject *pObj, const char *cProperty, int *piValue)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
VARIANT v;
|
|
WCHAR wcTmp[BUFF_SIZE];
|
|
CHeap_Exception he(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
|
|
BSTR bstrProp = SysAllocString(TcharToWchar(cProperty, wcTmp));
|
|
if(!bstrProp)
|
|
throw he;
|
|
|
|
VariantInit(&v);
|
|
|
|
if(SUCCEEDED(hr = pObj->Get(bstrProp, 0, &v, NULL, NULL))){
|
|
|
|
if(V_VT(&v) == VT_I4) *piValue = V_I4(&v);
|
|
else *piValue = 0;
|
|
}
|
|
|
|
SysFreeString(bstrProp);
|
|
VariantClear(&v);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CGenericClass::GetProperty(IWbemClassObject *pObj, const char *cProperty, bool *pbValue)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
VARIANT v;
|
|
WCHAR wcTmp[BUFF_SIZE];
|
|
CHeap_Exception he(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
|
|
BSTR bstrProp = SysAllocString(TcharToWchar(cProperty, wcTmp));
|
|
if(!bstrProp)
|
|
throw he;
|
|
|
|
VariantInit(&v);
|
|
|
|
if(SUCCEEDED(hr = pObj->Get(bstrProp, 0, &v, NULL, NULL))){
|
|
|
|
if((V_VT(&v) == VT_BOOL) & V_BOOL(&v)) *pbValue = true;
|
|
else *pbValue = false;
|
|
}
|
|
|
|
SysFreeString(bstrProp);
|
|
VariantClear(&v);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* CGenericClass::LaunchProcess()
|
|
*
|
|
* In:
|
|
* wcCommandLine - the commandline to pass to msimeth
|
|
*
|
|
* Out:
|
|
* uiStatus - The variable that will recieve the return value
|
|
* from the method call
|
|
*
|
|
*
|
|
* this method will handle method execution on NT4, where security
|
|
* restrictions prevent calling another DCOM server with an impersonating
|
|
* thread token. This method will launch another process to handle the
|
|
* opperation after setting up a pipe for passing status messages from the
|
|
* external process back to the provider.
|
|
*
|
|
*****************************************************************************/
|
|
HRESULT CGenericClass::LaunchProcess(WCHAR *wcAction, WCHAR *wcCommandLine, UINT *uiStatus)
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
|
|
//check to see if server already running
|
|
HANDLE hMutex = CreateMutex(NULL, TRUE, TEXT("MSIPROV_METHODS_SERVER"));
|
|
|
|
if(hMutex){
|
|
|
|
IWbemClassObject *pObj = NULL;
|
|
BSTR bstrProcess = SysAllocString(L"Win32_Process");
|
|
|
|
SetFileApisToOEM();
|
|
|
|
HANDLE hPipe = CreateNamedPipe(L"\\\\.\\pipe\\msimeth_pipe", PIPE_ACCESS_INBOUND,
|
|
(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT), PIPE_UNLIMITED_INSTANCES,
|
|
10000, 10000, 50000, NULL);
|
|
|
|
if(SUCCEEDED(hr = m_pNamespace->GetObject(bstrProcess, 0, m_pCtx, &pObj, NULL))){
|
|
|
|
IWbemClassObject *pInParam = NULL;
|
|
IWbemClassObject *pOutParam = NULL;
|
|
BSTR bstrCreate = SysAllocString(L"Create");
|
|
|
|
// get the method paramater objects
|
|
if(SUCCEEDED(hr = pObj->GetMethod(bstrCreate, 0, &pInParam, &pOutParam))){
|
|
|
|
VARIANT v;
|
|
BSTR bstrCommandLine = SysAllocString(L"CommandLine");
|
|
IWbemClassObject *pStartup = NULL;
|
|
|
|
VariantInit(&v);
|
|
V_VT(&v) = VT_BSTR;
|
|
|
|
WCHAR wcCommand[BUFF_SIZE];
|
|
WCHAR wcTmp[10];
|
|
UINT uiSize = BUFF_SIZE;
|
|
GetSystemDirectoryW(wcCommand, uiSize);
|
|
wcscat(wcCommand, L"\\wbem\\msimeth.exe ");
|
|
wcscat(wcCommand, wcAction);
|
|
wcscat(wcCommand, L" ");
|
|
wcscat(wcCommand, _itow(m_pRequest->m_iThreadID, wcTmp, 10));
|
|
wcscat(wcCommand, L" ");
|
|
wcscat(wcCommand, wcCommandLine);
|
|
|
|
V_BSTR(&v) = SysAllocString(wcCommand);
|
|
|
|
// populate the in parameters
|
|
if(SUCCEEDED(hr = pInParam->Put(bstrCommandLine, 0, &v, NULL))){
|
|
|
|
VariantClear(&v);
|
|
|
|
BSTR bstrProcessStartup = SysAllocString(L"Win32_ProcessStartup");
|
|
IWbemClassObject *pStartupObj = NULL;
|
|
|
|
if(SUCCEEDED(hr = m_pNamespace->GetObject(bstrProcessStartup, 0, m_pCtx,
|
|
&pStartupObj, NULL))){
|
|
|
|
IWbemClassObject *pStartupInst = NULL;
|
|
|
|
if(SUCCEEDED(hr = pStartupObj->SpawnInstance(0, &pStartupInst))){
|
|
|
|
LPVOID pEnv = GetEnvironmentStrings();
|
|
WCHAR *pwcVar = (WCHAR *)pEnv;
|
|
|
|
SAFEARRAYBOUND sbArrayBounds ;
|
|
|
|
long lCount = GetVarCount(pEnv);
|
|
sbArrayBounds.cElements = lCount;
|
|
sbArrayBounds.lLbound = 0;
|
|
|
|
if(V_ARRAY(&v) = SafeArrayCreate(VT_BSTR, 1, &sbArrayBounds)){
|
|
|
|
V_VT(&v) = VT_BSTR | VT_ARRAY ;
|
|
|
|
BSTR bstrVal;
|
|
|
|
//get the environment variables into a VARIANT
|
|
for(long j = 0; j < lCount; j++){
|
|
|
|
bstrVal = SysAllocString(pwcVar);
|
|
SafeArrayPutElement(V_ARRAY(&v), &j, bstrVal);
|
|
SysFreeString(bstrVal);
|
|
|
|
pwcVar = GetNextVar(pwcVar);
|
|
}
|
|
|
|
BSTR bstrEnvironmentVariables = SysAllocString(L"EnvironmentVariables");
|
|
|
|
if(SUCCEEDED(hr = pStartupInst->Put(bstrEnvironmentVariables, 0,
|
|
&v, NULL))){
|
|
|
|
VariantClear(&v);
|
|
|
|
V_VT(&v) = VT_UNKNOWN;
|
|
V_UNKNOWN(&v) = (IDispatch *)pStartupInst;
|
|
pStartupInst->AddRef();
|
|
|
|
BSTR bstrProcessStartupInformation = SysAllocString(L"ProcessStartupInformation");
|
|
|
|
hr = pInParam->Put(bstrProcessStartupInformation, 0, &v, NULL);
|
|
|
|
SysFreeString(bstrProcessStartupInformation);
|
|
}
|
|
|
|
SysFreeString(bstrEnvironmentVariables);
|
|
}
|
|
|
|
FreeEnvironmentStrings((LPWSTR)pEnv);
|
|
|
|
pStartupInst->Release();
|
|
}
|
|
|
|
pStartupObj->Release();
|
|
}
|
|
|
|
SysFreeString(bstrProcessStartup);
|
|
|
|
//we've no created our input object, so let's make the call
|
|
if(SUCCEEDED(hr = m_pNamespace->ExecMethod(bstrProcess, bstrCreate, 0,
|
|
m_pCtx, pInParam, &pOutParam, NULL))){
|
|
|
|
VariantClear(&v);
|
|
BSTR bstrReturnValue = SysAllocString(L"ReturnValue");
|
|
|
|
if(SUCCEEDED(hr = pOutParam->Get(bstrReturnValue, 0, &v, NULL, NULL))){
|
|
|
|
hr = V_I4(&v);
|
|
VariantClear(&v);
|
|
|
|
if(hr == 0){
|
|
|
|
BSTR bstrProcessID = SysAllocString(L"ProcessID");
|
|
|
|
if(SUCCEEDED(hr = pOutParam->Get(bstrProcessID, 0, &v, NULL, NULL))){
|
|
|
|
//open process handle to check for exit
|
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE,
|
|
(DWORD)V_I4(&v));
|
|
|
|
ReleaseMutex(hMutex);
|
|
|
|
if(hProcess){
|
|
|
|
BOOL bRead = FALSE;
|
|
DWORD dwRead = 0;
|
|
WCHAR wcBuf[BUFF_SIZE];
|
|
int nExitCode = STILL_ACTIVE;
|
|
|
|
if(!GetExitCodeProcess(hProcess, (unsigned long*)&nExitCode)){
|
|
|
|
hr = GetLastError();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
// Handle status messages as they are recieved
|
|
|
|
while(nExitCode == STILL_ACTIVE){
|
|
|
|
//synchronized pipe access
|
|
// WaitForSingleObject(hMutex, INFINITE);
|
|
|
|
bRead = ReadFile(hPipe, wcBuf, BUFF_SIZE, &dwRead, NULL);
|
|
|
|
// ReleaseMutex(hMutex);
|
|
|
|
if(!bRead){
|
|
|
|
switch(GetLastError()){
|
|
case ERROR_MORE_DATA:
|
|
//deal with unable to read whole message
|
|
break;
|
|
case ERROR_HANDLE_EOF:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if(bRead && dwRead){
|
|
|
|
//do some parsing, then...
|
|
int iContext = _wtoi(wcstok(wcBuf, L"~"));
|
|
UINT uiMessageType = _wtoi(wcstok(NULL, L"~"));
|
|
LPWSTR lpwMessage = wcstok(NULL, L"\n");
|
|
|
|
//process the message
|
|
MyEventHandler(m_pRequest, uiMessageType, lpwMessage);
|
|
}
|
|
|
|
if(!GetExitCodeProcess(hProcess, (unsigned long*)&nExitCode)){
|
|
|
|
hr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
*uiStatus = nExitCode;
|
|
|
|
CloseHandle(hPipe);
|
|
}
|
|
|
|
}
|
|
|
|
SysFreeString(bstrProcessID);
|
|
|
|
}else{
|
|
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
|
|
SysFreeString(bstrReturnValue);
|
|
}
|
|
|
|
}
|
|
|
|
pInParam->Release();
|
|
pOutParam->Release();
|
|
VariantClear(&v);
|
|
}
|
|
|
|
SysFreeString(bstrCreate);
|
|
pObj->Release();
|
|
}
|
|
|
|
SysFreeString(bstrProcess);
|
|
}
|
|
|
|
if(hMutex){
|
|
|
|
CloseHandle(hMutex);
|
|
hMutex = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
INSTALLUI_HANDLER CGenericClass::SetupExternalUI()
|
|
{
|
|
g_fpMsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
|
|
|
|
INSTALLUI_HANDLER ui = NULL;
|
|
ui = g_fpMsiSetExternalUIW ( MyEventHandler,
|
|
(
|
|
INSTALLLOGMODE_PROGRESS |
|
|
INSTALLLOGMODE_ACTIONDATA |
|
|
INSTALLLOGMODE_INFO |
|
|
INSTALLLOGMODE_WARNING |
|
|
INSTALLLOGMODE_ACTIONSTART
|
|
),
|
|
m_pRequest
|
|
);
|
|
|
|
g_fpMsiEnableLogW (
|
|
( INSTALLLOGMODE_ACTIONDATA |
|
|
INSTALLLOGMODE_INFO |
|
|
INSTALLLOGMODE_FATALEXIT |
|
|
INSTALLLOGMODE_ERROR |
|
|
INSTALLLOGMODE_WARNING |
|
|
INSTALLLOGMODE_USER |
|
|
INSTALLLOGMODE_VERBOSE |
|
|
INSTALLLOGMODE_RESOLVESOURCE |
|
|
INSTALLLOGMODE_OUTOFDISKSPACE |
|
|
INSTALLLOGMODE_COMMONDATA |
|
|
INSTALLLOGMODE_PROPERTYDUMP |
|
|
INSTALLLOGMODE_ACTIONSTART
|
|
),
|
|
g_wcpLoggingDir,
|
|
INSTALLLOGATTRIBUTES_APPEND
|
|
);
|
|
|
|
return ui;
|
|
}
|
|
|
|
void CGenericClass::RestoreExternalUI( INSTALLUI_HANDLER ui )
|
|
{
|
|
g_fpMsiSetExternalUIW ( ui, 0, NULL );
|
|
}
|
|
|
|
WCHAR * CGenericClass::GetNextVar(WCHAR *pwcStart)
|
|
{
|
|
|
|
WCHAR *pwc = pwcStart;
|
|
|
|
//get to end of variable
|
|
while(*pwc){ pwc++; }
|
|
|
|
return ++pwc;
|
|
}
|
|
|
|
long CGenericClass::GetVarCount(void * pEnv)
|
|
{
|
|
|
|
long lRetVal = 0;
|
|
WCHAR *pwc = (WCHAR *)pEnv;
|
|
|
|
//count the variables
|
|
while(*pwc){
|
|
|
|
//get to end of variable
|
|
while(*pwc){ pwc++; }
|
|
|
|
pwc++;
|
|
lRetVal++;
|
|
}
|
|
|
|
return lRetVal;
|
|
}
|
|
|
|
//Special Property Methods
|
|
HRESULT CGenericClass::PutProperty(IWbemClassObject *pObj, const char *wcProperty, WCHAR *wcValue, DWORD dwCount, ... )
|
|
{
|
|
if ( dwCount )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
CStringExt prop ( wcValue );
|
|
|
|
va_list argList;
|
|
va_start ( argList, dwCount );
|
|
hr = prop.AppendList ( 0, NULL, dwCount, argList );
|
|
va_end ( argList );
|
|
|
|
if SUCCEEDED ( hr )
|
|
{
|
|
hr = PutProperty ( pObj, wcProperty, prop );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
else
|
|
{
|
|
return PutProperty ( pObj, wcProperty, wcValue );
|
|
}
|
|
}
|
|
|
|
//Special Key Property Methods
|
|
HRESULT CGenericClass::PutKeyProperty ( IWbemClassObject *pObj,
|
|
const char *wcProperty,
|
|
WCHAR *wcValue,
|
|
bool *bKey,
|
|
CRequestObject *pRequest,
|
|
DWORD dwCount,
|
|
...
|
|
)
|
|
{
|
|
if ( dwCount )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
CStringExt prop ( wcValue );
|
|
|
|
va_list argList;
|
|
va_start ( argList, dwCount );
|
|
hr = prop.AppendList ( 0, NULL, dwCount, argList );
|
|
va_end ( argList );
|
|
|
|
if SUCCEEDED ( hr )
|
|
{
|
|
hr = PutKeyProperty ( pObj, wcProperty,prop, bKey, pRequest );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
else
|
|
{
|
|
return PutKeyProperty ( pObj, wcProperty, wcValue, bKey, pRequest );
|
|
}
|
|
}
|
|
|
|
HRESULT CGenericClass::GetBufferNeccessary ( MSIHANDLE& handle,
|
|
DWORD dwIndex,
|
|
DWORD& dwSize,
|
|
LPWSTR staticBuffer,
|
|
BOOL bThrow
|
|
)
|
|
{
|
|
HRESULT hResult = WBEM_S_NO_ERROR;
|
|
UINT uiStatus = ERROR_SUCCESS;
|
|
|
|
DWORD dwOldSize = dwSize;
|
|
|
|
uiStatus = g_fpMsiRecordGetStringW ( handle, dwIndex, staticBuffer, &dwSize );
|
|
if ( uiStatus != ERROR_SUCCESS )
|
|
{
|
|
if ( uiStatus == ERROR_MORE_DATA )
|
|
{
|
|
hResult = WBEM_S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ( bThrow )
|
|
{
|
|
CheckMSI ( uiStatus );
|
|
}
|
|
else
|
|
{
|
|
hResult = ConvertError ( uiStatus );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( hResult == WBEM_S_NO_ERROR )
|
|
{
|
|
if ( dwOldSize < dwSize )
|
|
{
|
|
hResult = WBEM_S_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hResult;
|
|
}
|
|
|
|
HRESULT CGenericClass::GetBuffer ( MSIHANDLE& handle,
|
|
DWORD dwIndex,
|
|
DWORD& dwSize,
|
|
DWORD& dwdynSize,
|
|
LPWSTR& dynBuffer,
|
|
BOOL bThrow
|
|
)
|
|
{
|
|
HRESULT hResult = WBEM_S_NO_ERROR;
|
|
UINT uiStatus = ERROR_SUCCESS;
|
|
|
|
if ( dwSize )
|
|
{
|
|
if ( dwdynSize < dwSize )
|
|
{
|
|
if ( dynBuffer )
|
|
{
|
|
delete [] dynBuffer;
|
|
dynBuffer = NULL;
|
|
}
|
|
|
|
if ( ( dynBuffer = new WCHAR [ dwSize + 1 ] ) != NULL )
|
|
{
|
|
dynBuffer [ 0 ] = 0;
|
|
dwdynSize = dwSize;
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
|
|
}
|
|
}
|
|
|
|
DWORD dwOldSize = dwSize;
|
|
|
|
try
|
|
{
|
|
uiStatus = g_fpMsiRecordGetStringW ( handle, dwIndex, dynBuffer, &dwSize );
|
|
}
|
|
catch ( ... )
|
|
{
|
|
if ( dynBuffer )
|
|
{
|
|
delete [] dynBuffer;
|
|
dynBuffer = NULL;
|
|
}
|
|
|
|
dwdynSize = 0;
|
|
|
|
throw;
|
|
}
|
|
|
|
if ( uiStatus != ERROR_SUCCESS )
|
|
{
|
|
BOOL bError = TRUE;
|
|
|
|
if ( dynBuffer && dynBuffer [ 0 ] != 0 )
|
|
{
|
|
dynBuffer [ 0 ] = 0;
|
|
}
|
|
|
|
// strange MSI problem !
|
|
//
|
|
// allocated buffer with lenght as expected
|
|
// buffer sent and ERROR_MORE_DATA was returned
|
|
// unfortunately requested lenght is equal as previous !
|
|
|
|
if ( uiStatus == ERROR_MORE_DATA )
|
|
{
|
|
if ( dwOldSize == dwSize )
|
|
{
|
|
bError = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( bError )
|
|
{
|
|
if ( dynBuffer )
|
|
{
|
|
delete [] dynBuffer;
|
|
dynBuffer = NULL;
|
|
}
|
|
|
|
dwdynSize = 0L;
|
|
|
|
if ( bThrow )
|
|
{
|
|
CheckMSI ( uiStatus );
|
|
}
|
|
else
|
|
{
|
|
hResult = ConvertError ( uiStatus );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hResult = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
return hResult;
|
|
}
|
|
|
|
HRESULT CGenericClass::PutPropertySpecial ( MSIHANDLE& handle,
|
|
DWORD dwIndex,
|
|
DWORD& dwSize,
|
|
LPWSTR staticBuffer,
|
|
DWORD& dwdynSize,
|
|
LPWSTR& dynBuffer,
|
|
LPCSTR tszPropName,
|
|
BOOL bThrow
|
|
)
|
|
{
|
|
HRESULT hResult = WBEM_S_NO_ERROR;
|
|
UINT uiStatus = ERROR_SUCCESS;
|
|
|
|
if ( handle )
|
|
{
|
|
hResult = GetBufferNeccessary ( handle, dwIndex, dwSize, staticBuffer, bThrow );
|
|
if SUCCEEDED ( hResult )
|
|
{
|
|
if ( hResult == WBEM_S_NO_ERROR )
|
|
{
|
|
hResult = PutProperty ( m_pObj, tszPropName, staticBuffer );
|
|
}
|
|
else
|
|
if ( hResult == WBEM_S_FALSE )
|
|
{
|
|
try
|
|
{
|
|
hResult = GetBuffer ( handle, dwIndex, dwSize, dwdynSize, dynBuffer, bThrow );
|
|
if SUCCEEDED ( hResult )
|
|
{
|
|
hResult = PutProperty ( m_pObj, tszPropName, dynBuffer );
|
|
|
|
if ( dynBuffer && dynBuffer [ 0 ] != 0 )
|
|
{
|
|
dynBuffer [ 0 ] = 0;
|
|
}
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
if ( dynBuffer )
|
|
{
|
|
delete [] dynBuffer;
|
|
dynBuffer = NULL;
|
|
}
|
|
|
|
dwdynSize = 0;
|
|
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hResult = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
return hResult;
|
|
}
|
|
|
|
HRESULT CGenericClass::PutPropertySpecial ( MSIHANDLE& handle,
|
|
DWORD dwIndex,
|
|
DWORD& dwSize,
|
|
LPWSTR staticBuffer,
|
|
DWORD& dwdynSize,
|
|
LPWSTR& dynBuffer,
|
|
BOOL bThrow,
|
|
DWORD dwCount,
|
|
...
|
|
)
|
|
{
|
|
HRESULT hResult = WBEM_S_NO_ERROR;
|
|
UINT uiStatus = ERROR_SUCCESS;
|
|
|
|
if ( handle )
|
|
{
|
|
va_list argList;
|
|
va_start ( argList, dwCount );
|
|
|
|
LPCSTR tszPropName = NULL;
|
|
|
|
try
|
|
{
|
|
hResult = GetBufferNeccessary ( handle, dwIndex, dwSize, staticBuffer, bThrow );
|
|
if SUCCEEDED ( hResult )
|
|
{
|
|
if ( hResult == WBEM_S_NO_ERROR )
|
|
{
|
|
for ( DWORD dw = 0; (dw < dwCount) && (SUCCEEDED ( hResult )) ; dw++ )
|
|
{
|
|
if ( ( tszPropName = va_arg ( argList, LPCSTR ) ) != NULL )
|
|
{
|
|
hResult = PutProperty ( m_pObj, tszPropName, staticBuffer );
|
|
; }
|
|
}
|
|
}
|
|
else
|
|
if ( hResult == WBEM_S_FALSE )
|
|
{
|
|
try
|
|
{
|
|
hResult = GetBuffer ( handle, dwIndex, dwSize, dwdynSize, dynBuffer, bThrow );
|
|
if SUCCEEDED ( hResult )
|
|
{
|
|
for ( DWORD dw = 0; (dw < dwCount) && (SUCCEEDED ( hResult )) ; dw++ )
|
|
{
|
|
if ( ( tszPropName = va_arg ( argList, LPCSTR ) ) != NULL )
|
|
{
|
|
hResult = PutProperty ( m_pObj, tszPropName, dynBuffer );
|
|
}
|
|
}
|
|
|
|
if ( dynBuffer && dynBuffer [ 0 ] != 0 )
|
|
{
|
|
dynBuffer [ 0 ] = 0;
|
|
}
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
if ( dynBuffer )
|
|
{
|
|
delete [] dynBuffer;
|
|
dynBuffer = NULL;
|
|
}
|
|
|
|
dwdynSize = 0;
|
|
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
va_end ( argList );
|
|
throw;
|
|
}
|
|
|
|
va_end ( argList );
|
|
}
|
|
else
|
|
{
|
|
hResult = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
return hResult;
|
|
}
|
|
|
|
HRESULT CGenericClass::GetBufferToPut ( MSIHANDLE& handle,
|
|
DWORD dwIndex,
|
|
DWORD& dwSize,
|
|
LPWSTR staticBuffer,
|
|
DWORD& dwdynSize,
|
|
LPWSTR& dynBuffer,
|
|
LPWSTR& Buffer,
|
|
BOOL bThrow
|
|
)
|
|
{
|
|
HRESULT hResult = WBEM_S_NO_ERROR;
|
|
UINT uiStatus = ERROR_SUCCESS;
|
|
|
|
if ( handle )
|
|
{
|
|
hResult = GetBufferNeccessary ( handle, dwIndex, dwSize, staticBuffer, bThrow );
|
|
if SUCCEEDED ( hResult )
|
|
{
|
|
if ( hResult == WBEM_S_NO_ERROR )
|
|
{
|
|
Buffer = staticBuffer;
|
|
}
|
|
else
|
|
if ( hResult == WBEM_S_FALSE )
|
|
{
|
|
try
|
|
{
|
|
hResult = GetBuffer ( handle, dwIndex, dwSize, dwdynSize, dynBuffer, bThrow );
|
|
if SUCCEEDED ( hResult )
|
|
{
|
|
Buffer = dynBuffer;
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
if ( dynBuffer )
|
|
{
|
|
delete [] dynBuffer;
|
|
dynBuffer = NULL;
|
|
}
|
|
|
|
dwdynSize = 0;
|
|
Buffer = NULL;
|
|
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hResult = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
return hResult;
|
|
}
|