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.
2712 lines
68 KiB
2712 lines
68 KiB
// RequestObject.cpp: implementation of the CRequestObject class.
|
|
|
|
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "precomp.h"
|
|
#include "requestobject.h"
|
|
#include <stdio.h>
|
|
#include <CRegCls.h>
|
|
#include <wininet.h>
|
|
|
|
//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";
|