// RequestObject.cpp: implementation of the CRequestObject class. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved // ////////////////////////////////////////////////////////////////////// #include "precomp.h" #include "requestobject.h" #include #include #include //Classes #include "ApplicationService.h" #include "Binary.h" #include "BindImage.h" #include "ClassInfoAction.h" #include "CommandLineAccess.h" #include "Condition.h" #include "CreateFolder.h" #include "DirectorySpecification.h" #include "DuplicateFile.h" #include "Environment.h" #include "ExtensionInfoAction.h" #include "FileSpecification.h" #include "FontInfoAction.h" #include "IniFile.h" #include "LaunchCondition.h" #include "MIMEInfoAction.h" #include "MoveFile.h" #include "ODBCAttribute.h" #include "ODBCDataSource.h" #include "ODBCDriver.h" #include "ODBCSourceAttribute.h" #include "ODBCTranslator.h" #include "Patch.h" #include "PatchPackAge.h" #include "ProgIDSpecification.h" #include "Product.h" #include "Property.h" #include "PublishComponent.h" #include "RemoveFile.h" #include "RemoveIniValue.h" #include "ReserveCost.h" #include "SelfRegModule.h" #include "ServiceControl.h" #include "ServiceSpecification.h" #include "ShortcutAction.h" #include "SoftwareElement.h" #include "SoftwareElementCondition.h" #include "SoftwareFeature.h" #include "TypeLibraryAction.h" //#include "Upgrade.h" #include "WriteRegistry.h" //Associations #include "ActionCheck.h" #include "ApplicationCommandLine.h" #include "CheckCheck.h" #include "InstalledSoftwareElement.h" #include "ODBCDataSourceAttribute.h" #include "ODBCDriverAttribute.h" #include "ODBCDriverSoftwareElement.h" #include "PatchFile.h" #include "ProductResource1.h" #include "ProductEnvironment.h" #include "ProductSoftwareFeatures.h" #include "ServiceSpecificationService.h" #include "ShortcutSAP.h" #include "SoftwareElementAction.h" #include "SoftwareElementCheck.h" #include "SoftwareElementServiceControl.h" #include "SoftwareFeatureAction.h" #include "SoftwareFeatureCondition.h" #include "SoftwareFeatureParent.h" #include "SoftwareFeatureSoftwareElements.h" CRITICAL_SECTION CRequestObject::m_cs; CHeap_Exception CRequestObject::m_he(CHeap_Exception::E_ALLOCATION_ERROR); ////////////////////////////////////////////////////////////////////// // event handler for methods ////////////////////////////////////////////////////////////////////// int WINAPI MyEventHandler ( LPVOID pvContext, UINT iMessageType, LPCWSTR szMessage ) { // request object CRequestObject* pObj = NULL; pObj = reinterpret_cast < CRequestObject* > ( pvContext ); BSTR bstrMsg = NULL; try { if ( pObj && pObj->m_iThreadID != THREAD_NO_PROGRESS ) { ProListNode *pNode = NULL; if ( ( pNode = pObj->GetNode ( pObj->m_iThreadID ) ) != NULL ) { if ( pNode->pSink != NULL) { //Get the values we need from the MessageType UINT uiMsg = iMessageType & 0x0F000000L; if(szMessage) { bstrMsg = SysAllocString(szMessage); } else { bstrMsg = SysAllocString(L""); } HRESULT hr = WBEM_S_NO_ERROR; HRESULT hrProgress = WBEM_STATUS_PROGRESS; bool bSuccess = true; switch(uiMsg) { case INSTALLMESSAGE_FATALEXIT: if(!pObj->CreateProgress(NULL, &hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_ERROR: if(!pObj->CreateProgress(NULL, &hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_WARNING: if(!pObj->CreateProgress(NULL, &hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_USER: if(!pObj->CreateProgress(NULL, &hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_INFO: if(!pObj->CreateProgress(NULL, &hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_FILESINUSE: if(!pObj->CreateProgress(NULL, &hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_RESOLVESOURCE: if(!pObj->CreateProgress(NULL, &hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_OUTOFDISKSPACE: if(!pObj->CreateProgress(NULL, &hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_ACTIONSTART: if(!pObj->ActionStartProgress(&hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_ACTIONDATA: if(!pObj->ActionDataProgress(&hr, pObj->m_iThreadID)) bSuccess = false; break; case INSTALLMESSAGE_PROGRESS: ProgressStruct ps; if(pObj->ParseProgress(bstrMsg, &ps)) { if(!pObj->CreateProgress(&ps, &hr, pObj->m_iThreadID)) bSuccess = false; } break; case INSTALLMESSAGE_INITIALIZE: break; case INSTALLMESSAGE_TERMINATE: break; default: bSuccess = false; break; } //Send the message if(bSuccess) { pNode->pSink->SetStatus(hrProgress, hr, bstrMsg, NULL); } } } } } catch(...) { } if ( bstrMsg ) { ::SysFreeString(bstrMsg); } return 0; } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CRequestObject::CRequestObject() { m_cRef = 0; m_bstrPath = NULL; m_bstrClass = NULL; m_pPackageHead = NULL; m_hKey = NULL; } CRequestObject::~CRequestObject() { } //*************************************************************************** // // CRequestObject::QueryInterface // CRequestObject::AddRef // CRequestObject::Release // // Purpose: IUnknown members for CRequestObject object. //*************************************************************************** /* STDMETHODIMP CRequestObject::QueryInterface(REFIID riid, PPVOID ppv) { *ppv = NULL; if(riid == IID_IMsiMethodStatusSink) *ppv = (IMsiMethodStatusSink *)this; if(riid == IID_IUnknown) *ppv = (IMsiMethodStatusSink *)this; if(NULL != *ppv){ AddRef(); return NOERROR; }else return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CRequestObject::AddRef(void) { InterlockedIncrement((long *)&m_cRef); return m_cRef; } STDMETHODIMP_(ULONG) CRequestObject::Release(void) { ULONG nNewCount = InterlockedDecrement((long *)&m_cRef); // if(0L == nNewCount) delete this; return nNewCount; } */ void CRequestObject::Initialize(IWbemServices *pNamespace) { m_pNamespace = pNamespace; m_pHandler = NULL; m_bstrClass = NULL; m_bstrPath = NULL; m_iPropCount = m_iValCount = 0; m_iThreadID = THREAD_NO_PROGRESS; m_pHead = NULL; m_dwCheckKeyPresentStatus = ERROR_SUCCESS; for(int i = 0; i < MSI_KEY_LIST_SIZE; i++) m_Property[i] = m_Value[i] = NULL; HANDLE hTokenImpersonationHandle; DWORD dwStatus; if(OpenThreadToken(GetCurrentThread(), (TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY), TRUE ,& hTokenImpersonationHandle)){ dwStatus = GetAccount(hTokenImpersonationHandle, m_wcDomain, m_wcUser ); if(dwStatus == 0) { if ( wcslen ( m_wcDomain ) + wcslen ( m_wcUser ) + 1 + 1 < BUFF_SIZE ) { wcscpy(m_wcAccount, m_wcDomain); wcscat(m_wcAccount, L"\\"); wcscat(m_wcAccount, m_wcUser); WCHAR wcSID[BUFF_SIZE]; if((dwStatus = GetSid(hTokenImpersonationHandle, wcSID)) == S_OK ){ CRegistry *pReg = new CRegistry(); if(!pReg) throw m_he; //check if SID already present under HKEY_USER ... m_dwCheckKeyPresentStatus = pReg->Open(HKEY_USERS, wcSID, KEY_READ) ; if(m_dwCheckKeyPresentStatus == ERROR_NOT_ENOUGH_MEMORY) throw m_he; pReg->Close(); delete pReg; } } } CloseHandle(hTokenImpersonationHandle); } } void CRequestObject::FinalRelease() { } HRESULT CRequestObject::CreateObject(BSTR bstrPath, IWbemObjectSink *pHandler, IWbemContext *pCtx) { HRESULT hr = WBEM_S_NO_ERROR; CGenericClass *pClass = NULL; m_bstrPath = SysAllocString(bstrPath); if(!m_bstrPath) throw m_he; if(ParsePath(bstrPath)){ try{ //create the appropriate class if(SUCCEEDED(hr = CreateClass(&pClass, pCtx))){ if(!pClass) throw m_he; //get the requested object hr = pClass->CreateObject(pHandler, ACTIONTYPE_GET); } }catch(...){ if(pClass){ pClass->CleanUp(); delete pClass; } throw; } if(pClass){ pClass->CleanUp(); delete pClass; } }else hr = WBEM_E_FAILED; return hr; } HRESULT CRequestObject::CreateClass(CGenericClass **pClass, IWbemContext *pCtx) { HRESULT hr = WBEM_S_NO_ERROR; //Create the appropriate class ///////////// // Classes // ///////////// if(0 == _wcsicmp(m_bstrClass, L"WIN32_APPLICATIONSERVICE")){ *pClass = new CApplicationService(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_BINARY")){ *pClass = new CBinary(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_BINDIMAGEACTION")){ *pClass = new CBindImage(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_CLASSINFOACTION")){ *pClass = new CClassInfoAction(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_COMMANDLINEACCESS")){ *pClass = new CCommandLineAccess(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_CONDITION")){ *pClass = new CCondition(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_CREATEFOLDERACTION")){ *pClass = new CCreateFolder(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_DIRECTORYSPECIFICATION")){ *pClass = new CDirectorySpecification(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_DUPLICATEFILEACTION")){ *pClass = new CDuplicateFile(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ENVIRONMENTSPECIFICATION")){ *pClass = new CEnvironment(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_EXTENSIONINFOACTION")){ *pClass = new CExtensionInfoAction(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_FILESPECIFICATION")){ *pClass = new CFileSpecification(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_FONTINFOACTION")){ *pClass = new CFontInfoAction(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_INIFILESPECIFICATION")){ *pClass = new CIniFile(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_LAUNCHCONDITION")){ *pClass = new CLaunchCondition(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_MIMEINFOACTION")){ *pClass = new CMIMEInfoAction(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_MOVEFILEACTION")){ *pClass = new CMoveFile(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ODBCATTRIBUTE")){ *pClass = new CODBCAttribute(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ODBCDATASOURCESPECIFICATION")){ *pClass = new CODBCDataSource(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ODBCDRIVERSPECIFICATION")){ *pClass = new CODBCDriver(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ODBCSOURCEATTRIBUTE")){ *pClass = new CODBCSourceAttribute(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ODBCTRANSLATORSPECIFICATION")){ *pClass = new CODBCTranslator(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PATCH")){ *pClass = new CPatch(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PATCHPACKAGE")){ *pClass = new CPatchPackAge(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PROGIDSPECIFICATION")){ *pClass = new CProgIDSpecification(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PRODUCT")){ *pClass = new CProduct(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PROPERTY")){ *pClass = new CProperty(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PUBLISHCOMPONENTACTION")){ *pClass = new CPublishComponent(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_REMOVEFILEACTION")){ *pClass = new CRemoveFile(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_REMOVEINIACTION")){ *pClass = new CRemoveIniValue(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_RESERVECOST")){ *pClass = new CReserveCost(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SELFREGMODULEACTION")){ *pClass = new CSelfRegModule(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SERVICECONTROL")){ *pClass = new CServiceControl(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SERVICESPECIFICATION")){ *pClass = new CServiceSpecification(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SHORTCUTACTION")){ *pClass = new CShortcutAction(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREELEMENT")){ *pClass = new CSoftwareElement(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREELEMENTCONDITION")){ *pClass = new CSoftwareElementCondition(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREFEATURE")){ *pClass = new CSoftwareFeature(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_TYPELIBRARYACTION")){ *pClass = new CTypeLibraryAction(this, m_pNamespace, pCtx); // }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_UPGRADE")){ // *pClass = new CUpgrade(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_REGISTRYACTION")){ *pClass = new CRegistryAction(this, m_pNamespace, pCtx); ////////////////// // Associations // ////////////////// }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ACTIONCHECK")){ *pClass = new CActionCheck(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_APPLICATIONCOMMANDLINE")){ *pClass = new CApplicationCommandLine(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_CHECKCHECK")){ *pClass = new CCheckCheck(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_INSTALLEDSOFTWAREELEMENT")){ *pClass = new CInstalledSoftwareElement(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ODBCDATASOURCEATTRIBUTE")){ *pClass = new CODBCDataSourceAttribute(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ODBCDRIVERATTRIBUTE")){ *pClass = new CODBCDriverAttribute(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_ODBCDRIVERSOFTWAREELEMENT")){ *pClass = new CODBCDriverSoftwareElement(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PATCHFILE")){ *pClass = new CPatchFile(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PRODUCTCHECK")){ *pClass = new CProductEnvironment(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PRODUCTRESOURCE")){ *pClass = new CProductResource(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_PRODUCTSOFTWAREFEATURES")){ *pClass = new CProductSoftwareFeatures(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SERVICESPECIFICATIONSERVICE")){ *pClass = new CServiceSpecificationService(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SHORTCUTSAP")){ *pClass = new CShortcutSAP(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREELEMENTACTION")){ *pClass = new CSoftwareElementAction(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREELEMENTCHECK")){ *pClass = new CSoftwareElementCheck(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREELEMENTRESOURCE")){ *pClass = new CSoftwareElementServiceControl(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREFEATUREACTION")){ *pClass = new CSoftwareFeatureAction(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREFEATURECHECK")){ *pClass = new CSoftwareFeatureCondition(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREFEATUREPARENT")){ *pClass = new CSoftwareFeatureParent(this, m_pNamespace, pCtx); }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREFEATURESOFTWAREELEMENTS")){ *pClass = new CSoftwareFeatureSofwareElements(this, m_pNamespace, pCtx); }else return WBEM_E_NOT_FOUND; if(!(*pClass)) throw m_he; return hr; }; HRESULT CRequestObject::CreateObjectEnum(BSTR bstrPath, IWbemObjectSink *pHandler, IWbemContext *pCtx) { HRESULT hr = WBEM_S_NO_ERROR; CGenericClass *pClass = NULL; m_bstrPath = SysAllocString(bstrPath); if(!m_bstrPath) throw m_he; if(ParsePath(bstrPath)){ try{ //Create the appropriate class if(SUCCEEDED(hr = CreateClass(&pClass, pCtx))){ if(!pClass) throw m_he; //Enumerate the objects hr = pClass->CreateObject(pHandler, ACTIONTYPE_ENUM); } }catch(...){ if(pClass){ pClass->CleanUp(); delete pClass; } throw; } if(pClass){ pClass->CleanUp(); delete pClass; } }else hr = WBEM_E_FAILED; return hr; } HRESULT CRequestObject::PutObject(IWbemClassObject *pInst, IWbemObjectSink *pHandler, IWbemContext *pCtx) { return WBEM_E_NOT_SUPPORTED; } HRESULT CRequestObject::ExecMethod(BSTR bstrPath, BSTR bstrMethod, IWbemClassObject *pInParams, IWbemObjectSink *pHandler, IWbemContext *pCtx) { HRESULT hr = WBEM_S_NO_ERROR; // WCHAR wcTmp[BUFF_SIZE]; m_bstrPath = SysAllocString(bstrPath); if(!m_bstrPath) throw m_he; //Initialize Eventing system if(!InitializeProgress(pHandler)) return WBEM_E_FAILED; if(ParsePath(bstrPath)){ if(0 == _wcsicmp(m_bstrClass, L"WIN32_PRODUCT")){ CProduct *pClass = new CProduct(this, m_pNamespace, pCtx); if(!pClass) throw m_he; //Static Methods if(0 == _wcsicmp(bstrMethod, L"ADMIN")) if(!IsInstance()){ try{ if ( pInParams ) { hr = pClass->Admin(this, pInParams, pHandler, pCtx); } else { hr = WBEM_E_INVALID_PARAMETER; } }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; else if(0 == _wcsicmp(bstrMethod, L"ADVERTISE")) if(!IsInstance()){ try{ if ( pInParams ) { hr = pClass->Advertise(this, pInParams, pHandler, pCtx); } else { hr = WBEM_E_INVALID_PARAMETER; } }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; else if(0 == _wcsicmp(bstrMethod, L"INSTALL")) if(!IsInstance()){ try{ if ( pInParams ) { hr = pClass->Install(this, pInParams, pHandler, pCtx); } else { hr = WBEM_E_INVALID_PARAMETER; } }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; //Non-Static Methods else if(0 == _wcsicmp(bstrMethod, L"CONFIGURE")) if(IsInstance()){ try{ if ( pInParams ) { hr = pClass->Configure(this, pInParams, pHandler, pCtx); } else { hr = WBEM_E_INVALID_PARAMETER; } }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; else if(0 == _wcsicmp(bstrMethod, L"REINSTALL")) if(IsInstance()){ try{ if ( pInParams ) { hr = pClass->Reinstall(this, pInParams, pHandler, pCtx); } else { hr = WBEM_E_INVALID_PARAMETER; } }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; else if(0 == _wcsicmp(bstrMethod, L"UNINSTALL")) if(IsInstance()){ try{ // doesn't matter as we do not expect pInParams hr = pClass->Uninstall(this, pInParams, pHandler, pCtx); }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; else if(0 == _wcsicmp(bstrMethod, L"UPGRADE")) if(IsInstance()){ try{ if ( pInParams ) { hr = pClass->Upgrade(this, pInParams, pHandler, pCtx); } else { hr = WBEM_E_INVALID_PARAMETER; } }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; else hr = WBEM_E_NOT_SUPPORTED; pClass->CleanUp(); delete pClass; }else if(0 == _wcsicmp(m_bstrClass, L"WIN32_SOFTWAREFEATURE")){ CSoftwareFeature *pClass = new CSoftwareFeature(this, m_pNamespace, pCtx); if(!pClass) throw m_he; if(0 == _wcsicmp(bstrMethod, L"CONFIGURE")) if(IsInstance()){ try{ if ( pInParams ) { hr = pClass->Configure(this, pInParams, pHandler, pCtx); } else { hr = WBEM_E_INVALID_PARAMETER; } }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; else if(0 == _wcsicmp(bstrMethod, L"REINSTALL")) if(IsInstance()){ try{ if ( pInParams ) { hr = pClass->Reinstall(this, pInParams, pHandler, pCtx); } else { hr = WBEM_E_INVALID_PARAMETER; } }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; else hr = WBEM_E_NOT_SUPPORTED; pClass->CleanUp(); delete pClass; }else hr = WBEM_E_NOT_SUPPORTED; }else return WBEM_E_FAILED; return hr; } HRESULT CRequestObject::DeleteObject(BSTR bstrPath, IWbemObjectSink *pHandler, IWbemContext *pCtx) { HRESULT hr = WBEM_S_NO_ERROR; // WCHAR wcTmp[BUFF_SIZE]; m_bstrPath = SysAllocString(bstrPath); if(!m_bstrPath) throw m_he; //Initialize Eventing system if(!InitializeProgress(pHandler)) return WBEM_E_FAILED; if(ParsePath(bstrPath)){ if(0 == _wcsicmp(m_bstrClass, L"WIN32_PRODUCT")){ CProduct *pClass = new CProduct(this, m_pNamespace, pCtx); if(!pClass) throw m_he; if(IsInstance()){ try{ hr = pClass->Uninstall(this, NULL, pHandler, pCtx); }catch(...){ pClass->CleanUp(); delete pClass; throw; } }else hr = WBEM_E_INVALID_METHOD_PARAMETERS; pClass->CleanUp(); delete pClass; }else hr = WBEM_E_NOT_SUPPORTED; }else hr = WBEM_E_FAILED; return hr; } #ifdef _EXEC_QUERY_SUPPORT HRESULT CRequestObject::ExecQuery(BSTR bstrQuery, IWbemObjectSink *pHandler, IWbemContext *pCtx) { HRESULT hr = WBEM_S_NO_ERROR; CGenericClass *pClass = NULL; if(ParseQuery(bstrQuery)){ try{ //Create the appropriate class if(SUCCEEDED(hr = CreateClass(&pClass, pCtx))){ if(!pClass) throw m_he; //Enumerate the objects hr = pClass->CreateObject(pHandler, ACTIONTYPE_QUERY); } }catch(...){ if(pClass){ pClass->CleanUp(); delete pClass; } throw; } if(pClass){ pClass->CleanUp(); delete pClass; } }else hr = WBEM_E_PROVIDER_NOT_CAPABLE; return hr; } bool CRequestObject::ParseQuery(BSTR bstrQuery) { LPWSTR wcTest = NULL; try { if ( ( wcTest = new WCHAR [ ::SysStringLen ( bstrQuery ) + 1 ] ) != NULL ) { wcscpy ( wcTest, bstrQuery ); } else { throw m_he; } } catch ( ... ) { if ( wcTest ) { delete [] wcTest; wcTest = NULL; } throw; } WCHAR *pwcTest = wcTest; WCHAR wcProp[BUFF_SIZE]; WCHAR wcClass[BUFF_SIZE]; WCHAR wcTmp[BUFF_SIZE]; bool bResult = false; if ( ExpectedToken ( &pwcTest, L"SELECT" ) ) { //Get the requested property list GetNextToken(&pwcTest, wcProp); if(*wcProp != L'*'){ while(ExpectedToken(&pwcTest, L",")){ //not doing anything here yet GetNextToken(&pwcTest, wcProp); } } if ( ExpectedToken ( &pwcTest, L"FROM" ) ) { //Get the class name if ( GetNextToken ( &pwcTest, wcClass ) != NULL ) { m_bstrClass = SysAllocString(wcClass); if ( !EOL ( &pwcTest ) ) { if ( ExpectedToken ( &pwcTest, L"WHERE" ) ) { m_iPropCount = -1; int iParens = 0; bool bContinue = true; //Get the "where" clause while ( bContinue && !EOL ( &pwcTest ) ) { GetNextToken(&pwcTest, wcTmp); if(_wcsicmp(wcTmp, L"(") == 0){ iParens++; }else if(_wcsicmp(wcTmp, L")") == 0){ iParens--; }else if(!((_wcsicmp(wcTmp, L"or") == 0) || (_wcsicmp(wcTmp, L"and") == 0))){ //if we have "or" or "and" skip over it... (treat all as or) if( m_iPropCount >= MSI_KEY_LIST_SIZE) { throw m_he; } m_Property[++m_iPropCount] = SysAllocString(wcTmp); //Syntax checking if ( ExpectedToken ( &pwcTest, L"=" ) ) { if(wcscmp(GetNextToken(&pwcTest, wcTmp), L"\"") == 0){ if( m_iPropCount >= MSI_KEY_LIST_SIZE) { throw m_he; } //Deal with quoted strings m_Value[m_iPropCount] = SysAllocString(GetStringValue(&pwcTest, wcTmp)); if ( !ExpectedToken ( &pwcTest, L"\"" ) ) { bContinue = false; bResult = false; } }else{ if( m_iPropCount >= MSI_KEY_LIST_SIZE) { throw m_he; } m_Value[m_iPropCount] = SysAllocString(wcTmp); } m_iValCount++; } else { bContinue = false; bResult = false; } } } m_iPropCount++; if(iParens == 0) { bResult = true; } } } else { bResult = true; } } } } if ( wcTest ) { delete [] wcTest; wcTest = NULL; } return bResult; } WCHAR * CRequestObject::GetStringValue(WCHAR **pwcString, WCHAR wcToken[]) { //eat white space while(**pwcString == L' '){ (*pwcString)++; } wcscpy(wcToken, *pwcString); WCHAR *pwcStart = wcToken; WCHAR *pwcToken = wcToken; WCHAR *pwcPrev; //deal with eol if(*pwcToken == NULL) return NULL; //deal with strings while((*pwcToken != NULL) && ((*pwcToken != L'\"') || (*pwcPrev == L'\\'))){ if((*pwcToken == L'\"') && (*pwcPrev == L'\\')){ WCHAR *pwcTmp = pwcPrev; while(*pwcPrev){ *pwcPrev = *pwcToken; pwcPrev = (pwcToken++); } pwcToken = pwcTmp; } pwcPrev = (pwcToken++); (*pwcString)++; } *pwcToken = NULL; return pwcStart; } bool CRequestObject::ExpectedToken(WCHAR **pwcString, WCHAR *pwcExpected) { WCHAR wcTmp[BUFF_SIZE]; GetNextToken(pwcString, wcTmp); if(_wcsicmp(wcTmp, pwcExpected) == 0) return true; else return false; } WCHAR * CRequestObject::GetNextProperty(WCHAR **pwcString, WCHAR wcProp[]) { //eat white space while(**pwcString == L' '){ (*pwcString)++; } wcscpy(wcProp, *pwcString); WCHAR *pwcStart = wcProp; WCHAR *pwcToken = wcProp; //deal with strings while(*pwcToken != L'='){ pwcToken++; (*pwcString)++; } *pwcToken = NULL; return pwcStart; } WCHAR * CRequestObject::GetNextValue(WCHAR **pwcString, WCHAR wcVal[]) { wcscpy(wcVal, *pwcString); WCHAR *pwcStart = wcVal; WCHAR *pwcToken = wcVal; WCHAR *pwcPrev; //deal with strings while((*pwcToken != L' ') || ((*pwcToken != L'\"') || (*pwcPrev == L'\\'))){ pwcPrev = (pwcToken++); (*pwcString)++; } *pwcToken = NULL; return pwcStart; } bool CRequestObject::EOL(WCHAR **pwcString) { while(**pwcString == L' ') (*pwcString)++; if(wcscmp(*pwcString, L"") == 0) return true; else return false; } WCHAR * CRequestObject::GetNextToken(WCHAR **pwcString, WCHAR wcToken[]) { //eat white space while(**pwcString == L' '){ (*pwcString)++; } wcscpy(wcToken, *pwcString); WCHAR *pwcStart = wcToken; WCHAR *pwcToken = wcToken; WCHAR *pwcPrev; //deal with special chars if((*pwcToken == L'(') || (*pwcToken == L')') || (*pwcToken == L',') || (*pwcToken == L'=') || (*pwcToken == L'"')){ *(++pwcToken) = NULL; (*pwcString)++; return pwcStart; } //deal with eol if(*pwcToken == NULL) return NULL; //deal with strings while((*pwcToken != NULL) && (*pwcToken != L' ') && (*pwcToken != L',') && (*pwcToken != L'=') && ((*pwcToken != L'\"') || (*pwcPrev == L'\\'))){ pwcPrev = (pwcToken++); (*pwcString)++; } *pwcToken = NULL; return pwcStart; } #endif //_EXEC_QUERY_SUPPORT bool CRequestObject::ParsePath(BSTR bstrPath) { if(wcslen(bstrPath) < 1) return false; LPWSTR wcTest = NULL; try { if ( ( wcTest = new WCHAR [ ::SysStringLen ( bstrPath ) + 1 ] ) != NULL ) { wcscpy ( wcTest, bstrPath ); } else { throw m_he; } } catch ( ... ) { if ( wcTest ) { delete [] wcTest; wcTest = NULL; } throw; } WCHAR *pwcTest = NULL; WCHAR *pwcClassStart = wcTest; WCHAR *pwcNamespace = NULL; WCHAR *pwcStart = NULL; WCHAR *pwcStrip = NULL; WCHAR wcPrevious = NULL; int iNumQuotes = 0; bool bClass = false; bool bDoubles = false; try { //Main Parsing Loop for(pwcTest = wcTest; *pwcTest; pwcTest++){ if((*pwcTest == L'\\') && !bClass){ for(pwcNamespace = pwcTest; *pwcNamespace != L':'; pwcNamespace++){} pwcClassStart = pwcNamespace + 1; pwcTest = pwcNamespace; }else if(*pwcTest == L'.'){ if(iNumQuotes == 0){ // issolate the class name. *pwcTest = NULL; if(m_bstrClass){ SysFreeString(m_bstrClass); m_bstrClass = NULL; } m_bstrClass = SysAllocString(pwcClassStart); if(!m_bstrClass) throw m_he; bClass = true; pwcStart = (pwcTest + 1); } }else if(*pwcTest == L'='){ if(iNumQuotes == 0){ if(!bClass){ // issolate the class name. *pwcTest = NULL; if(m_bstrClass){ SysFreeString(m_bstrClass); m_bstrClass = NULL; } m_bstrClass = SysAllocString(pwcClassStart); if(!m_bstrClass) throw m_he; bClass = true; pwcStart = (pwcTest + 1); }else{ // issolate the property name. *pwcTest = NULL; if(pwcStart != NULL){ if( m_iPropCount >= MSI_KEY_LIST_SIZE) { throw m_he; } m_Property[m_iPropCount] = SysAllocString(pwcStart); if(!m_Property[m_iPropCount++]) throw m_he; pwcStart = (pwcTest + 1); }else pwcStart = (pwcTest + 1); } } }else if(*pwcTest == L','){ if(iNumQuotes != 1){ // issolate the property value. *pwcTest = NULL; if(pwcStart != NULL){ if( m_iValCount >= MSI_KEY_LIST_SIZE) { throw m_he; } m_Value[m_iValCount] = SysAllocString(pwcStart); if(!m_Value[m_iValCount++]) throw m_he; pwcStart = (pwcTest + 1); }else return false; } }else if(*pwcTest == L'\"'){ if(wcPrevious != L'\\'){ // deal with quotes in path. iNumQuotes++; if(iNumQuotes == 1) pwcStart = (pwcTest + 1); else if(iNumQuotes == 2){ *pwcTest = NULL; iNumQuotes = 0; } }else if(iNumQuotes == 1){ //deal with embedded quotes for(pwcStrip = (--pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; } }else if((*pwcTest == L'\\') && (wcPrevious == L'\\') && bClass && !bDoubles){ for(pwcStrip = (--pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; } #ifdef _STRIP_ESCAPED_CHARS else if(*pwcTest == L'%'){ //deal with escaped URL characters if(*(pwcTest + 1) == L'0'){ if(*(pwcTest + 2) == L'7'){ //bell *pwcTest = L'\\'; *(++pwcTest) = L'a'; for(pwcStrip = (++pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; }else if(*(pwcTest + 2) == L'8'){ //backspace *pwcTest = L'\\'; *(++pwcTest) = L'b'; for(pwcStrip = (++pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; }else if(*(pwcTest + 2) == L'9'){ //horizontal tab *pwcTest = L'\\'; *(++pwcTest) = L't'; for(pwcStrip = (++pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; }else if((*(pwcTest + 2) == L'A') || (*(pwcTest + 2) == L'a')){ //newline *pwcTest = L'\\'; *(++pwcTest) = L'n'; for(pwcStrip = (++pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; }else if((*(pwcTest + 2) == L'B') || (*(pwcTest + 2) == L'b')){ //vertical tab *pwcTest = L'\\'; *(++pwcTest) = L'v'; for(pwcStrip = (++pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; }else if((*(pwcTest + 2) == L'C') || (*(pwcTest + 2) == L'c')){ //formfeed *pwcTest = L'\\'; *(++pwcTest) = L'f'; for(pwcStrip = (++pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; }else if((*(pwcTest + 2) == L'D') || (*(pwcTest + 2) == L'd')){ //carriage return *pwcTest = L'\\'; *(++pwcTest) = L'r'; for(pwcStrip = (++pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; }else return false; }else if(*(pwcTest + 1) == L'1'){ return false; }else if(*(pwcTest + 1) == L'2'){ if(*(pwcTest + 2) == L'0'){ //space *pwcTest++ = L' '; for(int ip = 0; ip < 2; ip++) for(pwcStrip = (pwcTest); *pwcStrip; pwcStrip++) *pwcStrip = *(pwcStrip + 1); *pwcStrip = NULL; }else return false; } } #endif //_STRIP_ESCAPED_CHARS if((wcPrevious == *pwcTest) && !bDoubles) bDoubles = true; else bDoubles = false; wcPrevious = *pwcTest; } // if we still have values to add, do so now if(pwcStart != NULL){ if( m_iValCount >= MSI_KEY_LIST_SIZE) { throw m_he; } m_Value[m_iValCount] = SysAllocString(pwcStart); if(!m_Value[m_iValCount++]) throw m_he; }else if((m_iPropCount < 1) && (m_iValCount < 1)){ if(m_bstrClass){ SysFreeString(m_bstrClass); m_bstrClass = NULL; } m_bstrClass = SysAllocString(pwcClassStart); if(!m_bstrClass) throw m_he; } if(iNumQuotes != 0) return false; if(m_iValCount != m_iPropCount){ if(m_iValCount > m_iPropCount){ if(m_iValCount != 1) return false; } else return false; } } catch ( ... ) { if ( wcTest ) { delete [] wcTest; wcTest = NULL; } throw; } if ( wcTest ) { delete [] wcTest; wcTest = NULL; } if(!m_bstrClass) return false; return true; } HRESULT CRequestObject::InitializeList(bool bGetList) { int i = 0; WCHAR wcGUIDBuf[39]; UINT uiStatus; bool bHaveItems = false; PackageListNode *pLast = NULL; try { if(bGetList) { m_pPackageHead = new PackageListNode(); if(!m_pPackageHead) throw m_he; PackageListNode *pPos = m_pPackageHead; try { if(m_dwCheckKeyPresentStatus != ERROR_SUCCESS) { LoadHive(); } while((uiStatus = g_fpMsiEnumProductsW(i++, wcGUIDBuf)) != ERROR_NO_MORE_ITEMS) { if(uiStatus != S_OK) { throw ConvertError(uiStatus); } bHaveItems = true; // ok ( products return string representation of GUID ) wcscpy(pPos->wcCode, wcGUIDBuf); pLast = pPos; pPos = pPos->pNext = new PackageListNode(); if(!pPos) { throw m_he; } } } catch(...) { //remove the key if it wasn't there b4.... if(m_dwCheckKeyPresentStatus != ERROR_SUCCESS) { UnloadHive(); } if ( pPos != m_pPackageHead ) { delete pPos; pPos = NULL; } throw; } //remove the key if it wasn't there b4.... if(m_dwCheckKeyPresentStatus != ERROR_SUCCESS) { UnloadHive(); } delete pPos; pPos = NULL; if( !bHaveItems ) { m_pPackageHead = NULL; return WBEM_S_NO_MORE_DATA; } else { if(pLast) { pLast->pNext = NULL; } else { return WBEM_E_FAILED; } } } else { m_pPackageHead = NULL; } } catch(HRESULT e_hr) { if(pLast) { pLast->pNext = NULL; } return e_hr; } catch(...) { if(pLast) { pLast->pNext = NULL; } throw; } return WBEM_S_NO_ERROR; } bool CRequestObject::DestroyList() { PackageListNode *pPos = m_pPackageHead; PackageListNode *pLast; while(pPos){ pLast = pPos; pPos = pPos->pNext; delete pLast; } m_pPackageHead = NULL; return true; } WCHAR * CRequestObject::Package(int iPos) { PackageListNode *pPos = m_pPackageHead; while(iPos-- > 0){ if(!pPos) return NULL; pPos = pPos->pNext; } if(!pPos) return NULL; else return pPos->wcCode; } bool CRequestObject::Cleanup() { //Let's destroy our list and clear up some space if(m_bstrClass != NULL) SysFreeString(m_bstrClass); if(m_bstrPath != NULL) SysFreeString(m_bstrPath); for(int i = 0; i < MSI_KEY_LIST_SIZE; i++){ if(m_Property[i] != NULL) SysFreeString(m_Property[i]); if(m_Value[i] != NULL) SysFreeString(m_Value[i]); } DestroyList(); if(m_iThreadID != THREAD_NO_PROGRESS){ ProListNode * pNode = RemoveNode(m_iThreadID); delete pNode; } return true; } bool CRequestObject::IsInstance() { if((m_iPropCount > 0) || (m_iValCount > 0)) return true; return false; } ProListNode * CRequestObject::InitializeProgress(IWbemObjectSink *pHandler) { try { if(!m_pHead) { m_pHead = new ProListNode(); if(!m_pHead) throw m_he; m_pHead->pNext = NULL; m_pHead->pSink = NULL; m_pHead->iThread = 0; m_pHead->wTotal = m_pHead->wComplete = 0; m_pHead->lTotal = m_pHead->lComplete = m_pHead->lActionData = 0; } } catch(...) { if ( m_pHead ) { delete m_pHead; m_pHead = NULL; } throw; } ProListNode *pNode = new ProListNode; if(!pNode) throw m_he; pNode->pNext = NULL; pNode->wTotal = pNode->wComplete = 0; pNode->lTotal = pNode->lComplete = pNode->lActionData = 0; pNode->pSink = pHandler; try { m_iThreadID = InsertNode(pNode); } catch(...) { throw; } if(m_iThreadID == THREAD_NO_PROGRESS) { delete pNode; pNode = NULL; } return pNode; } bool CRequestObject::ParseProgress(WCHAR *wcMessage, ProgressStruct *ps) { WCHAR *wcp = wcMessage; WCHAR *wcpStart = wcMessage; WCHAR *wcpVal; while(*wcp){ if(*wcp == L':'){ *wcp++ = NULL; wcpVal = wcp; while(*wcp == ' ') wcp++; while(*wcp && (*wcp != ' ')) wcp++; *wcp = NULL; switch(_wtoi(wcpStart)){ case 1: ps->field1 = _wtoi(wcpVal); break; case 2: ps->field2 = _wtoi(wcpVal); break; case 3: ps->field3 = _wtoi(wcpVal); break; case 4: ps->field4 = _wtoi(wcpVal); break; default: return false; } wcpStart = (wcp + 1); } wcp++; } return true; } bool CRequestObject::ActionDataProgress(HRESULT *hr, int iThread) { ProListNode *pNode = GetNode(iThread); if ( pNode ) { //add the actiondata increment if((pNode->lTotal != 0) && (pNode->lActionData != 0)){ pNode->lComplete += pNode->lActionData; pNode->wComplete = (WORD)((10000 * pNode->lComplete) / pNode->lTotal); } *hr = (pNode->wTotal << 16) + pNode->wComplete; return true; } else { *hr = WBEM_E_UNEXPECTED; return false; } } bool CRequestObject::ActionStartProgress(HRESULT *hr, int iThread) { ProListNode *pNode = GetNode(iThread); if ( pNode ) { //reset the actiondata increment pNode->lActionData = 0; *hr = (pNode->wTotal << 16) + pNode->wComplete; return true; } else { *hr = WBEM_E_UNEXPECTED; return false; } } bool CRequestObject::CreateProgress(ProgressStruct *ps, HRESULT *hr, int iThread) { bool bResult = true; ProListNode *pNode = GetNode(iThread); //parse the progress information we get from MSI if(ps){ switch(ps->field1){ //1:0 2:x 3:x 4:x case 0: if ( pNode ) { pNode->wTotal = 10000; pNode->lTotal = ps->field2; pNode->wComplete = 0; pNode->lComplete = 0; } break; //1:1 2:x 3:x 4:x case 1: //1:1 2:x 3:1 4:x if(ps->field3 == 1) { if ( pNode ) { pNode->lActionData = ps->field2; } } break; //1:2 2:x 3:x 4:x case 2: if ( pNode ) { pNode->lComplete += ps->field2; if(pNode->lTotal != 0) { pNode->wComplete = (WORD)((10000 * pNode->lComplete)/pNode->lTotal); } } break; //1:3 2:x 3:x 4:x case 3: if ( pNode ) { pNode->lTotal += ps->field2; if(pNode->lTotal != 0) { pNode->wComplete = (WORD)((10000 * pNode->lComplete)/pNode->lTotal); } } break; default: bResult = false; break; } } if ( pNode ) { *hr = (pNode->wTotal << 16) + pNode->wComplete; } else { *hr = WBEM_E_UNEXPECTED; bResult = false; } return bResult; } ProListNode * CRequestObject::GetNode(int iThread) { //initial sanity code if(!m_pHead) return NULL; ProListNode *ptr = m_pHead; while( ptr && (ptr->pNext) && (ptr->iThread < iThread) ) { ptr = ptr->pNext; } if( ptr && ptr->iThread == iThread ) { return ptr; } else { return NULL; } } // Note - does not delete, simply removes from list ProListNode * CRequestObject::RemoveNode(int iThread) { ProListNode *ptr = m_pHead; if ( ptr != NULL ) { while((ptr->pNext) && (ptr->pNext->iThread < iThread)) {ptr = ptr->pNext;} if(ptr->pNext){ if(ptr->pNext->iThread == iThread){ ProListNode *pTmp = ptr->pNext; ptr->pNext = ptr->pNext->pNext; return pTmp; }else return NULL; }else return NULL; } return NULL; } int CRequestObject::InsertNode(ProListNode *pNode) { int iID = 0; ProListNode *ptr = m_pHead; while(ptr->pNext){ if(ptr->iThread > iID){ pNode->iThread = iID; //If it's already here, fail if((ptr->pNext) && (ptr->pNext->iThread == pNode->iThread)) return THREAD_NO_PROGRESS; pNode->pNext = ptr->pNext; ptr->pNext = pNode; return iID; } iID++; } pNode->iThread = ++iID; //If it's already here, fail if((ptr->pNext) && (ptr->pNext->iThread == pNode->iThread)) return THREAD_NO_PROGRESS; pNode->pNext = ptr->pNext; ptr->pNext = pNode; return iID; } DWORD CRequestObject::GetAccount(HANDLE TokenHandle, WCHAR *wcDomain, WCHAR *wcUser) { DWORD dwStatus = S_OK; TOKEN_USER *tTokenUser = NULL; DWORD dwReturnLength = 0; TOKEN_INFORMATION_CLASS tTokenInformationClass = TokenUser; if(!GetTokenInformation(TokenHandle, tTokenInformationClass, NULL, 0, &dwReturnLength) && GetLastError () == ERROR_INSUFFICIENT_BUFFER){ tTokenUser = (TOKEN_USER*) new UCHAR[dwReturnLength]; if(tTokenUser){ try{ if(GetTokenInformation(TokenHandle, tTokenInformationClass, (void *)tTokenUser, dwReturnLength, &dwReturnLength)){ DWORD dwUserSize = BUFF_SIZE; DWORD dwDomainSize = BUFF_SIZE; SID_NAME_USE Use; if(!LookupAccountSidW(NULL, tTokenUser->User.Sid, wcUser, &dwUserSize, wcDomain, &dwDomainSize, &Use)){ dwStatus = GetLastError(); } }else dwStatus = GetLastError(); }catch(...){ delete [] (UCHAR *)tTokenUser; throw; } delete [] (UCHAR *)tTokenUser; }else{ throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } }else dwStatus = GetLastError(); return dwStatus ; } DWORD CRequestObject::GetSid(HANDLE TokenHandle, WCHAR *wcSID, DWORD dwSID) { DWORD dwStatus = S_OK ; TOKEN_USER *tTokenUser = NULL ; DWORD dwReturnLength = 0 ; TOKEN_INFORMATION_CLASS tTokenInformationClass = TokenUser ; if(!GetTokenInformation(TokenHandle, tTokenInformationClass, NULL, 0, &dwReturnLength) && GetLastError() == ERROR_INSUFFICIENT_BUFFER){ tTokenUser = (TOKEN_USER *) new UCHAR[dwReturnLength] ; if(tTokenUser){ try{ if(GetTokenInformation(TokenHandle, tTokenInformationClass, (void *)tTokenUser, dwReturnLength, &dwReturnLength)){ // Initialize m_strSid - human readable form of our SID SID_IDENTIFIER_AUTHORITY *psia = ::GetSidIdentifierAuthority(tTokenUser->User.Sid); // We assume that only last byte is used (authorities between 0 and 15). // Correct this if needed. // ASSERT(psia->Value[0] == psia->Value[1] == psia->Value[2] == psia->Value[3] // == psia->Value[4] == 0); DWORD dwTopAuthority = psia->Value[5]; LPWSTR bstrtTempSid = NULL; try { if ( ( bstrtTempSid = new WCHAR [ BUFF_SIZE ] ) == NULL ) { throw m_he; } } catch ( ... ) { if ( bstrtTempSid ) { delete [] bstrtTempSid; bstrtTempSid = NULL; } throw; } wcscpy(bstrtTempSid, L"S-1-"); WCHAR wstrAuth[32] = { L'\0' }; _itow(dwTopAuthority, wstrAuth, 10); wcscat(bstrtTempSid, wstrAuth); int iSubAuthorityCount = *(GetSidSubAuthorityCount(tTokenUser->User.Sid)); DWORD dwTempSidCur = BUFF_SIZE; DWORD dwTempSid = 0L; dwTempSid = wcslen ( bstrtTempSid ); for(int i = 0; i < iSubAuthorityCount; i++){ DWORD dwSubAuthority = *(GetSidSubAuthority( tTokenUser->User.Sid, i )); wstrAuth[ 0 ] = L'\0'; _itow(dwSubAuthority, wstrAuth,10); DWORD dwAuth = 0L; dwAuth = wcslen ( wstrAuth ); if ( dwTempSid + dwAuth + 1 + 1 < dwTempSidCur ) { wcscat(bstrtTempSid, L"-"); wcscat(bstrtTempSid, wstrAuth); dwTempSid = dwTempSid + dwAuth + 1; } else { LPWSTR wsz = NULL; try { if ( ( wsz = new WCHAR [ ( dwTempSid + dwAuth + 1 ) * 2 + 1 ] ) != NULL ) { wcscpy ( wsz, bstrtTempSid ); wcscat ( wsz, L"-" ); wcscat ( wsz, wstrAuth ); dwTempSid = wcslen ( wsz ); dwTempSidCur = dwTempSid * 2; } else { throw m_he; } if ( bstrtTempSid ) { delete [] bstrtTempSid; bstrtTempSid = NULL; } bstrtTempSid = wsz; } catch ( ... ) { if ( wsz ) { delete [] wsz; wsz = NULL; } if ( bstrtTempSid ) { delete [] bstrtTempSid; bstrtTempSid = NULL; } throw; } } } if ( wcslen ( bstrtTempSid ) + 1 < dwSID ) { wcscpy(wcSID, bstrtTempSid); } else { dwStatus = ERROR_OUTOFMEMORY; } if ( bstrtTempSid ) { delete [] bstrtTempSid; bstrtTempSid = NULL; } }else dwStatus = GetLastError(); }catch(...){ delete [] (UCHAR *)tTokenUser; throw ; } delete [] (UCHAR *)tTokenUser; }else throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR); }else dwStatus = GetLastError(); return dwStatus ; } DWORD CRequestObject::LoadHive(/*LPWSTR pszUserName, LPWSTR pszKeyName*/) { DWORD i, dwSIDSize, dwDomainNameSize, dwSubAuthorities ; char SIDBuffer [ _MAX_PATH ]; WCHAR szDomainName[_MAX_PATH], szSID[_MAX_PATH], szTemp[_MAX_PATH]; SID *pSID = (SID *) SIDBuffer ; PSID_IDENTIFIER_AUTHORITY pSIA ; SID_NAME_USE AccountType ; CRegistry Reg; DWORD dwRetCode = ERROR_INVALID_PARAMETER; // Set the necessary privs //======================== if ( ( dwRetCode = AcquirePrivilege() ) == ERROR_SUCCESS ) { // Look up the user's account info //================================ dwSIDSize = _MAX_PATH * sizeof ( char ) ; dwDomainNameSize = _MAX_PATH; BOOL bLookup = FALSE; bLookup = LookupAccountNameW ( NULL, m_wcAccount, pSID, &dwSIDSize, szDomainName, &dwDomainNameSize, &AccountType ); if(bLookup) { // Translate the SID into text (a la PSS article Q131320) //======================================================= pSIA = GetSidIdentifierAuthority(pSID) ; dwSubAuthorities = *GetSidSubAuthorityCount(pSID) ; dwSIDSize = swprintf(szSID, _T("S-%lu-"), (DWORD) SID_REVISION) ; if((pSIA->Value[0] != 0) || (pSIA->Value[1] != 0)){ dwSIDSize += swprintf(szSID + wcslen(szSID), L"0x%02hx%02hx%02hx%02hx%02hx%02hx", (USHORT) pSIA->Value[0], (USHORT) pSIA->Value[1], (USHORT) pSIA->Value[2], (USHORT) pSIA->Value[3], (USHORT) pSIA->Value[4], (USHORT) pSIA->Value[5]) ; }else{ dwSIDSize += swprintf(szSID + wcslen(szSID), L"%lu", (ULONG)(pSIA->Value[5] ) + (ULONG)(pSIA->Value[4] << 8) + (ULONG)(pSIA->Value[3] << 16) + (ULONG)(pSIA->Value[2] << 24)); } for(i = 0 ; i < dwSubAuthorities && dwRetCode == ERROR_SUCCESS; i++) { if ( dwSIDSize > _MAX_PATH * sizeof ( char ) ) { dwRetCode = ERROR_INSUFFICIENT_BUFFER; } else { try { dwSIDSize += swprintf(szSID + dwSIDSize, L"-%lu", *GetSidSubAuthority(pSID, i)) ; } catch ( ... ) { dwRetCode = ERROR_INVALID_PARAMETER; } } } if ( dwRetCode == ERROR_SUCCESS ) { // See if the key already exists //============================== dwRetCode = Reg.Open(HKEY_USERS, szSID, KEY_READ) ; // We need to keep a handle open. See m_hKey below, so we'll let the destructor close this. // Reg.vClose(); if(dwRetCode != ERROR_SUCCESS) { // Try to locate user's registry hive //=================================== swprintf(szTemp, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%s", szSID) ; dwRetCode = Reg.Open(HKEY_LOCAL_MACHINE, szTemp, KEY_READ); if(dwRetCode == ERROR_SUCCESS) { CHString chsTemp; dwRetCode = Reg.GetCurrentKeyValue ( L"ProfileImagePath", chsTemp ); Reg.Close(); if(dwRetCode == ERROR_SUCCESS) { // NT 4 doesn't include the file name in the registry //=================================================== if(!IsLessThan4()) { chsTemp += L"\\NTUSER.DAT"; } ExpandEnvironmentStrings ( (LPCTSTR) chsTemp, szTemp, _MAX_PATH ) ; // Try it three times, another process may have the file open bool bTryTryAgain = false; int nTries = 0; do{ // need to serialize access, using "write" because RegLoadKey wants exclusive access // even though it is a read operation try { EnterCriticalSection(&m_cs); } catch ( ... ) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } try { dwRetCode = (DWORD) RegLoadKey(HKEY_USERS, szSID, szTemp) ; } catch(...) { SafeLeaveCriticalSection(&m_cs); throw; } SafeLeaveCriticalSection(&m_cs); if((dwRetCode == ERROR_SHARING_VIOLATION) && (++nTries < 11)) { Sleep(20 * nTries); bTryTryAgain = true; } else { bTryTryAgain = false; } }while (bTryTryAgain); } } } } if(dwRetCode == ERROR_SUCCESS) { DWORD dwLen = 0L; dwLen = wcslen ( szSID ); if ( dwLen < 1024 ) { wcscpy(m_wcKeyName, szSID) ; WCHAR wcKey[BUFF_SIZE]; if ( dwLen + wcslen(L"\\Software") < BUFF_SIZE ) { wcscpy(wcKey, szSID); wcscat(wcKey, L"\\Software"); LONG lRetVal = 0L; lRetVal = RegOpenKeyExW(HKEY_USERS, wcKey, 0, KEY_QUERY_VALUE, &m_hKey); if ( lRetVal != ERROR_SUCCESS ) { dwRetCode = lRetVal; } } else { dwRetCode = ERROR_OUTOFMEMORY ; } } else { dwRetCode = ERROR_OUTOFMEMORY ; } } } else { dwRetCode = ERROR_BAD_USERNAME ; } // Restore original privilege level //================================= RestorePrivilege() ; } return dwRetCode ; } DWORD CRequestObject::UnloadHive(/*LPCWSTR pszKeyName*/) { DWORD dwRetCode = ( DWORD ) E_FAIL; if(m_hKey != NULL){ RegCloseKey(m_hKey); m_hKey = NULL; } if ( ( dwRetCode = AcquirePrivilege() ) == ERROR_SUCCESS ) { try { EnterCriticalSection(&m_cs); } catch ( ... ) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } try { dwRetCode = RegUnLoadKey(HKEY_USERS, m_wcKeyName); } catch(...) { SafeLeaveCriticalSection(&m_cs); throw; } SafeLeaveCriticalSection(&m_cs); RestorePrivilege() ; } DWORD dwRetCodeHelp = ERROR_SUCCESS; if ( FAILED ( dwRetCodeHelp = ( DWORD ) CoImpersonateClient() ) && SUCCEEDED ( dwRetCode ) ) { // return failure in the case ofimpersonation failed dwRetCode = dwRetCodeHelp; } return dwRetCode ; } DWORD CRequestObject::AcquirePrivilege() { BOOL bRetCode = FALSE; HANDLE hToken = INVALID_HANDLE_VALUE ; TOKEN_PRIVILEGES TPriv ; LUID LUID ; // Validate the platform //====================== // Try getting the thread token. If it fails the first time it's // because we're a system thread and we don't yet have a thread // token, so just impersonate self and try again. if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)) { try{ GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &m_dwSize); if (m_dwSize > 0){ // This is cleaned in the destructor, so no try/catch required m_pOriginalPriv = (TOKEN_PRIVILEGES*) new BYTE[m_dwSize]; if (m_pOriginalPriv == NULL){ throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } if(m_pOriginalPriv && GetTokenInformation(hToken, TokenPrivileges, m_pOriginalPriv, m_dwSize, &m_dwSize)){ bRetCode = LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &LUID); if(bRetCode){ TPriv.PrivilegeCount = 1 ; TPriv.Privileges[0].Luid = LUID ; TPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; bRetCode = AdjustTokenPrivileges(hToken, FALSE, &TPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL); } bRetCode = LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &LUID); if(bRetCode){ TPriv.PrivilegeCount = 1 ; TPriv.Privileges[0].Luid = LUID ; TPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; bRetCode = AdjustTokenPrivileges(hToken, FALSE, &TPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL) ; } } }catch(...){ CloseHandle(hToken); throw ; } CloseHandle(hToken); } if(!bRetCode){ return GetLastError(); } return ERROR_SUCCESS ; } void CRequestObject::RestorePrivilege() { if (m_pOriginalPriv != NULL){ HANDLE hToken; try{ if(OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TRUE, &hToken)){ AdjustTokenPrivileges(hToken, FALSE, m_pOriginalPriv, m_dwSize, NULL, NULL); CloseHandle(hToken) ; } }catch(...){ delete m_pOriginalPriv; m_pOriginalPriv = NULL; m_dwSize = 0; throw; } delete m_pOriginalPriv; m_pOriginalPriv = NULL; m_dwSize = 0; } } //Properties ///////////////////// const char * pAccesses = "Accesses"; const char * pAction = "Action"; const char * pActionID = "ActionID"; const char * pAntecedent = "Antecedent"; const char * pAppData = "AppData"; const char * pAppID = "AppID"; const char * pArgument = "Argument"; const char * pArguments = "Arguments"; const char * pAttribute = "Attribute"; const char * pAttributes = "Attributes"; const char * pCaption = "Caption"; const char * pCabinet = "Cabinet"; const char * pCheck = "Check"; const char * pCheckID = "CheckID"; const char * pCLSID = "CLSID"; const char * pCommand = "Command"; const char * pCommandLine = "CommandLine"; const char * pComponent = "Component"; const char * pComponentID = "ComponentID"; const char * pCondition = "Condition"; const char * pContext = "Context"; const char * pContentType = "ContentType"; const char * pCost = "Cost"; const char * pCreationClassName = "CreationClassName"; const char * pDataSource = "DataSource"; const char * pDefaultDir = "DefaultDir"; const char * pDefInprocHandler = "DefInprocHandler"; const char * pDependencies = "Dependencies"; const char * pDependent = "Dependent"; const char * pDescription = "Description"; const char * pDestination = "Destination"; const char * pDestFolder = "DestFolder"; const char * pDestName = "DestName"; const char * pDirectory = "Directory"; const char * pDirectoryName = "DirectoryName"; const char * pDirectoryPath = "DirectoryPath"; const char * pDirProperty = "DirProperty"; const char * pDiskID = "DiskID"; const char * pDiskPrompt = "DiskPrompt"; const char * pDisplay = "Display"; const char * pDisplayName = "DisplayName"; const char * pDomain = "Domain"; const char * pDriver = "Driver"; const char * pDriverDescription = "DriverDescription"; const char * pElement = "Element"; const char * pEntryName = "EntryName"; const char * pEntryValue = "EntryValue"; const char * pEnvironment = "Environment"; const char * pError = "Error"; const char * pErrorControl = "ErrorControl"; const char * pEvent = "Event"; const char * pExpression = "Expression"; const char * pExpressionType = "ExpressionType"; const char * pExtension = "Extension"; const char * pFeature = "Feature"; const char * pFeatures = "Features"; const char * pField = "Field"; const char * pFile = "File"; const char * pFileKey = "FileKey"; const char * pFileName = "FileName"; const char * pFileSize = "FileSize"; const char * pFileTypeMask = "FileTypeMask"; const char * pFontTitle = "FontTitle"; const char * pGroupComponent = "GroupComponent"; const char * pHotKey = "HotKey"; const char * pID = "ID"; const char * pIdentificationCode = "IdentificationCode"; const char * pIdentifyingNumber = "IdentifyingNumber"; const char * pIniFile = "IniFile"; const char * pInsertable = "Insertable"; const char * pInstallDate = "InstallDate"; const char * pInstallDate2 = "InstallDate2"; const char * pInstallLocation = "InstallLocation"; const char * pInstallMode = "InstallMode"; const char * pInstallState = "InstallState"; const char * pKey = "Key"; const char * pLanguage = "Language"; const char * pLastSequence = "LastSequence"; const char * pLastUse = "LastUse"; const char * pLevel = "Level"; const char * pLibID = "LibID"; const char * pLoadOrderGroup = "LoadOrderGroup"; const char * pLocation = "Location"; const char * pManufacturer = "Manufacturer"; const char * pMaxDate = "MaxDate"; const char * pMaxSize = "MaxSize"; const char * pMaxVersion = "MaxVersion"; const char * pMessage = "Message"; const char * pMIME = "MIME"; const char * pMinDate = "MinDate"; const char * pMinSize = "MinSize"; const char * pMinVersion = "MinVersion"; const char * pName = "Name"; const char * pNext = "Next"; const char * pOperator = "Operator"; const char * pOptions = "Options"; const char * pPackageCache = "PackageCache"; const char * pParent = "Parent"; const char * pPartComponent = "PartComponent"; const char * pPassword = "Password"; const char * pPatch = "Patch"; const char * pPatchID = "PatchID"; const char * pPatchSize = "PatchSize"; const char * pPath = "Path"; const char * pPermission = "Permission"; const char * pPrior = "Prior"; const char * pProduct = "Product"; const char * pProductCode = "ProductCode"; const char * pProductName = "ProductName"; const char * pProductVersion = "ProductVersion"; const char * pProgID = "ProgID"; const char * pProperty = "Property"; const char * pQual = "Qual"; const char * pRegistration = "Registration"; const char * pRegistry = "Registry"; const char * pRemoteName = "RemoteName"; const char * pReserveKey = "ReserveKey"; const char * pReserveLocal = "ReserveLocal"; const char * pReserveSource = "ReserveSource"; const char * pResource = "Resource"; const char * pRoot = "Root"; const char * pSection = "Section"; const char * pSequence = "Sequence"; const char * pServiceType = "ServiceType"; const char * pSetting = "Setting"; const char * pSetupFile = "SetupFile"; const char * pShellNew = "ShellNew"; const char * pShellNewValue = "ShellNewValue"; const char * pSignature = "Signature"; const char * pShortcut = "Shortcut"; const char * pShowCmd = "ShowCmd"; const char * pSoftware = "Software"; const char * pSoftwareElementID = "SoftwareElementID"; const char * pSoftwareElementState = "SoftwareElementState"; const char * pSource = "Source"; const char * pSourceFolder = "SourceFolder"; const char * pSourceName = "SourceName"; const char * pStartMode = "StartMode"; const char * pStartName = "StartName"; const char * pStartType = "StartType"; const char * pStatus = "Status"; const char * pSystem = "System"; const char * pSystemCreationClassName = "SystemCreationClassName"; const char * pSystemName = "SystemName"; const char * pTable = "Table"; const char * pTarget = "Target"; const char * pTargetOperatingSystem = "TargetOperatingSystem"; const char * pTranslator = "Translator"; const char * pType = "Type"; const char * pUpgradeCode = "UpgradeCode"; const char * pUser = "User"; const char * pValue = "Value"; const char * pVendor = "Vendor"; const char * pVerb = "Verb"; const char * pVersion = "Version"; const char * pVolumeLabel = "VolumeLabel"; const char * pWait = "Wait"; const char * pWkDir = "WkDir";