// SoftwareFeature.cpp: implementation of the CSoftwareFeature class. // // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved // //////////////////////////////////////////////////////////////////////// #include "precomp.h" #include "SoftwareFeature.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSoftwareFeature::CSoftwareFeature(CRequestObject *pObj, IWbemServices *pNamespace, IWbemContext *pCtx):CGenericClass(pObj, pNamespace, pCtx) { } CSoftwareFeature::~CSoftwareFeature() { } HRESULT CSoftwareFeature::CreateObject(IWbemObjectSink *pHandler, ACTIONTYPE atAction) { HRESULT hr = WBEM_S_NO_ERROR; int i = -1; int iEnum; long lDate; WCHAR wcBuf[BUFF_SIZE]; WCHAR wcName[BUFF_SIZE]; WCHAR wcParent[BUFF_SIZE]; WCHAR wcDesc[BUFF_SIZE]; #if !defined(_UNICODE) WCHAR wcTmp[BUFF_SIZE]; #endif WCHAR wcProductCode[39]; DWORD dwBufSize; DWORD dwBufSize2; DWORD dwCount; DWORD dwAttrib; WORD wDate; bool bMatch = false; UINT uiStatus; //These will change from class to class bool bFeature, bName, bVersion = false , bIDNum, bProductHandle; INSTALLSTATE piInstalled; while(!bMatch && m_pRequest->Package(++i) && (hr != WBEM_E_CALL_CANCELLED)){ wcscpy(wcProductCode, m_pRequest->Package(i)); //Open our database try { if ( GetView ( NULL, wcProductCode, NULL, NULL, FALSE, TRUE ) ) { bProductHandle = true; } else { bProductHandle = false; } iEnum = 0; // try to get available feature do { uiStatus = g_fpMsiEnumFeaturesW(wcProductCode, iEnum++, wcName, wcParent); } while ( uiStatus == ERROR_MORE_DATA ); while(!bMatch && (uiStatus != ERROR_NO_MORE_ITEMS) && (hr != WBEM_E_CALL_CANCELLED)){ CheckMSI(uiStatus); if(FAILED(hr = SpawnAnInstance(&m_pObj))) throw hr; //---------------------------------------------------- dwBufSize = BUFF_SIZE; CheckMSI(g_fpMsiGetProductInfoW(wcProductCode, #if defined(_UNICODE) INSTALLPROPERTY_PRODUCTNAME #else TcharToWchar(INSTALLPROPERTY_PRODUCTNAME, wcTmp) #endif , wcBuf, &dwBufSize)); PutKeyProperty(m_pObj, pProductName, wcBuf, &bName, m_pRequest); dwBufSize = BUFF_SIZE; if(ERROR_SUCCESS == g_fpMsiGetProductInfoW(wcProductCode, #if defined(_UNICODE) INSTALLPROPERTY_VERSIONSTRING #else TcharToWchar(INSTALLPROPERTY_VERSIONSTRING, wcTmp) #endif , wcBuf, &dwBufSize)) PutKeyProperty(m_pObj, pVersion, wcBuf, &bVersion, m_pRequest); else{ dwBufSize = BUFF_SIZE; if(ERROR_SUCCESS == g_fpMsiGetProductInfoW(wcProductCode, #if defined(_UNICODE) INSTALLPROPERTY_VERSION #else TcharToWchar(INSTALLPROPERTY_VERSION, wcTmp) #endif , wcBuf, &dwBufSize)) PutKeyProperty(m_pObj, pVersion, wcBuf, &bVersion, m_pRequest); } if ( bProductHandle ) { dwBufSize = BUFF_SIZE; CheckMSI(g_fpMsiGetProductPropertyW(msidata.GetProduct(), L"Manufacturer", wcBuf, &dwBufSize)); PutProperty(m_pObj, pVendor, wcBuf); dwBufSize = BUFF_SIZE; CheckMSI(g_fpMsiGetProductPropertyW(msidata.GetProduct(), L"ProductVersion", wcBuf, &dwBufSize)); PutKeyProperty(m_pObj, pVersion, wcBuf, &bVersion, m_pRequest); } PutKeyProperty(m_pObj, pIdentifyingNumber, wcProductCode, &bIDNum, m_pRequest); dwBufSize = BUFF_SIZE; PutKeyProperty(m_pObj, pName, wcName, &bFeature, m_pRequest); //==================================================== piInstalled = g_fpMsiQueryFeatureStateW(m_pRequest->Package(i), wcName); PutProperty(m_pObj, pInstallState, (int)piInstalled); if(ERROR_SUCCESS == g_fpMsiGetFeatureUsageW(wcProductCode, wcName, &dwCount, &wDate)){ PutProperty(m_pObj, pAccesses, (int)dwCount); lDate = (1980 + ((wDate & 65024) >> 9)) * 10000; lDate += ((wDate & 480) >> 5) * 100; lDate += (wDate & 31 ); //safe operation _ltow(lDate, wcBuf, 10); wcscat(wcBuf, L"******.000000+***"); PutProperty(m_pObj, pLastUse, wcBuf); } if ( bProductHandle ) { dwBufSize = dwBufSize2 = BUFF_SIZE; if ( ERROR_SUCCESS == g_fpMsiGetFeatureInfoW ( msidata.GetProduct (), wcName, &dwAttrib, wcBuf, &dwBufSize, wcDesc, &dwBufSize2 ) ) { PutProperty(m_pObj, pDescription, wcDesc); PutProperty(m_pObj, pCaption, wcBuf); PutProperty(m_pObj, pAttributes, (int)dwAttrib); } else { PutProperty(m_pObj, pDescription, wcName); PutProperty(m_pObj, pCaption, wcName); } } else { PutProperty(m_pObj, pDescription, wcName); PutProperty(m_pObj, pCaption, wcName); } //---------------------------------------------------- if(bFeature && bName && bVersion && bIDNum) bMatch = true; if((atAction != ACTIONTYPE_GET) || bMatch){ hr = pHandler->Indicate(1, &m_pObj); } m_pObj->Release(); m_pObj = NULL; // try to get available feature do { uiStatus = g_fpMsiEnumFeaturesW(wcProductCode, iEnum++, wcName, wcParent); } while ( uiStatus == ERROR_MORE_DATA ); } } catch(...) { msidata.CloseProduct (); if(m_pObj) { m_pObj->Release(); m_pObj = NULL; } throw; } msidata.CloseProduct (); } return hr; } bool CSoftwareFeature::CheckUsage(UINT uiStatus) { switch(uiStatus){ case ERROR_BAD_CONFIGURATION: throw WBEM_E_FAILED; case ERROR_INSTALL_FAILURE: return false; case ERROR_SUCCESS: return true; default: return false; } return false; } HRESULT CSoftwareFeature::Configure(CRequestObject *pReqObj, IWbemClassObject *pInParams, IWbemObjectSink *pHandler, IWbemContext *pCtx) { HRESULT hr = WBEM_S_NO_ERROR; HRESULT hrReturn = WBEM_S_NO_ERROR; int iState; UINT uiStatus = 1603; WCHAR wcCode[BUFF_SIZE]; WCHAR wcFeature[BUFF_SIZE]; BSTR bstrReturnValue = SysAllocString(L"ReturnValue"); if(!bstrReturnValue) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR); BSTR bstrConfigure = SysAllocString(L"Configure"); if(!bstrConfigure) { ::SysFreeString (bstrReturnValue); throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR); } IWbemClassObject *pClass = NULL; IWbemClassObject *pOutClass = NULL; IWbemClassObject *pOutParams = NULL; VARIANT v; INSTALLSTATE isState; int i = -1; bool bFoundCode = false; bool bFoundFeature = false; if(SUCCEEDED(hr = pReqObj->m_pNamespace->GetObject(pReqObj->m_bstrClass, 0, pCtx, &pClass, NULL))) { if(SUCCEEDED(hr = pClass->GetMethod(bstrConfigure, 0, NULL, &pOutClass))) { if(SUCCEEDED(hr = pOutClass->SpawnInstance(0, &pOutParams))) { //Get PackageLocation if(!SUCCEEDED(GetProperty(pInParams, "InstallState", &iState))) hrReturn = WBEM_E_INVALID_METHOD_PARAMETERS; //Get the Product Code while(pReqObj->m_Property[++i]) { if(wcscmp(pReqObj->m_Property[i], L"IdentifyingNumber") == 0) { if ( wcslen (pReqObj->m_Value[i]) < BUFF_SIZE ) { wcscpy(wcCode, pReqObj->m_Value[i]); bFoundCode = true; break; } } } //Get the Feature Name i = -1; while(pReqObj->m_Property[++i]) { if(wcscmp(pReqObj->m_Property[i], L"Name") == 0) { if ( wcslen (pReqObj->m_Value[i]) < BUFF_SIZE ) { wcscpy(wcFeature, pReqObj->m_Value[i]); bFoundFeature = true; break; } } } if(bFoundCode && bFoundFeature){ //Get the appropriate State switch(iState){ case 1: isState = INSTALLSTATE_DEFAULT; break; case 2: isState = INSTALLSTATE_ADVERTISED; break; case 3: isState = INSTALLSTATE_LOCAL; break; case 4: isState = INSTALLSTATE_ABSENT; break; case 5: isState = INSTALLSTATE_SOURCE; break; default: isState = INSTALLSTATE_NOTUSED; break; } //If everything is valid, proceed if((isState != INSTALLSTATE_NOTUSED) && (hrReturn == WBEM_S_NO_ERROR)){ if(!IsNT4()){ if ( msidata.Lock () ) { INSTALLUI_HANDLER ui = NULL; //Set UI Level w/ event callback ui = SetupExternalUI ( ); try { //Call Installer uiStatus = g_fpMsiConfigureFeatureW(wcCode, wcFeature, isState); } catch(...) { uiStatus = static_cast < UINT > ( RPC_E_SERVERFAULT ); } //Restore UI Level w/ event callback RestoreExternalUI ( ui ); msidata. Unlock(); } }else{ ///////////////// // NT4 fix code.... try{ WCHAR wcAction[20]; wcscpy(wcAction, L"/sfconfigure"); WCHAR wcTmp[100]; _itow((int)isState, wcTmp, 10); LPWSTR wcCommandLine = NULL; try { if ( ( wcCommandLine = new WCHAR [ wcslen ( wcCode ) + wcslen ( wcFeature ) + 3 + wcslen ( wcTmp ) ] ) != NULL ) { wcscpy(wcCommandLine, wcCode); wcscat(wcCommandLine, L" "); wcscat(wcCommandLine, wcFeature); wcscat(wcCommandLine, L" "); wcscat(wcCommandLine, wcTmp); hrReturn = LaunchProcess(wcAction, wcCommandLine, &uiStatus); delete [] wcCommandLine; } else { throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR); } } catch ( ... ) { if ( wcCommandLine ) { delete [] wcCommandLine; wcCommandLine = NULL; } hrReturn = E_OUTOFMEMORY; } }catch(...){ hrReturn = WBEM_E_FAILED; } //////////////////// } if(SUCCEEDED(hrReturn)){ //Set up ReturnValue VariantInit(&v); V_VT(&v) = VT_I4; V_I4(&v) = uiStatus; BSTR bstrReturnValue = SysAllocString(L"ReturnValue"); if(!bstrReturnValue) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR); if(SUCCEEDED(hrReturn = pOutParams->Put(bstrReturnValue, 0, &v, NULL))) pHandler->Indicate(1, &pOutParams); SysFreeString(bstrReturnValue); } }else hrReturn = WBEM_E_INVALID_METHOD_PARAMETERS; }else hr = WBEM_E_FAILED; pOutParams->Release(); }else hrReturn = WBEM_E_INVALID_METHOD_PARAMETERS; pOutClass->Release(); } pClass->Release(); } SysFreeString(bstrReturnValue); SysFreeString(bstrConfigure); return hrReturn; } HRESULT CSoftwareFeature::Reinstall(CRequestObject *pReqObj, IWbemClassObject *pInParams, IWbemObjectSink *pHandler, IWbemContext *pCtx) { HRESULT hr = WBEM_S_NO_ERROR; HRESULT hrReturn = WBEM_S_NO_ERROR; int iMode; UINT uiStatus = 1603; WCHAR wcCode[BUFF_SIZE]; WCHAR wcFeature[BUFF_SIZE]; BSTR bstrReturnValue = SysAllocString(L"ReturnValue"); if(!bstrReturnValue) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR); BSTR bstrReinstall = SysAllocString(L"Reinstall"); if(!bstrReinstall) { ::SysFreeString (bstrReturnValue); throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR); } IWbemClassObject *pClass = NULL; IWbemClassObject *pOutClass = NULL; IWbemClassObject *pOutParams = NULL; VARIANT v; DWORD dwMode; int i = -1; bool bFoundCode = false; bool bFoundFeature = false; if(SUCCEEDED(hr = pReqObj->m_pNamespace->GetObject(pReqObj->m_bstrClass, 0, pCtx, &pClass, NULL))){ if(SUCCEEDED(hr = pClass->GetMethod(bstrReinstall, 0, NULL, &pOutClass))){ if(SUCCEEDED(hr = pOutClass->SpawnInstance(0, &pOutParams))){ //Get Reinstall Mode if(!SUCCEEDED(GetProperty(pInParams, "ReinstallMode", &iMode))) hrReturn = WBEM_E_INVALID_METHOD_PARAMETERS; //Get the Product Code while(pReqObj->m_Property[++i]) { if(wcscmp(pReqObj->m_Property[i], L"IdentifyingNumber") == 0) { if ( wcslen (pReqObj->m_Value[i]) < BUFF_SIZE ) { wcscpy(wcCode, pReqObj->m_Value[i]); bFoundCode = true; break; } } } //Get the Feature Name i = -1; while(pReqObj->m_Property[++i]) { if(wcscmp(pReqObj->m_Property[i], L"Name") == 0) { if ( wcslen (pReqObj->m_Value[i]) < BUFF_SIZE ) { wcscpy(wcFeature, pReqObj->m_Value[i]); bFoundFeature = true; break; } } } if(bFoundCode && bFoundFeature){ //Get the appropriate ReinstallMode switch(iMode){ case 1: dwMode = REINSTALLMODE_FILEMISSING; break; case 2: dwMode = REINSTALLMODE_FILEOLDERVERSION; break; case 3: dwMode = REINSTALLMODE_FILEEQUALVERSION; break; case 4: dwMode = REINSTALLMODE_FILEEXACT; break; case 5: dwMode = REINSTALLMODE_FILEVERIFY; break; case 6: dwMode = REINSTALLMODE_FILEREPLACE; break; case 7: dwMode = REINSTALLMODE_USERDATA; break; case 8: dwMode = REINSTALLMODE_MACHINEDATA; break; case 9: dwMode = REINSTALLMODE_SHORTCUT; break; case 10: dwMode = REINSTALLMODE_PACKAGE; break; default: dwMode = NULL; break; } //If everything is valid, proceed if ( dwMode && hrReturn == WBEM_S_NO_ERROR ) { if(!IsNT4()){ if ( msidata.Lock () ) { INSTALLUI_HANDLER ui = NULL; //Set UI Level w/ event callback ui = SetupExternalUI ( ); try { //Call Installer uiStatus = g_fpMsiReinstallFeatureW(wcCode, wcFeature, dwMode); } catch(...) { uiStatus = static_cast < UINT > ( RPC_E_SERVERFAULT ); } //Restore UI Level w/ event callback RestoreExternalUI ( ui ); msidata. Unlock(); } }else{ ///////////////// // NT4 fix code.... try{ WCHAR wcAction[20]; wcscpy(wcAction, L"/sfreinstall"); WCHAR wcTmp[100]; _itow((int)dwMode, wcTmp, 10); LPWSTR wcCommandLine = NULL; try { if ( ( wcCommandLine = new WCHAR [ wcslen ( wcCode ) + wcslen ( wcFeature ) + 3 + wcslen ( wcTmp ) ] ) != NULL ) { wcscpy(wcCommandLine, wcCode); wcscat(wcCommandLine, L" "); wcscat(wcCommandLine, wcFeature); wcscat(wcCommandLine, L" "); wcscat(wcCommandLine, wcTmp); hrReturn = LaunchProcess(wcAction, wcCommandLine, &uiStatus); delete [] wcCommandLine; } else { throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR); } } catch ( ... ) { if ( wcCommandLine ) { delete [] wcCommandLine; wcCommandLine = NULL; } hrReturn = E_OUTOFMEMORY; } }catch(...){ hrReturn = WBEM_E_FAILED; } //////////////////// } if(SUCCEEDED(hrReturn)){ //Set up ReturnValue VariantInit(&v); V_VT(&v) = VT_I4; V_I4(&v) = uiStatus; BSTR bstrReturnValue = SysAllocString(L"ReturnValue"); if(!bstrReturnValue) throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR); if(SUCCEEDED(hrReturn = pOutParams->Put(bstrReturnValue, 0, &v, NULL))) pHandler->Indicate(1, &pOutParams); SysFreeString(bstrReturnValue); } }else hrReturn = WBEM_E_INVALID_METHOD_PARAMETERS; }else hr = WBEM_E_FAILED; pOutParams->Release(); }else hrReturn = WBEM_E_INVALID_METHOD_PARAMETERS; pOutClass->Release(); } pClass->Release(); } SysFreeString(bstrReturnValue); SysFreeString(bstrReinstall); return hrReturn; }