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.
532 lines
17 KiB
532 lines
17 KiB
/*++
|
|
|
|
Copyright (C) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
winmgmt.cpp
|
|
|
|
Abstract:
|
|
|
|
HotMof directory functions
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
#include <malloc.h>
|
|
|
|
#include <mofcomp.h> // 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<TCHAR> 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<TCHAR> delMe1(szHotMofDirFF);
|
|
|
|
size_t cchHotMofBad = lstrlen(szDirectory) + lstrlen(__TEXT("\\bad\\")) + 1;
|
|
TCHAR *szHotMofDirBAD = new TCHAR[cchHotMofBad];
|
|
if(!szHotMofDirBAD)return;
|
|
CDeleteMe<TCHAR> delMe2(szHotMofDirBAD);
|
|
|
|
size_t cchHotMofGood = lstrlen(szDirectory) + lstrlen(__TEXT("\\good\\")) + 1;
|
|
TCHAR *szHotMofDirGOOD = new TCHAR[cchHotMofGood];
|
|
if(!szHotMofDirGOOD)return;
|
|
CDeleteMe<TCHAR> 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<HANDLE,BOOL(*)(HANDLE),FindClose> 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<TCHAR> 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<TCHAR> 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;
|
|
}
|
|
|