|
|
#include "stdafx.h"
#include <setupapi.h>
#include <shlobj.h>
#include <ole2.h>
#include "lzexpand.h"
#include "log.h"
#include "dcomperm.h"
#include "strfn.h"
#include "other.h"
#include <direct.h>
#include <aclapi.h>
typedef struct _QUEUECONTEXT { HWND OwnerWindow; DWORD MainThreadId; HWND ProgressDialog; HWND ProgressBar; BOOL Cancelled; PTSTR CurrentSourceName; BOOL ScreenReader; BOOL MessageBoxUp; WPARAM PendingUiType; PVOID PendingUiParameters; UINT CancelReturnCode; BOOL DialogKilled; //
// If the SetupInitDefaultQueueCallbackEx is used, the caller can
// specify an alternate handler for progress. This is useful to
// get the default behavior for disk prompting, error handling, etc,
// but to provide a gas gauge embedded, say, in a wizard page.
//
// The alternate window is sent ProgressMsg once when the copy queue
// is started (wParam = 0. lParam = number of files to copy).
// It is then also sent once per file copied (wParam = 1. lParam = 0).
//
// NOTE: a silent installation (i.e., no progress UI) can be accomplished
// by specifying an AlternateProgressWindow handle of INVALID_HANDLE_VALUE.
//
HWND AlternateProgressWindow; UINT ProgressMsg; UINT NoToAllMask;
HANDLE UiThreadHandle;
#ifdef NOCANCEL_SUPPORT
BOOL AllowCancel; #endif
} QUEUECONTEXT, *PQUEUECONTEXT;
//-------------------------------------------------------------------
// purpose: install an section in an .inf file
//-------------------------------------------------------------------
int InstallInfSection_NoFiles(HINF InfHandle,TCHAR szINFFileName[],TCHAR szSectionName[]) { HWND Window = NULL; BOOL bReturn = FALSE; BOOL bReturnTemp = FALSE; // assume failure.
TCHAR ActualSection[1000]; DWORD ActualSectionLength; BOOL bPleaseCloseInfHandle = FALSE;
iisDebugOut_Start1(_T("InstallInfSection_NoFiles"),szSectionName,LOG_TYPE_PROGRAM_FLOW);
__try {
// Check if a valid infhandle as passed in....
// if so, use that, otherwise, use the passed in filename...
if(InfHandle == INVALID_HANDLE_VALUE) { // Try to use the filename.
if (_tcsicmp(szINFFileName, _T("")) == 0) { goto c1; }
// we have a filename entry. let's try to use it.
// Check if the file exists
if (!IsFileExist(szINFFileName)) { //MessageBox(NULL, "unable to find file", "cannot find file", MB_OK);
goto c1; } // Load the inf file and get the handle
InfHandle = SetupOpenInfFile(szINFFileName, NULL, INF_STYLE_WIN4, NULL); bPleaseCloseInfHandle = TRUE; } if(InfHandle == INVALID_HANDLE_VALUE) {goto c1;}
//
// See if there is an nt-specific section
//
SetupDiGetActualSectionToInstall(InfHandle,szSectionName,ActualSection,sizeof(ActualSection)/sizeof(TCHAR),&ActualSectionLength,NULL);
//
// Perform non-file operations for the section passed on the cmd line.
//
bReturn = SetupInstallFromInfSection(Window,InfHandle,ActualSection,SPINST_ALL & ~SPINST_FILES,NULL,NULL,0,NULL,NULL,NULL,NULL); if(!bReturn) {goto c1;}
//
// Install any services for the section
//
bReturn = SetupInstallServicesFromInfSection(InfHandle,ActualSection,0); if(!bReturn) { iisDebugOut((LOG_TYPE_TRACE, _T("SetupInstallServicesFromInfSection failed.Ret=%d.\n"), GetLastError())); }
//
// Refresh the desktop.
//
SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_FLUSHNOWAIT,0,0);
//
// If we get to here, then this routine has been successful.
//
bReturnTemp = TRUE;
c1: //
// If the bReturnTemp failed and it was because the user cancelled, then we don't want to consider
// that as an bReturnTemp (i.e., we don't want to give an bReturnTemp popup later).
//
if((bReturnTemp != TRUE) && (GetLastError() == ERROR_CANCELLED)) {bReturnTemp = TRUE;} if (bPleaseCloseInfHandle == TRUE) { if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);InfHandle = INVALID_HANDLE_VALUE;} }
;} __except(EXCEPTION_EXECUTE_HANDLER) { if (bPleaseCloseInfHandle == TRUE) { if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);InfHandle = INVALID_HANDLE_VALUE;} } }
//
// If the bReturnTemp failed because the user cancelled, then we don't want to consider
// that as an bReturnTemp (i.e., we don't want to give an bReturnTemp popup later).
//
if((bReturnTemp != TRUE) && (GetLastError() == ERROR_CANCELLED)) {bReturnTemp = TRUE;}
// Display installation failed message
//if(bReturnTemp) {MyMessageBox(NULL, _T("IDS_INF_FAILED"), MB_OK);}
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("InstallInfSection_NoFiles.[%s].End.Ret=%d.\n"), szSectionName, bReturnTemp)); return bReturnTemp; }
//-------------------------------------------------------------------
// purpose: install an section in an .inf file
//-------------------------------------------------------------------
int InstallInfSection(HINF InfHandle,TCHAR szINFFileName[],TCHAR szSectionName[]) { HWND Window = NULL; PTSTR SourcePath = NULL; //HINF InfHandle = INVALID_HANDLE_VALUE;
HSPFILEQ FileQueue = INVALID_HANDLE_VALUE; PQUEUECONTEXT QueueContext = NULL; BOOL bReturn = FALSE; BOOL bReturnTemp = FALSE; // assume failure.
TCHAR ActualSection[1000]; DWORD ActualSectionLength; BOOL bPleaseCloseInfHandle = FALSE;
iisDebugOut_Start1(_T("InstallInfSection"),szSectionName,LOG_TYPE_PROGRAM_FLOW);
__try {
// Check if a valid infhandle as passed in....
// if so, use that, otherwise, use the passed in filename...
if(InfHandle == INVALID_HANDLE_VALUE) { // Try to use the filename.
if (_tcsicmp(szINFFileName, _T("")) == 0) { goto c1; }
// we have a filename entry. let's try to use it.
// Check if the file exists
if (!IsFileExist(szINFFileName)) { //MessageBox(NULL, "unable to find file", "cannot find file", MB_OK);
goto c1; } // Load the inf file and get the handle
InfHandle = SetupOpenInfFile(szINFFileName, NULL, INF_STYLE_WIN4, NULL); bPleaseCloseInfHandle = TRUE; } if(InfHandle == INVALID_HANDLE_VALUE) {goto c1;}
//
// See if there is an nt-specific section
//
SetupDiGetActualSectionToInstall(InfHandle,szSectionName,ActualSection,sizeof(ActualSection)/sizeof(TCHAR),&ActualSectionLength,NULL);
//
// Create a setup file queue and initialize the default queue callback.
//
FileQueue = SetupOpenFileQueue(); if(FileQueue == INVALID_HANDLE_VALUE) {goto c1;}
//QueueContext = SetupInitDefaultQueueCallback(Window);
//if(!QueueContext) {goto c1;}
QueueContext = (PQUEUECONTEXT) SetupInitDefaultQueueCallbackEx(Window,NULL,0,0,0); if(!QueueContext) {goto c1;} QueueContext->PendingUiType = IDF_CHECKFIRST;
//
// Enqueue file operations for the section passed on the cmd line.
//
//SourcePath = NULL;
// SP_COPY_NOPRUNE = setupapi has a new deal which will prune files from the copyqueue if they already exist on the system.
// however, the problem with the new deal is that the pruning code does not check if you have the same file
// queued in the delete or rename queue. specify SP_COPY_NOPRUNE to make sure that our file never gets
// pruned (removed) from the copy queue. aaronl 12/4/98
//bReturn = SetupInstallFilesFromInfSection(InfHandle,NULL,FileQueue,ActualSection,SourcePath,SP_COPY_NEWER | SP_COPY_NOPRUNE);
bReturn = SetupInstallFilesFromInfSection(InfHandle,NULL,FileQueue,ActualSection,SourcePath, SP_COPY_NOPRUNE); if(!bReturn) {goto c1;}
//
// Commit file queue.
//
if(!SetupCommitFileQueue(Window, FileQueue, SetupDefaultQueueCallback, QueueContext)) {goto c1;}
//
// Perform non-file operations for the section passed on the cmd line.
//
bReturn = SetupInstallFromInfSection(Window,InfHandle,ActualSection,SPINST_ALL & ~SPINST_FILES,NULL,NULL,0,NULL,NULL,NULL,NULL); if(!bReturn) {goto c1;}
//
// Refresh the desktop.
//
SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_FLUSHNOWAIT,0,0);
//
// If we get to here, then this routine has been successful.
//
bReturnTemp = TRUE;
c1: //
// If the bReturnTemp failed and it was because the user cancelled, then we don't want to consider
// that as an bReturnTemp (i.e., we don't want to give an bReturnTemp popup later).
//
if((bReturnTemp != TRUE) && (GetLastError() == ERROR_CANCELLED)) {bReturnTemp = TRUE;} if(QueueContext) {SetupTermDefaultQueueCallback(QueueContext);QueueContext = NULL;} if(FileQueue != INVALID_HANDLE_VALUE) {SetupCloseFileQueue(FileQueue);FileQueue = INVALID_HANDLE_VALUE;} if (bPleaseCloseInfHandle == TRUE) { if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);InfHandle = INVALID_HANDLE_VALUE;} }
;} __except(EXCEPTION_EXECUTE_HANDLER) { if(QueueContext) {SetupTermDefaultQueueCallback(QueueContext);} if(FileQueue != INVALID_HANDLE_VALUE) {SetupCloseFileQueue(FileQueue);} if (bPleaseCloseInfHandle == TRUE) { if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);InfHandle = INVALID_HANDLE_VALUE;} } }
//
// If the bReturnTemp failed because the user cancelled, then we don't want to consider
// that as an bReturnTemp (i.e., we don't want to give an bReturnTemp popup later).
//
if((bReturnTemp != TRUE) && (GetLastError() == ERROR_CANCELLED)) {bReturnTemp = TRUE;}
// Display installation failed message
//if(bReturnTemp) {MyMessageBox(NULL, _T("IDS_INF_FAILED"), MB_OK);}
iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("InstallInfSection.[%s].End.Ret=%d.\n"), szSectionName, bReturnTemp)); return bReturnTemp; }
BOOL IsValidDriveType(LPTSTR szRoot) { BOOL fReturn = FALSE; int i;
i = GetDriveType(szRoot);
if (i == DRIVE_FIXED) {fReturn = TRUE;}
if (i == DRIVE_REMOVABLE) { BOOL b; ULONGLONG TotalSpace; DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters; DWORD FloppySpace = 10 * 1024 * 1024;// use 10MB to distinguish a floppy from other drives, like JAZ drive 1GB
b = GetDiskFreeSpace(szRoot,&SectorsPerCluster, &BytesPerSector, &NumberOfFreeClusters, &TotalNumberOfClusters); if (b) { TotalSpace = (ULONGLONG) TotalNumberOfClusters * SectorsPerCluster * BytesPerSector; if (TotalSpace > (ULONGLONG) FloppySpace) {fReturn = TRUE;} else { iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("GetDiskFreeSpace():Drive=DRIVE_REMOVABLE:Not Sufficient space on drive '%1!s!'. FAIL\n"), szRoot)); } } else { iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("GetDiskFreeSpace(Drive=DRIVE_REMOVABLE) on %1!s! returns err: 0x%2!x!. FAILURE\n"), szRoot, GetLastError())); } }
return (fReturn); }
// If lpszPath is a valid directory, return TRUE, and pass back the valid path in lpszPath to caller
// Otherwise, return FALSE.
BOOL IsValidDirectoryName(LPTSTR lpszPath) { DWORD err = 0; BOOL bReturn = FALSE; TCHAR szFullPath[_MAX_PATH]; LPTSTR p;
iisDebugOutSafeParams((LOG_TYPE_TRACE_WIN32_API, _T("IsValidDirectoryName %1!s!\n"), lpszPath)); err = GetFullPathName(lpszPath, _MAX_PATH, szFullPath, &p); if (err != 0) { if (szFullPath[1] == _T(':')) { // good, not a UNC name
// make sure it is a FIXED drive
TCHAR szRoot[4]; _tcsncpy(szRoot, szFullPath, 3); szRoot[3] = _T('\0'); if (IsValidDriveType(szRoot)) { // OK, ready to create each layered directory
TCHAR szBuffer[_MAX_PATH]; LPTSTR token, tail; CStringArray aDir; int i, n;
tail = szBuffer; token = _tcstok(szFullPath, _T("\\")); if (token) { _tcscpy(tail, token); tail += _tcslen(token); bReturn = TRUE; /* return TRUE if in the form of C:\ */ while ( ( token = _tcstok(NULL, _T("\\")) ) != NULL ) { *tail = _T('\\'); tail = _tcsinc(tail); _tcscpy(tail, token); // create it & rememeber it
err = GetFileAttributes(szBuffer); if (err == 0xFFFFFFFF) { // szBuffer contains a non-existing path
// create it
if (CreateDirectory(szBuffer, NULL)) { // succeed, remember the directory in an array
aDir.Add(szBuffer); } else { iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory:CreateDirectory failed on %1!s!, err=%2!x!.\n"), szBuffer, GetLastError())); bReturn = FALSE; break; } } else { // szBuffer contains an existing path,
// make sure it is a directory
if (!(err & FILE_ATTRIBUTE_DIRECTORY)) { iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory failure. %1!s! is not a valid directory.\n"), szBuffer)); bReturn = FALSE; break; } } tail += _tcslen(token); } if (bReturn) { // pass the valid directory to the caller
if (*(tail-1) == _T(':')) { *tail = _T('\\'); tail = _tcsinc(tail); } _tcscpy(lpszPath, szBuffer); } } // remove the created directories we remembered in the array
n = (int)aDir.GetSize(); for (i = n-1; i >= 0; i--) RemoveDirectory(aDir[i]); } else { iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory failure. %1!s! is not on a valid drive.\n"), szFullPath)); } } else { iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory failure. UNC name %1!s! is not allowed.\n"), szFullPath)); } } else { iisDebugOutSafeParams((LOG_TYPE_ERROR, _T("IsValidDirectory:GetFullPathName failed on %1!s!, err=%2!x!.\n"), lpszPath, GetLastError())); }
return (bReturn); }
BOOL IsValidNumber(LPCTSTR szValue) { LPTSTR p = (LPTSTR)szValue; while (*p) { if ( *p >= _T('0') && *p <= _T('9') ) { p = _tcsinc(p); continue; } else return FALSE; } return TRUE; }
// Calculate the size of a Multi-String in TCHAR, including the ending 2 '\0's.
int GetMultiStrSize(LPTSTR p) { int c = 0;
while (1) { if (*p) { p++; c++; } else { c++; if (*(p+1)) { p++; } else { c++; break; } } } return c; }
BOOL IsFileExist(LPCTSTR szFile) { // Check if the file has expandable Environment strings
LPTSTR pch = NULL; pch = _tcschr( (LPTSTR) szFile, _T('%')); if (pch) { TCHAR szValue[_MAX_PATH]; _tcscpy(szValue,szFile); if (!ExpandEnvironmentStrings( (LPCTSTR)szFile, szValue, sizeof(szValue)/sizeof(TCHAR))) {_tcscpy(szValue,szFile);}
return (GetFileAttributes(szValue) != 0xFFFFFFFF); } else { return (GetFileAttributes(szFile) != 0xFFFFFFFF); } }
void InetGetFilePath(LPCTSTR szFile, LPTSTR szPath) { // if UNC name \\computer\share\local1\local2
if (*szFile == _T('\\') && *(_tcsinc(szFile)) == _T('\\')) { TCHAR szTemp[_MAX_PATH], szLocal[_MAX_PATH]; TCHAR *p = NULL; int i = 0;
_tcscpy(szTemp, szFile); p = szTemp; while (*p) { if (*p == _T('\\')) i++; if (i == 4) { *p = _T('\0'); p = _tcsinc(p); // p is now pointing at local1\local2
break; } p = _tcsinc(p); } _tcscpy(szPath, szTemp); // now szPath contains \\computer\share
if (i == 4 && *p) { // p is pointing the local path now
_tcscpy(szLocal, p); p = _tcsrchr(szLocal, _T('\\')); if (p) *p = _T('\0'); _tcscat(szPath, _T("\\")); _tcscat(szPath, szLocal); // szPath contains \\computer\share\local1
} } else { // NOT UNC name
TCHAR *p; if (GetFullPathName(szFile, _MAX_PATH, szPath, &p)) { p = _tcsrchr(szPath, _T('\\')); if (p) { TCHAR *p2 = NULL; p2 = _tcsdec(szPath, p); if (p2) { if (*p2 == _T(':') ) {p = _tcsinc(p);} } *p = _T('\0'); } } else { iisDebugOutSafeParams((LOG_TYPE_WARN, _T("GetFullPathName: szFile=%1!s!, err=%2!d!\n"), szFile, GetLastError())); MyMessageBox(NULL, _T("GetFullPathName"), GetLastError(), MB_OK | MB_SETFOREGROUND); } }
return; }
BOOL InetDeleteFile(LPCTSTR szFileName) { // if file exists but DeleteFile() fails
if ( IsFileExist(szFileName) && !(::DeleteFile(szFileName)) ) { // if we cannot delete it, then move delay until reboot
// move it to top level dir on the same drive, and mark it as hidden
// Note: MoveFileEx() works only on the same drive if dealing with file-in-use
TCHAR TmpName[_MAX_PATH]; TCHAR csTmpPath[5] = _T("C:\\."); csTmpPath[0] = *szFileName; if ( GetTempFileName( (LPCTSTR)csTmpPath, _T("INT"), 0, TmpName ) == 0 || !MoveFileEx( szFileName, TmpName, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED|MOVEFILE_WRITE_THROUGH ) ) { return FALSE; } MoveFileEx( TmpName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT ); SetFileAttributes(TmpName, FILE_ATTRIBUTE_HIDDEN); }
return TRUE; }
BOOL InetCopyFile( LPCTSTR szSrc, LPCTSTR szDest) { INT err; INT fSrc; INT fDest; OFSTRUCT ofstruct;
do { // open source file
iisDebugOut_Start((_T("LZ32.dll:LZOpenFile()"))); if (( fSrc = LZOpenFile( (LPTSTR)szSrc, &ofstruct, OF_READ | OF_SHARE_DENY_NONE )) < 0 ) { iisDebugOut_End((_T("LZ32.dll:LZOpenFile"))); // cannot open src file
LZClose(fSrc);
UINT iMsg = MyMessageBox( NULL, IDS_CANNOT_OPEN_SRC_FILE, szSrc, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND ); switch ( iMsg ) { case IDABORT: return FALSE; case IDRETRY: break; case IDIGNORE: default: return TRUE; } } else { iisDebugOut_End((_T("LZ32.dll:LZOpenFile"))); break; } } while (TRUE);
// move the desintation file
CFileStatus status; if ( CFile::GetStatus( szDest, status )) { // try to remove it
if ( !InetDeleteFile( szDest )) { LZClose( fSrc ); return TRUE; } }
// open desination file
do { iisDebugOut_Start((_T("LZ32.dll:LZOpenFile()"))); if (( fDest = LZOpenFile( (LPTSTR)szDest, &ofstruct, OF_CREATE | OF_WRITE | OF_SHARE_DENY_NONE )) < 0 ) { iisDebugOut_End((_T("LZ32.dll:LZOpenFile"))); LZClose(fDest);
UINT iMsg = MyMessageBox( NULL, IDS_CANNOT_OPEN_DEST_FILE, szDest, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND ); switch ( iMsg ) { case IDABORT: LZClose(fSrc); return FALSE; case IDRETRY: break; case IDIGNORE: default: LZClose(fSrc); return TRUE; } } else { iisDebugOut_End((_T("LZ32.dll:LZOpenFile"))); break; } } while (TRUE);
do { iisDebugOut_Start((_T("LZ32.dll:LZCopy()"))); if (( err = LZCopy( fSrc, fDest )) < 0 ) { iisDebugOut_End((_T("LZ32.dll:LZCopy"))); LZClose( fSrc ); LZClose( fDest );
UINT iMsg = MyMessageBox( NULL, IDS_CANNOT_COPY_FILE, szSrc,szDest,ERROR_CANNOT_COPY, MB_ABORTRETRYIGNORE | MB_SETFOREGROUND ); switch ( iMsg ) { case IDABORT: return FALSE; case IDRETRY: break; case IDIGNORE: default: return TRUE; } } else { iisDebugOut_End((_T("LZ32.dll:LZCopy"))); LZClose( fSrc ); LZClose( fDest ); break; } } while (TRUE);
return TRUE; }
// Given a fullpathname of a directory, remove any empty dirs under it including itself
BOOL RecRemoveEmptyDir(LPCTSTR szName) { BOOL fReturn = FALSE; DWORD retCode; BOOL fRemoveDir = TRUE; WIN32_FIND_DATA FindFileData; HANDLE hFile = INVALID_HANDLE_VALUE; TCHAR szSubDir[_MAX_PATH] = _T(""); TCHAR szDirName[_MAX_PATH] = _T("");
retCode = GetFileAttributes(szName);
if (retCode == 0xFFFFFFFF || !(retCode & FILE_ATTRIBUTE_DIRECTORY)) return FALSE;
_stprintf(szDirName, _T("%s\\*"), szName); hFile = FindFirstFile(szDirName, &FindFileData);
if (hFile != INVALID_HANDLE_VALUE) { do { if (_tcsicmp(FindFileData.cFileName, _T(".")) != 0 && _tcsicmp(FindFileData.cFileName, _T("..")) != 0 ) { if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { _stprintf(szSubDir, _T("%s\\%s"), szName, FindFileData.cFileName); fRemoveDir = RecRemoveEmptyDir(szSubDir) && fRemoveDir; } else { CString csFileName = FindFileData.cFileName; CString csPrefix = csFileName.Left(3); CString csSuffix = csFileName.Right(4); if (_tcsicmp(csPrefix, _T("INT")) == 0 && _tcsicmp(csSuffix, _T(".tmp")) == 0 ) { // this is an INT*.tmp created by IIS
_stprintf(szSubDir, _T("%s\\%s"), szName, FindFileData.cFileName); if (!::DeleteFile(szSubDir)) fRemoveDir = FALSE; // this dir is not empty
} else fRemoveDir = FALSE; // it is a file, this Dir is not empty
} }
if (!FindNextFile(hFile, &FindFileData)) { FindClose(hFile); break; } } while (TRUE); }
if (fRemoveDir) { TCHAR szDirName[_MAX_PATH]; GetCurrentDirectory( _MAX_PATH, szDirName ); SetCurrentDirectory(g_pTheApp->m_csSysDir); fReturn = ::RemoveDirectory(szName); SetCurrentDirectory(szDirName); }
return fReturn;
}
// Given a fullpathname of a directory, remove the directory node
//
// Parameters
// szName - The name of file or directory
// bRemoveDirectoryItself - Should the directory itself be removed
//
BOOL RecRemoveDir(LPCTSTR szName, BOOL bRemoveDirectoryItself /* = TRUE */ ) { DWORD retCode; WIN32_FIND_DATA FindFileData; HANDLE hFile = INVALID_HANDLE_VALUE; TCHAR szSubDir[_MAX_PATH] = _T(""); TCHAR szDirName[_MAX_PATH] = _T("");
retCode = GetFileAttributes(szName);
if (retCode == 0xFFFFFFFF) return FALSE;
if (!(retCode & FILE_ATTRIBUTE_DIRECTORY)) { InetDeleteFile(szName); return TRUE; }
_stprintf(szDirName, _T("%s\\*"), szName); hFile = FindFirstFile(szDirName, &FindFileData);
if (hFile != INVALID_HANDLE_VALUE) { do { if ( _tcsicmp(FindFileData.cFileName, _T(".")) != 0 && _tcsicmp(FindFileData.cFileName, _T("..")) != 0 ) { _stprintf(szSubDir, _T("%s\\%s"), szName, FindFileData.cFileName); RecRemoveDir(szSubDir, TRUE); }
if ( !FindNextFile(hFile, &FindFileData) ) { FindClose(hFile); break; } } while (TRUE); }
if ( bRemoveDirectoryItself ) { return( ::RemoveDirectory(szName) ); }
return TRUE; }
//
// Given a directory path, this subroutine will create the direct layer by layer
//
BOOL CreateLayerDirectory( CString &str ) { BOOL fReturn = TRUE;
iisDebugOutSafeParams((LOG_TYPE_TRACE_WIN32_API, _T("CreateLayerDirectory %1!s!\n"), (LPCTSTR)str)); do { INT index=0; // INT iLength = str.GetLength();
INT iLength = _tcslen(str);
// first find the index for the first directory
if ( iLength > 2 ) { if ( *_tcsninc(str,1) == _T(':')) { // assume the first character is driver letter
if ( *_tcsninc(str,2) == _T('\\')) { index = 2; } else { index = 1; } } else if ( *_tcsninc(str,0) == _T('\\')) { if ( *_tcsninc(str,1) == _T('\\')) { BOOL fFound = FALSE; INT i; INT nNum = 0; // unc name
for (i = 2; i < iLength; i++ ) { if ( *_tcsninc(str,i) == _T('\\')) { // find it
nNum ++; if ( nNum == 2 ) { fFound = TRUE; break; } } } if ( fFound ) { index = i; } else { // bad name
break; } } else { index = 1; } } } else if ( *_tcsninc(str,0) == _T('\\')) { index = 0; }
// okay ... build directory
do { // find next one
do { if ( index < ( iLength - 1)) { index ++; } else { break; } } while ( *_tcsninc(str,index) != _T('\\'));
TCHAR szCurrentDir[_MAX_PATH+1]; TCHAR szLeftDir[_MAX_PATH+1]; ZeroMemory( szLeftDir, _MAX_PATH+1 );
GetCurrentDirectory( _MAX_PATH+1, szCurrentDir );
_tcsncpy( szLeftDir, str, index + 1 ); if ( !SetCurrentDirectory(szLeftDir) ) { if (( fReturn = CreateDirectory( szLeftDir, NULL )) != TRUE ) { break; } }
SetCurrentDirectory( szCurrentDir );
if ( index >= ( iLength - 1 )) { fReturn = TRUE; break; } } while ( TRUE ); } while (FALSE);
return(fReturn); }
// szResult = szParentDir \ szSubDir
BOOL AppendDir(LPCTSTR szParentDir, LPCTSTR szSubDir, LPTSTR szResult) { LPTSTR p = (LPTSTR)szParentDir;
ASSERT(szParentDir); ASSERT(szSubDir); ASSERT(*szSubDir && *szSubDir != _T('\\'));
if (*szParentDir == _T('\0')) _tcscpy(szResult, szSubDir); else { _tcscpy(szResult, szParentDir);
p = szResult; while (*p) p = _tcsinc(p);
if (*(_tcsdec(szResult, p)) != _T('\\')) _tcscat(szResult, _T("\\"));
_tcscat(szResult, szSubDir); } return TRUE; }
//***************************************************************************
//*
//* purpose: add's filename onto path
//*
//***************************************************************************
void AddPath(LPTSTR szPath, LPCTSTR szName ) { LPTSTR p = szPath; LPTSTR pPrev; ASSERT(szPath); ASSERT(szName);
// Find end of the string
while (*p){p = _tcsinc(p);} // If no trailing backslash then add one
pPrev = _tcsdec(szPath, p); if ( (!pPrev) || (*(pPrev) != _T('\\')) ) {_tcscat(szPath, _T("\\"));} // if there are spaces precluding szName, then skip
while ( *szName == ' ' ) szName = _tcsinc(szName);;
// Add new name to existing path string
_tcscat(szPath, szName); }
CString AddPath(CString szPath, LPCTSTR szName ) { TCHAR szPathCopy[_MAX_PATH] = _T(""); _tcscpy(szPathCopy,szPath); LPTSTR p = szPathCopy; ASSERT(szPathCopy); ASSERT(szName);
// Find end of the string
while (*p){p = _tcsinc(p);} // If no trailing backslash then add one
if (*(_tcsdec(szPathCopy, p)) != _T('\\')) {_tcscat(szPathCopy, _T("\\"));} // if there are spaces precluding szName, then skip
while ( *szName == _T(' ') ) szName = _tcsinc(szName);;
// make sure that the szName
// does not look like this "\filename"
CString csTempString = szName; if (_tcsicmp(csTempString.Left(1), _T("\\")) == 0) { csTempString = csTempString.Right( csTempString.GetLength() - 1); } // Add new name to existing path string
_tcscat(szPathCopy, csTempString);
return szPathCopy; //szPath = szPathCopy;
}
BOOL ReturnFileNameOnly(LPCTSTR lpFullPath, LPTSTR lpReturnFileName) { int iReturn = FALSE;
TCHAR pfilename_only[_MAX_FNAME]; TCHAR pextention_only[_MAX_EXT];
_tcscpy(lpReturnFileName, _T(""));
_tsplitpath( lpFullPath, NULL, NULL, pfilename_only, pextention_only); if (pextention_only) {_tcscat(pfilename_only,pextention_only);} if (pfilename_only) { _tcscpy(lpReturnFileName, pfilename_only); iReturn = TRUE; } else { // well, we don't have anything in pfilename_only
// that's probably because we got some strange path name like:
// /??/c:\somethng\filename.txt
// so... let's just return everything after the last "\" character.
LPTSTR pszTheLastBackSlash = _tcsrchr((LPTSTR) lpFullPath, _T('\\')); _tcscpy(lpReturnFileName, pszTheLastBackSlash); iReturn = TRUE; } return iReturn; }
BOOL ReturnFilePathOnly(LPCTSTR lpFullPath, LPTSTR lpReturnPathOnly) { int iReturn = FALSE; TCHAR szDrive_only[_MAX_DRIVE]; TCHAR szPath_only[_MAX_PATH]; TCHAR szFilename_only[_MAX_PATH]; TCHAR szFilename_ext_only[_MAX_EXT];
_tcscpy(lpReturnPathOnly, _T("")); _tsplitpath( lpFullPath, szDrive_only, szPath_only, szFilename_only, szFilename_ext_only); _tcscpy(lpReturnPathOnly, szDrive_only); _tcscat(lpReturnPathOnly, szPath_only); iReturn = TRUE;
return iReturn; }
void DeleteFilesWildcard(TCHAR *szDir, TCHAR *szFileName) { WIN32_FIND_DATA FindFileData; HANDLE hFile = INVALID_HANDLE_VALUE; TCHAR szFileToBeDeleted[_MAX_PATH];
_stprintf(szFileToBeDeleted, _T("%s\\%s"), szDir, szFileName);
hFile = FindFirstFile(szFileToBeDeleted, &FindFileData); if (hFile != INVALID_HANDLE_VALUE) { do { if ( _tcsicmp(FindFileData.cFileName, _T(".")) != 0 && _tcsicmp(FindFileData.cFileName, _T("..")) != 0 ) { if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // this is a directory, so let's skip it
} else { // this is a file, so let's Delete it.
TCHAR szTempFileName[_MAX_PATH]; _stprintf(szTempFileName, _T("%s\\%s"), szDir, FindFileData.cFileName); // set to normal attributes, so we can delete it
SetFileAttributes(szTempFileName, FILE_ATTRIBUTE_NORMAL); // delete it, hopefully
InetDeleteFile(szTempFileName); } }
// get the next file
if ( !FindNextFile(hFile, &FindFileData) ) { FindClose(hFile); break; } } while (TRUE); }
return; }
int IsThisDriveNTFS(IN LPTSTR FileName) { BOOL Ntfs = FALSE; TCHAR szDriveRootPath[_MAX_DRIVE + 5]; DWORD DontCare; TCHAR NameBuffer[100];
// get the Drive only.
_tsplitpath( FileName, szDriveRootPath, NULL, NULL, NULL); _tcscat(szDriveRootPath, _T("\\"));
//
// find out what the file system is
//
if (0 != GetVolumeInformation(szDriveRootPath,NULL,0,NULL,&DontCare,&DontCare,NameBuffer,sizeof(NameBuffer)/sizeof(TCHAR))) { if (0 == _tcsicmp(NameBuffer,_T("NTFS"))) {Ntfs = TRUE;} }
return Ntfs; }
// take something like
// e:\winnt\system32 and return back %systemroot%\system23
// e:\winnt\system32\inetsrv and return back %systemroot%\system23\inetsrv
int ReverseExpandEnvironmentStrings(LPTSTR szOriginalDir,LPTSTR szNewlyMungedDir) { int iReturn = FALSE; int iWhere = 0; TCHAR szSystemDir[_MAX_PATH]; CString csTempString; CString csTempString2;
// default it with the input string
_tcscpy(szNewlyMungedDir, szOriginalDir);
// get the c:\winnt\system32 dir
if (0 == GetSystemDirectory(szSystemDir, _MAX_PATH)) { // we weren't able to get the systemdirectory, so just return whatever was put in
iReturn = TRUE; goto ReverseExpandEnvironmentStrings_Exit; }
csTempString = szOriginalDir; csTempString2 = szSystemDir;
// Find the "e:\winnt\system32"
iWhere = csTempString.Find(szSystemDir); if (-1 != iWhere) { CString AfterString;
// there is a "e:\winnt\system32" in the string
// Get the after e:\winnt\system32 stuff
AfterString = csTempString.Right(csTempString.GetLength() - (iWhere + csTempString2.GetLength()));
// Take everything after the string and append it to our new string.
_tcscpy(szNewlyMungedDir, _T("%SystemRoot%\\System32")); _tcscat(szNewlyMungedDir, AfterString);
// return true!
iReturn = TRUE; }
ReverseExpandEnvironmentStrings_Exit: return iReturn; }
DWORD ReturnFileSize(LPCTSTR myFileName) { DWORD dwReturn = 0xFFFFFFFF; HANDLE hFile = CreateFile(myFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { dwReturn = GetFileSize(hFile, NULL); CloseHandle(hFile); } return dwReturn; }
BOOL IsFileExist_NormalOrCompressed(LPCTSTR szFile) { int iReturn = FALSE; TCHAR szDrive_only[_MAX_DRIVE]; TCHAR szPath_only[_MAX_PATH]; TCHAR szFilename_only[_MAX_PATH]; TCHAR szFilename_ext_only[_MAX_EXT];
TCHAR szCompressedName[_MAX_PATH];
// Check if the file exsts
// if it doesn't, check if maybe the compressed file exists.
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s.\n"), szFile)); if (IsFileExist(szFile) != TRUE) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s not exist.\n"), szFile)); // check if maybe the compressed file exists
_tsplitpath( szFile, szDrive_only, szPath_only, szFilename_only, szFilename_ext_only);
// Replace the last character with an '_'
int nLen = 0; nLen = _tcslen(szFilename_ext_only); *_tcsninc(szFilename_ext_only, nLen-1) = _T('_'); _stprintf(szCompressedName,_T("%s%s%s%s"),szDrive_only, szPath_only, szFilename_only, szFilename_ext_only);
// see if it exists
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s.\n"), szCompressedName)); if (IsFileExist(szCompressedName) != TRUE) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s. no exist.\n"), szCompressedName)); goto IsFileExist_RegOrCompressed_Exit; } else { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("IsFileExist_NormalOrCompressed:%s. exist.\n"), szCompressedName)); } }
// we got this far, that must mean things are okay.
iReturn = TRUE;
IsFileExist_RegOrCompressed_Exit: return iReturn; }
// Clean leading & trailing spaces
// Clean trailing backslashes
BOOL CleanPathString(LPTSTR szPath) { CString csPath = szPath;
csPath.TrimLeft(); csPath.TrimRight();
_tcscpy(szPath, (LPCTSTR)csPath);
return TRUE; }
//
// Return 0 if there was nothing to compare
// Return 1 if Source is Equal to Destination
// Return 2 if Source is Larger than Destination
// Return 3 if Source is Less than Destination
//
INT VerCmp(LPTSTR szSrcVerString, LPTSTR szDestVerString) { INT iReturn = 0; const DWORD MAX_NUM_OF_VER_FIELDS = 32; DWORD dwSrcVer[MAX_NUM_OF_VER_FIELDS], dwDestVer[MAX_NUM_OF_VER_FIELDS]; memset( (PVOID)dwSrcVer, 0, sizeof(dwSrcVer)); memset( (PVOID)dwDestVer, 0, sizeof(dwDestVer)); int i=0; TCHAR szSeps[] = _T("."); TCHAR *token; BOOL bNotEqual = FALSE;
// expand src version string into a dword arrary
i = 0; token = _tcstok(szSrcVerString, szSeps); while ( token && (i < MAX_NUM_OF_VER_FIELDS) ) { dwSrcVer[i++] = _ttoi(token); token = _tcstok(NULL, szSeps); }
// expand dest version string into a dword arrary
i = 0; token = _tcstok(szDestVerString, szSeps); while ( token && (i < MAX_NUM_OF_VER_FIELDS) ) { dwDestVer[i++] = _ttoi(token); token = _tcstok(NULL, szSeps); }
// Check for Equality
for (i=0; i<MAX_NUM_OF_VER_FIELDS; i++) { if (dwSrcVer[i] != dwDestVer[i]) { bNotEqual = TRUE; break; } }
if (TRUE == bNotEqual) { // int compare each field
for (i=0; i<MAX_NUM_OF_VER_FIELDS; i++) { if (dwSrcVer[i] > dwDestVer[i]) {return 2;} if (dwSrcVer[i] < dwDestVer[i]) {return 3;} } // if we haven't return here, then
// there probably wasn't anything to loop thru (for 0=0 till 0)
return 0; } else { // it is equal so return so
return 1; } }
DWORD atodw(LPCTSTR lpszData) { DWORD i = 0, sum = 0; TCHAR *s, *t;
s = (LPTSTR)lpszData; t = (LPTSTR)lpszData;
while (*t) t = _tcsinc(t); t = _tcsdec(lpszData, t);
if (*s == _T('0') && (*(_tcsinc(s)) == _T('x') || *(_tcsinc(s)) == _T('X'))) s = _tcsninc(s, 2);
while (s <= t) { if ( *s >= _T('0') && *s <= _T('9') ) i = *s - _T('0'); else if ( *s >= _T('a') && *s <= _T('f') ) i = *s - _T('a') + 10; else if ( *s >= _T('A') && *s <= _T('F') ) i = *s - _T('A') + 10; else break;
sum = sum * 16 + i; s = _tcsinc(s); } return sum; }
void MakePath(LPTSTR lpPath) { LPTSTR lpTmp; lpTmp = CharPrev( lpPath, lpPath + _tcslen(lpPath));
// chop filename off
while ( (lpTmp > lpPath) && *lpTmp && (*lpTmp != '\\') ) lpTmp = CharPrev( lpPath, lpTmp );
if ( *CharPrev( lpPath, lpTmp ) != ':' ) *lpTmp = '\0'; else *CharNext(lpTmp) = '\0'; return; }
CString ReturnUniqueFileName(CString csInputFullName) { TCHAR szPathCopy[_MAX_PATH] = _T(""); _tcscpy(szPathCopy,csInputFullName); long iNum = 1; do { _stprintf(szPathCopy,TEXT("%s.%d"),csInputFullName,iNum); // Check if the file exists
if (!IsFileExist(szPathCopy)){goto ReturnUniqueFileName_Exit;} iNum++; } while (iNum <= 50);
ReturnUniqueFileName_Exit: // returns %s50 if there are fifty copies aleady!
return szPathCopy; }
/*---------------------------------------------------------------------------*
Description: Displays the current running version of setup to the debug output and setup log. -----------------------------------------------------------------------------*/ void DisplayVerOnCurrentModule() { TCHAR tszModuleName[_MAX_PATH+1]; if ( GetModuleFileName((HINSTANCE)g_MyModuleHandle, tszModuleName, _MAX_PATH+1) != 0 ) { LogFileVersion(tszModuleName, TRUE); }
return; }
void MyGetVersionFromFile(LPCTSTR lpszFilename, LPDWORD pdwMSVer, LPDWORD pdwLSVer, LPTSTR pszReturnLocalizedVersion) { struct TRANSARRAY { WORD wLanguageID; WORD wCharacterSet; }; unsigned uiSize; DWORD dwVerInfoSize; DWORD dwHandle; VS_FIXEDFILEINFO * lpVSFixedFileInfo; LPTSTR lpBuffer = NULL; LPVOID lpVerBuffer = NULL;
LPTSTR pszTheResult = NULL; TCHAR QueryString[48] = _T(""); TRANSARRAY *lpTransArray;
*pdwMSVer = *pdwLSVer = 0L;
dwVerInfoSize = GetFileVersionInfoSize( (LPTSTR) lpszFilename, &dwHandle); if (dwVerInfoSize) { // Alloc the memory for the version stamping
lpBuffer = (LPTSTR) LocalAlloc(LPTR, dwVerInfoSize); if (lpBuffer) { int iTemp = 0; iTemp = GetFileVersionInfo( (LPTSTR) lpszFilename, dwHandle, dwVerInfoSize, lpBuffer);
// Read version stamping info
if (iTemp) { // Get the value for Translation
if (VerQueryValue(lpBuffer, _T("\\"), (LPVOID*)&lpVSFixedFileInfo, &uiSize) && (uiSize)) { *pdwMSVer = lpVSFixedFileInfo->dwFileVersionMS; *pdwLSVer = lpVSFixedFileInfo->dwFileVersionLS; }
// get a pointer to the translation table information
if (VerQueryValue(lpBuffer, _T("\\VarFileInfo\\Translation"), &lpVerBuffer, &uiSize) && (uiSize)) { lpTransArray = (TRANSARRAY *) lpVerBuffer; // lpTransArray points to the translation array. dwFixedLength has number of bytes in array
_stprintf(QueryString, _T("\\StringFileInfo\\%04x%04x\\FileVersion"), lpTransArray[0].wLanguageID, lpTransArray[0].wCharacterSet); if (VerQueryValue(lpBuffer, QueryString, (LPVOID*) &pszTheResult, &uiSize)) { _tcscpy(pszReturnLocalizedVersion, pszTheResult); } } } } }
if(lpBuffer) {LocalFree(lpBuffer);lpBuffer=NULL;} return ; }
BOOL MyGetDescriptionFromFile(LPCTSTR lpszFilename, LPTSTR pszReturnDescription) { BOOL bRet = FALSE; struct TRANSARRAY { WORD wLanguageID; WORD wCharacterSet; }; unsigned uiSize; DWORD dwVerInfoSize; DWORD dwHandle; LPTSTR lpBuffer = NULL; LPVOID lpTempBuffer = NULL;
LPTSTR pszTheResult = NULL; TCHAR QueryString[52] = _T(""); TRANSARRAY *lpTransArray;
dwVerInfoSize = GetFileVersionInfoSize( (LPTSTR) lpszFilename, &dwHandle); if (dwVerInfoSize) { // Alloc the memory for the version stamping
lpBuffer = (LPTSTR) LocalAlloc(LPTR, dwVerInfoSize); if (lpBuffer) { int iTemp = 0; iTemp = GetFileVersionInfo( (LPTSTR) lpszFilename, dwHandle, dwVerInfoSize, lpBuffer);
// Read version stamping info
if (iTemp) { // get a pointer to the translation table information
if (VerQueryValue(lpBuffer, _T("\\VarFileInfo\\Translation"), &lpTempBuffer, &uiSize) && (uiSize)) { lpTransArray = (TRANSARRAY *) lpTempBuffer; // lpTransArray points to the translation array. dwFixedLength has number of bytes in array
_stprintf(QueryString, _T("\\StringFileInfo\\%04x%04x\\FileDescription"), lpTransArray[0].wLanguageID, lpTransArray[0].wCharacterSet); if (VerQueryValue(lpBuffer, QueryString, (LPVOID*) &pszTheResult, &uiSize)) { _tcscpy(pszReturnDescription, pszTheResult); bRet = TRUE; } } } } }
if(lpBuffer) {LocalFree(lpBuffer);lpBuffer=NULL;} return bRet; }
//
// Returns True if the filename has a version stamp which is part of ntop4.0
//
int IsFileLessThanThisVersion(IN LPCTSTR lpszFullFilePath, IN DWORD dwNtopMSVer, IN DWORD dwNtopLSVer) { int iReturn = FALSE; DWORD dwMSVer, dwLSVer; TCHAR szLocalizedVersion[100] = _T(""); // if the filename has a version number
// and it's larger than the release version of ntop 4.2.622.1, 4.02.0622 (localized version)
// return back true! if not, then return back false.
// see if the file exists
if (!IsFileExist(lpszFullFilePath)) {goto iFileWasPartOfIIS4_Exit;}
// get the fileinformation
// includes version and localizedversion
MyGetVersionFromFile(lpszFullFilePath, &dwMSVer, &dwLSVer, szLocalizedVersion); if (!dwMSVer) { iisDebugOut((LOG_TYPE_TRACE, _T("iFileWasPartOfIIS4:%s.No version."), lpszFullFilePath)); goto iFileWasPartOfIIS4_Exit; }
// okay, there is a version on this.
iisDebugOut((LOG_TYPE_TRACE, _T("iFileWasPartOfIIS4:%d.%d.%d.%d, %s, %s"), HIWORD(dwMSVer), LOWORD(dwMSVer), HIWORD(dwLSVer), LOWORD(dwLSVer), szLocalizedVersion, lpszFullFilePath));
// Check if the version is smaller than what was shipped with iis4.0
// NTOP versions were 4.02.0622
if (dwMSVer < dwNtopMSVer) {goto iFileWasPartOfIIS4_Exit;}
// check if the file has a smaller minor version number
if ( (dwMSVer == dwNtopMSVer) && (dwLSVer < dwNtopLSVer) ) {goto iFileWasPartOfIIS4_Exit;}
// this is a ntop 4.0 or greater versioned file
iReturn = TRUE;
iFileWasPartOfIIS4_Exit: return iReturn; }
void MakeSureDirAclsHaveAtLeastRead(LPTSTR lpszDirectoryPath) { iisDebugOut_Start1(_T("MakeSureDirAclsHaveAtLeastRead"),lpszDirectoryPath, LOG_TYPE_TRACE);
DWORD err; TCHAR szThePath[_MAX_PATH];
if (FALSE == IsThisDriveNTFS(lpszDirectoryPath)) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("MakeSureDirAclsHaveAtLeastRead:filesys is not ntfs."))); goto MakeSureDirAclsHaveAtLeastRead_Exit; }
do { //
// Loop through all the files in the physical path
//
_tcscpy(szThePath, lpszDirectoryPath); _tcscat(szThePath, _T("\\*"));
WIN32_FIND_DATA w32data; HANDLE hFind = ::FindFirstFile(szThePath, &w32data); if (hFind == INVALID_HANDLE_VALUE) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("MakeSureDirAclsHaveAtLeastRead:WARNING.filenotfound:%s"),lpszDirectoryPath)); // No files...
break; } //
// First, set the new ACL on the folder itself.
//
err = SetAccessOnFile(lpszDirectoryPath, TRUE); err = SetAccessOnFile(lpszDirectoryPath, FALSE); err = ERROR_SUCCESS; //if (err != ERROR_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("MakeSureDirAclsHaveAtLeastRead:%s:FAILED WARNING.ret=0x%x."),lpszDirectoryPath,err));}
//
// Now do all the files in it
//
do { //
// Only set the acl on files, not sub-directories
//
if (w32data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { continue; }
//
// Build the current file's full path name
//
_tcscpy(szThePath, lpszDirectoryPath); _tcscat(szThePath, _T("\\")); _tcscat(szThePath, w32data.cFileName);
err = SetAccessOnFile(szThePath, TRUE); err = SetAccessOnFile(szThePath, FALSE); err = ERROR_SUCCESS; //if (err != ERROR_SUCCESS){iisDebugOut((LOG_TYPE_WARN, _T("MakeSureDirAclsHaveAtLeastRead:%s:FAILED WARNING.ret=0x%x."),szThePath,err));}
} while(SUCCEEDED(err) && FindNextFile(hFind, &w32data)); FindClose(hFind); } while(FALSE);
MakeSureDirAclsHaveAtLeastRead_Exit: return; }
DWORD SetAccessOnFile(IN LPTSTR FileName, BOOL bDoForAdmin) { DWORD dwError = 0; TCHAR TrusteeName[50]; PACL ExistingDacl = NULL; PACL NewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL;
// access stuff.
DWORD AccessMask = GENERIC_ALL; EXPLICIT_ACCESS explicitaccess; ACCESS_MODE option; DWORD InheritFlag = NO_INHERITANCE;
// other
PSID principalSID = NULL; BOOL bWellKnownSID = FALSE;
// other other
LPCTSTR ServerName = NULL; // local machine
DWORD cbName = 200; TCHAR lpGuestGrpName[200]; TCHAR ReferencedDomainName[200]; DWORD cbReferencedDomainName = sizeof(ReferencedDomainName); SID_NAME_USE sidNameUse = SidTypeUser;
// get current Dacl on specified file
dwError = GetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,&ExistingDacl,NULL,&psd); if(dwError != ERROR_SUCCESS) { iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile: GetNamedSecurityInfo failed on %s. err=0x%x\n"),FileName,dwError)); goto SetAccessOnFile_Exit; } // set defaults
option = GRANT_ACCESS; InheritFlag = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
if (bDoForAdmin) { // Do for Administrators -- should be more access
AccessMask = SYNCHRONIZE ; AccessMask |= GENERIC_ALL; _tcscpy(TrusteeName,_T("BUILTIN\\ADMINISTRATORS")); _tcscpy(TrusteeName,_T("administrators")); } else { // Do for Administrators -- should be more access
AccessMask = SYNCHRONIZE ; AccessMask |= GENERIC_READ; _tcscpy(TrusteeName,_T("EVERYONE")); }
// Get the SID for the certain string (administrator or everyone)
dwError = GetPrincipalSID(TrusteeName, &principalSID, &bWellKnownSID); if (dwError != ERROR_SUCCESS) { iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile:GetPrincipalSID(%s) FAILED. Error()= 0x%x\n"), TrusteeName, dwError)); goto SetAccessOnFile_Exit; }
// using Sid, get the "localized" name
if (0 == LookupAccountSid(ServerName, principalSID, lpGuestGrpName, &cbName, ReferencedDomainName, &cbReferencedDomainName, &sidNameUse)) { iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile:LookupAccountSid(%s) FAILED. GetLastError()= 0x%x\n"), TrusteeName, GetLastError())); goto SetAccessOnFile_Exit; }
// using the "localized" name, build explicit access structure
BuildExplicitAccessWithName(&explicitaccess,lpGuestGrpName,AccessMask,option,InheritFlag); explicitaccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; explicitaccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME; explicitaccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
// set the acl with this certain access stuff
dwError = SetEntriesInAcl(1,&explicitaccess,ExistingDacl,&NewAcl); if(dwError != ERROR_SUCCESS) { // it may error because the user is already there
//iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile: SetEntriesInAcl failed on %s. for trustee=%s. err=0x%x\n"),FileName,explicitaccess.Trustee.ptstrName,dwError));
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("SetAccessOnFile: SetEntriesInAcl failed on %s. for trustee=%s. err=0x%x\n"),FileName,explicitaccess.Trustee.ptstrName,dwError)); goto SetAccessOnFile_Exit; }
// apply new security to file
dwError = SetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,NewAcl,NULL); if(dwError != ERROR_SUCCESS) { iisDebugOut((LOG_TYPE_WARN, _T("SetAccessOnFile: SetNamedSecurityInfo failed on %s. err=0x%x\n"),FileName,dwError)); goto SetAccessOnFile_Exit; }
// everything is kool!
dwError = ERROR_SUCCESS;
SetAccessOnFile_Exit: if(NewAcl != NULL){LocalFree(NewAcl);} if(psd != NULL){LocalFree(psd);} if (principalSID) { if (bWellKnownSID) FreeSid (principalSID); else free (principalSID); } return dwError; }
int CreateAnEmptyFile(CString strTheFullPath) { int iReturn = FALSE; HANDLE hFile = NULL;
if (IsFileExist(strTheFullPath) == TRUE) { return TRUE; }
// Open existing file or create a new one.
hFile = CreateFile(strTheFullPath,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if (hFile == INVALID_HANDLE_VALUE) { hFile = NULL; iisDebugOutSafeParams((LOG_TYPE_WARN, _T("CreateAnEmptyFile:() failed to CreateFile %1!s!. POTENTIAL PROBLEM. FAILURE.\n"), strTheFullPath)); } else { // write to the file
if (hFile) { iReturn = TRUE; /*
DWORD dwBytesWritten = 0; char szTestData[2]; strcpy(szTestData, " "); if (WriteFile(hFile,szTestData,strlen(szTestData),&dwBytesWritten,NULL)) { // everything is hunky dory. don't print anything
iReturn = TRUE; } else { // error writing to the file.
iisDebugOutSafeParams((LOG_TYPE_WARN, _T("CreateAnEmptyFile:WriteFile(%1!s!) Failed. POTENTIAL PROBLEM. FAILURE. Error=0x%2!x!.\n"), strTheFullPath, GetLastError())); } */ } }
if (hFile) { CloseHandle(hFile); }
return iReturn; }
DWORD GrantUserAccessToFile(IN LPTSTR FileName,IN LPTSTR TrusteeName) { iisDebugOut_Start1(_T("GrantUserAccessToFile"),FileName,LOG_TYPE_TRACE);
DWORD dwError = 0; PACL ExistingDacl = NULL; PACL NewAcl = NULL; PSECURITY_DESCRIPTOR psd = NULL;
// access stuff.
DWORD AccessMask = GENERIC_ALL; EXPLICIT_ACCESS explicitaccess; ACCESS_MODE option; DWORD InheritFlag = NO_INHERITANCE;
// other
PSID principalSID = NULL; BOOL bWellKnownSID = FALSE;
// other other
LPCTSTR ServerName = NULL; // local machine
DWORD cbName = 200; TCHAR lpGuestGrpName[200]; TCHAR ReferencedDomainName[200]; DWORD cbReferencedDomainName = sizeof(ReferencedDomainName); SID_NAME_USE sidNameUse = SidTypeUser;
if (IsFileExist(FileName) != TRUE) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GrantUserAccessToFile:file doesn't exist."))); goto GrantUserAccessToFile_Exit; }
if (FALSE == IsThisDriveNTFS(FileName)) { iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GrantUserAccessToFile:filesys is not ntfs."))); goto GrantUserAccessToFile_Exit; }
// get current Dacl on specified file
dwError = GetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,&ExistingDacl,NULL,&psd); if(dwError != ERROR_SUCCESS) { psd = NULL; iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile: GetNamedSecurityInfo failed on %s.\n"),FileName)); goto GrantUserAccessToFile_Exit; } // set defaults
option = GRANT_ACCESS; InheritFlag = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
// assign access
AccessMask = SYNCHRONIZE ; AccessMask |= GENERIC_ALL; //AccessMask = MAXIMUM_ALLOWED;
// Get the SID for the certain string (administrator or everyone)
dwError = GetPrincipalSID(TrusteeName, &principalSID, &bWellKnownSID); if (dwError != ERROR_SUCCESS) { principalSID = NULL; iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile:GetPrincipalSID(%s) FAILED. Error()= 0x%x\n"), TrusteeName, dwError)); goto GrantUserAccessToFile_Exit; }
// using Sid, get the "localized" name
if (0 == LookupAccountSid(ServerName, principalSID, lpGuestGrpName, &cbName, ReferencedDomainName, &cbReferencedDomainName, &sidNameUse)) { iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile:LookupAccountSid(%s) FAILED. GetLastError()= 0x%x\n"), TrusteeName, GetLastError())); goto GrantUserAccessToFile_Exit; }
// using the "localized" name, build explicit access structure
BuildExplicitAccessWithName(&explicitaccess,lpGuestGrpName,AccessMask,option,InheritFlag); explicitaccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; explicitaccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME; explicitaccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; if (_tcsicmp(TrusteeName, _T("administrators")) == 0 || _tcsicmp(TrusteeName, _T("everyone")) == 0) { explicitaccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; }
// set the acl with this certain access stuff
dwError = SetEntriesInAcl(1,&explicitaccess,ExistingDacl,&NewAcl); if(dwError != ERROR_SUCCESS) { NewAcl = NULL; // it may error because the user is already there
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("GrantUserAccessToFile: SetEntriesInAcl failed on %s. for trustee=%s. err=0x%x\n"),FileName,explicitaccess.Trustee.ptstrName,dwError)); goto GrantUserAccessToFile_Exit; }
// apply new security to file
dwError = SetNamedSecurityInfo(FileName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,NewAcl,NULL); if(dwError != ERROR_SUCCESS) { iisDebugOut((LOG_TYPE_WARN, _T("GrantUserAccessToFile: SetNamedSecurityInfo failed on %s. err=0x%x\n"),FileName,dwError)); goto GrantUserAccessToFile_Exit; }
// everything is kool!
dwError = ERROR_SUCCESS;
GrantUserAccessToFile_Exit: if(NewAcl != NULL){LocalFree(NewAcl);} if(psd != NULL){LocalFree(psd);} if (principalSID) { if (bWellKnownSID) FreeSid (principalSID); else free (principalSID); } iisDebugOut_End1(_T("GrantUserAccessToFile"),FileName); return dwError; }
#ifndef _CHICAGO_
DWORD SetDirectorySecurity( IN LPCTSTR szDirPath, IN LPCTSTR szPrincipal, IN INT iAceType, IN DWORD dwAccessMask, IN DWORD dwInheritMask, IN BOOL DontInheritFromParentAndOverWriteAccess ) { DWORD dwStatus = ERROR_FILE_NOT_FOUND;
if (ACCESS_ALLOWED_ACE_TYPE == iAceType || ACCESS_DENIED_ACE_TYPE == iAceType) { if (IsFileExist(szDirPath) == TRUE) { PSID principalSID = NULL; BOOL bWellKnownSID = FALSE; dwStatus = GetPrincipalSID((LPTSTR) szPrincipal, &principalSID, &bWellKnownSID); if (dwStatus == ERROR_SUCCESS) { PSECURITY_DESCRIPTOR psd = NULL; dwStatus = SetAccessOnDirOrFile((TCHAR*) szDirPath,principalSID,iAceType,dwAccessMask,dwInheritMask,&psd,DontInheritFromParentAndOverWriteAccess);
//DumpAdminACL(INVALID_HANDLE_VALUE,psd);
if (psd) {free(psd);psd=NULL;} } } } return dwStatus; }
// -------------------------------------------------------------------------------------
// Function: RemovePrincipalFromFileAcl
//
// Remove a Access Control Entry from an Access Control List for a file/directory for a
// particular SID
//
// -------------------------------------------------------------------------------------
DWORD RemovePrincipalFromFileAcl(IN TCHAR *pszFile,IN LPTSTR szPrincipal) { PACL pdacl; SECURITY_DESCRIPTOR_CONTROL sdc; PSECURITY_DESCRIPTOR psdRelative = NULL; PSECURITY_DESCRIPTOR psdAbsolute = NULL; DWORD cbSize = 0; BOOL bRes = 0; DWORD dwSecurityDescriptorRevision; BOOL fHasDacl = FALSE; BOOL fDaclDefaulted = FALSE; BOOL bUserExistsToBeDeleted; DWORD dwError = ERROR_SUCCESS;
// get the size of the security descriptor
bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,0,&cbSize);
if ( !bRes ) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { psdRelative = malloc(cbSize);
if (!psdRelative) { return ERROR_INSUFFICIENT_BUFFER; }
bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,cbSize,&cbSize); } }
if (!bRes) { if (psdRelative) { free(psdRelative); } return (GetLastError()); }
// get security descriptor control from the security descriptor
if (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc,(LPDWORD) &dwSecurityDescriptorRevision)) { dwError = GetLastError(); } else if (SE_DACL_PRESENT & sdc) { // Acl's are present, so we will attempt to remove the one passes in.
if (GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,(PACL *) &pdacl, (LPBOOL) &fDaclDefaulted)) { // Remove ACE from Acl
dwError = RemovePrincipalFromACL(pdacl,szPrincipal,&bUserExistsToBeDeleted);
if (dwError == ERROR_SUCCESS) { psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(GetSecurityDescriptorLength(psdRelative));
if (psdAbsolute) { if ( !(InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION)) || !(SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdacl, fDaclDefaulted)) || !(IsValidSecurityDescriptor(psdAbsolute)) || !(SetFileSecurity(pszFile,(SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION),psdAbsolute)) ) { dwError = GetLastError(); }
if (psdAbsolute) { free(psdAbsolute); } } else { dwError = ERROR_INSUFFICIENT_BUFFER; } } } else { dwError = GetLastError(); } }
if (psdRelative) { free(psdRelative); }
return dwError; }
DWORD SetAccessOnDirOrFile(IN TCHAR *pszFile,PSID psidGroup,INT iAceType,DWORD dwAccessMask,DWORD dwInheritMask,PSECURITY_DESCRIPTOR* ppsd,BOOL DontInheritFromParentAndOverWriteAccess) { PSECURITY_DESCRIPTOR psdAbsolute = NULL; PACL pdacl; DWORD cbSecurityDescriptor = 0; DWORD dwSecurityDescriptorRevision; DWORD cbDacl = 0; SECURITY_DESCRIPTOR_CONTROL sdc; PACL pdaclNew = NULL; DWORD cbAddDaclLength = 0; BOOL fAceFound = FALSE; BOOL fHasDacl = FALSE; BOOL fDaclDefaulted = FALSE; ACCESS_ALLOWED_ACE* pAce; DWORD i; BOOL fAceForGroupPresent = FALSE; DWORD dwMask; PSECURITY_DESCRIPTOR psdRelative = NULL; DWORD cbSize = 0; BOOL bRes = 0;
// get the size of the security descriptor
bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,0,&cbSize); DWORD dwError = GetLastError(); if (ERROR_INSUFFICIENT_BUFFER == dwError) { psdRelative = malloc(cbSize); if (!psdRelative) { return ERROR_INSUFFICIENT_BUFFER; }
bRes = GetFileSecurity(pszFile,DACL_SECURITY_INFORMATION,psdRelative,cbSize,&cbSize); }
if (!bRes) { if (psdRelative){free(psdRelative);} return (GetLastError()); }
// get security descriptor control from the security descriptor
if (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc,(LPDWORD) &dwSecurityDescriptorRevision)) { return (GetLastError()); }
// check if DACL is present
if (SE_DACL_PRESENT & sdc) { ACE_HEADER *pAceHeader;
// get dacl
if (!GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,(PACL *) &pdacl, (LPBOOL) &fDaclDefaulted)) { return ( GetLastError()); }
// check if pdacl is null
// if it is then security is wide open -- this could be a fat drive.
if (NULL == pdacl) { return ERROR_SUCCESS; }
// get dacl length
cbDacl = pdacl->AclSize; // now check if SID's ACE is there
for (i = 0; i < pdacl->AceCount; i++) { if (!GetAce(pdacl, i, (LPVOID *) &pAce)) { return ( GetLastError()); }
pAceHeader = (ACE_HEADER *)pAce;
// check if group sid is already there
if (EqualSid((PSID) &(pAce->SidStart), psidGroup)) { if (ACCESS_DENIED_ACE_TYPE == iAceType) { if (pAceHeader->AceType == ACCESS_DENIED_ACE_TYPE) { // If the correct access is present, return success
if ((pAce->Mask & dwAccessMask) == dwAccessMask) { return ERROR_SUCCESS; } fAceForGroupPresent = TRUE; break; } } else { if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { if (FALSE == DontInheritFromParentAndOverWriteAccess) { // If the correct access is present, return success
if ((pAce->Mask & dwAccessMask) == dwAccessMask) { return ERROR_SUCCESS; } } fAceForGroupPresent = TRUE; break; } } } } // if the group did not exist, we will need to add room
// for another ACE
if (!fAceForGroupPresent) { // get length of new DACL
cbAddDaclLength = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psidGroup); } } else { // get length of new DACL
cbAddDaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid (psidGroup); }
// get memory needed for new DACL
//pdaclNew = (PACL) malloc (cbDacl + cbAddDaclLength);
pdaclNew = (PACL) LocalAlloc(LMEM_FIXED, cbDacl + cbAddDaclLength); if (!pdaclNew) { return (GetLastError()); }
// get the sd length
cbSecurityDescriptor = GetSecurityDescriptorLength(psdRelative);
// get memory for new SD
psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(cbSecurityDescriptor + cbAddDaclLength); if (!psdAbsolute) { dwError = GetLastError(); goto ErrorExit; } // change self-relative SD to absolute by making new SD
if (!InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION)) { dwError = GetLastError(); goto ErrorExit; } // init new DACL
if (!InitializeAcl(pdaclNew, cbDacl + cbAddDaclLength, ACL_REVISION)) { dwError = GetLastError(); goto ErrorExit; }
// Add a new ACE for our SID if one was not already present
if ( (!fAceForGroupPresent) && (ACCESS_DENIED_ACE_TYPE == iAceType) ) { if (!AddAccessDeniedAce(pdaclNew, ACL_REVISION, dwAccessMask,psidGroup)) { dwError = GetLastError(); goto ErrorExit; } }
// now add in all of the ACEs into the new DACL (if org DACL is there)
if (SE_DACL_PRESENT & sdc) { ACE_HEADER *pAceHeader; DWORD aceHeader_Flags = 0;
for (i = 0; i < pdacl->AceCount; i++) { // get ace from original dacl
if (!GetAce(pdacl, i, (LPVOID*) &pAce)) { dwError = GetLastError(); goto ErrorExit; }
pAceHeader = (ACE_HEADER *)pAce;
aceHeader_Flags = pAce->Header.AceFlags;
if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { dwMask = pAce->Mask; if (ACCESS_ALLOWED_ACE_TYPE == iAceType) { // If an ACE for our SID exists, we just need to bump
// up the access level instead of creating a new ACE
if (EqualSid((PSID) &(pAce->SidStart), psidGroup)) { if (FALSE == DontInheritFromParentAndOverWriteAccess) { dwMask = dwAccessMask | pAce->Mask; } else { dwMask = dwAccessMask; aceHeader_Flags = dwInheritMask; } } }
if (!AddAccessAllowedAceEx(pdaclNew, ACL_REVISION, aceHeader_Flags,dwMask,(PSID) &(pAce->SidStart))) { dwError = GetLastError(); goto ErrorExit; } } else if (pAceHeader->AceType == ACCESS_DENIED_ACE_TYPE) { dwMask = pAce->Mask; if (ACCESS_DENIED_ACE_TYPE == iAceType) { // If an ACE for our SID exists, we just need to bump
// up the access level instead of creating a new ACE
if (EqualSid((PSID) &(pAce->SidStart), psidGroup)) { dwMask = dwAccessMask | pAce->Mask; } } if (!AddAccessDeniedAceEx(pdaclNew, ACL_REVISION, pAce->Header.AceFlags,dwMask,(PSID) &(pAce->SidStart))) { dwError = GetLastError(); goto ErrorExit; } } else { // copy denied or audit ace.
if (!AddAce(pdaclNew, ACL_REVISION, 0xFFFFFFFF,pAce, pAceHeader->AceSize )) { dwError = GetLastError(); goto ErrorExit; } }
//iisDebugOut((LOG_TYPE_TRACE, _T("OrgAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
} }
// Add a new ACE for our SID if one was not already present
if ( (!fAceForGroupPresent) && (ACCESS_ALLOWED_ACE_TYPE == iAceType) ) { if (!AddAccessAllowedAce(pdaclNew, ACL_REVISION, dwAccessMask,psidGroup)) { dwError = GetLastError(); goto ErrorExit; } }
// change the header on an existing ace to have inherit
for (i = 0; i < pdaclNew->AceCount; i++) { if (!GetAce(pdaclNew, i, (LPVOID *) &pAce)) { return ( GetLastError()); }
// CONTAINER_INHERIT_ACE = Other containers that are contained by the primary object inherit the entry.
// INHERIT_ONLY_ACE = The ACE does not apply to the primary object to which the ACL is attached, but objects contained by the primary object inherit the entry.
// NO_PROPAGATE_INHERIT_ACE = The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are not propagated to an inherited entry.
// OBJECT_INHERIT_ACE = Noncontainer objects contained by the primary object inherit the entry.
// SUB_CONTAINERS_ONLY_INHERIT = Other containers that are contained by the primary object inherit the entry. This flag corresponds to the CONTAINER_INHERIT_ACE flag.
// SUB_OBJECTS_ONLY_INHERIT = Noncontainer objects contained by the primary object inherit the entry. This flag corresponds to the OBJECT_INHERIT_ACE flag.
// SUB_CONTAINERS_AND_OBJECTS_INHERIT = Both containers and noncontainer objects that are contained by the primary object inherit the entry. This flag corresponds to the combination of the CONTAINER_INHERIT_ACE and OBJECT_INHERIT_ACE flags.
//iisDebugOut((LOG_TYPE_TRACE, _T("NewAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
// if it's our SID, then change the header to be inherited
if (EqualSid((PSID) &(pAce->SidStart), psidGroup)) { pAce->Header.AceFlags |= dwInheritMask; } }
if (TRUE == DontInheritFromParentAndOverWriteAccess) { // Reorder ace's
// -------------
// ugly.
dwError = ReOrderACL(&pdaclNew); if (ERROR_SUCCESS != dwError) { goto ErrorExit; } } // check if everything went ok
if (!IsValidAcl(pdaclNew)) { dwError = ERROR_INVALID_ACL; goto ErrorExit; }
// now set security descriptor DACL
if (!SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdaclNew, fDaclDefaulted)) { dwError = GetLastError(); goto ErrorExit; }
// check if everything went ok
if (!IsValidSecurityDescriptor(psdAbsolute)) { dwError = ERROR_INVALID_SECURITY_DESCR; goto ErrorExit; }
// now set the reg key security (this will overwrite any existing security)
bRes = SetFileSecurity(pszFile,(SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION),psdAbsolute); if (bRes) { dwError = ERROR_SUCCESS; }
if (ppsd) { *ppsd = psdRelative; }
ErrorExit: // free memory
if (psdAbsolute) { free (psdAbsolute); if (pdaclNew) { //free((VOID*) pdaclNew);
LocalFree(pdaclNew);pdaclNew=NULL; } }
return dwError; }
//+--------------------------------------------------------------------------
//
// Function: SetAccessOnRegKey
//
// Purpose: Adds access for a specified SID to a registry key
//
// Arguments:
// hkey [in] The registry key that will receive the
// modified security descriptor
// psidGroup [in] The SID (in self-relative mode) that will be
// granted access to the key
// dwAccessMask [in] The access level to grant
// ppsd [out] The previous security descriptor
//
// Returns: DWORD. ERROR_SUCCESS or a failure code from winerror.h
//
//+--------------------------------------------------------------------------
DWORD SetAccessOnRegKey(HKEY hkey, PSID psidGroup, DWORD dwAccessMask, DWORD dwInheritMask, PSECURITY_DESCRIPTOR* ppsd) { PSECURITY_DESCRIPTOR psdAbsolute = NULL; PACL pdacl; DWORD cbSecurityDescriptor = 0; DWORD dwSecurityDescriptorRevision; DWORD cbDacl = 0; SECURITY_DESCRIPTOR_CONTROL sdc; PACL pdaclNew = NULL; DWORD cbAddDaclLength = 0; BOOL fAceFound = FALSE; BOOL fHasDacl = FALSE; BOOL fDaclDefaulted = FALSE; ACCESS_ALLOWED_ACE* pAce; DWORD i; BOOL fAceForGroupPresent = FALSE; DWORD dwMask; PSECURITY_DESCRIPTOR psdRelative = NULL; DWORD cbSize = 0;
// Get the current security descriptor for hkey
//
DWORD dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION, psdRelative, &cbSize);
if (ERROR_INSUFFICIENT_BUFFER == dwError) { psdRelative = malloc(cbSize); if (!psdRelative) { return ERROR_INSUFFICIENT_BUFFER; } dwError = RegGetKeySecurity(hkey, DACL_SECURITY_INFORMATION, psdRelative, &cbSize); }
// get security descriptor control from the security descriptor
if ( (!psdRelative) || (dwError != ERROR_SUCCESS) || (!GetSecurityDescriptorControl(psdRelative, (PSECURITY_DESCRIPTOR_CONTROL) &sdc,(LPDWORD) &dwSecurityDescriptorRevision)) ) { return (GetLastError()); }
// check if DACL is present
if (SE_DACL_PRESENT & sdc) { ACE_HEADER *pAceHeader;
// get dacl
if (!GetSecurityDescriptorDacl(psdRelative, (LPBOOL) &fHasDacl,(PACL *) &pdacl, (LPBOOL) &fDaclDefaulted)) { return ( GetLastError()); }
// check if pdacl is null
// if it is then security is wide open -- this could be a fat drive.
if (NULL == pdacl) { return ERROR_SUCCESS; }
// get dacl length
cbDacl = pdacl->AclSize; // now check if SID's ACE is there
for (i = 0; i < pdacl->AceCount; i++) { if (!GetAce(pdacl, i, (LPVOID *) &pAce)) { return ( GetLastError()); }
pAceHeader = (ACE_HEADER *)pAce; if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { // check if group sid is already there
if (EqualSid((PSID) &(pAce->SidStart), psidGroup)) { // If the correct access is present, return success
if ((pAce->Mask & dwAccessMask) == dwAccessMask) { return ERROR_SUCCESS; } fAceForGroupPresent = TRUE; break; } } } // if the group did not exist, we will need to add room
// for another ACE
if (!fAceForGroupPresent) { // get length of new DACL
cbAddDaclLength = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psidGroup); } } else { // get length of new DACL
cbAddDaclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid (psidGroup); }
// get memory needed for new DACL
//pdaclNew = (PACL) malloc (cbDacl + cbAddDaclLength);
pdaclNew = (PACL) LocalAlloc(LMEM_FIXED, cbDacl + cbAddDaclLength); if (!pdaclNew) { return (GetLastError()); }
// get the sd length
cbSecurityDescriptor = GetSecurityDescriptorLength(psdRelative);
// get memory for new SD
psdAbsolute = (PSECURITY_DESCRIPTOR) malloc(cbSecurityDescriptor + cbAddDaclLength); if (!psdAbsolute) { dwError = GetLastError(); goto ErrorExit; } // change self-relative SD to absolute by making new SD
if (!InitializeSecurityDescriptor(psdAbsolute, SECURITY_DESCRIPTOR_REVISION)) { dwError = GetLastError(); goto ErrorExit; } // init new DACL
if (!InitializeAcl(pdaclNew, cbDacl + cbAddDaclLength, ACL_REVISION)) { dwError = GetLastError(); goto ErrorExit; }
// now add in all of the ACEs into the new DACL (if org DACL is there)
if (SE_DACL_PRESENT & sdc) { ACE_HEADER *pAceHeader;
for (i = 0; i < pdacl->AceCount; i++) { // get ace from original dacl
if (!GetAce(pdacl, i, (LPVOID*) &pAce)) { dwError = GetLastError(); goto ErrorExit; }
pAceHeader = (ACE_HEADER *)pAce; if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { // If an ACE for our SID exists, we just need to bump
// up the access level instead of creating a new ACE
//
if (EqualSid((PSID) &(pAce->SidStart), psidGroup)) { dwMask = dwAccessMask | pAce->Mask; } else { dwMask = pAce->Mask; }
//iisDebugOut((LOG_TYPE_TRACE, _T("OrgAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
// now add ace to new dacl
if (!AddAccessAllowedAceEx(pdaclNew, ACL_REVISION, pAce->Header.AceFlags,dwMask,(PSID) &(pAce->SidStart))) { dwError = GetLastError(); goto ErrorExit; } } else { // copy denied or audit ace.
if (!AddAce(pdaclNew, ACL_REVISION, 0xFFFFFFFF, pAce, pAceHeader->AceSize )) { dwError = GetLastError(); goto ErrorExit; } } } }
// Add a new ACE for our SID if one was not already present
if (!fAceForGroupPresent) { // now add new ACE to new DACL
if (!AddAccessAllowedAce(pdaclNew, ACL_REVISION, dwAccessMask,psidGroup)) { dwError = GetLastError(); goto ErrorExit; } } // change the header on an existing ace to have inherit
for (i = 0; i < pdaclNew->AceCount; i++) { if (!GetAce(pdaclNew, i, (LPVOID *) &pAce)) { return ( GetLastError()); } // CONTAINER_INHERIT_ACE = Other containers that are contained by the primary object inherit the entry.
// INHERIT_ONLY_ACE = The ACE does not apply to the primary object to which the ACL is attached, but objects contained by the primary object inherit the entry.
// NO_PROPAGATE_INHERIT_ACE = The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE flags are not propagated to an inherited entry.
// OBJECT_INHERIT_ACE = Noncontainer objects contained by the primary object inherit the entry.
// SUB_CONTAINERS_ONLY_INHERIT = Other containers that are contained by the primary object inherit the entry. This flag corresponds to the CONTAINER_INHERIT_ACE flag.
// SUB_OBJECTS_ONLY_INHERIT = Noncontainer objects contained by the primary object inherit the entry. This flag corresponds to the OBJECT_INHERIT_ACE flag.
// SUB_CONTAINERS_AND_OBJECTS_INHERIT = Both containers and noncontainer objects that are contained by the primary object inherit the entry. This flag corresponds to the combination of the CONTAINER_INHERIT_ACE and OBJECT_INHERIT_ACE flags.
//iisDebugOut((LOG_TYPE_TRACE, _T("NewAce[%d]=0x%x\n"),i,pAce->Header.AceFlags));
// if it's our SID, then change the header to be inherited
if (EqualSid((PSID) &(pAce->SidStart), psidGroup)) { //pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | INHERITED_ACE;
//pAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | dwInheritMask;
pAce->Header.AceFlags |= dwInheritMask; } }
// ugly.
dwError = ReOrderACL(&pdaclNew); if (ERROR_SUCCESS != dwError) { goto ErrorExit; }
// check if everything went ok
if (!IsValidAcl(pdaclNew)) { dwError = ERROR_INVALID_ACL; goto ErrorExit; }
// now set security descriptor DACL
if (!SetSecurityDescriptorDacl(psdAbsolute, TRUE, pdaclNew, fDaclDefaulted)) { dwError = GetLastError(); goto ErrorExit; }
// check if everything went ok
if (!IsValidSecurityDescriptor(psdAbsolute)) { dwError = ERROR_INVALID_SECURITY_DESCR; goto ErrorExit; }
// now set the reg key security (this will overwrite any
// existing security)
dwError = RegSetKeySecurity(hkey, (SECURITY_INFORMATION)(DACL_SECURITY_INFORMATION), psdAbsolute);
if (ppsd) { *ppsd = psdRelative; } ErrorExit: // free memory
if (psdAbsolute) { free (psdAbsolute); if (pdaclNew) { //free((VOID*) pdaclNew);
LocalFree(pdaclNew);pdaclNew=NULL;
} }
return dwError; }
BOOL AddUserAccessToSD( IN PSECURITY_DESCRIPTOR pSd, IN PSID pSid, IN DWORD NewAccess, IN UCHAR TheAceType, OUT PSECURITY_DESCRIPTOR *ppSdNew ) { ULONG i; BOOL bReturn = FALSE; BOOL Result; BOOL DaclPresent; BOOL DaclDefaulted; DWORD Length; DWORD NewAclLength; ACCESS_ALLOWED_ACE* OldAce; PACE_HEADER NewAce; ACL_SIZE_INFORMATION AclInfo; PACL Dacl = NULL; PACL NewDacl = NULL; PACL NewAceDacl = NULL; PSECURITY_DESCRIPTOR NewSD = NULL; PSECURITY_DESCRIPTOR OldSD = NULL; PSECURITY_DESCRIPTOR outpSD = NULL; DWORD cboutpSD = 0; BOOL fAceForGroupPresent = FALSE; DWORD dwMask;
OldSD = pSd;
iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AddUserAccessToSD start\n")));
// only do if the ace is allowed/denied
if (ACCESS_ALLOWED_ACE_TYPE != TheAceType && ACCESS_DENIED_ACE_TYPE != TheAceType) { iisDebugOut((LOG_TYPE_TRACE, _T("AddUserAccessToSD useless param\n"))); goto AddUserAccessToSD_Exit; }
// Convert SecurityDescriptor to absolute format. It generates
// a new SecurityDescriptor for its output which we must free.
if ( !MakeAbsoluteCopyFromRelative(OldSD, &NewSD) ) { iisDebugOut((LOG_TYPE_ERROR, _T("MakeAbsoluteCopyFromRelative failed\n"))); goto AddUserAccessToSD_Exit;
}
// Must get DACL pointer from new (absolute) SD
if(!GetSecurityDescriptorDacl(NewSD,&DaclPresent,&Dacl,&DaclDefaulted)) { iisDebugOut((LOG_TYPE_ERROR, _T("GetSecurityDescriptorDacl failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit;
}
// If no DACL, no need to add the user since no DACL
// means all accesss
if( !DaclPresent ) { bReturn = TRUE; goto AddUserAccessToSD_Exit; }
// Code can return DaclPresent, but a NULL which means
// a NULL Dacl is present. This allows all access to the object.
if( Dacl == NULL ) { bReturn = TRUE; goto AddUserAccessToSD_Exit; }
// Get the current ACL's size
if( !GetAclInformation(Dacl,&AclInfo,sizeof(AclInfo),AclSizeInformation) ) { iisDebugOut((LOG_TYPE_ERROR, _T("GetAclInformation failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; }
// Check if access is already there
// --------------------------------
// Check to see if this SID already exists in there
// if it does (and it has the right access we want) then forget it, we don't have to do anything more.
for (i = 0; i < AclInfo.AceCount; i++) { ACE_HEADER *pAceHeader; ACCESS_ALLOWED_ACE* pAce = NULL;
if (!GetAce(Dacl, i, (LPVOID *) &pAce)) { iisDebugOut((LOG_TYPE_ERROR, _T("GetAce failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; }
pAceHeader = (ACE_HEADER *)pAce;
// check if group sid is already there
if (EqualSid((PSID) &(pAce->SidStart), pSid)) { if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { // If the correct access is present, return success
if ((pAce->Mask & NewAccess) == NewAccess) { //iisDebugOut((LOG_TYPE_TRACE, _T("AddUserAccessToSD:correct access already present. Exiting,1=0x%x,2=0x%x,3=0x%x\n"),pAce->Mask,NewAccess,(pAce->Mask & NewAccess)));
bReturn = TRUE; goto AddUserAccessToSD_Exit; } else { // the ace that exist doesn't have the permissions that we want.
// If an ACE for our SID exists, we just need to bump
// up the access level instead of creating a new ACE
fAceForGroupPresent = TRUE; } } break; } } // If we have to create a new ACE
// (because our user isn't listed in the existing ACL)
// then let's Create a new ACL to put the new access allowed ACE on
// --------------------------------
if (!fAceForGroupPresent) { NewAclLength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG) + GetLengthSid( pSid );
NewAceDacl = (PACL) LocalAlloc( LMEM_FIXED, NewAclLength ); if ( NewAceDacl == NULL ) { iisDebugOut((LOG_TYPE_ERROR, _T("LocalAlloc failed\n"))); goto AddUserAccessToSD_Exit; }
if(!InitializeAcl( NewAceDacl, NewAclLength, ACL_REVISION )) { iisDebugOut((LOG_TYPE_ERROR, _T("InitializeAcl failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; }
if (ACCESS_DENIED_ACE_TYPE == TheAceType) { Result = AddAccessDeniedAce(NewAceDacl,ACL_REVISION,NewAccess,pSid); } else { Result = AddAccessAllowedAce(NewAceDacl,ACL_REVISION,NewAccess,pSid); } if( !Result ) { iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedAce failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; } // Grab the 1st ace from the Newly created Dacl
if(!GetAce( NewAceDacl, 0, (void **)&NewAce )) { iisDebugOut((LOG_TYPE_ERROR, _T("GetAce failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; }
// add CONTAINER_INHERIT_ACE TO AceFlags
//NewAce->AceFlags |= CONTAINER_INHERIT_ACE;
Length = AclInfo.AclBytesInUse + NewAce->AceSize; } else { Length = AclInfo.AclBytesInUse; }
// Allocate new DACL
NewDacl = (PACL) LocalAlloc( LMEM_FIXED, Length ); if(NewDacl == NULL) { iisDebugOut((LOG_TYPE_ERROR, _T("LocalAlloc failed\n"))); goto AddUserAccessToSD_Exit; } if(!InitializeAcl( NewDacl, Length, ACL_REVISION )) { iisDebugOut((LOG_TYPE_ERROR, _T("InitializeAcl failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; }
// Insert new ACE at the front of the new DACL
if (!fAceForGroupPresent) { if(!AddAce( NewDacl, ACL_REVISION, 0, NewAce, NewAce->AceSize )) { iisDebugOut((LOG_TYPE_ERROR, _T("AddAce failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; } }
// ----------------------------------------
// Read thru the old Dacl and get the ACE's
// add it to the new Dacl
// ----------------------------------------
for ( i = 0; i < AclInfo.AceCount; i++ ) { ACE_HEADER *pAceHeader;
Result = GetAce( Dacl, i, (LPVOID*) &OldAce ); if( !Result ) { iisDebugOut((LOG_TYPE_ERROR, _T("GetAce failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; }
pAceHeader = (ACE_HEADER *)OldAce;
// If an ACE for our SID exists, we just need to bump
// up the access level instead of creating a new ACE
//
if (pAceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE) { dwMask = OldAce->Mask; if (fAceForGroupPresent) { if (EqualSid((PSID) &(OldAce->SidStart), pSid)) { dwMask = NewAccess | OldAce->Mask; } }
// now add ace to new dacl
Result = AddAccessAllowedAceEx(NewDacl, ACL_REVISION, OldAce->Header.AceFlags,dwMask,(PSID) &(OldAce->SidStart)); if( !Result ) { iisDebugOut((LOG_TYPE_ERROR, _T("AddAccessAllowedAceEx failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; } } else { // copy denied or audit ace.
if (!AddAce(NewDacl, ACL_REVISION, 0xFFFFFFFF,OldAce, pAceHeader->AceSize )) { iisDebugOut((LOG_TYPE_ERROR, _T("AddAce failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; } } }
// Set new DACL for Security Descriptor
if(!SetSecurityDescriptorDacl(NewSD,TRUE,NewDacl,FALSE)) { iisDebugOut((LOG_TYPE_ERROR, _T("SetSecurityDescriptorDacl failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; }
// The new SD is in absolute format. change it to Relative before we pass it back
cboutpSD = 0; MakeSelfRelativeSD(NewSD, outpSD, &cboutpSD); outpSD = (PSECURITY_DESCRIPTOR)GlobalAlloc(GPTR, cboutpSD); if ( !outpSD ) { iisDebugOut((LOG_TYPE_ERROR, _T("GlobalAlloc failed\n"))); goto AddUserAccessToSD_Exit; }
if (!MakeSelfRelativeSD(NewSD, outpSD, &cboutpSD)) { iisDebugOut((LOG_TYPE_ERROR, _T("MakeSelfRelativeSD failed with 0x%x\n"),GetLastError())); goto AddUserAccessToSD_Exit; }
// The new SD is passed back in relative format,
*ppSdNew = outpSD;
bReturn = TRUE;
AddUserAccessToSD_Exit: if (NewSD){free( NewSD );NewSD = NULL;} if (NewDacl){LocalFree( NewDacl );NewDacl = NULL;} if (NewAceDacl){LocalFree( NewAceDacl );NewAceDacl = NULL;} iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AddUserAccessToSD end\n"))); return bReturn; }
DWORD SetRegistryKeySecurityAdmin(HKEY hkey, DWORD samDesired,PSECURITY_DESCRIPTOR* ppsdOld) { PSID psid; SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY; DWORD dwError = ERROR_SUCCESS;
// Get sid for the local Administrators group
if (!AllocateAndInitializeSid(&sidAuth, 2,SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,0, 0, 0, 0, 0, 0, &psid) ) { dwError = GetLastError(); }
if (ERROR_SUCCESS == dwError) { // Add all access privileges for the local administrators group
dwError = SetAccessOnRegKey(hkey, psid, samDesired, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE | INHERITED_ACE, ppsdOld); }
return dwError; }
DWORD SetRegistryKeySecurity( IN HKEY hkeyRootKey, IN LPCTSTR szKeyPath, IN LPCTSTR szPrincipal, IN DWORD dwAccessMask, IN DWORD dwInheritMask, IN BOOL bDoSubKeys, IN LPTSTR szExclusiveList ) { DWORD dwStatus; HKEY hkeyThisKey; DWORD dwKeyIndex; DWORD dwSubKeyLen; TCHAR szSubKeyName[_MAX_PATH]; FILETIME FileTime; TCHAR *szExclusiveStart; BOOL fSetSecurityRec;
dwStatus = RegOpenKeyEx(hkeyRootKey,szKeyPath,0L,KEY_ALL_ACCESS,&hkeyThisKey); if (ERROR_SUCCESS == dwStatus) { PSID principalSID = NULL; BOOL bWellKnownSID = FALSE; if (ERROR_SUCCESS == GetPrincipalSID((LPTSTR) szPrincipal, &principalSID, &bWellKnownSID)) { PSECURITY_DESCRIPTOR psd = NULL; SetAccessOnRegKey(hkeyThisKey,principalSID,dwAccessMask,dwInheritMask,&psd); if (psd) {free(psd);} if (bDoSubKeys) { dwKeyIndex = 0; dwSubKeyLen = sizeof(szSubKeyName) / sizeof(TCHAR);
while (RegEnumKeyEx (hkeyThisKey,dwKeyIndex,szSubKeyName,&dwSubKeyLen,NULL,NULL,NULL,&FileTime) == ERROR_SUCCESS) { // subkey found so set subkey security
// attach on the inherited ace attribute since everything under this will be inherited
dwInheritMask |= INHERITED_ACE;
fSetSecurityRec = TRUE;
szExclusiveStart = szExclusiveList; while ( szExclusiveStart != NULL ) { szExclusiveStart = _tcsstr(szExclusiveStart,szSubKeyName);
// If we have found the substring, and the character after it is a NULL terminator or a ',', and
// it is at the begining of the string, or it had a , before it, then it is a match.
if ( ( szExclusiveStart != NULL ) && ( ( *(szExclusiveStart + dwSubKeyLen) == '\0' ) || ( *(szExclusiveStart + dwSubKeyLen) == ',' ) ) && ( ( szExclusiveStart == szExclusiveList) || (*(szExclusiveStart - 1) == ',') ) ) { fSetSecurityRec = FALSE; break; }
// Increment to move past current search result
if (szExclusiveStart) { szExclusiveStart = szExclusiveStart + dwSubKeyLen; } }
if ( fSetSecurityRec ) { dwStatus = SetRegistryKeySecurity(hkeyThisKey,szSubKeyName,szPrincipal,dwAccessMask,dwInheritMask,bDoSubKeys,szExclusiveList); }
// set variables for next call
dwKeyIndex++; dwSubKeyLen = sizeof(szSubKeyName) / sizeof(TCHAR); } } } RegCloseKey(hkeyThisKey); } return dwStatus; }
#endif
|