Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3641 lines
101 KiB

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