|
|
/******************************************************************************
* * Copyright (c) 2000 Microsoft Corporation * * Module Name: * utils.cpp * * Abstract: * Definitions of commonly used util functions. * * Revision History: * Brijesh Krishnaswami (brijeshk) 03/17/2000 * created * *****************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winioctl.h>
#include "srdefs.h"
#include "utils.h"
#include <dbgtrace.h>
#include <stdio.h>
#include <objbase.h>
#include <ntlsa.h>
#include <accctrl.h>
#include <aclapi.h>
#include <malloc.h>
#include <wchar.h>
#include "srapi.h"
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile
#define WBEM_DIRECTORY L"wbem"
#define FRAMEDYN_DLL L"framedyn.dll"
// forward declaration for Delnode_Recurse
BOOL SRGetAltFileName( LPCWSTR cszPath, LPWSTR szAltName );
#define TRACEID 1893
// this function converts an ANSI string to UNICODE.
// this also allocates the memory for the new string
WCHAR * ConvertToUnicode(CHAR * pszString) { WCHAR * pwszUnicodeString = NULL; DWORD dwBytesNeeded = 0;
TENTER("ConvertToUnicode"); dwBytesNeeded = (lstrlenA(pszString) + 1) * sizeof(WCHAR); pwszUnicodeString = (PWCHAR) SRMemAlloc(dwBytesNeeded); if(NULL == pwszUnicodeString) { TRACE(0, "Not enough memory"); goto cleanup; } // Convert filename to Unicode
if (!MultiByteToWideChar(CP_ACP, // code page
0, // no options
pszString, // ANSI string
-1, // NULL terminated string
pwszUnicodeString, // output buffer
dwBytesNeeded/sizeof(WCHAR))) // size in wide chars
{ DWORD dwReturnCode; dwReturnCode=GetLastError(); TRACE(0, "Failed to do conversion ec=%d", dwReturnCode); SRMemFree(pwszUnicodeString); goto cleanup; } cleanup: TLEAVE(); return pwszUnicodeString; }
// this function converts a UNICODE string to ANSI.
// this also allocates the memory for the new string
CHAR * ConvertToANSI(WCHAR * pwszString) { CHAR * pszANSIString = NULL; DWORD dwBytesNeeded = lstrlenW(pwszString) + sizeof(char);
TENTER("ConvertToANSI");
// note that the string may already be NULL terminated - however
// we cannot assume this and will still allocate space to put a
// NULL character in the end.
pszANSIString = (PCHAR) SRMemAlloc(dwBytesNeeded); if(NULL == pszANSIString) { TRACE(0, "Not enough memory"); goto cleanup; }
// Convert filename to Unicode
if (!WideCharToMultiByte(CP_ACP, // code page
0, // no options
pwszString, // Wide char string
dwBytesNeeded, // no of wchars
pszANSIString, // output buffer
dwBytesNeeded, // size of buffer
NULL, // address of default for unmappable
// characters
NULL)) // address of flag set when default
// char. used
{ DWORD dwReturnCode; dwReturnCode=GetLastError(); TRACE(0, "Failed to do conversion ec=%d", dwReturnCode); SRMemFree(pszANSIString); //this sets pwszUnicodeString to NULL
goto cleanup; }
// set last char to NULL
pszANSIString[dwBytesNeeded-1] = '\0';
cleanup: TraceFunctLeave(); return pszANSIString; }
//+---------------------------------------------------------------------------
//
// Function: TakeOwn
//
// Synopsis: attempts to take ACL ownership of the file for deletion
//
// Arguments: [pwszFile] -- file name
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD TakeOwn (const WCHAR *pwszFile) { SID * pSid = NULL; DWORD dwErr = ERROR_SUCCESS; SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
if (FALSE == SetSecurityDescriptorDacl (&sd, TRUE, NULL, FALSE )) { dwErr = GetLastError(); goto Err; }
if (FALSE == SetFileSecurity (pwszFile, DACL_SECURITY_INFORMATION, &sd)) { dwErr = GetLastError(); goto Err; }
// Okay, that didn't work, try to make Administrator the owner
if (dwErr != ERROR_SUCCESS) { SID_IDENTIFIER_AUTHORITY SepNtAuthority = SECURITY_NT_AUTHORITY;
if (FALSE == AllocateAndInitializeSid( &SepNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, (void **) &pSid )) { dwErr = GetLastError(); goto Err; }
if (FALSE == SetSecurityDescriptorOwner (&sd, pSid, FALSE )) { dwErr = GetLastError(); goto Err; }
if (FALSE == SetFileSecurity(pwszFile, OWNER_SECURITY_INFORMATION, &sd)) { dwErr = GetLastError(); goto Err; } }
Err: if (pSid != NULL) FreeSid (pSid);
return dwErr; }
//+---------------------------------------------------------------------------
//
// Function: CopyFile_Recurse
//
// Synopsis: attempt to copy disk space used by a file tree
//
// Arguments: [pwszSource] -- directory name
// [pwszDest] -- destination directory name
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CopyFile_Recurse (const WCHAR *pwszSource, const WCHAR *pwszDest) { DWORD dwErr = ERROR_SUCCESS; WIN32_FIND_DATA fd; HANDLE hFile; WCHAR wcsPath[MAX_PATH]; WCHAR wcsDest2[MAX_PATH];
if (lstrlenW(pwszSource) + 4 >= MAX_PATH) return ERROR_SUCCESS;
lstrcpy (wcsPath, pwszSource); lstrcat (wcsPath, TEXT("\\*.*"));
hFile = FindFirstFile(wcsPath, &fd);
if (hFile == INVALID_HANDLE_VALUE) { dwErr = GetLastError(); return dwErr; }
do { if (!lstrcmp(fd.cFileName, L".") || !lstrcmp(fd.cFileName, L"..")) { continue; }
if (lstrlenW(pwszSource) + lstrlenW(fd.cFileName) + 1 >= MAX_PATH || lstrlenW(pwszDest) + lstrlenW(fd.cFileName) + 1 >= MAX_PATH) continue; // skip files with long paths
lstrcpy (wcsPath, pwszSource); // construct the full path name
lstrcat (wcsPath, TEXT("\\")); lstrcat (wcsPath, fd.cFileName);
lstrcpy (wcsDest2, pwszDest); // construct the full path name
lstrcat (wcsDest2, TEXT("\\")); lstrcat (wcsDest2, fd.cFileName);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (FALSE == CreateDirectoryW (wcsDest2, NULL)) { dwErr = GetLastError(); if (dwErr != ERROR_ALREADY_EXISTS) { FindClose (hFile); return dwErr; } else dwErr = ERROR_SUCCESS; }
dwErr = CopyFile_Recurse (wcsPath, wcsDest2); if (dwErr != ERROR_SUCCESS) { FindClose (hFile); return dwErr; } } else { //
// We found a file. Copy it.
//
if (FALSE == CopyFileW (wcsPath, wcsDest2, FALSE)) { dwErr = GetLastError(); FindClose (hFile); return dwErr; } }
} while (FindNextFile(hFile, &fd)); // Find the next entry
FindClose(hFile); // Close the search handle
return ERROR_SUCCESS; }
//+---------------------------------------------------------------------------
//
// Function: GetFileSize_Recurse
//
// Synopsis: attempt to count disk space used by a file tree
//
// Arguments: [pwszDir] -- directory name
// [pllTotalBytes] -- output counter
// [pfStop] -- TRUE if stop signalled
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD GetFileSize_Recurse (const WCHAR *pwszDir, INT64 *pllTotalBytes, BOOL *pfStop) { DWORD dwErr = ERROR_SUCCESS; WIN32_FIND_DATA fd; HANDLE hFile; WCHAR wcsPath[MAX_PATH];
if (lstrlenW(pwszDir) + 4 >= MAX_PATH) // skip paths too long
return ERROR_SUCCESS;
lstrcpy (wcsPath, pwszDir); lstrcat (wcsPath, TEXT("\\*.*"));
hFile = FindFirstFile(wcsPath, &fd);
if (hFile == INVALID_HANDLE_VALUE) { dwErr = GetLastError(); return dwErr; }
do { if (pfStop != NULL && TRUE == *pfStop) { FindClose (hFile); return ERROR_OPERATION_ABORTED; }
if (!lstrcmp(fd.cFileName, L".") || !lstrcmp(fd.cFileName, L"..")) { continue; }
if (lstrlenW(pwszDir) + lstrlenW(fd.cFileName) + 1 >= MAX_PATH) continue; // skip files too long
lstrcpy (wcsPath, pwszDir); // construct the full path name
lstrcat (wcsPath, TEXT("\\")); lstrcat (wcsPath, fd.cFileName);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { //
// Found a directory. Skip mount points
//
if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { continue; }
dwErr = GetFileSize_Recurse(wcsPath, pllTotalBytes, pfStop); if (dwErr != ERROR_SUCCESS) { FindClose(hFile); return dwErr; } } else { //
// We found a file. Update the counter
//
ULARGE_INTEGER ulTemp; ulTemp.LowPart = fd.nFileSizeLow; ulTemp.HighPart = fd.nFileSizeHigh;
#if 0
ulTemp.LowPart = GetCompressedFileSize (wcsPath, &ulTemp.HighPart);
dwErr = (ulTemp.LowPart == 0xFFFFFFFF) ? GetLastError() : ERROR_SUCCESS;
if (dwErr != ERROR_SUCCESS) { FindClose (hFile); return dwErr; } #endif
*pllTotalBytes += ulTemp.QuadPart;
// The file size does not contain the size of the
// NTFS alternate data streams
}
} while (FindNextFile(hFile, &fd)); // Find the next entry
FindClose(hFile); // Close the search handle
return ERROR_SUCCESS; }
//+---------------------------------------------------------------------------
//
// Function: CompressFile
//
// Synopsis: attempt to compress to decompress an NTFS file
//
// Arguments: [pwszPath] -- directory or file name
// [fCompress] -- TRUE compress, FALSE decompress
// [fDirectory] -- TRUE if directory, FALSE if file
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CompressFile (const WCHAR *pwszPath, BOOL fCompress, BOOL fDirectory) { DWORD dwErr = ERROR_SUCCESS; DWORD dwReturned = 0;
TENTER("CompressFile");
if (pwszPath == NULL) return ERROR_INVALID_PARAMETER;
DWORD dwFileAttr = GetFileAttributes(pwszPath);
if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY)) { dwFileAttr &= ~FILE_ATTRIBUTE_READONLY; if (FALSE == SetFileAttributes (pwszPath, dwFileAttr)) { TRACE(0, "SetFileAttributes ignoring %ld", GetLastError()); } else dwFileAttr |= FILE_ATTRIBUTE_READONLY; }
USHORT usFormat = fCompress ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE;
HANDLE hFile = CreateFile( pwszPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, fDirectory ? FILE_FLAG_BACKUP_SEMANTICS : 0, NULL );
if (hFile == INVALID_HANDLE_VALUE) { dwErr = GetLastError(); TRACE(0, "CompressFile: cannot open %ld %ws", dwErr, pwszPath); return dwErr; }
if (FALSE == DeviceIoControl (hFile, FSCTL_SET_COMPRESSION, &usFormat, sizeof(usFormat), NULL, 0, &dwReturned, NULL)) { dwErr = GetLastError(); TRACE(0, "CompressFile: cannot compress/uncompress %ld %ws", dwErr, pwszPath); }
CloseHandle (hFile);
if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY)) { if (FALSE == SetFileAttributes (pwszPath, dwFileAttr)) { TRACE(0, "SetFileAttributes failed ignoring %ld", GetLastError()); } }
TLEAVE(); return dwErr; }
// returns system drive - as L"C:\\" if C: is the system drive
BOOL GetSystemDrive(LPWSTR pszDrive) { if (pszDrive) return ExpandEnvironmentStrings(L"%SystemDrive%\\", pszDrive, MAX_SYS_DRIVE); else return FALSE; }
// BUGBUG - pszDrive should have driveletter in caps,
// and needs to be of format L"C:\\" if C: is the system drive
BOOL IsSystemDrive(LPWSTR pszDriveOrGuid) { WCHAR szSystemDrive[MAX_PATH]; WCHAR szSystemGuid[MAX_PATH];
if (pszDriveOrGuid) { if (0 == ExpandEnvironmentStrings(L"%SystemDrive%\\", szSystemDrive, sizeof(szSystemDrive)/sizeof(WCHAR))) { return FALSE; } if (0 == wcsncmp(pszDriveOrGuid, L"\\\\?\\Volume", 10)) // guid
{ if (! GetVolumeNameForVolumeMountPoint(szSystemDrive, szSystemGuid, MAX_PATH)) { return FALSE; } return lstrcmpi(pszDriveOrGuid, szSystemGuid) ? FALSE : TRUE; } else // drive
{ return lstrcmpi(pszDriveOrGuid, szSystemDrive) ? FALSE : TRUE; } } else { return FALSE; } }
DWORD RegReadDWORD(HKEY hKey, LPCWSTR pszName, PDWORD pdwValue) { DWORD dwType = REG_DWORD; DWORD dwSize = sizeof(DWORD); DWORD dwRc = RegQueryValueEx(hKey, pszName, 0, &dwType, (LPBYTE) pdwValue, &dwSize); return dwRc; }
DWORD RegWriteDWORD(HKEY hKey, LPCWSTR pszName, PDWORD pdwValue) { DWORD dwType = REG_DWORD; DWORD dwSize = sizeof(DWORD); DWORD dwRc = RegSetValueEx(hKey, pszName, 0, dwType, (LPBYTE) pdwValue, dwSize); return dwRc; }
// function that returns n where pszStr is of form <someprefix>n
ULONG GetID( LPCWSTR pszStr) { ULONG ulID = 0;
while (*pszStr && (*pszStr < L'0' || *pszStr > L'9')) pszStr++;
ulID = (ULONG) _wtol(pszStr); return ulID; }
LPWSTR GetMachineGuid() { HKEY hKey = NULL; static WCHAR s_szGuid[GUID_STRLEN] = L""; static LPWSTR s_pszGuid = NULL;
if (! s_pszGuid) // first time
{ ULONG ulType, ulSize = sizeof(s_szGuid); DWORD dwErr;
dwErr = RegOpenKeyEx (HKEY_LOCAL_MACHINE, s_cszSRCfgRegKey, 0, KEY_READ, &hKey); if (dwErr != ERROR_SUCCESS) goto Err; dwErr = RegQueryValueEx (hKey, s_cszSRMachineGuid, 0, &ulType, (BYTE *) &s_szGuid, &ulSize); if (dwErr != ERROR_SUCCESS) goto Err;
s_pszGuid = (LPWSTR) s_szGuid; }
Err: if (hKey) RegCloseKey(hKey);
return s_pszGuid; }
// util function to construct <pszDrive>_Restore.{MachineGuid}\\pszSuffix
LPWSTR MakeRestorePath(LPWSTR pszDest, LPCWSTR pszDrive, LPCWSTR pszSuffix) { LPWSTR pszGuid = GetMachineGuid(); wsprintf(pszDest, L"%s%s\\%s", pszDrive, s_cszSysVolInfo, s_cszRestoreDir);
if (pszGuid) { // lstrcat(pszDest, L".");
lstrcat(pszDest, pszGuid); }
if (pszSuffix && lstrlen(pszSuffix) > 0) { lstrcat(pszDest, L"\\"); lstrcat(pszDest, pszSuffix); }
return pszDest; }
// set start type of specified service directly in the registry
DWORD SetServiceStartupRegistry(LPCWSTR pszName, DWORD dwStartType) { DWORD dwRc; HKEY hKey = NULL; WCHAR szKey[MAX_PATH];
lstrcpy(szKey, L"System\\CurrentControlSet\\Services\\"); lstrcat(szKey, pszName);
dwRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, KEY_WRITE, NULL, &hKey); if (ERROR_SUCCESS != dwRc) goto done;
dwRc = RegWriteDWORD(hKey, L"Start", &dwStartType);
done: if (hKey) RegCloseKey(hKey); return dwRc; }
// get start type of specified service directly from the registry
DWORD GetServiceStartupRegistry(LPCWSTR pszName, PDWORD pdwStartType) { DWORD dwRc; HKEY hKey = NULL; WCHAR szKey[MAX_PATH];
lstrcpy(szKey, L"System\\CurrentControlSet\\Services\\"); lstrcat(szKey, pszName);
dwRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, KEY_QUERY_VALUE, NULL, &hKey); if (ERROR_SUCCESS != dwRc) goto done;
dwRc = RegReadDWORD(hKey, L"Start", pdwStartType);
done: if (hKey) RegCloseKey(hKey); return dwRc; }
DWORD SetServiceStartup(LPCWSTR pszName, DWORD dwStartType) { TraceFunctEnter("SetServiceStartup"); DWORD dwError=ERROR_INTERNAL_ERROR; SC_HANDLE hService=NULL; SC_HANDLE hSCManager=NULL; hSCManager = OpenSCManager(NULL, // computer name - local machine
NULL,//SCM DB name - SERVICES_ACTIVE_DATABASE
SC_MANAGER_ALL_ACCESS); // access type
if( NULL == hSCManager) { dwError = GetLastError(); // file not found
DebugTrace(TRACEID,"OpenSCManager failed 0x%x", dwError); goto done; } hService = OpenService(hSCManager, // handle to SCM database
pszName, // service name
SERVICE_CHANGE_CONFIG); // access
if( NULL == hService) { dwError = GetLastError(); // file not found
DebugTrace(TRACEID,"OpenService failed 0x%x", dwError); goto done; }
if (FALSE==ChangeServiceConfig( hService, // handle to service
SERVICE_NO_CHANGE, // type of service
dwStartType, // when to start service
SERVICE_NO_CHANGE, // severity of start failure
NULL, // service binary file name
NULL, // load ordering group name
NULL, // tag identifier
NULL, // array of dependency names
NULL, // account name
NULL, // account password
NULL)) // display name
{ dwError = GetLastError(); // file not found
DebugTrace(TRACEID,"ChangeServiceConfig failed 0x%x", dwError); goto done; }
dwError = ERROR_SUCCESS;
done: if (NULL != hService) { _VERIFY(CloseServiceHandle(hService)); // handle to service or
// SCM object
}
if (NULL != hSCManager) { _VERIFY(CloseServiceHandle(hSCManager)); // handle to service or
// SCM object
} if ((dwError != ERROR_SUCCESS) && (dwError != ERROR_ACCESS_DENIED)) { // service control methods failed. Just update the registry
// directly
dwError = SetServiceStartupRegistry(pszName, dwStartType); } TraceFunctLeave(); return dwError; }
DWORD GetServiceStartup(LPCWSTR pszName, PDWORD pdwStartType) { TraceFunctEnter("SetServiceStartup"); DWORD dwError=ERROR_INTERNAL_ERROR; SC_HANDLE hService=NULL; SC_HANDLE hSCManager=NULL; QUERY_SERVICE_CONFIG *pconfig = NULL; DWORD cbBytes = 0, cbBytes2 = 0;
hSCManager = OpenSCManager(NULL, // computer name - local machine
NULL,//SCM DB name - SERVICES_ACTIVE_DATABASE
SC_MANAGER_ALL_ACCESS); // access type
if( NULL == hSCManager) { dwError = GetLastError(); // file not found
DebugTrace(TRACEID,"OpenSCManager failed 0x%x", dwError); goto done; } hService = OpenService(hSCManager, // handle to SCM database
pszName, // service name
SERVICE_QUERY_CONFIG); // access
if( NULL == hService) { dwError = GetLastError(); // file not found
DebugTrace(TRACEID,"OpenService failed 0x%x", dwError); goto done; }
if (FALSE==QueryServiceConfig( hService, // handle to service
NULL, 0, &cbBytes )) { dwError = GetLastError(); if (ERROR_INSUFFICIENT_BUFFER == dwError) { pconfig = (QUERY_SERVICE_CONFIG *) SRMemAlloc(cbBytes); if (!pconfig) { trace(TRACEID, "! SRMemAlloc"); goto done; } if (FALSE==QueryServiceConfig( hService, // handle to service
pconfig, cbBytes, &cbBytes2 )) { dwError = GetLastError(); DebugTrace(TRACEID,"! QueryServiceConfig (second) : %ld", dwError); goto done; }
if (pdwStartType) { *pdwStartType = pconfig->dwStartType; } dwError = ERROR_SUCCESS; } else { trace(TRACEID, "! QueryServiceConfig (first) : %ld", dwError); } }
done: SRMemFree(pconfig); if (NULL != hService) { _VERIFY(CloseServiceHandle(hService)); // handle to service or
// SCM object
}
if (NULL != hSCManager) { _VERIFY(CloseServiceHandle(hSCManager)); // handle to service or
// SCM object
} TraceFunctLeave(); return dwError; }
// this function returns whether the SR service is running
BOOL IsSRServiceRunning() { TraceFunctEnter("IsSRServiceRunning"); BOOL fReturn; DWORD dwError=ERROR_INTERNAL_ERROR; SC_HANDLE hService=NULL; SC_HANDLE hSCManager=NULL; SERVICE_STATUS ServiceStatus;
// assume FALSE by default
fReturn = FALSE; hSCManager = OpenSCManager(NULL, // computer name - local machine
NULL,//SCM DB name - SERVICES_ACTIVE_DATABASE
SC_MANAGER_ALL_ACCESS); // access type
if( NULL == hSCManager) { dwError = GetLastError(); DebugTrace(TRACEID,"OpenSCManager failed 0x%x", dwError); goto done; } hService = OpenService(hSCManager, // handle to SCM database
s_cszServiceName, // service name
SERVICE_QUERY_STATUS); // access
if( NULL == hService) { dwError = GetLastError(); DebugTrace(TRACEID,"OpenService failed 0x%x", dwError); goto done; }
if (FALSE == QueryServiceStatus(hService, // handle to service
&ServiceStatus)) // service status
{ dwError = GetLastError(); DebugTrace(TRACEID,"QueryServiceStatus failed 0x%x", dwError); goto done; }
if (ServiceStatus.dwCurrentState == SERVICE_RUNNING) { fReturn = TRUE; } else { DebugTrace(TRACEID,"SR Service is not running"); fReturn = FALSE; }
done: if (NULL != hService) { _VERIFY(CloseServiceHandle(hService)); // handle to service or
// SCM object
}
if (NULL != hSCManager) { _VERIFY(CloseServiceHandle(hSCManager)); // handle to service or
// SCM object
} TraceFunctLeave(); return fReturn; }
// this function returns whether the SR service is running
BOOL IsSRServiceStopped(SC_HANDLE hService) { TraceFunctEnter("IsSRServiceStopped"); SERVICE_STATUS ServiceStatus; BOOL fReturn; DWORD dwError; // assume FALSE by default
fReturn = FALSE; if (FALSE == QueryServiceStatus(hService, // handle to service
&ServiceStatus)) // service status
{ dwError = GetLastError(); DebugTrace(TRACEID,"QueryServiceStatus failed 0x%x", dwError); goto done; }
if (ServiceStatus.dwCurrentState == SERVICE_STOPPED) { DebugTrace(TRACEID,"SR Service is not running"); fReturn = TRUE; } else { DebugTrace(TRACEID,"SR Service is running"); fReturn = FALSE; }
done: TraceFunctLeave(); return fReturn; }
// private function to stop the SR service
// fWait - if TRUE : function is synchronous - waits till service is stopped completely
// if FALSE : function is asynchronous - does not wait for service to complete stopping
BOOL StopSRService(BOOL fWait) { TraceFunctEnter("StopSRService"); BOOL fReturn=FALSE; SC_HANDLE hSCManager; SERVICE_STATUS ServiceStatus; SC_HANDLE hService=NULL; DWORD dwError; hSCManager = OpenSCManager(NULL, // computer name - local machine
NULL,//SCM DB name - SERVICES_ACTIVE_DATABASE
SC_MANAGER_ALL_ACCESS); // access type
if (NULL == hSCManager) { dwError = GetLastError(); DebugTrace(TRACEID,"OpenSCManager failed 0x%x", dwError); goto done; } hService = OpenService(hSCManager, // handle to SCM database
s_cszServiceName, // service name
SERVICE_ALL_ACCESS); // access
if( NULL == hService) { dwError = GetLastError(); DebugTrace(TRACEID,"OpenService failed 0x%x", dwError); goto done; }
fReturn = ControlService(hService, // handle to service
SERVICE_CONTROL_STOP, // control code
&ServiceStatus); // status information
if (FALSE == fReturn) { dwError = GetLastError(); DebugTrace(TRACEID,"ControlService failed 0x%x", dwError); goto done; } if (fWait) { DWORD dwCount; //
// query the service until it stops
// try thrice
//
Sleep(500); for (dwCount=0; dwCount < 3; dwCount++) { if (TRUE == IsSRServiceStopped(hService)) { break; } Sleep(2000); } if (dwCount == 3) { fReturn=IsSRServiceStopped(hService); } else { fReturn=TRUE; } }
done:
if (NULL != hService) { _VERIFY(CloseServiceHandle(hService)); // handle to service or
// SCM object
}
if (NULL != hSCManager) { _VERIFY(CloseServiceHandle(hSCManager)); // handle to service or
// SCM object
} TraceFunctLeave(); return fReturn; }
//+---------------------------------------------------------------------------
//
// Function: GetLsaSecret
//
// Synopsis: obtains the LSA secret info as Unicode strings
//
// Arguments: [hPolicy] -- LSA policy object handle
// [wszSecret] -- secret name
// [ppusSecretValue] -- dynamically allocated value
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD GetLsaSecret (LSA_HANDLE hPolicy, const WCHAR *wszSecret, UNICODE_STRING ** ppusSecretValue) { TENTER ("GetLsaSecret");
LSA_HANDLE hSecret; UNICODE_STRING usSecretName; DWORD dwErr = ERROR_SUCCESS;
RtlInitUnicodeString (&usSecretName, wszSecret); if (LSA_SUCCESS (LsaOpenSecret (hPolicy, &usSecretName, SECRET_QUERY_VALUE, &hSecret))) { if (!LSA_SUCCESS (LsaQuerySecret (hSecret, ppusSecretValue, NULL, NULL, NULL))) { *ppusSecretValue = NULL;
TRACE(0, "Cannot query secret %ws", wszSecret); } LsaClose (hSecret); }
TLEAVE();
return dwErr; } //+---------------------------------------------------------------------------
//
// Function: SetLsaSecret
//
// Synopsis: sets the LSA secret info
//
// Arguments: [hPolicy] -- LSA policy object handle
// [wszSecret] -- secret name
// [wszSecretValue] -- secret value
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD SetLsaSecret (PVOID hPolicy, const WCHAR *wszSecret, WCHAR * wszSecretValue) { TENTER ("SetLsaSecret");
LSA_HANDLE hSecret; UNICODE_STRING usSecretName; UNICODE_STRING usSecretValue; DWORD dwErr = ERROR_SUCCESS;
hPolicy = (LSA_HANDLE) hPolicy;
RtlInitUnicodeString (&usSecretName, wszSecret); RtlInitUnicodeString (&usSecretValue, wszSecretValue);
if (LSA_SUCCESS (LsaOpenSecret (hPolicy, &usSecretName, SECRET_SET_VALUE, &hSecret))) { if (!LSA_SUCCESS (LsaSetSecret (hSecret, &usSecretValue, NULL))) { TRACE(0, "Cannot set secret %ws", wszSecret); } LsaClose (hSecret); }
TLEAVE();
return dwErr; }
//+---------------------------------------------------------------------------
//
// Function: WriteNtUnicodeString
//
// Synopsis: writes a NT unicode string to disk
//
// Arguments: [hFile] -- file handle
// [pus] -- NT unicode string
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD WriteNtUnicodeString (HANDLE hFile, UNICODE_STRING *pus) { DWORD dwErr = ERROR_SUCCESS; DWORD cb = 0;
if (pus != NULL && FALSE == WriteFile (hFile, (BYTE *)pus->Buffer, pus->Length, &cb, NULL)) { dwErr = GetLastError(); } else if (FALSE == WriteFile (hFile, (BYTE *) L"", sizeof(WCHAR), &cb, NULL)) { dwErr = GetLastError(); } return dwErr; }
//+---------------------------------------------------------------------------
//
// Function: GetLsaRestoreState
//
// Synopsis: gets the LSA machine and autologon password
//
// Arguments: [hKeySoftware] -- Software registry key
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD GetLsaRestoreState (HKEY hKeySoftware) { TENTER ("GetLsaRestoreState");
HKEY hKey = NULL; LSA_OBJECT_ATTRIBUTES loa; LSA_HANDLE hLsa = NULL; DWORD dwErr = ERROR_SUCCESS;
loa.Length = sizeof(LSA_OBJECT_ATTRIBUTES); loa.RootDirectory = NULL; loa.ObjectName = NULL; loa.Attributes = 0; loa.SecurityDescriptor = NULL; loa.SecurityQualityOfService = NULL;
if (LSA_SUCCESS (LsaOpenPolicy(NULL, &loa, POLICY_VIEW_LOCAL_INFORMATION, &hLsa))) { UNICODE_STRING * pusSecret = NULL;
dwErr = RegOpenKeyEx (hKeySoftware, hKeySoftware == HKEY_LOCAL_MACHINE ? s_cszSRRegKey : L"Microsoft\\Windows NT\\CurrentVersion\\SystemRestore", 0, KEY_READ | KEY_WRITE, &hKey);
if (dwErr != ERROR_SUCCESS) goto Err;
if (ERROR_SUCCESS==GetLsaSecret (hLsa, s_cszMachineSecret, &pusSecret)) { if (pusSecret != NULL && pusSecret->Length > 0) dwErr = RegSetValueEx (hKey, s_cszMachineSecret, 0, REG_BINARY, (BYTE *) pusSecret->Buffer, pusSecret->Length);
LsaFreeMemory (pusSecret); pusSecret = NULL; }
if (ERROR_SUCCESS==GetLsaSecret(hLsa, s_cszAutologonSecret, &pusSecret)) { if (pusSecret != NULL && pusSecret->Length > 0) dwErr = RegSetValueEx (hKey, s_cszAutologonSecret, 0, REG_BINARY, (BYTE *) pusSecret->Buffer, pusSecret->Length);
LsaFreeMemory (pusSecret); pusSecret = NULL; } }
Err: if (hLsa != NULL) LsaClose (hLsa);
if (hKey != NULL) RegCloseKey (hKey);
TLEAVE();
return dwErr; }
//+---------------------------------------------------------------------------
//
// Function: GetDomainMembershipInfo
//
// Synopsis: writes current domain and computer name into a file
//
// Arguments: [pwszPath] -- file name
// [pwszzBuffer] -- output multistring buffer
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD GetDomainMembershipInfo (WCHAR *pwszPath, WCHAR *pwszzBuffer) { TENTER("GetDomainMembershipInfo");
POLICY_PRIMARY_DOMAIN_INFO* ppdi = NULL; LSA_OBJECT_ATTRIBUTES loa; LSA_HANDLE hLsa = NULL; HANDLE hFile = INVALID_HANDLE_VALUE; DWORD dwComputerLength = MAX_COMPUTERNAME_LENGTH + 1; DWORD dwRc = ERROR_SUCCESS; ULONG cbWritten; WCHAR wszComputer[MAX_COMPUTERNAME_LENGTH+1];
loa.Length = sizeof(LSA_OBJECT_ATTRIBUTES); loa.RootDirectory = NULL; loa.ObjectName = NULL; loa.Attributes = 0; loa.SecurityDescriptor = NULL; loa.SecurityQualityOfService = NULL;
if (FALSE == GetComputerNameW (wszComputer, &dwComputerLength)) { dwRc = GetLastError(); trace(0, "! GetComputerNameW : %ld", dwRc); return dwRc; }
if (LSA_SUCCESS (LsaOpenPolicy(NULL, &loa, POLICY_VIEW_LOCAL_INFORMATION, &hLsa))) {
if (pwszPath != NULL) { hFile = CreateFileW ( pwszPath, // file name
GENERIC_WRITE, // file access
0, // share mode
NULL, // SD
CREATE_ALWAYS, // how to create
0, // file attributes
NULL); // handle to template file
if (INVALID_HANDLE_VALUE == hFile) { dwRc = GetLastError(); trace(0, "! CreateFileW : %ld", dwRc); goto Err; }
if (FALSE == WriteFile (hFile, (BYTE *) wszComputer, (dwComputerLength+1)*sizeof(WCHAR), &cbWritten, NULL)) { dwRc = GetLastError(); trace(0, "! WriteFile : %ld", dwRc); goto Err; } } if (pwszzBuffer != NULL) { lstrcpy (pwszzBuffer, wszComputer); pwszzBuffer += dwComputerLength + 1; }
if (LSA_SUCCESS (LsaQueryInformationPolicy( hLsa, PolicyPrimaryDomainInformation, (VOID **) &ppdi ))) { const WCHAR *pwszFlag = (ppdi->Sid > 0) ? L"1" : L"0";
if (pwszPath != NULL) { dwRc = WriteNtUnicodeString (hFile, &ppdi->Name); if (dwRc != ERROR_SUCCESS) { trace(0, "! WriteNtUnicodeString : %ld", dwRc); } if (FALSE == WriteFile (hFile, (BYTE *) pwszFlag, (lstrlenW(pwszFlag)+1)*sizeof(WCHAR), &cbWritten, NULL)) { dwRc = GetLastError(); trace(0, "! WriteFile : %ld", dwRc); goto Err; } } if (pwszzBuffer != NULL) { ULONG ul = ppdi->Name.Length / sizeof(WCHAR); memcpy (pwszzBuffer, ppdi->Name.Buffer, ppdi->Name.Length); pwszzBuffer [ul] = L'\0'; lstrcpy (&pwszzBuffer[ul+1], pwszFlag); } } }
Err: if (hLsa != NULL) LsaClose (hLsa);
if (hFile != INVALID_HANDLE_VALUE) CloseHandle (hFile);
TLEAVE();
return dwRc; }
//++
//
// Method: DoesFileExist
//
// Synopsis: Checks if a file by the specified exists
//
// Arguments:[pszFileName] File name
//
// Returns: TRUE if the specified string is a file
// False otherwise
//
// History: AshishS Created 7/30/96
//
//--
BOOL DoesFileExist(const TCHAR * pszFileName) { DWORD dwFileAttr, dwError; TraceFunctEnter("DoesFileExist");
DebugTrace(TRACEID, "Checking for %S", pszFileName); dwFileAttr = GetFileAttributes(pszFileName);
if (dwFileAttr == 0xFFFFFFFF ) { dwError = GetLastError(); // file not found
DebugTrace(TRACEID,"GetFileAttributes failed 0x%x", dwError); TraceFunctLeave(); return FALSE ; } if (dwFileAttr & FILE_ATTRIBUTE_DIRECTORY) { DebugTrace(TRACEID, "It is a Directory "); TraceFunctLeave(); return FALSE; } DebugTrace(TRACEID, "File exists"); TraceFunctLeave(); return TRUE; }
//++
//
// Method: DoesDirExist
//
// Synopsis: Checks if the specified string is a directory
//
// Arguments: [pszFileName] Directory name
//
// Returns: TRUE if the specified string is a directory,
// False otherwise
//
// History: AshishS Created 7/30/96
//
//--
BOOL DoesDirExist(const TCHAR * pszFileName ) { DWORD dwFileAttr; TraceFunctEnter("DoesDirExist");
//DebugTrace(TRACEID, " Checking for %S", pszFileName);
dwFileAttr = GetFileAttributes(pszFileName);
if (dwFileAttr == 0xFFFFFFFF ) { // file not found
//DebugTrace(TRACEID,"GetFileAttributes failed 0x%x",
//GetLastError());
TraceFunctLeave(); return FALSE ; } if (dwFileAttr & FILE_ATTRIBUTE_DIRECTORY) { //DebugTrace(TRACEID, "Directory exists ");
TraceFunctLeave(); return TRUE ; }
//DebugTrace(TRACEID, "Directory does not exist");
TraceFunctLeave(); return FALSE; }
// sets acl allowing specific access to LocalSystem/Admin
// and to everyone
DWORD SetAclInObject(HANDLE hObject, DWORD dwObjectType, DWORD dwSystemMask, DWORD dwEveryoneMask, BOOL fInherit) { tenter("SetAclInObject"); DWORD dwRes, dwDisposition; PSID pEveryoneSID = NULL, pAdminSID = NULL, pSystemSID = NULL; PACL pACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; EXPLICIT_ACCESS ea[3]; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; LONG lRes;
// Create a well-known SID for the Everyone group.
if(! AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID) ) { dwRes = GetLastError(); trace(0, "AllocateAndInitializeSid Error %u\n", dwRes); goto Cleanup; }
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow Everyone read access to the key.
ZeroMemory(&ea, 3 * sizeof(EXPLICIT_ACCESS)); ea[0].grfAccessPermissions = dwEveryoneMask; ea[0].grfAccessMode = SET_ACCESS; ea[0].grfInheritance = fInherit ? SUB_CONTAINERS_AND_OBJECTS_INHERIT : NO_INHERITANCE; ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID;
// Create a SID for the BUILTIN\Administrators group.
if(! AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID) ) { dwRes = GetLastError(); trace(0, "AllocateAndInitializeSid Error %u\n", dwRes); goto Cleanup; }
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow the Administrators group full access to the key.
ea[1].grfAccessPermissions = dwSystemMask; ea[1].grfAccessMode = SET_ACCESS; ea[1].grfInheritance= fInherit ? SUB_CONTAINERS_AND_OBJECTS_INHERIT : NO_INHERITANCE; ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID;
// Create a SID for the LocalSystem account
if(! AllocateAndInitializeSid( &SIDAuthNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSID) ) { dwRes = GetLastError(); trace(0, "AllocateAndInitializeSid Error %u\n", dwRes ); goto Cleanup; }
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow the LocalSystem full access to the key.
ea[2].grfAccessPermissions = dwSystemMask; ea[2].grfAccessMode = SET_ACCESS; ea[2].grfInheritance= fInherit ? SUB_CONTAINERS_AND_OBJECTS_INHERIT : NO_INHERITANCE; ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[2].Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea[2].Trustee.ptstrName = (LPTSTR) pSystemSID;
// Create a new ACL that contains the new ACEs.
dwRes = SetEntriesInAcl(3, ea, NULL, &pACL); if (ERROR_SUCCESS != dwRes) { dwRes = GetLastError(); trace(0, "SetEntriesInAcl Error %u\n", dwRes ); goto Cleanup; }
// Initialize a security descriptor.
pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSD == NULL) { trace(0, "LocalAlloc Error %u\n", GetLastError() ); goto Cleanup; } if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { dwRes = GetLastError(); trace(0, "InitializeSecurityDescriptor Error %u\n", dwRes ); goto Cleanup; } // Add the ACL to the security descriptor.
if (!SetSecurityDescriptorDacl(pSD, TRUE, // fDaclPresent flag
pACL, FALSE)) // not a default DACL
{ dwRes = GetLastError(); trace(0, "SetSecurityDescriptorDacl Error %u\n", dwRes ); goto Cleanup; }
dwRes = SetSecurityInfo(hObject, (SE_OBJECT_TYPE) dwObjectType, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL); if (ERROR_SUCCESS != dwRes) { trace(0, "SetSecurityInfo Error %u\n", dwRes ); goto Cleanup; }
Cleanup: if (pEveryoneSID) FreeSid(pEveryoneSID); if (pAdminSID) FreeSid(pAdminSID); if (pSystemSID) FreeSid(pSystemSID); if (pACL) LocalFree(pACL); if (pSD) LocalFree(pSD);
tleave(); return dwRes; }
// sets acl to a named object allowing specific access to
// LocalSystem/Admin and to everyone
DWORD SetAclInNamedObject(WCHAR * pszDirName, DWORD dwObjectType, DWORD dwSystemMask, DWORD dwEveryoneMask, DWORD dwSystemInherit, DWORD dwEveryOneInherit) { tenter("SetAclInNamedObject"); DWORD dwRes, dwDisposition; PSID pEveryoneSID = NULL, pAdminSID = NULL; PSID pSystemSID = NULL; PACL pACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; EXPLICIT_ACCESS ea[3]; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; LONG lRes; BOOL fReturn;
// Create a well-known SID for the Everyone group.
if(! AllocateAndInitializeSid( &SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID) ) { dwRes = GetLastError(); trace(0, "AllocateAndInitializeSid Error %u\n", dwRes); goto Cleanup; }
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow Everyone read access to the key.
ZeroMemory(ea, sizeof(ea)); ea[0].grfAccessPermissions = dwEveryoneMask; ea[0].grfAccessMode = SET_ACCESS; ea[0].grfInheritance = dwEveryOneInherit; ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID;
// Create a SID for the BUILTIN\Administrators group.
if(! AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID) ) { dwRes = GetLastError(); trace(0, "AllocateAndInitializeSid Error %u\n", dwRes); goto Cleanup; }
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow the Administrators group full access to the key.
ea[1].grfAccessPermissions = dwSystemMask; ea[1].grfAccessMode = SET_ACCESS; ea[1].grfInheritance= dwSystemInherit; ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID;
// Create a SID for the LocalSystem account
if(! AllocateAndInitializeSid( &SIDAuthNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSID) ) { dwRes = GetLastError(); trace(0, "AllocateAndInitializeSid Error %u\n", dwRes ); goto Cleanup; }
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow the LocalSystem full access to the key.
ea[2].grfAccessPermissions = dwSystemMask; ea[2].grfAccessMode = SET_ACCESS; ea[2].grfInheritance= dwSystemInherit; ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[2].Trustee.TrusteeType = TRUSTEE_IS_USER; ea[2].Trustee.ptstrName = (LPTSTR) pSystemSID;
// Create a new ACL that contains the new ACEs.
dwRes = SetEntriesInAcl(3, ea, NULL, &pACL); if (ERROR_SUCCESS != dwRes) { dwRes = GetLastError(); trace(0, "SetEntriesInAcl Error %u\n", dwRes ); goto Cleanup; }
// Initialize a security descriptor.
pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSD == NULL) { trace(0, "LocalAlloc Error %u\n", GetLastError() ); goto Cleanup; } if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { dwRes = GetLastError(); trace(0, "InitializeSecurityDescriptor Error %u\n", dwRes ); goto Cleanup; } // Add the ACL to the security descriptor.
if (!SetSecurityDescriptorDacl(pSD, TRUE, // fDaclPresent flag
pACL, FALSE)) // not a default DACL
{ dwRes = GetLastError(); trace(0, "SetSecurityDescriptorDacl Error %u\n", dwRes ); goto Cleanup; }
dwRes = SetNamedSecurityInfo(pszDirName, (SE_OBJECT_TYPE) dwObjectType, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL); if (ERROR_SUCCESS != dwRes) { trace(0, "SetSecurityInfo Error %u\n", dwRes ); goto Cleanup; } dwRes = ERROR_SUCCESS; Cleanup: if (pEveryoneSID) FreeSid(pEveryoneSID); if (pAdminSID) FreeSid(pAdminSID); if (pSystemSID) FreeSid(pSystemSID); if (pACL) LocalFree(pACL); if (pSD) LocalFree(pSD);
tleave(); return dwRes; }
DWORD SetCorrectACLOnDSRoot(WCHAR * wcsPath) { return SetAclInNamedObject(wcsPath, // restore dir name
SE_FILE_OBJECT, STANDARD_RIGHTS_ALL | GENERIC_ALL, // system and admin access
FILE_WRITE_DATA|SYNCHRONIZE, // everyone - just the right
// to create a file in the directory
SUB_CONTAINERS_AND_OBJECTS_INHERIT, // Inherit system and admin
// ACLs to children
SUB_CONTAINERS_ONLY_INHERIT); //Inherit everyone ACL only
//to subcontainers
}
DWORD GetWorldEffectivePermissions(PACL pDacl, ACCESS_MASK * pAccessMask) { TraceFunctEnter("GetWorldEffectivePermissions"); DWORD dwReturn; TRUSTEE WorldTrustee; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; PSID pEveryoneSID = NULL; // 1. build the trustee structure for World
// 1a Create a well-known SID for the Everyone group.
if(! AllocateAndInitializeSid( &SIDAuthWorld, 1, // nSubAuthorityCount
SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID) ) { dwReturn = GetLastError(); trace(0, "AllocateAndInitializeSid Error %u\n", dwReturn); goto cleanup; }
ZeroMemory(&WorldTrustee, sizeof(WorldTrustee)); WorldTrustee.MultipleTrusteeOperation=NO_MULTIPLE_TRUSTEE; WorldTrustee.TrusteeForm = TRUSTEE_IS_SID; WorldTrustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; WorldTrustee.ptstrName = (LPTSTR) pEveryoneSID;
// call the API to get rights for World
dwReturn=GetEffectiveRightsFromAcl(pDacl, // ACL
&WorldTrustee, pAccessMask); cleanup: if (pEveryoneSID) FreeSid(pEveryoneSID); TraceFunctLeave(); return dwReturn; }
// returns if Everyone has write access to the directory
BOOL IsDirectoryWorldAccessible(WCHAR * pszObjectName) { TraceFunctEnter("IsDirectoryWorldAccessible"); BOOL fReturn=FALSE; // Assume FALSE by default
DWORD dwReturn; PACL pDacl; PSECURITY_DESCRIPTOR pSecurityDescriptor=NULL; ACCESS_MASK AccessMask; // Get Security Info from directory
dwReturn=GetNamedSecurityInfo(pszObjectName, // object name
SE_FILE_OBJECT, // object type
DACL_SECURITY_INFORMATION, //information type
NULL, // owner SID
NULL, // primary group SID
&pDacl, // DACL
NULL, // SACL
&pSecurityDescriptor);// SD
if (ERROR_SUCCESS != dwReturn) { ErrorTrace(0, "GetNamedSecurityInfo error %u\n", dwReturn); pSecurityDescriptor=NULL; goto cleanup; } // Get Effective permissions of World from this ACL
dwReturn=GetWorldEffectivePermissions(pDacl, &AccessMask); if (ERROR_SUCCESS != dwReturn) { ErrorTrace(0, "GetWorldEffectPermissions error %u\n", dwReturn); goto cleanup; } // Check if world has Access. We will just check for FILE_APPEND_DATA
// which is the right to create a subdirectory.
fReturn = (0 !=(AccessMask&FILE_APPEND_DATA)); cleanup: // release memory
if (NULL!= pSecurityDescriptor) { _VERIFY(NULL==LocalFree(pSecurityDescriptor)); } TraceFunctLeave(); return fReturn; }
// This function compares given SID with administrators group and system
BOOL IsSidOfAdminOrSystem(PSID pSid) { TraceFunctEnter("IsFileOwnedByAdminOrSystem"); BOOL fReturn=FALSE; // Assume FALSE by default
PSID pAdminSID = NULL; PSID pSystemSID = NULL; SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; DWORD dwRes; // create SIDs of Admins and System
// Create a SID for the BUILTIN\Administrators group.
if(! AllocateAndInitializeSid( &SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID) ) { dwRes = GetLastError(); trace(0, "AllocateAndInitializeSid Error %u", dwRes); goto cleanup; }
if (EqualSid(pAdminSID, pSid)) { trace(0, "passed in SID is Admin SID"); fReturn=TRUE; goto cleanup; }
// Create a SID for the LocalSystem account
if(! AllocateAndInitializeSid( &SIDAuthNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSID) ) { dwRes = GetLastError(); trace(0, "AllocateAndInitializeSid Error %u\n", dwRes ); goto cleanup; }
if (EqualSid(pSystemSID, pSid)) { trace(0, "passed in SID is System SID"); fReturn=TRUE; goto cleanup; } cleanup:
if (pAdminSID) FreeSid(pAdminSID); if (pSystemSID) FreeSid(pSystemSID); TraceFunctLeave(); return fReturn; }
BOOL IsVolumeNTFS(WCHAR * pszFileName) { TENTER ("IsVolumeNTFS"); BOOL fReturn=FALSE; DWORD dwErr = ERROR_SUCCESS; WCHAR szFileNameCopy[2*MAX_PATH]; DWORD dwFsFlags; WCHAR * pszVolumeNameEnd; DWORD dwFileNameLength;
dwFileNameLength = lstrlen(pszFileName); if ( (dwFileNameLength >= sizeof(szFileNameCopy)/sizeof(WCHAR)) || (dwFileNameLength < 4) ) { // file name too long. Cannot be a valid changelog
TRACE(0, "Filename not of proper length %d", dwFileNameLength); fReturn=FALSE; // assume not NTFS
goto cleanup; }
lstrcpy(szFileNameCopy, pszFileName); pszVolumeNameEnd=ReturnPastVolumeName(szFileNameCopy); // NULL terminate after end of volume name to get just the volume name
*pszVolumeNameEnd=L'\0';
// Get the volume label and flags
if (TRUE == GetVolumeInformationW (szFileNameCopy,// root directory
NULL,// volume name buffer
0, // length of name buffer
NULL, // volume serial number
NULL,// maximum file name length
&dwFsFlags,// file system options
NULL,// file system name buffer
0))// length of file system name buffer
{
if (dwFsFlags & FS_PERSISTENT_ACLS) { fReturn=TRUE; } else { fReturn=FALSE; } } else { dwErr = GetLastError(); TRACE(0, "GetVolumeInformation failed : %ld", dwErr); fReturn=FALSE; // assume not NTFS
}
cleanup: TLEAVE();
return fReturn;
}
// returns if the file is owned by the administrators group or system
BOOL IsFileOwnedByAdminOrSystem(WCHAR * pszObjectName) { TraceFunctEnter("IsFileOwnedByAdminOrSystem"); BOOL fReturn=FALSE; // Assume FALSE by default
DWORD dwReturn; PSID pSidOwner=NULL; PSECURITY_DESCRIPTOR pSecurityDescriptor=NULL; ACCESS_MASK AccessMask;
if (FALSE == IsVolumeNTFS(pszObjectName)) { // if the volume is not NTFS, return success
fReturn=TRUE; goto cleanup; } // Get Security Info from directory
dwReturn=GetNamedSecurityInfo(pszObjectName, // object name
SE_FILE_OBJECT, // object type
OWNER_SECURITY_INFORMATION,//information type
&pSidOwner, // owner SID
NULL, // primary group SID
NULL, // DACL
NULL, // SACL
&pSecurityDescriptor);// SD
if (ERROR_SUCCESS != dwReturn) { ErrorTrace(0, "GetNamedSecurityInfo error %u\n", dwReturn); pSecurityDescriptor=NULL; goto cleanup; } // Compare SID with administrators group and system
fReturn=IsSidOfAdminOrSystem(pSidOwner); cleanup: // release memory
if (NULL!= pSecurityDescriptor) { _VERIFY(NULL==LocalFree(pSecurityDescriptor)); } TraceFunctLeave(); return fReturn; }
//+---------------------------------------------------------------------------
//
// Function: Delnode_Recurse
//
// Synopsis: attempt to delete a directory tree
//
// Arguments: [pwszDir] -- directory name
// [fIncludeRoot] -- delete top level directory and files
// [pfStop] -- TRUE if stop signaled
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD Delnode_Recurse (const WCHAR *pwszDir, BOOL fDeleteRoot, BOOL *pfStop) { tenter("Delnode_Recurse");
DWORD dwErr = ERROR_SUCCESS; WIN32_FIND_DATA *pfd = NULL; HANDLE hFile = INVALID_HANDLE_VALUE; WCHAR * pwcsPath = NULL;
if (lstrlenW (pwszDir) > MAX_PATH-5) { dwErr = ERROR_INVALID_PARAMETER; trace (0, "Delnode_Recurse failed with %d", dwErr); goto cleanup; }
if (NULL == (pfd = new WIN32_FIND_DATA)) { dwErr = ERROR_NOT_ENOUGH_MEMORY; trace (0, "Delnode_Recurse failed with %d", dwErr); goto cleanup; }
if (NULL == (pwcsPath = new WCHAR[MAX_PATH])) { dwErr = ERROR_NOT_ENOUGH_MEMORY; trace (0, "Delnode_Recurse failed with %d", dwErr); goto cleanup; }
lstrcpy (pwcsPath, pwszDir); lstrcat (pwcsPath, TEXT("\\*.*"));
hFile = FindFirstFileW (pwcsPath, pfd);
if (hFile == INVALID_HANDLE_VALUE) { // if the directory does not exist, then return success
dwErr = ERROR_SUCCESS; goto cleanup; }
do { if (pfStop != NULL && TRUE == *pfStop) { dwErr = ERROR_OPERATION_ABORTED; trace (0, "Delnode_Recurse failed with %d", dwErr); goto cleanup; }
if (!lstrcmp(pfd->cFileName, L".") || !lstrcmp(pfd->cFileName, L"..")) { continue; }
if (lstrlenW(pwszDir) + lstrlenW(pfd->cFileName) + 1 >= MAX_PATH) continue; // ignore excessively long names
lstrcpy (pwcsPath, pwszDir); // construct the full path name
lstrcat (pwcsPath, TEXT("\\")); lstrcat (pwcsPath, pfd->cFileName);
if (pfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { //
// Found a directory. Skip mount points
//
if (pfd->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { continue; }
dwErr = Delnode_Recurse (pwcsPath, TRUE, pfStop); if (dwErr != ERROR_SUCCESS) { trace (0, "Delnode_Recurse failed with %d, ignoring", dwErr); dwErr = ERROR_SUCCESS; // try to delete more directories
} } else if (fDeleteRoot) { //
// We found a file. Set the file attributes,
// and try to delete it.
//
if ((pfd->dwFileAttributes & FILE_ATTRIBUTE_READONLY) || (pfd->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) { SetFileAttributesW (pwcsPath, FILE_ATTRIBUTE_NORMAL); }
if (FALSE == DeleteFileW (pwcsPath)) { if (ERROR_SUCCESS == (dwErr = TakeOwn (pwcsPath))) { if (FALSE == DeleteFileW (pwcsPath)) { dwErr = GetLastError(); } } if (dwErr != ERROR_SUCCESS) { trace (0, "DeleteFile or TakeOwn failed with %d", dwErr); goto cleanup; } } }
} while (FindNextFile(hFile, pfd)); // Find the next entry
FindClose(hFile); // Close the search handle
hFile = INVALID_HANDLE_VALUE;
if (fDeleteRoot) { DWORD dwAttr = GetFileAttributes(pwszDir);
if (dwAttr != 0xFFFFFFFF && (dwAttr & FILE_ATTRIBUTE_READONLY)) { dwAttr &= ~FILE_ATTRIBUTE_READONLY; if (FALSE == SetFileAttributes (pwszDir, dwAttr)) { TRACE(0, "SetFileAttributes ignoring %ld", GetLastError()); } }
if (FALSE == RemoveDirectoryW (pwszDir)) { if (ERROR_SUCCESS == (dwErr = TakeOwn (pwszDir))) { if (FALSE == RemoveDirectoryW (pwszDir)) { LONG lLast = lstrlenW (pwszDir) - 1; if (lLast < 0) lLast = 0;
dwErr = GetLastError();
if (pwszDir[lLast] != L')' && // already renamed
TRUE == SRGetAltFileName (pwszDir, pwcsPath) && TRUE == MoveFile (pwszDir, pwcsPath)) dwErr = ERROR_SUCCESS; else trace (0, "RemoveDirectory failed with %d", dwErr); } } } }
cleanup: if (hFile != INVALID_HANDLE_VALUE) FindClose (hFile);
if (NULL != pfd) delete pfd;
if (NULL != pwcsPath) delete [] pwcsPath;
tleave(); return dwErr; }
//
// util function that checks the SR Stop event
// to see if it has been signalled or not
// will return TRUE if the event does not exist
//
BOOL IsStopSignalled(HANDLE hEvent) { TENTER("IsStopSignalled"); BOOL fRet, fOpened = FALSE; DWORD dwRc; if (! hEvent) { hEvent = OpenEvent(SYNCHRONIZE, FALSE, s_cszSRStopEvent); if (! hEvent) { // if cannot open, then assume that service is not stopped
// if client is running on different desktop than service (multiple user magic)
// then it cannot open the event, though service might be running
dwRc = GetLastError(); TRACE(0, "! OpenEvent : %ld", dwRc); TLEAVE(); return FALSE; }
fOpened = TRUE; }
fRet = (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0));
if (fOpened) CloseHandle(hEvent);
TLEAVE(); return fRet; }
void PostTestMessage(UINT msg, WPARAM wp, LPARAM lp) { HWINSTA hwinstaUser; HDESK hdeskUser = NULL; DWORD dwThreadId; HWINSTA hwinstaSave; HDESK hdeskSave; DWORD dwRc;
TENTER("PostTestMessage");
//
// save current values
//
GetDesktopWindow(); hwinstaSave = GetProcessWindowStation(); dwThreadId = GetCurrentThreadId(); hdeskSave = GetThreadDesktop(dwThreadId);
//
// change desktop and winstation to interactive user
//
hwinstaUser = OpenWindowStation(L"WinSta0", FALSE, MAXIMUM_ALLOWED);
if (hwinstaUser == NULL) { dwRc = GetLastError(); trace(0, "! OpenWindowStation : %ld", dwRc); goto done; } SetProcessWindowStation(hwinstaUser); hdeskUser = OpenDesktop(L"Default", 0, FALSE, MAXIMUM_ALLOWED); if (hdeskUser == NULL) { dwRc = GetLastError(); trace(0, "! OpenDesktop : %ld", dwRc); goto done; } SetThreadDesktop(hdeskUser);
if (FALSE == PostMessage(HWND_BROADCAST, msg, wp, lp)) { trace(0, "! PostMessage"); }
done: //
// restore old values
//
if (hdeskSave) SetThreadDesktop(hdeskSave);
if (hwinstaSave) SetProcessWindowStation(hwinstaSave);
//
// close opened handles
//
if (hdeskUser) CloseDesktop(hdeskUser);
if (hwinstaUser) CloseWindowStation(hwinstaUser); TLEAVE(); }
//+-------------------------------------------------------------------------
//
// Function: RemoveTrailingFilename
//
// Synopsis: This function takes as input parameter a string which
// contains a filename. It removes the last filename (or
// directory ) from the string including the '\' or '/'
// before the last filename.
//
// Arguments: IN/OUT pszString - string to be modified.
// IN tchSlash - file name separator - must be '/' or'\'
//
//
// Returns: nothing
//
// History: AshishS Created 5/22/96
//
//------------------------------------------------------------------------
void RemoveTrailingFilename(WCHAR * pszString, WCHAR wchSlash) { WCHAR * pszStringStart; DWORD dwStrlen;
pszStringStart = pszString; dwStrlen = lstrlen ( pszString); // first go the end of the string
pszString += dwStrlen ; // now walk backwards till we see the first '\'
// also maintain a count of how many characters we have
// gone back.
while ( (*pszString != wchSlash) && ( dwStrlen) ) { pszString--; dwStrlen --; } *pszString = TEXT('\0'); }
// this function create the parent directory under the specified file
// name if it already does not exist
BOOL CreateParentDirectory(WCHAR * pszFileName) { TraceFunctEnter("CreateParentDirectory"); BOOL fReturn = FALSE; DWORD dwError; // get the parent directory
RemoveTrailingFilename(pszFileName, L'\\');
if (FALSE == DoesDirExist(pszFileName)) { if (FALSE == CreateDirectory(pszFileName, // directory name
NULL)) // SD
{ dwError = GetLastError(); ErrorTrace(TRACEID, "Could not create directory %S ec=%d", pszFileName, dwError); goto cleanup; } } fReturn = TRUE; cleanup: TraceFunctLeave(); return fReturn; }
// this function creates all sub directories under the specified file
// name.
BOOL CreateBaseDirectory(const WCHAR * pszFileName) { BOOL fRetVal = FALSE; DWORD dwCurIndex,dwBufReqd; DWORD dwStrlen; TraceFunctEnter("CreateBaseDirectory"); DWORD dwError; WCHAR * pszFileNameCopy; dwBufReqd = (lstrlen(pszFileName) + 1) * sizeof(WCHAR); pszFileNameCopy = (WCHAR *) _alloca(dwBufReqd); if (NULL == pszFileNameCopy) { ErrorTrace(0, "alloca for size %d failed", dwBufReqd); goto cleanup; } lstrcpy(pszFileNameCopy, pszFileName);
// do a fast check to see if the parent directory exists
if (TRUE == CreateParentDirectory(pszFileNameCopy)) { fRetVal = TRUE; goto cleanup; } lstrcpy(pszFileNameCopy, pszFileName); dwStrlen = lstrlen(pszFileNameCopy); // check to see if this is a filename starting with the GUID
if (0==wcsncmp( pszFileNameCopy, VOLUMENAME_FORMAT, lstrlen(VOLUMENAME_FORMAT))) { // this is of the format \\?\Volume
// skip over the initial part
dwCurIndex = lstrlen(VOLUMENAME_FORMAT)+1; // skip over the GUID part also
while (dwCurIndex < dwStrlen) { dwCurIndex++; if (TEXT('\\') == pszFileNameCopy[dwCurIndex-1] ) { break; } } } else { // the filename is of the regular format
// we start at index 1 and not at 0 because we want to handle
// path name like \foo\abc.txt
dwCurIndex = 1; }
while (dwCurIndex < dwStrlen) { if (TEXT('\\') == pszFileNameCopy[dwCurIndex] ) { // NULL terminate at the '\' to get the sub directory
// name.
pszFileNameCopy[dwCurIndex] = TEXT('\0'); if (FALSE == DoesDirExist(pszFileNameCopy)) { if (FALSE == CreateDirectory(pszFileNameCopy, // directory name
NULL)) // SD
{ dwError = GetLastError(); ErrorTrace(TRACEID, "Could not create directory %S ec=%d", pszFileNameCopy, dwError); pszFileNameCopy[dwCurIndex] = TEXT('\\'); goto cleanup; } DebugTrace(TRACEID, "Created directory %S", pszFileNameCopy); } // restore the \ to get the file name again.
pszFileNameCopy[dwCurIndex] = TEXT('\\'); } dwCurIndex ++; } fRetVal = TRUE; cleanup: TraceFunctLeave(); return fRetVal; }
// The following function logs the name of a file in the DS. The
// problem right now is that the path of the DS is so long that the
// relevant information is thrown away from the trace buffer.
void LogDSFileTrace(DWORD dwTraceID, const WCHAR * pszPrefix, // Initial message to be traced
const WCHAR * pszDSFile) { WCHAR * pszBeginName; TraceQuietEnter("LogDSFileTrace"); // first see if the file is in the DS
pszBeginName = wcschr(pszDSFile, L'\\'); if (NULL == pszBeginName) { goto cleanup; } // skip over the first \ .
pszBeginName++; // comapare if the first part is "system volume information"
if (0!=_wcsnicmp(s_cszSysVolInfo, pszBeginName, lstrlen(s_cszSysVolInfo))) { goto cleanup; }
// skip over the next \ .
pszBeginName = wcschr(pszBeginName, L'\\'); if (NULL == pszBeginName) { goto cleanup; }
pszBeginName++;
// now skip over the _restore directory
// first see if the file is in the DS
pszBeginName = wcschr(pszBeginName, L'\\'); if (NULL == pszBeginName) { goto cleanup; }
DebugTrace(dwTraceID, "%S %S", pszPrefix, pszBeginName); cleanup: // the file is not in the DS - or we are printing out the initial
// part for debugging purposes.
DebugTrace(dwTraceID, "%S%S", pszPrefix, pszDSFile); return; }
// the following function calls pfnMethod on all the files specified
// by the pszFindFileData filter.
DWORD ProcessGivenFiles(WCHAR * pszBaseDir, PPROCESSFILEMETHOD pfnMethod, WCHAR * pszFindFileData) { TraceFunctEnter("ProcessGivenFiles"); WIN32_FIND_DATA FindFileData; HANDLE hFindFirstFile = INVALID_HANDLE_VALUE; DWORD dwErr, dwReturn = ERROR_INTERNAL_ERROR; BOOL fContinue; LogDSFileTrace(0, L"FileData is ", pszFindFileData); hFindFirstFile = FindFirstFile(pszFindFileData, &FindFileData); DebugTrace(0, "FindFirstFile returned %d", hFindFirstFile); if (INVALID_HANDLE_VALUE == hFindFirstFile) { dwErr = GetLastError(); DebugTrace(0, "FindFirstFile failed ec=%d. Filename is %S", dwErr, pszFindFileData);
// what if even one file does not exist
if ( (ERROR_FILE_NOT_FOUND == dwErr) || (ERROR_PATH_NOT_FOUND == dwErr) || (ERROR_NO_MORE_FILES == dwErr)) { // this is a success condition
dwReturn = ERROR_SUCCESS; goto cleanup; } if (ERROR_SUCCESS != dwErr) { dwReturn = dwErr; } goto cleanup; } fContinue = TRUE; while (TRUE==fContinue) { LogDSFileTrace(0, L"FileName is ", FindFileData.cFileName);
// now check to see if the file length is valid. This is
// becuase a hacker can introduce a file in the datastore
// that is too long and can cause us to overflow our buffers.
if ( MAX_PATH <= lstrlen(pszBaseDir) +lstrlen(s_cszRegHiveCopySuffix)+ lstrlen(FindFileData.cFileName) + 2 ) { // Filename is too long. It cannot be a file created by
// system restore. It probably is a file created by a hacker.
// Ignore this file
ErrorTrace(0, "Ignoring long file %S", FindFileData.cFileName); ErrorTrace(0, "Base dir %S", pszBaseDir ); dwErr = ERROR_SUCCESS; } else { dwErr = pfnMethod(pszBaseDir, FindFileData.cFileName); if (ERROR_SUCCESS != dwErr) { ErrorTrace(0, "pfnMethod failed. ec=%d.file=%S ", dwErr, FindFileData.cFileName); goto cleanup; } } fContinue = FindNextFile(hFindFirstFile, &FindFileData); } dwErr=GetLastError(); if (ERROR_NO_MORE_FILES != dwErr) { _ASSERT(0); ErrorTrace(0, "dwErr != ERROR_NO_MORE_FILES. It is %d", dwErr); goto cleanup; } dwReturn = ERROR_SUCCESS;
cleanup: if (INVALID_HANDLE_VALUE != hFindFirstFile) { _VERIFY(TRUE == FindClose(hFindFirstFile)); } TraceFunctLeave(); return dwReturn; }
DWORD DeleteGivenFile(WCHAR * pszBaseDir, // Base Directory
const WCHAR * pszFile) // file to delete
{ TraceFunctEnter("DeleteGivenFile"); DWORD dwErr, dwReturn = ERROR_INTERNAL_ERROR; WCHAR szDataFile[MAX_PATH];
// construct the path name of the file
wsprintf(szDataFile, L"%s\\%s", pszBaseDir, pszFile);
if (TRUE != DeleteFile(szDataFile)) { dwErr = GetLastError(); if (ERROR_SUCCESS != dwErr) { dwReturn = dwErr; } ErrorTrace(0, "DeleteFile failed ec=%d", dwErr); LogDSFileTrace(0,L"File was ", szDataFile); goto cleanup; }
dwReturn = ERROR_SUCCESS; cleanup: TraceFunctLeave(); return dwReturn; }
//++-----------------------------------------------------------------------
//
// Function: WriteRegKey
//
// Synopsis: This function writes into a registry key. It also creates it
// if it does not exist.
//
// Arguments:
//
// Returns: TRUE no error
// FALSE a fatal error happened
//
// History: AshishS Created 5/22/96
//------------------------------------------------------------------------
BOOL WriteRegKey(BYTE * pbRegValue, DWORD dwNumBytes, const TCHAR * pszRegKey, const TCHAR * pszRegValueName, DWORD dwRegType) { HKEY hRegKey; LONG lResult; DWORD dwDisposition; TraceFunctEnter("WriteRegKey"); //read registry to find out name of the file
if ( (lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszRegKey, // address of subkey name
0, // reserved
NULL, // address of class string
0, // special options flag
KEY_WRITE, // samDesired
NULL, // address of key security structure
&hRegKey, // address of handle of open key
&dwDisposition // address of disposition value buffer
)) != ERROR_SUCCESS ) { ErrorTrace(TRACEID, "RegCreateKeyEx error 0x%x", lResult); _ASSERT(0); goto cleanup; }
if ( (lResult =RegSetValueEx( hRegKey, pszRegValueName, 0, // reserved
dwRegType,// flag for value type
pbRegValue, // address of value data
dwNumBytes // size of value data
)) != ERROR_SUCCESS ) { ErrorTrace(TRACEID, "RegSetValueEx error 0x%x", lResult); _ASSERT(0); _VERIFY(RegCloseKey(hRegKey)==ERROR_SUCCESS); goto cleanup; }
_VERIFY(RegCloseKey(hRegKey)==ERROR_SUCCESS);
TraceFunctLeave(); return TRUE;
cleanup: TraceFunctLeave(); return FALSE; }
//++------------------------------------------------------------------------
//
// Function: ReadRegKey
//
// Synopsis: This function reads a registry key and creates it
// if it does not exist with the default value.
//
// Arguments:
//
// Returns: TRUE no error
// FALSE a fatal error happened
//
// History: AshishS Created 5/22/96
//------------------------------------------------------------------------
BOOL ReadRegKeyOrCreate(BYTE * pbRegValue, // The value of the reg key will be
// stored here
DWORD * pdwNumBytes, // Pointer to DWORD conataining
// the number of bytes in the above buffer - will be
// set to actual bytes stored.
const TCHAR * pszRegKey, // Reg Key to be opened
const TCHAR * pszRegValueName, // Reg Value to query
DWORD dwRegTypeExpected, BYTE * pbDefaultValue, // default value
DWORD dwDefaultValueSize) // size of default value
{ if (!ReadRegKey(pbRegValue,//Buffer to store value
pdwNumBytes, // Length of above buffer
pszRegKey, // Reg Key name
pszRegValueName, // Value name
dwRegTypeExpected) ) // Type expected
{ // read reg key failed - use default value and create this
// key
return WriteRegKey(pbDefaultValue, dwDefaultValueSize, pszRegKey, pszRegValueName, dwRegTypeExpected); } return TRUE; }
//++------------------------------------------------------------------------
//
// Function: ReadRegKey
//
// Synopsis: This function reads a registry key.
//
// Arguments:
//
// Returns: TRUE no error
// FALSE a fatal error happened
//
// History: AshishS Created 5/22/96
//------------------------------------------------------------------------
BOOL ReadRegKey(BYTE * pbRegValue, // The value of the reg key will be
// stored here
DWORD * pdwNumBytes, // Pointer to DWORD conataining
// the number of bytes in the above buffer - will be
// set to actual bytes stored.
const TCHAR * pszRegKey, // Reg Key to be opened
const TCHAR * pszRegValueName, // Reg Value to query
DWORD dwRegTypeExpected) // Expected type of Value
{ HKEY hRegKey; DWORD dwRegType; LONG lResult; TraceFunctEnter("ReadRegKey"); DebugTrace(TRACEID, "Trying to open %S %S", pszRegKey, pszRegValueName); //read registry to find out name of the file
if ( (lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszRegKey, // address of subkey name
0, // reserved
KEY_READ, // samDesired
&hRegKey // address of handle of open key
)) != ERROR_SUCCESS ) { ErrorTrace(TRACEID, "RegOpenKeyEx open error 0x%x", lResult); goto cleanup; }
if ( (lResult =RegQueryValueEx( hRegKey, pszRegValueName, 0, // reserved
&dwRegType,// address of buffer
// for value type
pbRegValue, pdwNumBytes)) != ERROR_SUCCESS ) { _VERIFY(RegCloseKey(hRegKey)==ERROR_SUCCESS); ErrorTrace(TRACEID, "RegQueryValueEx failed error 0x%x", lResult); goto cleanup; } _VERIFY(RegCloseKey(hRegKey)==ERROR_SUCCESS); if ( dwRegType != dwRegTypeExpected ) { ErrorTrace(TRACEID, "RegType is %d, not %d", dwRegType, dwRegTypeExpected); goto cleanup; } TraceFunctLeave(); return TRUE; cleanup: TraceFunctLeave(); return FALSE; }
// this function sets the error hit by restore in the registry
BOOL SetRestoreError(DWORD dwRestoreError) { TraceFunctEnter("SetDiskSpaceError"); DWORD dwNumBytes=sizeof(DWORD); BOOL fResult=FALSE; // assume FALSE by default
DebugTrace(TRACEID, "Setting disk space error to %d", dwRestoreError);
if (FALSE== WriteRegKey((BYTE*)&dwRestoreError, // The value of the
// reg key will be set to this value
dwNumBytes, // Pointer to DWORD containing
// the number of bytes in the above buffer
s_cszSRRegKey, // Reg Key to be opened
s_cszRestoreDiskSpaceError, // Reg Value to query
REG_DWORD)) // Expected type of Value
{ fResult = FALSE; goto cleanup; }
fResult= TRUE; cleanup:
TraceFunctLeave(); return fResult; }
// this function checks to see of the restore failed because of disk space
BOOL CheckForDiskSpaceError() { TraceFunctEnter("CheckForDiskSpaceError"); DWORD dwRestoreError; DWORD dwNumBytes=sizeof(DWORD); BOOL fResult=FALSE; // assume FALSE by default
if (FALSE==ReadRegKey((BYTE*)&dwRestoreError, // The value of the
// reg key will be stored here
&dwNumBytes, // Pointer to DWORD containing
// the number of bytes in the above buffer - will be
// set to actual bytes stored.
s_cszSRRegKey, // Reg Key to be opened
s_cszRestoreDiskSpaceError, // Reg Value to query
REG_DWORD)) // Expected type of Value
{ fResult = FALSE; }
if (dwRestoreError == ERROR_DISK_FULL) { DebugTrace(TRACEID,"Restore failed because of disk space"); fResult= TRUE; }
TraceFunctLeave(); return fResult; }
// this function sets the status whether restore was done in safe mode
BOOL SetRestoreSafeModeStatus(DWORD dwSafeModeStatus) { TraceFunctEnter("SetRestoreSafeModeStatus"); DWORD dwNumBytes=sizeof(DWORD); BOOL fResult=FALSE; // assume FALSE by default
DebugTrace(TRACEID, "Setting restore safe mode status to %d", dwSafeModeStatus);
if (FALSE== WriteRegKey((BYTE*)&dwSafeModeStatus, // The value of the
// reg key will be set to this value
dwNumBytes, // Pointer to DWORD containing
// the number of bytes in the above buffer
s_cszSRRegKey, // Reg Key to be opened
s_cszRestoreSafeModeStatus, // Reg Value to query
REG_DWORD)) // Expected type of Value
{ fResult = FALSE; goto cleanup; }
fResult= TRUE; cleanup:
TraceFunctLeave(); return fResult; }
// this function checks to see is the last restore was done in safe mode
BOOL WasLastRestoreInSafeMode() { TraceFunctEnter("WasLastRestoreInSafeMode"); DWORD dwRestoreSafeModeStatus; DWORD dwNumBytes=sizeof(DWORD); BOOL fResult=FALSE; // assume FALSE by default
if (FALSE==ReadRegKey((BYTE*)&dwRestoreSafeModeStatus, // The value of the
// reg key will be stored here
&dwNumBytes, // Pointer to DWORD containing
// the number of bytes in the above buffer - will be
// set to actual bytes stored.
s_cszSRRegKey, // Reg Key to be opened
s_cszRestoreSafeModeStatus, // Reg Value to query
REG_DWORD)) // Expected type of Value
{ fResult = FALSE; }
if (dwRestoreSafeModeStatus != 0 ) { DebugTrace(TRACEID,"Last restore was done in safe mode"); fResult= TRUE; } else { DebugTrace(TRACEID,"Last restore was not done in safe mode"); }
TraceFunctLeave(); return fResult; }
#define MAX_LEN_SYSERR 1024
LPCWSTR GetSysErrStr() { LPCWSTR cszStr = GetSysErrStr( ::GetLastError() ); return( cszStr ); }
LPCWSTR GetSysErrStr( DWORD dwErr ) { static WCHAR szErr[MAX_LEN_SYSERR+1];
::FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szErr, MAX_LEN_SYSERR, NULL );
return( szErr ); }
/****************************************************************************/
LPWSTR SRGetRegMultiSz( HKEY hkRoot, LPCWSTR cszSubKey, LPCWSTR cszValue, LPDWORD pdwData ) { TraceFunctEnter("SRGetRegMultiSz"); LPCWSTR cszErr; DWORD dwRes; HKEY hKey = NULL; DWORD dwType; DWORD cbData = 0; LPWSTR szBuf = NULL;
dwRes = ::RegOpenKeyEx( hkRoot, cszSubKey, 0, KEY_ALL_ACCESS, &hKey ); if ( dwRes != ERROR_SUCCESS ) { cszErr = ::GetSysErrStr( dwRes ); ErrorTrace(0, "::RegOpenKey() failed - %ls", cszErr); goto Exit; }
dwRes = ::RegQueryValueEx( hKey, cszValue, 0, &dwType, NULL, &cbData ); if ( dwRes != ERROR_SUCCESS ) { cszErr = ::GetSysErrStr( dwRes ); ErrorTrace(0, "::RegQueryValueEx(len) failed - %ls", cszErr); goto Exit; } if ( dwType != REG_MULTI_SZ ) { ErrorTrace(0, "Type of '%ls' is %u (not REG_MULTI_SZ)...", cszValue, dwType); goto Exit; } if ( cbData == 0 ) { ErrorTrace(0, "Value '%ls' is empty...", cszValue); goto Exit; }
szBuf = new WCHAR[cbData+2]; if (! szBuf) { ErrorTrace(0, "Cannot allocate memory"); goto Exit; } dwRes = ::RegQueryValueEx( hKey, cszValue, 0, &dwType, (LPBYTE)szBuf, &cbData ); if ( dwRes != ERROR_SUCCESS ) { cszErr = ::GetSysErrStr( dwRes ); ErrorTrace(0, "::RegQueryValueEx(data) failed - %ls", cszErr); delete [] szBuf; szBuf = NULL; }
if ( pdwData != NULL ) *pdwData = cbData;
Exit: if ( hKey != NULL ) ::RegCloseKey( hKey ); TraceFunctLeave(); return( szBuf ); }
/****************************************************************************/
BOOL SRSetRegMultiSz( HKEY hkRoot, LPCWSTR cszSubKey, LPCWSTR cszValue, LPCWSTR cszData, DWORD cbData ) { TraceFunctEnter("SRSetRegMultiSz"); BOOL fRet = FALSE; LPCWSTR cszErr; DWORD dwRes; HKEY hKey = NULL;
dwRes = ::RegOpenKeyEx( hkRoot, cszSubKey, 0, KEY_ALL_ACCESS, &hKey ); if ( dwRes != ERROR_SUCCESS ) { cszErr = ::GetSysErrStr( dwRes ); ErrorTrace(0, "::RegOpenKey() failed - %ls", cszErr); goto Exit; }
dwRes = ::RegSetValueEx( hKey, cszValue, 0, REG_MULTI_SZ, (LPBYTE)cszData, cbData ); if ( dwRes != ERROR_SUCCESS ) { cszErr = ::GetSysErrStr( dwRes ); ErrorTrace(0, "::RegSetValueEx() failed - %ls", cszErr); goto Exit; }
fRet = TRUE; Exit: if ( hKey != NULL ) ::RegCloseKey( hKey ); TraceFunctLeave(); return( fRet ); }
// this returns the name after the volume name
// For example input: c:\file output: file
// input \\?\Volume{GUID}\file1 output: file1
WCHAR * ReturnPastVolumeName(const WCHAR * pszFileName) { DWORD dwStrlen, dwCurIndex; dwStrlen = lstrlen(pszFileName); // check to see if this is a filename starting with the GUID
if (0==wcsncmp( pszFileName, VOLUMENAME_FORMAT, lstrlen(VOLUMENAME_FORMAT))) { // this is of the format \\?\Volume
// skip over the initial part
dwCurIndex = lstrlen(VOLUMENAME_FORMAT)+1; // skip over the GUID part also
while (dwCurIndex < dwStrlen) { dwCurIndex++; if (TEXT('\\') == pszFileName[dwCurIndex-1] ) { break; } } } else { // the filename is of the regular format
dwCurIndex = 3; } return (WCHAR *)pszFileName + dwCurIndex; }
void SRLogEvent (HANDLE hEventSource, WORD wType, DWORD dwID, void * pRawData, DWORD dwDataSize, const WCHAR * pszS1, const WCHAR * pszS2, const WCHAR * pszS3) { const WCHAR* ps[3]; ps[0] = pszS1; ps[1] = pszS2; ps[2] = pszS3;
WORD iStr = 0; for (int i = 0; i < 3; i++) { if (ps[i] != NULL) iStr++; }
if (hEventSource) { ::ReportEvent( hEventSource, wType, 0, dwID, NULL, // sid
iStr, dwDataSize, ps, pRawData); } }
BOOL IsPowerUsers() { BOOL fReturn = FALSE; PSID psidPowerUsers; DWORD dwErr; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
TENTER("IsPowerUsers");
if ( AllocateAndInitializeSid ( &SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0, 0, &psidPowerUsers)) { if (! CheckTokenMembership(NULL, psidPowerUsers, &fReturn)) { dwErr = GetLastError(); TRACE(0, "! CheckTokenMembership : %ld", dwErr); }
FreeSid (psidPowerUsers); } else { dwErr = GetLastError(); TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr); }
TLEAVE(); return fReturn; }
// function to check if caller is running in admin context
BOOL IsAdminOrSystem() { BOOL fReturn = FALSE; PSID psidAdmin, psidSystem; DWORD dwErr; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
TENTER("IsAdminOrSystem");
//
// check if caller is Admin
//
if ( AllocateAndInitializeSid ( &SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin) ) { if (! CheckTokenMembership(NULL, psidAdmin, &fReturn)) { dwErr = GetLastError(); TRACE(0, "! CheckTokenMembership : %ld", dwErr); }
FreeSid (psidAdmin);
//
// if so, scoot
//
if (fReturn) { goto done; }
//
// check if caller is localsystem
//
if ( AllocateAndInitializeSid ( &SystemSidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psidSystem) ) { if (! CheckTokenMembership(NULL, psidSystem, &fReturn)) { dwErr = GetLastError(); TRACE(0, "! CheckTokenMembership : %ld", dwErr); }
FreeSid(psidSystem); } else { dwErr = GetLastError(); TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr); } } else { dwErr = GetLastError(); TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr); }
done: TLEAVE(); return (fReturn); }
DWORD SRLoadString(LPCWSTR pszModule, DWORD dwStringId, LPWSTR pszString, DWORD cbBytes) { DWORD dwErr = ERROR_SUCCESS; HINSTANCE hModule = NULL; if (hModule = LoadLibraryEx(pszModule, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE)) { if (! LoadString(hModule, dwStringId, pszString, cbBytes)) { dwErr = GetLastError(); } FreeLibrary(hModule); } else dwErr = GetLastError();
return dwErr; }
//
// replace CurrentControlSet in pszString with ControlSetxxx
//
void ChangeCCS(HKEY hkMount, LPWSTR pszString) { tenter("ChangeCCS"); int nCS = lstrlen(L"CurrentControlSet");
if (_wcsnicmp(pszString, L"CurrentControlSet", nCS) == 0) { WCHAR szCS[20] = L"ControlSet001"; DWORD dwCurrent = 0; HKEY hKey = NULL; if (ERROR_SUCCESS == RegOpenKeyEx(hkMount, L"Select", 0, KEY_READ, &hKey)) { if (ERROR_SUCCESS == RegReadDWORD(hKey, L"Current", &dwCurrent)) { wsprintf(szCS, L"ControlSet%03d", (int) dwCurrent); } RegCloseKey(hKey); } else { trace(0, "! RegOpenKeyEx : %ld", GetLastError()); } WCHAR szTemp[MAX_PATH];
lstrcpy(szTemp, &(pszString[nCS])); wsprintf(pszString, L"%s%s", szCS, szTemp); trace(0, "ChangeCCS: pszString = %S", pszString); } tleave(); }
WCHAR * SRPathFindExtension (WCHAR * pwszPath) { WCHAR *pwszDot = NULL;
if (pwszPath != NULL) for (; *pwszPath; pwszPath++) { switch (*pwszPath) { case L'.': pwszDot = pwszPath; // remember the last dot
break; case L'\\': case L' ': pwszDot = NULL; // extensions can't have spaces
break; // forget last dot, it was in a directory
} }
return pwszDot; }
// In order to prevent endless loop in case of disk failure, try only up to
// a predefined number.
#define MAX_ALT_INDEX 1000
//
// This function makes an unique alternative name of given file name, keeping
// path and extension.
//
BOOL SRGetAltFileName( LPCWSTR cszPath, LPWSTR szAltName ) { TraceFunctEnter("SRGetAltFileName"); BOOL fRet = FALSE; WCHAR szNewPath[SR_MAX_FILENAME_LENGTH]; LPWSTR szExtPos; WCHAR szExtBuf[SR_MAX_FILENAME_LENGTH]; int nAltIdx;
if (lstrlenW (cszPath) >= SR_MAX_FILENAME_LENGTH) goto Exit;
::lstrcpy( szNewPath, cszPath ); szExtPos = SRPathFindExtension( szNewPath ); if ( szExtPos != NULL ) { ::lstrcpy( szExtBuf, szExtPos ); } else { szExtBuf[0] = L'\0'; szExtPos = &szNewPath[ lstrlen(szNewPath) ]; // end of string
}
for ( nAltIdx = 2; nAltIdx < MAX_ALT_INDEX; nAltIdx++ ) { ::wsprintf( szExtPos, L"(%d)%s", nAltIdx, szExtBuf ); if ( ::GetFileAttributes( szNewPath ) == 0xFFFFFFFF ) break; } if ( nAltIdx == MAX_ALT_INDEX ) { ErrorTrace(0, "Couldn't get alternative name."); goto Exit; }
::lstrcpy( szAltName, szNewPath );
fRet = TRUE; Exit: TraceFunctLeave(); return( fRet ); }
CSRClientLoader::CSRClientLoader() { m_hSRClient=NULL; m_hFrameDyn=NULL; }
CSRClientLoader::~CSRClientLoader() { // unload library here
if (m_hFrameDyn != NULL) { _VERIFY(FreeLibrary(m_hFrameDyn)); }
if (m_hSRClient != NULL) { _VERIFY(FreeLibrary(m_hSRClient)); } }
BOOL CSRClientLoader::LoadFrameDyn() { TraceFunctEnter("LoadFrameDyn");
WCHAR szFrameDynPath[MAX_PATH+100]; DWORD dwCharsCopied, dwBufSize,dwError; BOOL fReturn=FALSE;
m_hFrameDyn=LoadLibrary(FRAMEDYN_DLL); // file name of module
if (m_hFrameDyn != NULL) { // we are done.
fReturn = TRUE; goto cleanup; }
// framedyn.dll could not be loaded. Try to load framedyn.dll
// from the explicit path. (system32\wbem\framedyn.dll)
dwError = GetLastError(); ErrorTrace(0,"Failed to load framedyn.dll on first attempt. ec=%d", dwError);
// get the windows system32 directory
// add wbem\framedyn.dll
// Call LoadLibrary on this path
dwBufSize = sizeof(szFrameDynPath)/sizeof(WCHAR); dwCharsCopied=GetSystemDirectory( szFrameDynPath, //buffer for system directory
dwBufSize); // size of directory buffer
if (dwCharsCopied == 0) { dwError = GetLastError(); ErrorTrace(0,"Failed to load system directory. ec=%d", dwError); goto cleanup; }
// check if buffer is big enough.
if (dwBufSize < dwCharsCopied + sizeof(FRAMEDYN_DLL)/sizeof(WCHAR) + sizeof(WBEM_DIRECTORY)/sizeof(WCHAR)+ 3 ) { ErrorTrace(0,"Buffer not big enough. WinSys is %d chars long", dwCharsCopied); goto cleanup; }
lstrcat(szFrameDynPath, L"\\" WBEM_DIRECTORY L"\\" FRAMEDYN_DLL);
m_hFrameDyn=LoadLibrary(szFrameDynPath); // file name of module
if (m_hFrameDyn == NULL) { // we are done.
fReturn = FALSE; dwError = GetLastError(); ErrorTrace(0,"Failed to load framedyn.dll on second attempt. ec=%d", dwError); goto cleanup; }
fReturn=TRUE; cleanup: TraceFunctLeave(); return fReturn; }
BOOL CSRClientLoader::LoadSrClient() { TraceFunctEnter("LoadSrClient"); DWORD dwError; BOOL fReturn=FALSE; if (m_hSRClient != NULL) { fReturn=TRUE; goto cleanup; }
// sometimes srclient.dll cannot be loaded because framedyn.dll
// cannot be loaded because of the PATH variable being messed up.
// Explicitly load framedyn.dll from %windir%\system32\wbem
// and then try again.
if (FALSE == LoadFrameDyn()) { ErrorTrace(0,"Failed to load framedyn.dll"); // we can still try to load srclient.dll
} m_hSRClient=LoadLibrary(L"srclient.dll"); // file name of module
if (m_hSRClient == NULL) { dwError = GetLastError(); ErrorTrace(0,"Failed to load srclient.dll. ec=%d", dwError); goto cleanup; }
fReturn=TRUE; cleanup: TraceFunctLeave(); return fReturn; }
|