// database.cpp, implementation of CSecurityDatabase class // Copyright (c)1997-1999 Microsoft Corporation // ////////////////////////////////////////////////////////////////////// #include "precomp.h" #include "database.h" #include "persistmgr.h" //#include #include #include "requestobject.h" const DWORD dwSecDBVersion = 1; /* Routine Description: Name: CSecurityDatabase::CSecurityDatabase Functionality: This is the constructor. Pass along the parameters to the base class Virtual: No (you know that, constructor won't be virtual!) Arguments: pKeyChain - Pointer to the ISceKeyChain COM interface which is prepared by the caller who constructs this instance. pNamespace - Pointer to WMI namespace of our provider (COM interface). Passed along by the caller. Must not be NULL. pCtx - Pointer to WMI context object (COM interface). Passed along by the caller. It's up to WMI whether this interface pointer is NULL or not. Return Value: None as any constructor Notes: if you create any local members, think about initialize them here */ CSecurityDatabase::CSecurityDatabase ( IN ISceKeyChain *pKeyChain, IN IWbemServices *pNamespace, IN IWbemContext *pCtx ) : CGenericClass(pKeyChain, pNamespace, pCtx) { } /* Routine Description: Name: CSecurityDatabase::~CSecurityDatabase Functionality: Destructor. Necessary as good C++ discipline since we have virtual functions. Virtual: Yes. Arguments: none as any destructor Return Value: None as any destructor Notes: if you create any local members, think about whether there is any need for a non-trivial destructor */ CSecurityDatabase::~CSecurityDatabase () { } //Sce_Database /* Routine Description: Name: CSecurityDatabase::CreateObject Functionality: Create WMI objects (Sce_Database). Depending on parameter atAction, this creation may mean: (a) Get a single instance (atAction == ACTIONTYPE_GET) (b) Get several instances satisfying some criteria (atAction == ACTIONTYPE_QUERY) Virtual: Yes. Arguments: pHandler - COM interface pointer for notifying WMI for creation result. atAction - Get single instance ACTIONTYPE_GET Get several instances ACTIONTYPE_QUERY Return Value: Success: it must return success code (use SUCCEEDED to test). It is not guaranteed to return WBEM_NO_ERROR. The returned objects are indicated to WMI, not directly passed back via parameters. Failure: Various errors may occurs. Except WBEM_E_NOT_FOUND, any such error should indicate the failure of getting the wanted instance. If WBEM_E_NOT_FOUND is returned in querying situations, this may not be an error depending on caller's intention. Notes: for Sce_Database, we don't support delete! */ HRESULT CSecurityDatabase::CreateObject ( IN IWbemObjectSink *pHandler, IN ACTIONTYPE atAction ) { // // we know how to: // Get single instance ACTIONTYPE_GET // Get several instances ACTIONTYPE_QUERY // if ( ACTIONTYPE_GET != atAction && ACTIONTYPE_QUERY != atAction ) { return WBEM_E_NOT_SUPPORTED; } // // Sce_Database class has only one key property (path) // DWORD dwCount = 0; HRESULT hr = m_srpKeyChain->GetKeyPropertyCount(&dwCount); if (SUCCEEDED(hr) && dwCount == 1) { // // We must have the pPath key property. // m_srpKeyChain->GetKeyPropertyValue WBEM_S_FALSE if the key is not recognized // So, we need to test against WBEM_S_FALSE if the property is mandatory // CComVariant varPath; hr = m_srpKeyChain->GetKeyPropertyValue(pPath, &varPath); if (FAILED(hr) || hr == WBEM_S_FALSE) { return WBEM_E_NOT_FOUND; } if (SUCCEEDED(hr) && hr != WBEM_S_FALSE && varPath.vt == VT_BSTR) { // // Create the database instance // // // expand those env variable tokens inside a path // CComBSTR bstrExpandedPath; // // bDb will be returned true if the the path is pointing to a database type file // BOOL bDb=FALSE; hr = CheckAndExpandPath(varPath.bstrVal, &bstrExpandedPath, &bDb); if ( !bDb ) { hr = WBEM_E_INVALID_OBJECT_PATH; } else { // // make sure the store (just a file) really exists // DWORD dwAttrib = GetFileAttributes(bstrExpandedPath); if ( dwAttrib != -1 ) { hr = ConstructInstance(pHandler, bstrExpandedPath, varPath.bstrVal); } else { hr = WBEM_E_NOT_FOUND; } } } } else if (SUCCEEDED(hr)) { // // the object says that it has more than one key properties, // we know that is incorrect // hr = WBEM_E_INVALID_OBJECT; } return hr; } /* Routine Description: Name: CSecurityDatabase::ConstructInstance Functionality: This is private function to create an instance of Sce_Database. Virtual: No. Arguments: pHandler - COM interface pointer for notifying WMI of any events. wszDatabaseName - file path to the database. wszLogDatabasePath - Log path. Return Value: Success: it must return success code (use SUCCEEDED to test). It is not guaranteed to return WBEM_NO_ERROR. Failure: Various errors may occurs. Any such error should indicate the creating the instance. Notes: */ HRESULT CSecurityDatabase::ConstructInstance ( IN IWbemObjectSink *pHandler, IN LPCWSTR wszDatabaseName, IN LPCWSTR wszLogDatabasePath ) { // Get information from the database // ================== HRESULT hr = WBEM_S_NO_ERROR; SCESTATUS rc; // // hProfile is where SCE reads info to // PVOID hProfile=NULL; rc = SceOpenProfile(wszDatabaseName, SCE_JET_FORMAT, &hProfile); if ( rc != SCESTATUS_SUCCESS ) { // // SCE returned errors needs to be translated to HRESULT. // return ProvDosErrorToWbemError(ProvSceStatusToDosError(rc)); } PWSTR wszDescription = NULL; SYSTEMTIME stConfig; SYSTEMTIME stAnalyze; CComBSTR bstrConfig; CComBSTR bstrAnalyze; // // need to free wszDescription // rc = SceGetScpProfileDescription(hProfile, &wszDescription); if ( SCESTATUS_SUCCESS == rc ) { rc = SceGetDbTime(hProfile, &stConfig, &stAnalyze); } // // SCE returned errors needs to be translated to HRESULT. // In case this is not an error, hr will be assigned to WBEM_NO_ERROR // hr = ProvDosErrorToWbemError(ProvSceStatusToDosError(rc)); SceCloseProfile( &hProfile ); // // now log it // CComBSTR bstrLogOut; // // the use of the macro SCE_PROV_IfErrorGotoCleanup cause // a "goto CleanUp;" with hr set to the return value from // the function (macro parameter) // if ( SUCCEEDED(hr) ) { SCE_PROV_IfErrorGotoCleanup(MakeSingleBackSlashPath((PWSTR)wszLogDatabasePath, L'\\', &bstrLogOut)); // // convert the time stamp // SCE_PROV_IfErrorGotoCleanup(GetDMTFTime(stConfig, &bstrConfig)); SCE_PROV_IfErrorGotoCleanup(GetDMTFTime(stAnalyze, &bstrAnalyze)); // // create a blank object that can be filled with properties // CComPtr srpObj; SCE_PROV_IfErrorGotoCleanup(SpawnAnInstance(&srpObj)); // // create a property mgr for this new object to put properties // CScePropertyMgr ScePropMgr; ScePropMgr.Attach(srpObj); // // put properties: path, description, analyze, and configuration // SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pPath, bstrLogOut)); SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pDescription, wszDescription)); if (bstrAnalyze) { SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pLastAnalysis, bstrAnalyze)); } if (bstrConfig) { SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pLastConfiguration, bstrConfig)); } // // put version // SCE_PROV_IfErrorGotoCleanup(ScePropMgr.PutProperty(pVersion, dwSecDBVersion)); // // inform WMI of the new instance it requests // SCE_PROV_IfErrorGotoCleanup(pHandler->Indicate(1, &srpObj)); } CleanUp: delete [] wszDescription; return hr; } /* Routine Description: Name: GetDMTFTime Functionality: Helper to format a string version time stamp. Virtual: No. Arguments: t_Systime - the system time to format. bstrOut - out parameter to return the string version of the time. Return Value: Success: WBEM_NO_ERROR. Failure: Various errors may occurs. Any such error should indicate failure to format. Notes: */ HRESULT GetDMTFTime ( IN SYSTEMTIME t_Systime, IN BSTR *bstrOut ) { if ( !bstrOut ) { return WBEM_E_INVALID_PARAMETER; } *bstrOut = SysAllocStringLen(NULL, DMTFLEN + 1); if ( ! (*bstrOut) ) { return WBEM_E_OUT_OF_MEMORY; } HRESULT hr = WBEM_NO_ERROR; FILETIME t_ft; LONG micros=0; if ( SystemTimeToFileTime(&t_Systime, &t_ft) ) { ULONGLONG uTime=0; uTime = t_ft.dwHighDateTime; uTime = uTime << 32; uTime |= t_ft.dwLowDateTime; LONGLONG tmpMicros = uTime % 10000000; micros = (LONG)(tmpMicros / 10); } swprintf((*bstrOut), L"%04.4d%02.2d%02.2d%02.2d%02.2d%02.2d.%06.6d%c%03.3ld", t_Systime.wYear, t_Systime.wMonth, t_Systime.wDay, t_Systime.wHour, t_Systime.wMinute, t_Systime.wSecond, micros, L'-', 0 ); return hr; }