/*++ Copyright (C) 2000-2001 Microsoft Corporation Module Name: winmgmt.cpp Abstract: HotMof directory functions --*/ #include "precomp.h" #include #include // for AUTORECOVERY_REQUIRED #include "winmgmt.h" // this project #include "arrtempl.h" // for CDeleteMe // // // CheckNoResyncSwitch // ////////////////////////////////////////////////////////////////// BOOL CheckNoResyncSwitch( void ) { BOOL bRetVal = TRUE; DWORD dwVal = 0; Registry rCIMOM(WBEM_REG_WINMGMT); if (rCIMOM.GetDWORDStr( WBEM_NORESYNCPERF, &dwVal ) == Registry::no_error) { bRetVal = !dwVal; if ( bRetVal ) { DEBUGTRACE((LOG_WINMGMT, "NoResyncPerf in CIMOM is set to TRUE - ADAP will not be shelled\n")); } } // If we didn't get anything there, we should try the volatile key if ( bRetVal ) { Registry rAdap( HKEY_LOCAL_MACHINE, KEY_READ, WBEM_REG_ADAP); if ( rAdap.GetDWORD( WBEM_NOSHELL, &dwVal ) == Registry::no_error ) { bRetVal = !dwVal; if ( bRetVal ) { DEBUGTRACE((LOG_WINMGMT, "NoShell in ADAP is set to TRUE - ADAP will not be shelled\n")); } } } return bRetVal; } // // // CheckNoResyncSwitch // ////////////////////////////////////////////////////////////////// BOOL CheckSetupSwitch( void ) { BOOL bRetVal = FALSE; DWORD dwVal = 0; Registry r(WBEM_REG_WINMGMT); if (r.GetDWORDStr( WBEM_WMISETUP, &dwVal ) == Registry::no_error) { bRetVal = dwVal; DEBUGTRACE((LOG_WINMGMT, "Registry entry is indicating a setup is %d\n",bRetVal)); } return bRetVal; } // // // CheckGlobalSetupSwitch // ////////////////////////////////////////////////////////////////// BOOL CheckGlobalSetupSwitch( void ) { BOOL bRetVal = FALSE; DWORD dwVal = 0; Registry r(TEXT("system\\Setup")); if (r.GetDWORD(TEXT("SystemSetupInProgress"), &dwVal ) == Registry::no_error) { if(dwVal == 1) bRetVal = TRUE; } return bRetVal; } // // // // This function will place a volatile registry key under the // CIMOM key in which we will write a value indicating // we should not shell ADAP. This way, after a setup runs, WINMGMT // will NOT automatically shell ADAP dredges of the registry, // until the system is rebooted and the volatile registry key is removed. // // /////////////////////////////////////////////////////////////////////////// void SetNoShellADAPSwitch( void ) { DWORD dwDisposition = 0; Registry r( HKEY_LOCAL_MACHINE, REG_OPTION_VOLATILE, KEY_READ | KEY_WRITE, WBEM_REG_ADAP ); if ( ERROR_SUCCESS == r.GetLastError() ) { if ( r.SetDWORD( WBEM_NOSHELL, 1 ) != Registry::no_error ) { DEBUGTRACE( ( LOG_WINMGMT, "Failed to create NoShell value in volatile reg key: %d\n", r.GetLastError() ) ); } } else { DEBUGTRACE( ( LOG_WINMGMT, "Failed to create volatile ADAP reg key: %d\n", r.GetLastError() ) ); } } // // // bool IsValidMulti // // // Does a sanity check on a multstring. // ////////////////////////////////////////////////////////////////////// BOOL IsValidMulti(TCHAR * pMultStr, DWORD dwSize) { // Divide the size by the size of a tchar, in case these // are WCHAR strings dwSize /= sizeof(TCHAR); if(pMultStr && dwSize >= 2 && pMultStr[dwSize-2]==0 && pMultStr[dwSize-1]==0) return TRUE; return FALSE; } // // // BOOL IsStringPresetn // // // Searches a multstring for the presense of a string. // // //////////////////////////////////////////////////////////////////// BOOL IsStringPresent(TCHAR * pTest, TCHAR * pMultStr) { TCHAR * pTemp; for(pTemp = pMultStr; *pTemp; pTemp += lstrlen(pTemp) + 1) if(!lstrcmpi(pTest, pTemp)) return TRUE; return FALSE; } // // // AddToAutoRecoverList // // //////////////////////////////////////////////////////////////////// void AddToAutoRecoverList(TCHAR * pFileName) { TCHAR cFullFileName[MAX_PATH+1]; TCHAR * lpFile; DWORD dwSize; TCHAR * pNew = NULL; TCHAR * pTest; DWORD dwNewSize = 0; // Get the full file name long lRet = GetFullPathName(pFileName, MAX_PATH, cFullFileName, &lpFile); if(lRet == 0) return; BOOL bFound = FALSE; Registry r(WBEM_REG_WINMGMT); TCHAR *pMulti = r.GetMultiStr(__TEXT("Autorecover MOFs"), dwSize); CVectorDeleteMe dm_(pMulti); // Ignore the empty string case if(dwSize == 1) { pMulti = NULL; } if(pMulti) { if(!IsValidMulti(pMulti, dwSize)) { return; // bail out, messed up multistring } bFound = IsStringPresent(cFullFileName, pMulti); if(!bFound) { // The registry entry does exist, but doesnt have this name // Make a new multistring with the file name at the end dwNewSize = dwSize + ((lstrlen(cFullFileName) + 1) * sizeof(TCHAR)); size_t cchSizeOld = dwSize / sizeof(TCHAR); size_t cchSizeNew = dwNewSize / sizeof(TCHAR); pNew = new TCHAR[cchSizeNew]; if(!pNew) return; memcpy(pNew, pMulti, dwSize); // Find the double null for(pTest = pNew; pTest[0] || pTest[1]; pTest++); // intentional semi // Tack on the path and ensure a double null; pTest++; size_t cchSizeTmp = cchSizeNew - cchSizeOld; StringCchCopy(pTest,cchSizeTmp,cFullFileName); pTest+= lstrlen(cFullFileName)+1; *pTest = 0; // add second numm } } else { // The registry entry just doesnt exist. // Create it with a value equal to our name dwNewSize = ((lstrlen(cFullFileName) + 2) * sizeof(TCHAR)); pNew = new TCHAR[dwNewSize / sizeof(TCHAR)]; if(!pNew) return; size_t cchSizeTmp = dwNewSize / sizeof(TCHAR); StringCchCopy(pNew,cchSizeTmp, cFullFileName); pTest = pNew + lstrlen(pNew) + 1; *pTest = 0; // add second null } if(pNew) { // We will cast pNew, since the underlying function will have to cast to // LPBYTE and we will be WCHAR if UNICODE is defined r.SetMultiStr(__TEXT("Autorecover MOFs"), pNew, dwNewSize); delete [] pNew; } FILETIME ftCurTime; LARGE_INTEGER liCurTime; TCHAR szBuff[50]; GetSystemTimeAsFileTime(&ftCurTime); liCurTime.LowPart = ftCurTime.dwLowDateTime; liCurTime.HighPart = ftCurTime.dwHighDateTime; _ui64tow(liCurTime.QuadPart, szBuff, 10); r.SetStr(__TEXT("Autorecover MOFs timestamp"), szBuff); } // // LoadMofsInDirectory // // //////////////////////////////////////////////////////////////////////////////////////// void LoadMofsInDirectory(const TCHAR *szDirectory) { if (NULL == szDirectory) return; if(CheckGlobalSetupSwitch()) return; // not hot compiling during setup! size_t cchHotMof = lstrlen(szDirectory) + lstrlen(__TEXT("\\*")) + 1; TCHAR *szHotMofDirFF = new TCHAR[cchHotMof]; if(!szHotMofDirFF)return; CDeleteMe delMe1(szHotMofDirFF); size_t cchHotMofBad = lstrlen(szDirectory) + lstrlen(__TEXT("\\bad\\")) + 1; TCHAR *szHotMofDirBAD = new TCHAR[cchHotMofBad]; if(!szHotMofDirBAD)return; CDeleteMe delMe2(szHotMofDirBAD); size_t cchHotMofGood = lstrlen(szDirectory) + lstrlen(__TEXT("\\good\\")) + 1; TCHAR *szHotMofDirGOOD = new TCHAR[cchHotMofGood]; if(!szHotMofDirGOOD)return; CDeleteMe delMe3(szHotMofDirGOOD); IWinmgmtMofCompiler * pCompiler = NULL; //Find search parameter StringCchCopy(szHotMofDirFF,cchHotMof, szDirectory); StringCchCat(szHotMofDirFF,cchHotMof, __TEXT("\\*")); //Where bad mofs go StringCchCopy(szHotMofDirBAD,cchHotMofBad, szDirectory); StringCchCat(szHotMofDirBAD,cchHotMofBad, __TEXT("\\bad\\")); //Where good mofs go StringCchCopy(szHotMofDirGOOD,cchHotMofGood, szDirectory); StringCchCat(szHotMofDirGOOD,cchHotMofGood, __TEXT("\\good\\")); //Make sure directories exist WCHAR * pSDDL = TEXT("D:P(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)"); if (FAILED(TestDirExistAndCreateWithSDIfNotThere((TCHAR *)szDirectory,pSDDL))) { return; }; if (FAILED(TestDirExistAndCreateWithSDIfNotThere(szHotMofDirBAD,pSDDL))) { return; }; if (FAILED(TestDirExistAndCreateWithSDIfNotThere(szHotMofDirGOOD,pSDDL))) { return; }; //Find file... WIN32_FIND_DATA ffd; HANDLE hFF = FindFirstFile(szHotMofDirFF, &ffd); if (hFF != INVALID_HANDLE_VALUE) { OnDelete cm(hFF); do { //We only process if this is a file if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { //Create a full filename with path size_t cchSizeTmp = lstrlen(szDirectory) + lstrlen(__TEXT("\\")) + lstrlen(ffd.cFileName) + 1; TCHAR *szFullFilename = new TCHAR[cchSizeTmp]; if(!szFullFilename) return; CDeleteMe delMe4(szFullFilename); StringCchCopy(szFullFilename,cchSizeTmp, szDirectory); StringCchCat(szFullFilename,cchSizeTmp, __TEXT("\\")); StringCchCat(szFullFilename,cchSizeTmp, ffd.cFileName); TRACE((LOG_WINMGMT,"Auto-loading MOF %s\n", szFullFilename)); //We need to hold off on this file until it has been finished writing //otherwise the CompileFile will not be able to read the file! HANDLE hMof = INVALID_HANDLE_VALUE; DWORD dwRetry = 10; while (hMof == INVALID_HANDLE_VALUE) { hMof = CreateFile(szFullFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //If cannot open yet sleep for a while if (hMof == INVALID_HANDLE_VALUE) { if (--dwRetry == 0) break; Sleep(1000); } } DWORD dwRetCode; WBEM_COMPILE_STATUS_INFO Info; DWORD dwAutoRecoverRequired = 0; if (hMof == INVALID_HANDLE_VALUE) { TRACE((LOG_WINMGMT,"Auto-loading MOF %s failed because we could not open it for exclusive access\n", szFullFilename)); dwRetCode = 1; } else { CloseHandle(hMof); if (pCompiler == 0) { SCODE sc = CoCreateInstance(CLSID_MofCompilerOOP, 0, CLSCTX_LOCAL_SERVER| CLSCTX_ENABLE_AAA, IID_IWinmgmtMofCompilerOOP, (LPVOID *) &pCompiler); /* SCODE sc = CoCreateInstance(CLSID_WinmgmtMofCompiler, 0, CLSCTX_INPROC_SERVER, IID_IWinmgmtMofCompiler, (LPVOID *) &pCompiler); */ if(sc != S_OK) return; } dwRetCode = pCompiler->WinmgmtCompileFile(szFullFilename, NULL, WBEM_FLAG_DONT_ADD_TO_LIST, // autocomp, check, etc 0, 0, NULL, NULL, &Info); } TCHAR *szNewDir = (dwRetCode?szHotMofDirBAD:szHotMofDirGOOD); cchSizeTmp = lstrlen(szNewDir) + lstrlen(ffd.cFileName) + 1; TCHAR *szNewFilename = new TCHAR[cchSizeTmp]; if(!szNewFilename) return; CDeleteMe delMe5(szNewFilename); StringCchCopy(szNewFilename,cchSizeTmp, szNewDir); StringCchCat(szNewFilename,cchSizeTmp, ffd.cFileName); //Make sure we have access to delete the old file... DWORD dwOldAttribs = GetFileAttributes(szNewFilename); if (dwOldAttribs != -1) { dwOldAttribs &= ~FILE_ATTRIBUTE_READONLY; SetFileAttributes(szNewFilename, dwOldAttribs); if (DeleteFile(szNewFilename)) { TRACE((LOG_WINMGMT, "Removing old MOF %s\n", szNewFilename)); } } TRACE((LOG_WINMGMT, "Loading of MOF %s was %s. Moving to %s\n", szFullFilename, dwRetCode?"unsuccessful":"successful", szNewFilename)); MoveFile(szFullFilename, szNewFilename); //Now mark the file as read only so no one deletes it!!! //Like that stops anyone deleting files :-) dwOldAttribs = GetFileAttributes(szNewFilename); if (dwOldAttribs != -1) { dwOldAttribs |= FILE_ATTRIBUTE_READONLY; SetFileAttributes(szNewFilename, dwOldAttribs); } if ((dwRetCode == 0) && (Info.dwOutFlags & AUTORECOVERY_REQUIRED)) { //We need to add this item into the registry for auto-recovery purposes TRACE((LOG_WINMGMT, "MOF %s had an auto-recover pragrma. Updating registry.\n", szNewFilename)); AddToAutoRecoverList(szNewFilename); } } } while (FindNextFile(hFF, &ffd)); } if (pCompiler) pCompiler->Release(); } // // // bool InitHotMofStuff // // ////////////////////////////////////////////////////////////////// BOOL InitHotMofStuff( IN OUT struct _PROG_RESOURCES * pProgRes) { // Get the installation directory if (pProgRes->szHotMofDirectory) { delete [] pProgRes->szHotMofDirectory; pProgRes->szHotMofDirectory = NULL; } Registry r1(WBEM_REG_WINMGMT); // The HotMof same permission as the autorecover TCHAR * pMofDir = NULL; if (r1.GetStr(__TEXT("MOF Self-Install Directory"), &pMofDir)) { size_t cchSizeTmp = MAX_PATH + 1 + lstrlen(__TEXT("\\wbem\\mof")); pMofDir = new TCHAR[cchSizeTmp]; if (NULL == pMofDir) return false; DWORD dwRet = GetSystemDirectory(pMofDir, MAX_PATH + 1); if (0 == dwRet || dwRet > (MAX_PATH)) { delete [] pMofDir; return false; } StringCchCat(pMofDir,cchSizeTmp, __TEXT("\\wbem\\mof")); if(r1.SetStr(__TEXT("MOF Self-Install Directory"),pMofDir) == Registry::failed) { ERRORTRACE((LOG_WINMGMT,"Unable to set 'Hot MOF Directory' in the registry\n")); delete [] pMofDir; return false; } } pProgRes->szHotMofDirectory = pMofDir; // Ensure the directory is there and secure it if not there // =================================== TCHAR * pString =TEXT("D:P(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)"); HRESULT hRes; if (FAILED(hRes = TestDirExistAndCreateWithSDIfNotThere(pProgRes->szHotMofDirectory,pString))) { ERRORTRACE((LOG_WINMGMT,"TestDirExistAndCreateWithSDIfNotThere %S hr %08x\n",pMofDir,hRes)); return false; } //Create an event on change notification for the MOF directory pProgRes->ghMofDirChange = FindFirstChangeNotification(pProgRes->szHotMofDirectory, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME); if (pProgRes->ghMofDirChange == INVALID_HANDLE_VALUE) { pProgRes->ghMofDirChange = CreateEvent(NULL, FALSE, FALSE, NULL); if (pProgRes->ghMofDirChange == NULL) return false; } return true; }