Leaked source code of windows server 2003
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

/*++
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;
}