835 lines
22 KiB
C++
835 lines
22 KiB
C++
|
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#include <tchar.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_WBEMCORE, "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_WBEMCORE,
|
||
|
"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_WBEMCORE, "Registry entry is indicating a setup is running\n"));
|
||
|
}
|
||
|
return bRetVal;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// CheckGlobalSetupSwitch
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
BOOL
|
||
|
CheckGlobalSetupSwitch( void )
|
||
|
{
|
||
|
BOOL bRetVal = FALSE;
|
||
|
DWORD dwVal = 0;
|
||
|
Registry r(_T("system\\Setup"));
|
||
|
if (r.GetDWORD(_T("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 )
|
||
|
{
|
||
|
HKEY hKey = NULL;
|
||
|
DWORD dwDisposition = 0;
|
||
|
|
||
|
Registry r( HKEY_LOCAL_MACHINE,
|
||
|
REG_OPTION_VOLATILE, KEY_ALL_ACCESS, 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() ) );
|
||
|
}
|
||
|
|
||
|
RegCloseKey( hKey );
|
||
|
}
|
||
|
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);
|
||
|
|
||
|
// Ignore the empty string case
|
||
|
|
||
|
if(dwSize == 1)
|
||
|
{
|
||
|
delete pMulti;
|
||
|
pMulti = NULL;
|
||
|
}
|
||
|
if(pMulti)
|
||
|
{
|
||
|
if(!IsValidMulti(pMulti, dwSize))
|
||
|
{
|
||
|
delete pMulti;
|
||
|
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));
|
||
|
pNew = new TCHAR[dwNewSize / sizeof(TCHAR)];
|
||
|
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++;
|
||
|
lstrcpy(pTest, 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;
|
||
|
lstrcpy(pNew, 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;
|
||
|
_ui64tot(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!
|
||
|
|
||
|
TCHAR *szHotMofDirFF = new TCHAR[lstrlen(szDirectory) + lstrlen(__TEXT("\\*")) + 1];
|
||
|
if(!szHotMofDirFF)return;
|
||
|
CDeleteMe<TCHAR> delMe1(szHotMofDirFF);
|
||
|
|
||
|
TCHAR *szHotMofDirBAD = new TCHAR[lstrlen(szDirectory) + lstrlen(__TEXT("\\bad\\")) + 1];
|
||
|
if(!szHotMofDirBAD)return;
|
||
|
CDeleteMe<TCHAR> delMe2(szHotMofDirBAD);
|
||
|
|
||
|
TCHAR *szHotMofDirGOOD = new TCHAR[lstrlen(szDirectory) + lstrlen(__TEXT("\\good\\")) + 1];
|
||
|
if(!szHotMofDirGOOD)return;
|
||
|
CDeleteMe<TCHAR> delMe3(szHotMofDirGOOD);
|
||
|
|
||
|
IWinmgmtMofCompiler * pCompiler = NULL;
|
||
|
|
||
|
//Find search parameter
|
||
|
lstrcpy(szHotMofDirFF, szDirectory);
|
||
|
lstrcat(szHotMofDirFF, __TEXT("\\*"));
|
||
|
|
||
|
//Where bad mofs go
|
||
|
lstrcpy(szHotMofDirBAD, szDirectory);
|
||
|
lstrcat(szHotMofDirBAD, __TEXT("\\bad\\"));
|
||
|
|
||
|
//Where good mofs go
|
||
|
lstrcpy(szHotMofDirGOOD, szDirectory);
|
||
|
lstrcat(szHotMofDirGOOD, __TEXT("\\good\\"));
|
||
|
|
||
|
//Make sure directories exist
|
||
|
WbemCreateDirectory(szDirectory);
|
||
|
WbemCreateDirectory(szHotMofDirBAD);
|
||
|
WbemCreateDirectory(szHotMofDirGOOD);
|
||
|
|
||
|
//Find file...
|
||
|
WIN32_FIND_DATA ffd;
|
||
|
HANDLE hFF = FindFirstFile(szHotMofDirFF, &ffd);
|
||
|
|
||
|
if (hFF != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
//We only process if this is a file
|
||
|
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||
|
{
|
||
|
//Create a full filename with path
|
||
|
TCHAR *szFullFilename = new TCHAR[lstrlen(szDirectory) + lstrlen(__TEXT("\\")) + lstrlen(ffd.cFileName) + 1];
|
||
|
if(!szFullFilename) return;
|
||
|
CDeleteMe<TCHAR> delMe4(szFullFilename);
|
||
|
lstrcpy(szFullFilename, szDirectory);
|
||
|
lstrcat(szFullFilename, __TEXT("\\"));
|
||
|
lstrcat(szFullFilename, ffd.cFileName);
|
||
|
|
||
|
|
||
|
TRACE((LOG_WBEMCORE,"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_WBEMCORE,"Auto-loading MOF %s failed because we could not open it for exclusive access\n", szFullFilename));
|
||
|
dwRetCode = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CloseHandle(hMof);
|
||
|
|
||
|
//Load the MOF file
|
||
|
if(szFullFilename)
|
||
|
{
|
||
|
|
||
|
if (pCompiler == 0)
|
||
|
{
|
||
|
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);
|
||
|
TCHAR *szNewFilename = new TCHAR[lstrlen(szNewDir) + lstrlen(ffd.cFileName) + 1];
|
||
|
if(!szNewFilename) return;
|
||
|
CDeleteMe<TCHAR> delMe5(szNewFilename);
|
||
|
|
||
|
lstrcpy(szNewFilename, szNewDir);
|
||
|
lstrcat(szNewFilename, 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);
|
||
|
|
||
|
//Move it to directory
|
||
|
if (DeleteFile(szNewFilename))
|
||
|
{
|
||
|
TRACE((LOG_WBEMCORE, "Removing old MOF %s\n", szNewFilename));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TRACE((LOG_WBEMCORE, "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_WBEMCORE, "MOF %s had an auto-recover pragrma. Updating registry.\n", szNewFilename));
|
||
|
AddToAutoRecoverList(szNewFilename);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} while (FindNextFile(hFF, &ffd));
|
||
|
|
||
|
FindClose(hFF);
|
||
|
}
|
||
|
if (pCompiler)
|
||
|
pCompiler->Release();
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// bool InitHotMofStuff
|
||
|
//
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////
|
||
|
|
||
|
BOOL InitHotMofStuff( IN OUT struct _PROG_RESOURCES * pProgRes)
|
||
|
{
|
||
|
|
||
|
// Get the installation directory
|
||
|
|
||
|
if (pProgRes->szHotMofDirectory)
|
||
|
{
|
||
|
delete [] pProgRes->szHotMofDirectory;
|
||
|
}
|
||
|
|
||
|
Registry r1(WBEM_REG_WBEM);
|
||
|
|
||
|
if (r1.GetStr(__TEXT("MOF Self-Install Directory"), &pProgRes->szHotMofDirectory) == Registry::failed)
|
||
|
{
|
||
|
// Look for the install directory
|
||
|
TCHAR * pWorkingDir;
|
||
|
|
||
|
if (r1.GetStr(__TEXT("Installation Directory"), &pWorkingDir))
|
||
|
{
|
||
|
ERRORTRACE((LOG_WINMGMT,"Unable to read 'Installation Directory' from registry\n"));
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
pProgRes->szHotMofDirectory = new TCHAR [lstrlen(pWorkingDir) + lstrlen(__TEXT("\\MOF")) +1];
|
||
|
if(!pProgRes->szHotMofDirectory)return false;
|
||
|
_stprintf(pProgRes->szHotMofDirectory, __TEXT("%s\\MOF"), pWorkingDir);
|
||
|
delete pWorkingDir;
|
||
|
if(r1.SetStr(__TEXT("MOF Self-Install Directory"), pProgRes->szHotMofDirectory) == Registry::failed)
|
||
|
{
|
||
|
ERRORTRACE((LOG_WINMGMT,"Unable to create 'Hot MOF Directory' in the registry\n"));
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Construct the path to the database.
|
||
|
// ===================================
|
||
|
|
||
|
WbemCreateDirectory(pProgRes->szHotMofDirectory);
|
||
|
|
||
|
|
||
|
//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;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
BuildSD( OUT PSECURITY_DESCRIPTOR *ppSD,
|
||
|
DWORD dwSids,
|
||
|
PSID * ArraySids,
|
||
|
DWORD AccessType)
|
||
|
{
|
||
|
BOOL Status;
|
||
|
ULONG SDLength;
|
||
|
PACL pEventDacl = NULL;
|
||
|
PSECURITY_DESCRIPTOR pEventSD = NULL;
|
||
|
ULONG ulWorldAccess = 0;
|
||
|
ULONG ulAdminAccess = 0;
|
||
|
|
||
|
if (!ppSD)
|
||
|
{
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
DWORD i;
|
||
|
DWORD dwLenSids = 0;
|
||
|
for (i=0;i<dwSids;i++)
|
||
|
{
|
||
|
dwLenSids += GetLengthSid(ArraySids[i]);
|
||
|
}
|
||
|
|
||
|
SDLength = sizeof(SECURITY_DESCRIPTOR) +
|
||
|
(ULONG) sizeof(ACL) +
|
||
|
(dwSids * ((ULONG) sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) + dwLenSids;
|
||
|
|
||
|
|
||
|
pEventSD = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(),0,SDLength);
|
||
|
|
||
|
if (pEventSD == NULL)
|
||
|
{
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
|
||
|
pEventDacl = (PACL) ((PBYTE) pEventSD + sizeof(SECURITY_DESCRIPTOR));
|
||
|
|
||
|
Status = InitializeAcl( pEventDacl,
|
||
|
SDLength - sizeof(SECURITY_DESCRIPTOR),
|
||
|
ACL_REVISION);
|
||
|
|
||
|
if (Status)
|
||
|
{
|
||
|
for (i=0; (i<dwSids) && Status; i++)
|
||
|
{
|
||
|
Status = AddAccessAllowedAce (
|
||
|
pEventDacl,
|
||
|
ACL_REVISION,
|
||
|
AccessType,
|
||
|
ArraySids[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now initialize security descriptors
|
||
|
// that export this protection
|
||
|
//
|
||
|
|
||
|
if (Status)
|
||
|
{
|
||
|
Status = InitializeSecurityDescriptor(pEventSD,
|
||
|
SECURITY_DESCRIPTOR_REVISION1);
|
||
|
|
||
|
if (Status)
|
||
|
{
|
||
|
Status = SetSecurityDescriptorDacl(
|
||
|
pEventSD,
|
||
|
TRUE, // DaclPresent
|
||
|
pEventDacl,
|
||
|
FALSE); // DaclDefaulted
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Status)
|
||
|
{
|
||
|
*ppSD = pEventSD;
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HeapFree(GetProcessHeap(),0,pEventSD);
|
||
|
return GetLastError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
SetEventDacl(HANDLE hEvent,DWORD Permission){
|
||
|
|
||
|
BOOL bRet = FALSE;
|
||
|
|
||
|
PSID pSidLocalSvc = NULL;
|
||
|
SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
|
||
|
|
||
|
bRet = AllocateAndInitializeSid( &id, 1,
|
||
|
SECURITY_LOCAL_SERVICE_RID,0,0,0,0,0,0,0,&pSidLocalSvc);
|
||
|
|
||
|
PSID pSidSystem = NULL;
|
||
|
SID_IDENTIFIER_AUTHORITY id2 = SECURITY_NT_AUTHORITY;
|
||
|
|
||
|
if (bRet)
|
||
|
{
|
||
|
bRet = AllocateAndInitializeSid( &id2, 1,
|
||
|
SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,&pSidSystem);
|
||
|
};
|
||
|
|
||
|
PSID pSidAdmins = NULL;
|
||
|
SID_IDENTIFIER_AUTHORITY id3 = SECURITY_NT_AUTHORITY;
|
||
|
|
||
|
if (bRet)
|
||
|
{
|
||
|
bRet = AllocateAndInitializeSid( &id3, 2,
|
||
|
SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS,0,0,0,0,0,0,&pSidAdmins);
|
||
|
};
|
||
|
|
||
|
|
||
|
PSID ArraySid[] = {pSidLocalSvc,pSidSystem,pSidAdmins};
|
||
|
|
||
|
if (bRet)
|
||
|
{
|
||
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
||
|
if (NO_ERROR == BuildSD(&pSD,sizeof(ArraySid)/sizeof(PSID),ArraySid,Permission))
|
||
|
{
|
||
|
bRet = SetKernelObjectSecurity(hEvent,
|
||
|
DACL_SECURITY_INFORMATION,
|
||
|
pSD);
|
||
|
|
||
|
HeapFree(GetProcessHeap(),0,pSD);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DWORD i;
|
||
|
for (i=0;i<sizeof(ArraySid)/sizeof(PSID);i++)
|
||
|
{
|
||
|
if (ArraySid[i])
|
||
|
{
|
||
|
FreeSid(ArraySid[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
BuildACL( DWORD dwSids,
|
||
|
PSID * ArraySids,
|
||
|
DWORD * AccessType,
|
||
|
DWORD * Flags,
|
||
|
OUT PACL * ppACL,
|
||
|
OUT DWORD * nBytes)
|
||
|
{
|
||
|
BOOL Status;
|
||
|
ULONG ACLLength;
|
||
|
PACL pDacl = NULL;
|
||
|
ULONG ulWorldAccess = 0;
|
||
|
ULONG ulAdminAccess = 0;
|
||
|
|
||
|
if (!ppACL)
|
||
|
{
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
DWORD i;
|
||
|
DWORD dwLenSids = 0;
|
||
|
for (i=0;i<dwSids;i++)
|
||
|
{
|
||
|
dwLenSids += GetLengthSid(ArraySids[i]);
|
||
|
}
|
||
|
|
||
|
ACLLength = (ULONG) sizeof(ACL) +
|
||
|
(dwSids * ((ULONG) sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) + dwLenSids;
|
||
|
|
||
|
|
||
|
pDacl = (PACL) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,ACLLength);
|
||
|
|
||
|
if (pDacl == NULL)
|
||
|
{
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
|
||
|
Status = InitializeAcl( pDacl,
|
||
|
ACLLength,
|
||
|
ACL_REVISION);
|
||
|
|
||
|
if (Status)
|
||
|
{
|
||
|
for (i=0; (i<dwSids) && Status; i++)
|
||
|
{
|
||
|
Status = AddAccessAllowedAceEx (
|
||
|
pDacl,
|
||
|
ACL_REVISION,
|
||
|
Flags[i],
|
||
|
AccessType[i],
|
||
|
ArraySids[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Status)
|
||
|
{
|
||
|
*ppACL = pDacl;
|
||
|
return NO_ERROR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
HeapFree(GetProcessHeap(),0,pDacl);
|
||
|
return GetLastError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*BOOL
|
||
|
AddAccountToDacl(HANDLE hToken,
|
||
|
BYTE SubCount,
|
||
|
DWORD dw0,
|
||
|
DWORD dw1,
|
||
|
DWORD dw2,
|
||
|
DWORD dw3,
|
||
|
DWORD dw4,
|
||
|
DWORD dw5,
|
||
|
DWORD dw6,
|
||
|
DWORD dw7,
|
||
|
DWORD dwAccess,
|
||
|
DWORD AceFlag){
|
||
|
|
||
|
BOOL bRet = FALSE;
|
||
|
DWORD i;
|
||
|
|
||
|
PSID pSidAccount = NULL;
|
||
|
SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
|
||
|
|
||
|
bRet = AllocateAndInitializeSid( &id, SubCount,
|
||
|
dw0,dw1,dw2,dw3,dw4,dw5,dw6,dw7,&pSidAccount);
|
||
|
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
|
||
|
PACL pDacl;
|
||
|
|
||
|
if (bRet)
|
||
|
{
|
||
|
DWORD dwReq = 0;
|
||
|
bRet = GetTokenInformation(hToken,
|
||
|
TokenDefaultDacl,
|
||
|
NULL,
|
||
|
0,
|
||
|
&dwReq);
|
||
|
if ((FALSE == bRet) &&
|
||
|
(ERROR_INSUFFICIENT_BUFFER == GetLastError()))
|
||
|
{
|
||
|
TOKEN_DEFAULT_DACL * pTDD = (TOKEN_DEFAULT_DACL *)_alloca(dwReq+sizeof(void*));
|
||
|
bRet = GetTokenInformation(hToken,
|
||
|
TokenDefaultDacl,
|
||
|
pTDD,
|
||
|
dwReq,
|
||
|
&dwReq);
|
||
|
pDacl = pTDD->DefaultDacl;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!bRet)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
IVAN, if you plan to use this, please make sure that pDacl is
|
||
|
initialized in all cases. There was a prefix bug on this
|
||
|
|
||
|
WORD Count = pDacl->AceCount;
|
||
|
PSID * ArraySid = (PSID *)_alloca((Count+1)*sizeof(PSID));
|
||
|
DWORD * Access = (DWORD *)_alloca((Count+1)*sizeof(DWORD));
|
||
|
DWORD * AceFlags = (DWORD *)_alloca((Count+1)*sizeof(DWORD));
|
||
|
|
||
|
|
||
|
for(i=0;i<Count;i++)
|
||
|
{
|
||
|
ACCESS_ALLOWED_ACE * pAce;
|
||
|
if (GetAce(pDacl,i,(PVOID *)&pAce))
|
||
|
{
|
||
|
PSID pSid;
|
||
|
AllocateAndInitializeSid(&id,8,0,0,0,0,0,0,0,0,&pSid);
|
||
|
CopySid(40,pSid,(PSID)(&pAce->SidStart));
|
||
|
ArraySid[i] = pSid;
|
||
|
Access[i] = pAce->Mask;
|
||
|
AceFlags[i] = pAce->Header.AceFlags;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
ArraySid[i] = pSidAccount;
|
||
|
Access[i] = dwAccess;
|
||
|
AceFlags[i] = AceFlag;
|
||
|
|
||
|
|
||
|
PACL pACL = NULL;
|
||
|
DWORD dwBytes;
|
||
|
if (NO_ERROR == BuildACL((Count+1),ArraySid,Access,AceFlags,&pACL,&dwBytes))
|
||
|
{
|
||
|
TOKEN_DEFAULT_DACL tddNew;
|
||
|
tddNew.DefaultDacl = pACL;
|
||
|
|
||
|
bRet = SetTokenInformation(hToken,
|
||
|
TokenDefaultDacl,
|
||
|
&tddNew,
|
||
|
dwBytes);
|
||
|
|
||
|
HeapFree(GetProcessHeap(),0,pACL);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
for (i=0;i<(DWORD)(Count+1);i++)
|
||
|
{
|
||
|
if (ArraySid[i])
|
||
|
{
|
||
|
FreeSid(ArraySid[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
|
||
|
}
|
||
|
|
||
|
*/
|