|
|
//*************************************************************
//
// Utility functions
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1995
// All rights reserved
//
//*************************************************************
#include "uenv.h"
#include <iphlpapi.h>
#include <winsock2.h>
#include <mswsock.h>
#include <Aclapi.h>
#include <windns.h>
#include "strsafe.h"
#define PCOMMON_IMPL
#include "pcommon.h"
#define NETWORK_PROVIDER L"System\\CurrentControlSet\\Services\\lanmanworkstation\\NetworkProvider"
#define PROVIDER_NAME L"Name"
INT g_iMachineRole = -1; LPVOID g_lpTestData = NULL; CRITICAL_SECTION *g_PingCritSec; LPCTSTR c_szUNCFilePrefix = TEXT("\\\\?\\UNC\\"); LPCTSTR c_szLocalFilePrefix = TEXT("\\\\?\\"); const DWORD c_dwLocalFilePrefixLen = sizeof(c_szLocalFilePrefix) / sizeof(TCHAR); // Length of szLocalFilePrefix in unit of TCHAR.
//
// Local function proto-types
//
DWORD IsSlowLink (HKEY hKeyRoot, LPTSTR lpDCAddress, BOOL *bSlow, DWORD* pdwAdapterIndex ); DWORD GetNetworkProvider(NETRESOURCE *psNR);
#ifdef __cplusplus
extern "C" { #endif
DWORD APIENTRY NPAddConnection3ForCSCAgent( HWND hwndOwner, LPNETRESOURCE lpNetResource, LPTSTR pszPassword, LPTSTR pszUserName, DWORD dwFlags, BOOL *lpfIsDfsConnect );
DWORD APIENTRY NPCancelConnectionForCSCAgent ( LPCTSTR szName, BOOL fForce );
#ifdef __cplusplus
} #endif
DWORD GetGroupPolicyNetworkName( LPWSTR szNetworkName, LPDWORD pdwByteCount ) { HKEY hKey; DWORD dwError = ERROR_SUCCESS;
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History", 0, KEY_READ, &hKey ); if ( dwError == ERROR_SUCCESS ) { DWORD dwType = REG_SZ; dwError = RegQueryValueEx( hKey, L"NetworkName", 0, &dwType, (LPBYTE) szNetworkName, pdwByteCount ); RegCloseKey (hKey); }
return dwError; }
int GetNetworkName( LPWSTR* pszName, DWORD dwAdapterIndex ) { int iError; WSAQUERYSET restrictions; GUID WsMobilityServiceClassGuid = NLA_SERVICE_CLASS_GUID; WSADATA wsaData; HANDLE hQuery; PWSAQUERYSET pResult = 0; DWORD length; BOOL bFinish = FALSE; PWS2_32_API pWS2_32 = Loadws2_32Api(); PIPHLPAPI_API pIpHlpApi = LoadIpHlpApi();
if ( !pWS2_32 ) { return GetLastError(); }
if ( !pIpHlpApi ) { return GetLastError(); }
//
// Initialize Winsock
//
iError = pWS2_32->pfnWSAStartup( MAKEWORD(2, 2), &wsaData ); if ( iError ) { return iError; }
//
// Initialize the query for network names
//
ZeroMemory(&restrictions, sizeof(restrictions)); restrictions.dwSize = sizeof(restrictions); restrictions.lpServiceClassId = &WsMobilityServiceClassGuid; restrictions.dwNameSpace = NS_NLA;
//
// Make sure we do not ask for the blobs that take a long time to get
//
if ( pWS2_32->pfnWSALookupServiceBegin( &restrictions, LUP_NOCONTAINERS, &hQuery ) ) { iError = pWS2_32->pfnWSAGetLastError(); pWS2_32->pfnWSACleanup(); return iError; }
//
// Start loop of getting network names
//
while ( !bFinish ) { int error; length = 0;
//
// Do call twice, first to get size of buffer for second call
//
error = pWS2_32->pfnWSALookupServiceNext( hQuery, 0, &length, 0 ); iError = pWS2_32->pfnWSAGetLastError(); if ( iError != WSAEFAULT && iError != WSA_E_NO_MORE ) { break; }
pResult = (PWSAQUERYSET) LocalAlloc( LPTR, length ); if ( !pResult ) { iError = GetLastError(); break; }
//
// Get a network name
//
if ( !pWS2_32->pfnWSALookupServiceNext( hQuery, 0, &length, pResult ) ) { if ( pResult->lpBlob ) { int next; NLA_BLOB *blob = (NLA_BLOB *)pResult->lpBlob->pBlobData;
do { //
// We are looking for the blob containing the network GUID
//
if ( blob->header.type == NLA_INTERFACE ) { //
// "\\DEVICE\\TCPIP_" + "{GUID"
//
WCHAR szAdapter[64]; DWORD dwAdapter; WCHAR* szEnd = NULL; size_t cchRemain = 0; HRESULT hr = E_FAIL;
//
// Convert guid to device name
//
StringCchCopyExW( szAdapter, ARRAYSIZE(szAdapter), L"\\DEVICE\\TCPIP_", &szEnd, &cchRemain, 0); if (MultiByteToWideChar(CP_ACP, 0, (LPCSTR)blob->data.interfaceData.adapterName, -1, szEnd, cchRemain)) { //
// Get the index for the network
//
if ( pIpHlpApi->pfnGetAdapterIndex( szAdapter, &dwAdapter ) == NO_ERROR ) { //
// Is it the index we are after
//
if ( dwAdapterIndex == dwAdapter && pResult->lpszServiceInstanceName ) { //
// Yes, copy the network name into the buffer
//
DWORD dwSize = sizeof( WCHAR ) * ( wcslen(pResult->lpszServiceInstanceName) + 1 ); *pszName = (LPWSTR) LocalAlloc( LPTR, dwSize ); if ( !*pszName ) { iError = GetLastError(); } else { StringCbCopyW( *pszName, dwSize, pResult->lpszServiceInstanceName ); bFinish = TRUE; iError = 0; } } } } else { iError = GetLastError(); } }
//
// There maybe multiple blobs for each interface so make sure we find them all
//
next = blob->header.nextOffset; blob = (NLA_BLOB *)(((char *)blob) + next);
} while ( next ); }
LocalFree( pResult ); } else { iError = pWS2_32->pfnWSAGetLastError(); if ( iError == WSA_E_NO_MORE ) { iError = 0; } LocalFree( pResult ); break; } }
//
// tidy up
//
pWS2_32->pfnWSALookupServiceEnd( hQuery ); pWS2_32->pfnWSACleanup(); return iError; }
//*************************************************************
//
// ProduceWFromA()
//
// Purpose: Creates a buffer for a Unicode string and copies
// the ANSI text into it (converting in the process)
//
// Parameters: pszA - ANSI string
//
//
// Return: Unicode pointer if successful
// NULL if an error occurs
//
// Comments: The caller needs to free this pointer.
//
//
// History: Date Author Comment
// 5/24/95 ericflo Ported
//
//*************************************************************
LPWSTR ProduceWFromA(LPCSTR pszA) { LPWSTR pszW; int cch;
if (!pszA) return (LPWSTR)pszA;
cch = MultiByteToWideChar(CP_ACP, 0, pszA, -1, NULL, 0);
if (cch == 0) cch = 1;
pszW = LocalAlloc(LPTR, cch * sizeof(WCHAR));
if (pszW) { if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszA, -1, pszW, cch)) { LocalFree(pszW); pszW = NULL; } }
return pszW; }
//*************************************************************
//
// ProduceAFromW()
//
// Purpose: Creates a buffer for an ANSI string and copies
// the Unicode text into it (converting in the process)
//
// Parameters: pszW - Unicode string
//
//
// Return: ANSI pointer if successful
// NULL if an error occurs
//
// Comments: The caller needs to free this pointer.
//
//
// History: Date Author Comment
// 5/24/95 ericflo Ported
//
//*************************************************************
LPSTR ProduceAFromW(LPCWSTR pszW) { LPSTR pszA; int cch;
if (!pszW) return (LPSTR)pszW;
cch = WideCharToMultiByte(CP_ACP, 0, pszW, -1, NULL, 0, NULL, NULL);
if (cch == 0) cch = 1;
pszA = LocalAlloc(LPTR, cch * sizeof(char));
if (pszA) { if (!WideCharToMultiByte(CP_ACP, 0, pszW, -1, pszA, cch, NULL, NULL)) { LocalFree(pszA); pszA = NULL; } }
return pszA; }
//*************************************************************
//
// CheckSlash()
//
// Purpose: Checks for an ending slash and adds one if
// it is missing.
//
// Parameters: lpDir - directory
//
// Return: Pointer to the end of the string
//
// Comments:
//
// History: Date Author Comment
// 6/19/95 ericflo Created
//
//*************************************************************
LPTSTR CheckSlash (LPTSTR lpDir) { LPTSTR lpEnd;
lpEnd = lpDir + lstrlen(lpDir);
if (*(lpEnd - 1) != TEXT('\\')) { *lpEnd = TEXT('\\'); lpEnd++; *lpEnd = TEXT('\0'); }
return lpEnd; }
//*************************************************************
//
// CheckSlashEx()
//
// Purpose: Checks for an ending slash and adds one if
// it is missing. It will take the buffer size
// to make it safe (not overflow the buffer).
//
// Parameters: lpDir - directory
// cchBuffer - buffer size
// pcchRemain - buffer remained after patch '\'
// can be NULL if not needed.
//
// Return: Pointer to the end of the string, NULL for
// overflowed buffer.
//
// Comments:
//
// History: Date Author Comment
// 06/19/95 ericflo Created
// 02/11/02 mingzhu Make it safe
//
//*************************************************************
LPTSTR CheckSlashEx(LPTSTR lpDir, UINT cchBuffer, UINT* pcchRemain ) { LPTSTR lpEnd = NULL; UINT cchLen = lstrlen(lpDir);
if (cchLen >= cchBuffer - 1) // Overflowed or full buffer
{ DmAssert(cchLen == cchBuffer - 1); // Should never happen
if (pcchRemain) *pcchRemain = 0; lpEnd = NULL; } else { lpEnd = lpDir + cchLen; if (pcchRemain) *pcchRemain = cchBuffer - 1 - cchLen; if (*(lpEnd - 1) != TEXT('\\')) { *lpEnd = TEXT('\\'); lpEnd++; *lpEnd = TEXT('\0'); if (pcchRemain) (*pcchRemain) --; } } return lpEnd; }
//*************************************************************
//
// CheckSemicolon()
//
// Purpose: Checks for an ending slash and adds one if
// it is missing.
//
// Parameters: lpDir - directory
//
// Return: Pointer to the end of the string
//
// Comments:
//
// History: Date Author Comment
// 6/19/95 ericlfo Created
//
//*************************************************************
LPTSTR CheckSemicolon (LPTSTR lpDir) { LPTSTR lpEnd;
lpEnd = lpDir + lstrlen(lpDir);
if (*(lpEnd - 1) != TEXT(';')) { *lpEnd = TEXT(';'); lpEnd++; *lpEnd = TEXT('\0'); }
return lpEnd; }
//*************************************************************
//
// Delnode_Recurse()
//
// Purpose: Recursive delete function for Delnode
//
// Parameters: lpDir - Full Directory Path.
// dwSize - Allocated size of the working buffer
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 8/10/95 ericflo Created
// 04/08/2002 mingzhu Added functionality to take ownership
//
// Notes:
// This function modifies the working buffer.
// This doesn't maintain the right error code. It ignores all
// errors and tries to delete as much as possible..
//
//*************************************************************
BOOL Delnode_Recurse (LPTSTR lpDir, DWORD dwSize) { BOOL bOwn = FALSE, bRetVal = FALSE; LPTSTR lpEnd = NULL, lpWrkDir = NULL; WIN32_FIND_DATA* pfd = NULL; HANDLE hFile; DWORD dwWrkDirSize; DWORD cchEnd; // buffer size for lpEnd
HRESULT hr; BOOL bDeleteSuccess;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: Entering, lpDir = <%s>"), lpDir));
//
// Each filename or a directory has to be less than MAX_PATH in the worst case.
// So make sure that we have at least MAX_PATH + 2 (for a slash and '\0'
// space left in the working buffer case.
//
// In the normal case, when we have a path of length ~MAX_PATH it will do only
// 1 allocation
//
if ((DWORD)(lstrlen(lpDir) + MAX_PATH+2) > (dwSize)) { dwWrkDirSize = dwSize+2*MAX_PATH; lpWrkDir = (LPTSTR)LocalAlloc(LPTR, dwWrkDirSize*sizeof(TCHAR)); if (!lpWrkDir) { DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Couldn't allocate memory for working buffer. Error - %d"), GetLastError())); goto Exit; }
StringCchCopy(lpWrkDir, dwWrkDirSize, lpDir); bOwn = TRUE;
} else { lpWrkDir = lpDir; dwWrkDirSize = dwSize; }
//
// append "*.*" to the directory name
//
lpEnd = CheckSlashEx(lpWrkDir, dwWrkDirSize, &cchEnd); StringCchCopy(lpEnd, cchEnd, c_szStarDotStar);
//
// Allocate fd in the heap, reduce stack usage
//
pfd = (WIN32_FIND_DATA*) LocalAlloc(LPTR, sizeof(WIN32_FIND_DATA)); if (!pfd) { DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Couldn't allocate memory for WIN32_FIND_DATA. Error - %d"), GetLastError())); goto Exit; }
//
// Find the first file
//
hFile = FindFirstFile(lpWrkDir, pfd);
if (hFile == INVALID_HANDLE_VALUE) {
if ((GetLastError() == ERROR_FILE_NOT_FOUND) || (GetLastError() == ERROR_PATH_NOT_FOUND)) { bRetVal = TRUE; goto Exit; } else if ((GetLastError() == ERROR_ACCESS_DENIED)) { //
// Now we got an access denied, we will try to take the ownership of the directory and
// add admin full access to it so that we can recurse into it and delete it.This only
// works when the caller is an admin.
//
*lpEnd = TEXT('\0'); // Restore the original name
hr = TakeOwnership(lpWrkDir); if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: TakeOwnership failed. Error = 0x%08X"), hr)); goto Exit; }
hr = AddAdminAccess(lpWrkDir); if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: AddAdminAccess failed. Error = 0x%08X"), hr)); goto Exit; }
// Append "*.*" and try again
StringCchCopy(lpEnd, cchEnd, c_szStarDotStar); hFile = FindFirstFile(lpWrkDir, pfd); if (hFile == INVALID_HANDLE_VALUE) { DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: FindFirstFile failed. Error = %d"), GetLastError())); goto Exit; } } else { DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: FindFirstFile failed. Error = %d"), GetLastError())); goto Exit; } }
do {
//
// Check for "." and ".."
//
if (!lstrcmpi(pfd->cFileName, c_szDot)) { continue; }
if (!lstrcmpi(pfd->cFileName, c_szDotDot)) { continue; }
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: FindFile found: <%s>"), pfd->cFileName));
// Note that fd.cFileName will not exceed MAX_PATH, so the buffer is
// always large enough to hold it in this algorithm.
StringCchCopy(lpEnd, cchEnd, pfd->cFileName);
if (pfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
//
// Found a directory.
//
if (pfd->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Found a reparse point <%s>, Will not recurse into it!"), lpWrkDir)); } else { Delnode_Recurse(lpWrkDir, dwWrkDirSize); // ignore errors and go ahead..
StringCchCopy(lpEnd, cchEnd, pfd->cFileName); }
if (pfd->dwFileAttributes & FILE_ATTRIBUTE_READONLY) { pfd->dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY; SetFileAttributes (lpWrkDir, pfd->dwFileAttributes); }
if (!RemoveDirectory (lpWrkDir)) { bDeleteSuccess = FALSE; if (GetLastError() == ERROR_ACCESS_DENIED) { if ( SUCCEEDED(TakeOwnership(lpWrkDir)) && SUCCEEDED(AddAdminAccess(lpWrkDir)) && RemoveDirectory(lpWrkDir) ) { bDeleteSuccess = TRUE; } } if (!bDeleteSuccess) { DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to delete directory <%s>. Error = %d"), lpWrkDir, GetLastError())); } }
} else {
//
// We found a file. Set the file attributes,
// and try to delete it.
//
if ((pfd->dwFileAttributes & FILE_ATTRIBUTE_READONLY) || (pfd->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) { SetFileAttributes (lpWrkDir, FILE_ATTRIBUTE_NORMAL); }
if (!DeleteFile (lpWrkDir)) { bDeleteSuccess = FALSE; if (GetLastError() == ERROR_ACCESS_DENIED) { if ( SUCCEEDED(TakeOwnership(lpWrkDir)) && SUCCEEDED(AddAdminAccess(lpWrkDir)) && DeleteFile(lpWrkDir) ) { bDeleteSuccess = TRUE; } } if (!bDeleteSuccess) { DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to delete <%s>. Error = %d"), pfd->cFileName, GetLastError())); } }
}
//
// Find the next entry
//
} while (FindNextFile(hFile, pfd));
//
// Close the search handle
//
FindClose(hFile);
//
// Success.
//
DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: Leaving <%s>"), lpDir));
bRetVal = TRUE;
Exit: if (bOwn) LocalFree(lpWrkDir);
if (pfd) LocalFree(pfd); return bRetVal; }
//*************************************************************
//
// Delnode()
//
// Purpose: Recursive function that deletes files and
// directories.
//
// Parameters: lpDir - Directory
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/23/95 ericflo Created
// 6/27/00 santanuc modified to allow deletion of file with path length > MAX_PATH
//
//*************************************************************
BOOL Delnode (LPTSTR lpDir) { LPTSTR lpWrkDir = NULL; DWORD dwWrkDirSize; BOOL bRetVal = FALSE;
lpWrkDir = SupportLongFileName(lpDir, &dwWrkDirSize);
if (!lpWrkDir) { DebugMsg((DM_WARNING, TEXT("Delnode: Failed to Allocate memory. Error = %d"), GetLastError())); goto Exit; }
if (!Delnode_Recurse (lpWrkDir, dwWrkDirSize)) { DebugMsg((DM_WARNING, TEXT("Delnode: Delnode recurse failed with error %d"), GetLastError())); } if (!RemoveDirectory (lpDir)) { DWORD dwError;
dwError = GetLastError();
if ((dwError != ERROR_FILE_NOT_FOUND) && (dwError != ERROR_PATH_NOT_FOUND)) { DebugMsg((DM_VERBOSE, TEXT("Delnode: Failed to delete directory <%s>. Error = %d"), lpDir, dwError)); }
goto Exit; }
bRetVal = TRUE;
DebugMsg((DM_VERBOSE, TEXT("Delnode: Deleted directory <%s> successfully."), lpDir));
Exit: if (lpWrkDir) { LocalFree(lpWrkDir); }
return bRetVal; }
//*************************************************************
//
// CreateSystemDirectory()
//
// Purpose: A directory with system bit turned on can be created using
// CreateSystemDirectory.
//
// This API causes a system directory with the specified pathname to be
// created. If the underlying file system supports security on files
// and directories, then the SecurityDescriptor argument is applied to
// the new directory.
//
// This call is similar to DOS (int 21h, function 39h) and OS/2's
// DosCreateDir.
//
//
// Parameters: lpPathName - Supplies the pathname of the system directory to be created.
// lpSecurityAttributes - An optional parameter that, if present, and
// supported on the target file system supplies a security
// descriptor for the new directory.
//
//
// Return: TRUE - The operation was successful.
// FALSE/NULL - The operation failed. Extended error status is available
// using GetLastError.
//
// Comments: This function is exactly same as CreateDirectory API with the exception
// that the directory is created using attribute FILE_ATTRIBUTE_SYSTEM.
// This allows newly created directory to not inherit the encryption property
// from parent directory if the parent directory is encrypted.
//
// History: Date Author Comments
// 07/18/00 santanuc To avoid deadlock situation when Documents and Settings
// directory is encrypted.
//
//*************************************************************
BOOL CreateSystemDirectory(LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { NTSTATUS Status; OBJECT_ATTRIBUTES Obja; HANDLE Handle; UNICODE_STRING FileName; IO_STATUS_BLOCK IoStatusBlock; BOOLEAN TranslationStatus; RTL_RELATIVE_NAME_U RelativeName; PVOID FreeBuffer; ULONG dwErrorCode;
// Note : ANSI version may cause error calling the following
TranslationStatus = RtlDosPathNameToRelativeNtPathName_U( lpPathName, &FileName, NULL, &RelativeName);
if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return FALSE; }
//
// dont create a directory unless there is room in the directory for
// at least an 8.3 name. This way everyone will be able to delete all
// files in the directory by using del *.* which expands to path+\*.*
//
if ( FileName.Length > ((MAX_PATH-12)<<1) ) { DWORD L; LPWSTR lp;
if ( !(lpPathName[0] == TEXT('\\') && lpPathName[1] == TEXT('\\') && lpPathName[2] == TEXT('?') && lpPathName[3] == TEXT('\\')) ) { L = GetFullPathNameW(lpPathName,0,NULL,&lp); if ( !L || L+12 > MAX_PATH ) { RtlReleaseRelativeName(&RelativeName); RtlFreeHeap(RtlProcessHeap(), 0,FileName.Buffer); SetLastError(ERROR_FILENAME_EXCED_RANGE); return FALSE; } } }
FreeBuffer = FileName.Buffer;
if ( RelativeName.RelativeName.Length ) { FileName = RelativeName.RelativeName; } else { RelativeName.ContainingDirectory = NULL; }
InitializeObjectAttributes( &Obja, &FileName, OBJ_CASE_INSENSITIVE, RelativeName.ContainingDirectory, NULL );
if ( ARGUMENT_PRESENT(lpSecurityAttributes) ) { Obja.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor; } // Creating the directory with attribute FILE_ATTRIBUTE_SYSTEM to avoid inheriting encryption
// property from parent directory
Status = NtCreateFile( &Handle, FILE_LIST_DIRECTORY | SYNCHRONIZE, &Obja, &IoStatusBlock, NULL, FILE_ATTRIBUTE_SYSTEM, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0L );
RtlReleaseRelativeName(&RelativeName); RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
if ( NT_SUCCESS(Status) ) { NtClose(Handle); return TRUE; } else { if ( RtlIsDosDeviceName_U((LPWSTR)lpPathName) ) { Status = STATUS_NOT_A_DIRECTORY; }
// Since RtlNtStatusToDosError function can't convert STATUS_TIMEOUT, we have to
// do it explicitly
if (Status == STATUS_TIMEOUT) { SetLastError(ERROR_TIMEOUT); } else { dwErrorCode = RtlNtStatusToDosError( Status ); SetLastError( dwErrorCode ); } return FALSE; } }
//*************************************************************
//
// CreateNestedDirectory()
//
// Purpose: Creates a subdirectory and all it's parents
// if necessary using CreateNestedDirectoryEx.
//
// Parameters: lpDirectory - Directory name
// lpSecurityAttributes - Security Attributes
//
// Return: > 0 if successful
// 0 if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/18/00 santanuc Created
//
//*************************************************************
UINT CreateNestedDirectory(LPCTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { // Call CreateNestedDirectoryEx with inherit encryption property
return CreateNestedDirectoryEx(lpDirectory, lpSecurityAttributes, TRUE); }
//*************************************************************
//
// CreateNestedDirectoryEx()
//
// Purpose: Creates a subdirectory and all it's parents
// if necessary.
//
// Parameters: lpDirectory - Directory name
// lpSecurityAttributes - Security Attributes
// bInheritEncryption - Flag indicating whether newly created directory should inherit
// encryption property from parent directory.
//
// Return: > 0 if successful
// 0 if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 8/08/95 ericflo Created
// 7/18/00 santanuc added a new flag bInheritEncryption to avoid deadlock when
// Documents and Settings directory is encrypted.
//
//*************************************************************
UINT CreateNestedDirectoryEx(LPCTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes, BOOL bInheritEncryption) { TCHAR szDirectory[2*MAX_PATH]; LPTSTR lpEnd; WIN32_FILE_ATTRIBUTE_DATA fad;
//
// Check for NULL pointer
//
if (!lpDirectory || !(*lpDirectory)) { DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: Received a NULL pointer."))); return 0; }
//
// Test if the directory exists already
//
if (GetFileAttributesEx (lpDirectory, GetFileExInfoStandard, &fad)) { if (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { return ERROR_ALREADY_EXISTS; } else { SetLastError(ERROR_ACCESS_DENIED); return 0; } }
//
// First, see if we can create the directory without having
// to build parent directories.
//
if ( bInheritEncryption ) { if (CreateDirectory (lpDirectory, lpSecurityAttributes)) return 1; } else { if (CreateSystemDirectory (lpDirectory, lpSecurityAttributes)) { SetFileAttributes(lpDirectory, FILE_ATTRIBUTE_NORMAL); // turn off the system attribute
return 1; } }
//
// No luck, copy the string to a buffer we can munge
//
StringCchCopy(szDirectory, ARRAYSIZE(szDirectory), lpDirectory);
//
// Find the first subdirectory name
//
lpEnd = szDirectory;
if (szDirectory[1] == TEXT(':')) { lpEnd += 3; } else if (szDirectory[1] == TEXT('\\')) {
//
// Skip the first two slashes
//
lpEnd += 2;
//
// Find the slash between the server name and
// the share name.
//
while (*lpEnd && *lpEnd != TEXT('\\')) { lpEnd++; }
if (!(*lpEnd)) { return 0; }
//
// Skip the slash, and find the slash between
// the share name and the directory name.
//
lpEnd++;
while (*lpEnd && *lpEnd != TEXT('\\')) { lpEnd++; }
if (!(*lpEnd)) { return 0; }
//
// Leave pointer at the beginning of the directory.
//
lpEnd++;
} else if (szDirectory[0] == TEXT('\\')) { lpEnd++; }
while (*lpEnd) {
while (*lpEnd && *lpEnd != TEXT('\\')) { lpEnd++; }
if (*lpEnd == TEXT('\\')) { *lpEnd = TEXT('\0');
if (!GetFileAttributesEx (szDirectory, GetFileExInfoStandard, &fad)) {
if ( bInheritEncryption ) { if (!CreateDirectory (szDirectory, lpSecurityAttributes)) { DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: CreateDirectory failed with %d."), GetLastError())); return 0; } }
else { if (!CreateSystemDirectory (szDirectory, lpSecurityAttributes)) { DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: CreateDirectory failed with %d."), GetLastError())); return 0; } else SetFileAttributes(szDirectory, FILE_ATTRIBUTE_NORMAL); // turn off the system attribute
}
}
*lpEnd = TEXT('\\'); lpEnd++; } }
//
// Create the final directory
//
if ( bInheritEncryption ) { if (CreateDirectory (lpDirectory, lpSecurityAttributes)) return 1; } else { if (CreateSystemDirectory (lpDirectory, lpSecurityAttributes)) { SetFileAttributes(lpDirectory, FILE_ATTRIBUTE_NORMAL); // turn off the system attribute
return 1; } }
if (GetLastError() == ERROR_ALREADY_EXISTS) { return ERROR_ALREADY_EXISTS; }
//
// Failed
//
DebugMsg((DM_VERBOSE, TEXT("CreateNestedDirectory: Failed to create the directory with error %d."), GetLastError()));
return 0;
}
//*************************************************************
//
// GetProfilesDirectory()
//
// Purpose: Returns the location of the "profiles" directory
//
// Parameters: lpProfilesDir - Buffer to write result to
// lpcchSize - Size of the buffer in chars.
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: If false is returned, lpcchSize holds the number of
// characters needed.
//
// History: Date Author Comment
// 9/18/95 ericflo Created
//
//*************************************************************
BOOL WINAPI GetProfilesDirectory(LPTSTR lpProfilesDir, LPDWORD lpcchSize) { return GetProfilesDirectoryEx (lpProfilesDir, lpcchSize, TRUE); }
//*************************************************************
//
// GetProfilesDirectoryEx()
//
// Purpose: Returns the location of the "profiles" directory
//
// Parameters: lpProfilesDir - Buffer to write result to
// lpcchSize - Size of the buffer in chars.
// bExpand - Expand directory name
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: If false is returned, lpcchSize holds the number of
// characters needed.
//
// History: Date Author Comment
// 12/15/97 ericflo Created
//
//*************************************************************
BOOL GetProfilesDirectoryEx(LPTSTR lpProfilesDir, LPDWORD lpcchSize, BOOL bExpand) { TCHAR szDirectory[MAX_PATH]; TCHAR szTemp[MAX_PATH]; DWORD dwLength; HKEY hKey = INVALID_HANDLE_VALUE; LONG lResult; DWORD dwSize, dwType; BOOL bRetVal = FALSE;
//
// Arg check
//
if (!lpcchSize) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; }
szDirectory[0] = TEXT('\0'); szTemp[0] = TEXT('\0');
lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH, 0, KEY_READ, &hKey);
if (lResult == ERROR_SUCCESS) {
dwSize = sizeof(szTemp);
lResult = RegQueryValueEx (hKey, PROFILES_DIRECTORY, NULL, &dwType, (LPBYTE) szTemp, &dwSize);
if (lResult == ERROR_SUCCESS) {
if ((dwType == REG_EXPAND_SZ) || (dwType == REG_SZ)) {
if (bExpand && (dwType == REG_EXPAND_SZ)) { if((dwLength = ExpandEnvironmentStrings(szTemp, szDirectory, MAX_PATH)) == 0) { goto Exit; } else if(dwLength > MAX_PATH) { SetLastError(ERROR_BAD_PATHNAME); goto Exit; } } else { StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), szTemp); } } }
RegCloseKey (hKey); hKey = INVALID_HANDLE_VALUE; }
if (szDirectory[0] == TEXT('\0')) {
LoadString (g_hDllInstance, IDS_PROFILES_ROOT, szTemp, ARRAYSIZE(szTemp));
if (bExpand) { if((dwLength = ExpandEnvironmentStrings(szTemp, szDirectory, MAX_PATH)) == 0) { goto Exit; } else if(dwLength > MAX_PATH) { SetLastError(ERROR_BAD_PATHNAME); goto Exit; } } else { StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), szTemp); } }
dwLength = lstrlen(szDirectory) + 1;
if (lpProfilesDir) {
if (*lpcchSize >= dwLength) { StringCchCopy (lpProfilesDir, *lpcchSize, szDirectory); bRetVal = TRUE;
} else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); }
*lpcchSize = dwLength;
Exit:
if(hKey != INVALID_HANDLE_VALUE) { RegCloseKey(hKey); }
return bRetVal; }
//*************************************************************
//
// GetDefaultUserProfileDirectory()
//
// Purpose: Returns the location of the Default User's profile
//
// Parameters: lpProfileDir - Buffer to write result to
// lpcchSize - Size of the buffer in chars.
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: If false is returned, lpcchSize holds the number of
// characters needed.
//
// History: Date Author Comment
// 12/8/97 ericflo Created
//
//*************************************************************
BOOL WINAPI GetDefaultUserProfileDirectory(LPTSTR lpProfileDir, LPDWORD lpcchSize) { return GetDefaultUserProfileDirectoryEx(lpProfileDir, lpcchSize, TRUE); }
//*************************************************************
//
// GetDefaultUserProfileDirectoryEx()
//
// Purpose: Returns the location of the Default User's profile
//
// Parameters: lpProfileDir - Buffer to write result to
// lpcchSize - Size of the buffer in chars.
// bExpand - Expand the path or not
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: If false is returned, lpcchSize holds the number of
// characters needed.
//
// History: Date Author Comment
// 12/8/97 ericflo Created
//
//*************************************************************
BOOL WINAPI GetDefaultUserProfileDirectoryEx(LPTSTR lpProfileDir, LPDWORD lpcchSize, BOOL bExpand) { TCHAR szDirectory[MAX_PATH]; TCHAR szProfileName[MAX_PATH]; LPTSTR lpEnd; int cchEnd; DWORD dwSize, dwLength, dwType; BOOL bRetVal = FALSE; LONG lResult; HKEY hKey;
//
// Arg check
//
if (!lpcchSize) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; }
//
// Get the profiles root
//
szDirectory[0] = TEXT('\0'); dwSize = ARRAYSIZE(szDirectory);
if (!GetProfilesDirectoryEx(szDirectory, &dwSize, bExpand)) { DebugMsg((DM_WARNING, TEXT("GetDefaultUserProfileDirectory: Failed to get profiles root."))); *lpcchSize = 0; return FALSE; }
//
// Query for the Default User profile name
//
lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("GetDefaultUserProfileDirectoryEx: Failed to open profile list key with %d."), lResult)); SetLastError(lResult); return FALSE; }
dwSize = sizeof(szProfileName); lResult = RegQueryValueEx (hKey, DEFAULT_USER_PROFILE, NULL, &dwType, (LPBYTE) szProfileName, &dwSize);
if (lResult != ERROR_SUCCESS) { StringCchCopy (szProfileName, ARRAYSIZE(szProfileName), DEFAULT_USER); }
RegCloseKey (hKey);
//
// Put them together
//
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd); if (cchEnd < lstrlen(szProfileName) + 1) { DebugMsg((DM_WARNING, TEXT("GetDefaultUserProfileDirectory: path > MAX_PATH."))); SetLastError(ERROR_BAD_PATHNAME); return FALSE; } StringCchCopy (lpEnd, cchEnd, szProfileName);
//
// Save the result if possible
dwLength = lstrlen(szDirectory) + 1;
if (lpProfileDir) {
if (*lpcchSize >= dwLength) { StringCchCopy (lpProfileDir, *lpcchSize, szDirectory); bRetVal = TRUE;
} else { SetLastError(ERROR_INSUFFICIENT_BUFFER); }
} else { SetLastError(ERROR_INSUFFICIENT_BUFFER); }
*lpcchSize = dwLength;
return bRetVal; }
//*************************************************************
//
// GetAllUsersProfileDirectory()
//
// Purpose: Returns the location of the All Users profile
//
// Parameters: lpProfileDir - Buffer to write result to
// lpcchSize - Size of the buffer in chars.
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: If false is returned, lpcchSize holds the number of
// characters needed.
//
// History: Date Author Comment
// 12/8/97 ericflo Created
//
//*************************************************************
BOOL WINAPI GetAllUsersProfileDirectory(LPTSTR lpProfileDir, LPDWORD lpcchSize) { return GetAllUsersProfileDirectoryEx(lpProfileDir, lpcchSize, TRUE); }
//*************************************************************
//
// GetAllUsersProfileDirectoryEx()
//
// Purpose: Returns the location of the All Users profile
//
// Parameters: lpProfileDir - Buffer to write result to
// lpcchSize - Size of the buffer in chars.
// bExpand - Expand the path or not
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: If false is returned, lpcchSize holds the number of
// characters needed.
//
// History: Date Author Comment
// 12/8/97 ericflo Created
//
//*************************************************************
BOOL GetAllUsersProfileDirectoryEx (LPTSTR lpProfileDir, LPDWORD lpcchSize, BOOL bExpand) { TCHAR szDirectory[MAX_PATH]; TCHAR szProfileName[MAX_PATH]; LPTSTR lpEnd; int cchEnd; DWORD dwSize, dwLength, dwType; BOOL bRetVal = FALSE; LONG lResult; HKEY hKey;
//
// Arg check
//
if (!lpcchSize) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; }
//
// Get the profiles root
//
szDirectory[0] = TEXT('\0'); dwSize = ARRAYSIZE(szDirectory);
if (!GetProfilesDirectoryEx(szDirectory, &dwSize, bExpand)) { DebugMsg((DM_WARNING, TEXT("GetAllUsersProfileDirectoryEx: Failed to get profiles root."))); *lpcchSize = 0; return FALSE; }
//
// Query for the All Users profile name
//
lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("GetAllUsersProfileDirectoryEx: Failed to open profile list key with %d."), lResult)); SetLastError(lResult); return FALSE; }
dwSize = sizeof(szProfileName); lResult = RegQueryValueEx (hKey, ALL_USERS_PROFILE, NULL, &dwType, (LPBYTE) szProfileName, &dwSize);
if (lResult != ERROR_SUCCESS) { StringCchCopy(szProfileName, ARRAYSIZE(szProfileName), ALL_USERS); }
RegCloseKey (hKey);
//
// Put them together
//
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd); if (cchEnd < lstrlen(szProfileName) + 1) { DebugMsg((DM_WARNING, TEXT("GetDefaultUserProfileDirectory: path > MAX_PATH."))); SetLastError(ERROR_BAD_PATHNAME); return FALSE; } StringCchCopy (lpEnd, cchEnd, szProfileName);
//
// Save the result if possible
dwLength = lstrlen(szDirectory) + 1;
if (lpProfileDir) {
if (*lpcchSize >= dwLength) { StringCchCopy (lpProfileDir, *lpcchSize, szDirectory); bRetVal = TRUE;
} else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); }
*lpcchSize = dwLength;
return bRetVal; }
//*************************************************************
//
// GetProfileListKeyName()
//
// Purpose: Returns the key name for a specific user under ProfileList.
// Using safe string functions
//
// Parameters: szKeyName - Buffer of the returned name
// cchKeyName - size of the buffer
// szSidString - sid string for a specific user
//
// Return: S_OK if successful
// Error Code if an error occurs
//
// Comments: If error code is returned, content of szKeyName may
// change.
//
// History: Date Author Comment
// 02/21/2002 mingzhu Created
//
//*************************************************************
HRESULT GetProfileListKeyName(LPTSTR szKeyName, DWORD cchKeyName, LPTSTR szSidString) { HRESULT hr;
hr = StringCchCopy(szKeyName, cchKeyName, PROFILE_LIST_PATH); if (SUCCEEDED(hr)) { hr = StringCchCat(szKeyName, cchKeyName, TEXT("\\")); if (SUCCEEDED(hr)) { hr = StringCchCat(szKeyName, cchKeyName, szSidString); } }
return hr; }
//*************************************************************
//
// GetKeyNameForUser()
//
// Purpose: Returns the user's key name in for specific user.
// Using safe string functions
//
// Parameters: szKeyName - Buffer of the returned name
// cchKeyName - size of the buffer
// szSidString - sid string for a specific user
// szSubKey - subkey name under the key's hive
//
// Return: S_OK if successful
// Error Code if an error occurs
//
// Comments: If error code is returned, content of szKeyName may
// change.
//
// History: Date Author Comment
// 02/21/2002 mingzhu Created
//
//*************************************************************
HRESULT GetKeyNameForUser(LPTSTR szKeyName, DWORD cchKeyName, LPTSTR szSidString, LPTSTR szSubKey) { HRESULT hr;
hr = StringCchCopy(szKeyName, cchKeyName, szSidString); if (SUCCEEDED(hr)) { hr = StringCchCat(szKeyName, cchKeyName, TEXT("\\")); if (SUCCEEDED(hr)) { hr = StringCchCat(szKeyName, cchKeyName, szSubKey); } }
return hr; }
//*************************************************************
//
// SafeExpandEnvironmentStrings()
//
// Purpose: a wrapper of ExpandEnvironmentStrings() to
// handle small buffer errors more explictly.
//
// Parameters: lpSrc - Src string contains the env var
// lpDst - Output buffer
// nSize - Size of output buffer
//
// Return: S_OK if successful
// else if an error occurs
//
// History: Date Author Comment
// 02/21/2002 mingzhu Created
//
//*************************************************************
HRESULT SafeExpandEnvironmentStrings(LPCTSTR lpSrc, LPTSTR lpDst, DWORD nSize) { DWORD dwErr; HRESULT hr;
dwErr = ExpandEnvironmentStrings(lpSrc, lpDst, nSize); if (dwErr == 0) hr = HRESULT_FROM_WIN32(GetLastError()); else if (dwErr > nSize) hr = STRSAFE_E_INSUFFICIENT_BUFFER; else hr = S_OK;
return hr; }
//*************************************************************
//
// AppendName()
//
// Purpose: append a file name to a folder name, or append a subkey name
// to a parent key name, add a slash if neccesory.
//
// Parameters: lpBuffer - output buffer to hold the appended path
// cchBuffer - size of the output buffer
// lpParent - path/parent key name to append to
// lpChild - file/subkey name to append
// lppEnd - optional returned pointer to the end of the slash of lpParent,
// can be used to further append other children to the same parent
// pcchEnd - optional returned pointer to the buffer size pointered by *lppEnd
//
// Return: S_OK if successful
// else if an error occurs
//
// History: Date Author Comment
// 03/05/2002 mingzhu Created
//
//*************************************************************
HRESULT AppendName( LPTSTR lpBuffer, UINT cchBuffer, LPCTSTR lpParent, LPCTSTR lpChild, LPTSTR* lppEnd, UINT* pcchEnd) { HRESULT hr; LPTSTR lpEnd; UINT cchEnd;
hr = StringCchCopy(lpBuffer, cchBuffer, lpParent); if (SUCCEEDED(hr)) { lpEnd = CheckSlashEx(lpBuffer, cchBuffer, &cchEnd); if (!lpEnd) { hr = STRSAFE_E_INSUFFICIENT_BUFFER; } else { hr = StringCchCopy(lpEnd, cchEnd, lpChild); } }
if (SUCCEEDED(hr)) { if (lppEnd) *lppEnd = lpEnd; if (pcchEnd) *pcchEnd = cchEnd; }
return hr; }
//*************************************************************
//
// GetUserProfileDirectory()
//
// Purpose: Returns the root of the user's profile directory.
//
// Parameters: hToken - User's token
// lpProfileDir - Output buffer
// lpcchSize - Size of output buffer
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: If false is returned, lpcchSize holds the number of
// characters needed.
//
// History: Date Author Comment
// 9/18/95 ericflo Created
//
//*************************************************************
BOOL WINAPI GetUserProfileDirectory(HANDLE hToken, LPTSTR lpProfileDir, LPDWORD lpcchSize) { DWORD dwLength = MAX_PATH * sizeof(TCHAR); DWORD dwType; BOOL bRetVal = FALSE; LPTSTR lpSidString; TCHAR szBuffer[MAX_PATH]; TCHAR szDirectory[MAX_PATH]; HKEY hKey; LONG lResult; HRESULT hr;
//
// Parameter check
//
if (!hToken) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; }
if (!lpcchSize) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; }
//
// Retrieve the user's sid string
//
lpSidString = GetSidString(hToken);
if (!lpSidString) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; }
//
// Check the registry
//
hr = GetProfileListKeyName(szBuffer, ARRAYSIZE(szBuffer), lpSidString); if (FAILED(hr)) { DeleteSidString(lpSidString); SetLastError(HRESULT_CODE(hr)); return FALSE; }
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) { DeleteSidString(lpSidString); SetLastError(lResult); return FALSE; }
lResult = RegQueryValueEx(hKey, PROFILE_IMAGE_VALUE_NAME, NULL, &dwType, (LPBYTE) szBuffer, &dwLength);
if (lResult != ERROR_SUCCESS) { RegCloseKey (hKey); DeleteSidString(lpSidString); SetLastError(lResult); return FALSE; }
//
// Clean up
//
RegCloseKey(hKey); DeleteSidString(lpSidString);
//
// Expand and get the length of string
//
hr = SafeExpandEnvironmentStrings(szBuffer, szDirectory, ARRAYSIZE(szDirectory)); if (FAILED(hr)) { SetLastError(HRESULT_CODE(hr)); return FALSE; }
dwLength = lstrlen(szDirectory) + 1;
//
// Save the string if appropriate
//
if (lpProfileDir) {
if (*lpcchSize >= dwLength) { StringCchCopy (lpProfileDir, *lpcchSize, szDirectory); bRetVal = TRUE;
} else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); }
*lpcchSize = dwLength;
return bRetVal; }
//*************************************************************
//
// GetUserProfileDirFromSid()
//
// Purpose: Returns the root of the user's profile directory.
//
// Parameters: pSid - User's SID
// lpProfileDir - Output buffer
// lpcchSize - Size of output buffer
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: If false is returned, lpcchSize holds the number of
// characters needed.
//
// History: Date Author Comment
// 03/08/01 santanuc Created
//
//*************************************************************
BOOL WINAPI GetUserProfileDirFromSid(PSID pSid, LPTSTR lpProfileDir, LPDWORD lpcchSize) { DWORD dwLength = MAX_PATH * sizeof(TCHAR); DWORD dwType; BOOL bRetVal = FALSE; UNICODE_STRING UnicodeString; TCHAR szBuffer[MAX_PATH]; TCHAR szDirectory[MAX_PATH]; HKEY hKey; LONG lResult; NTSTATUS NtStatus; HRESULT hr;
//
// Parameter check
//
if (!pSid) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; }
if (!lpcchSize) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; }
//
// Retrieve the user's sid string
//
NtStatus = RtlConvertSidToUnicodeString( &UnicodeString, pSid, (BOOLEAN)TRUE // Allocate memory
); //
// See if the conversion to a string worked
//
if (!NT_SUCCESS(NtStatus)) { SetLastError(RtlNtStatusToDosError(NtStatus)); DebugMsg((DM_WARNING, TEXT("GetUserProfileDirFromSid: RtlConvertSidToUnicodeString failed, status = 0x%x"), NtStatus)); return FALSE; }
//
// Check the registry
//
hr = GetProfileListKeyName(szBuffer, ARRAYSIZE(szBuffer), UnicodeString.Buffer); if (FAILED(hr)) { RtlFreeUnicodeString(&UnicodeString); SetLastError(HRESULT_CODE(hr)); return FALSE; }
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) { RtlFreeUnicodeString(&UnicodeString); SetLastError(lResult); return FALSE; }
lResult = RegQueryValueEx(hKey, PROFILE_IMAGE_VALUE_NAME, NULL, &dwType, (LPBYTE) szBuffer, &dwLength);
if (lResult != ERROR_SUCCESS) { RegCloseKey (hKey); RtlFreeUnicodeString(&UnicodeString); SetLastError(lResult); return FALSE; }
//
// Clean up
//
RegCloseKey(hKey); RtlFreeUnicodeString(&UnicodeString);
//
// Expand and get the length of string
//
hr = SafeExpandEnvironmentStrings(szBuffer, szDirectory, ARRAYSIZE(szDirectory));
if (FAILED(hr)) { SetLastError(HRESULT_CODE(hr)); return FALSE; } dwLength = lstrlen(szDirectory) + 1;
//
// Save the string if appropriate
//
if (lpProfileDir) {
if (*lpcchSize >= dwLength) { StringCchCopy (lpProfileDir, *lpcchSize, szDirectory); bRetVal = TRUE;
} else { SetLastError(ERROR_INSUFFICIENT_BUFFER); } } else { SetLastError(ERROR_INSUFFICIENT_BUFFER); }
*lpcchSize = dwLength;
return bRetVal; }
//*************************************************************
//
// GetUserAppDataPath()
//
// Purpose: Returns the path for user's Appdata.
//
// Parameters: hToken - User's token
// lpFolderPath - Output buffer
//
// Return: ERROR_SUCCESS if successful
// otherwise the error code
//
// Comments: If error occurs then lpFolderPath set to empty.
// Used by Crypto guys to avoid calling SHGetFolderPath.
//
// History: Date Author Comment
//
//*************************************************************
DWORD WINAPI GetUserAppDataPath( HANDLE hToken, BOOL fLocalAppData, LPTSTR lpFolderPath ) { DWORD dwSize, dwType; LPTSTR lpSidString = NULL; DWORD dwError = ERROR_SUCCESS; HKEY hKey = NULL; TCHAR szBuffer[MAX_PATH]; HRESULT hr;
//
// Parameter check
//
if (!hToken) { dwError = ERROR_INVALID_HANDLE; goto Exit; }
if (!lpFolderPath) { dwError = ERROR_INVALID_PARAMETER; goto Exit; } else { *lpFolderPath = TEXT('\0'); }
//
// Retrieve the user's sid string
//
lpSidString = GetSidString(hToken);
if (!lpSidString) { dwError = ERROR_INVALID_HANDLE; goto Exit; }
//
// Check the registry
//
hr = GetKeyNameForUser(szBuffer, ARRAYSIZE(szBuffer), lpSidString, USER_SHELL_FOLDERS);
if (FAILED(hr)) { dwError = HRESULT_CODE(hr); goto Exit; }
dwError = RegOpenKeyEx(HKEY_USERS, szBuffer, 0, KEY_READ, &hKey); if (dwError != ERROR_SUCCESS) { goto Exit; }
dwSize = MAX_PATH * sizeof(TCHAR); dwError = RegQueryValueEx(hKey, fLocalAppData ? TEXT("Local AppData") : TEXT("AppData"), NULL, &dwType, (LPBYTE) szBuffer, &dwSize);
if (ERROR_SUCCESS == dwError) {
dwSize = MAX_PATH; if (!ExpandEnvironmentStringsForUser(hToken, szBuffer, lpFolderPath, dwSize)) { dwError = GetLastError(); } }
Exit:
//
// Clean up
//
if (lpSidString) { DeleteSidString(lpSidString); }
if (hKey) { RegCloseKey(hKey); }
SetLastError(dwError); return dwError; }
//*************************************************************
//
// StringToInt()
//
// Purpose: Converts a string to an integer
//
// Parameters: lpNum - Number to convert
//
// Return: The number
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
int StringToInt(LPTSTR lpNum) { int i = 0; BOOL bNeg = FALSE;
if (*lpNum == TEXT('-')) { bNeg = TRUE; lpNum++; }
while (*lpNum >= TEXT('0') && *lpNum <= TEXT('9')) { i *= 10; i += (int)(*lpNum-TEXT('0')); lpNum++; }
if (bNeg) { i *= -1; }
return(i); }
//*************************************************************
//
// HexStringToInt()
//
// Purpose: Converts a hex string to an integer, stops
// on first invalid character
//
// Parameters: lpNum - Number to convert
//
// Return: The number
//
// Comments: Originally for use in "ExtractCSIDL" tested
// exclusively with 0x0000 numbers format
//
// History: Date Author Comment
// 6/9/98 stephstm Created
//
//*************************************************************
unsigned int HexStringToUInt(LPCTSTR lpcNum) { unsigned int i = 0;
while (1) { if(*lpcNum != TEXT('x') && *lpcNum != TEXT('X') ) { if(*lpcNum >= TEXT('0') && *lpcNum <= TEXT('9')) { i *= 16; i += (unsigned int)(*lpcNum-TEXT('0')); } else { if(*lpcNum >= TEXT('a') && *lpcNum <= TEXT('f')) { i *= 16; i += (unsigned int)(*lpcNum-TEXT('a')) + 10; } else { if(*lpcNum >= TEXT('A') && *lpcNum <= TEXT('F')) { i *= 16; i += (unsigned int)(*lpcNum-TEXT('A')) + 10; } else break; } } } lpcNum++; }
return(i); }
//*************************************************************
//
// RegRenameKey()
//
// Purpose: Renames a registry key
//
// Parameters: hKeyRoot - Root key
// lpSubKey1 - SubKey to rename from
// lpSubKey2 - SubKey to rename to
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 20/9/99 ushaji created
// 05/02/2002 mingzhu Make this function support subkeys (recursive)
//
//*************************************************************
LONG RegRenameKey(HKEY hKeyRoot, LPTSTR lpSrcKey, LPTSTR lpDestKey) { HKEY hSrcKey=NULL, hDestKey=NULL; LONG lResult; DWORD dwDisposition; DWORD dwValues, dwMaxValueNameLen, dwMaxValueLen, dwType; DWORD dwMaxValueNameLenLocal, dwMaxValueLenLocal, i, dwSDSize; DWORD dwSrcSubkeyLen, dwDestSubkeyLen, dwSubkeyLen; DWORD dwSubkeys, dwMaxSubkeyNameLen, dwMaxSubkeyNameLenLocal; LPTSTR lpSrcSubkey = NULL; LPTSTR lpDestSubkey = NULL; LPTSTR lpSubkey = NULL; LPTSTR lpValueName=NULL; LPBYTE lpData=NULL; PSECURITY_DESCRIPTOR pSD = NULL; HRESULT hr;
//
// Verbose Debug Message
//
DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: renaming %s to %s"), lpSrcKey, lpDestKey));
if (!lpSrcKey || !lpDestKey) return ERROR_INVALID_PARAMETER; lResult = RegOpenKeyEx(hKeyRoot, lpSrcKey, 0, KEY_ALL_ACCESS, &hSrcKey);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot open src key %s with error %d"), lpSrcKey, lResult)); goto Exit; }
if (RegDelnode(hKeyRoot, lpDestKey) != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot delete dest key %s."), lpDestKey)); goto Exit; }
lResult = RegQueryInfoKey(hSrcKey, NULL, NULL, NULL, &dwSubkeys, &dwMaxSubkeyNameLen, NULL, &dwValues, &dwMaxValueNameLen, &dwMaxValueLen, &dwSDSize, NULL);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot query src key %s with error %d"), lpSrcKey, lResult)); goto Exit; }
pSD = LocalAlloc(LPTR, sizeof(BYTE)*dwSDSize);
if (!pSD) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot allocate memory error"))); lResult = GetLastError(); goto Exit; }
lResult = RegGetKeySecurity(hSrcKey, DACL_SECURITY_INFORMATION, pSD, &dwSDSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot get sd with error %d"), lResult)); goto Exit; }
lResult = RegCreateKeyEx(hKeyRoot, lpDestKey, 0, L"", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hDestKey, &dwDisposition);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot open dest key %s with error %d"), lpDestKey, lResult)); goto Exit; }
lResult = RegSetKeySecurity(hDestKey, DACL_SECURITY_INFORMATION, pSD);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot get sd with error %d"), lResult)); goto Exit; }
lpValueName = (LPTSTR) LocalAlloc(LPTR, sizeof(TCHAR)*(dwMaxValueNameLen+1));
if (!lpValueName) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot allocate memory for valuename"))); lResult = GetLastError(); goto Exit; }
lpData = (LPBYTE) LocalAlloc(LPTR, sizeof(BYTE)*dwMaxValueLen);
if (!lpData) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot allocate memory for lpData"))); lResult = GetLastError(); goto Exit; }
for (i = 0; i < dwValues; i++) {
dwMaxValueNameLenLocal = dwMaxValueNameLen+1; dwMaxValueLenLocal = dwMaxValueLen;
lResult = RegEnumValue(hSrcKey, i, lpValueName, &dwMaxValueNameLenLocal, NULL, &dwType, lpData, &dwMaxValueLenLocal);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot enum src key value with error %d"), lResult)); goto Exit; }
lResult = RegSetValueEx(hDestKey, lpValueName, 0, dwType, lpData, dwMaxValueLenLocal);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot set dest value %s with error %d"), lpValueName, lResult)); goto Exit; } }
//
// Allocate buffer for local, src and dest subkeys
//
lpSubkey = (LPTSTR) LocalAlloc(LPTR, sizeof(TCHAR)*(dwMaxSubkeyNameLen + 1)); if (!lpSubkey) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot allocate memory for subkey"))); lResult = GetLastError(); goto Exit; }
dwSrcSubkeyLen = lstrlen(lpSrcKey) + dwMaxSubkeyNameLen + 2; lpSrcSubkey = (LPTSTR) LocalAlloc(LPTR, sizeof(TCHAR)*(dwSrcSubkeyLen)); if (!lpSrcSubkey) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot allocate memory for src subkey"))); lResult = GetLastError(); goto Exit; }
dwDestSubkeyLen = lstrlen(lpDestKey) + dwMaxSubkeyNameLen + 2; lpDestSubkey = (LPTSTR) LocalAlloc(LPTR, sizeof(TCHAR)*(dwDestSubkeyLen)); if (!lpDestSubkey) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot allocate memory for dest subkey"))); lResult = GetLastError(); goto Exit; }
//
// Enumerate subkeys and call this function recursively
//
for (i = 0; i < dwSubkeys; i++) {
// Enumerate local subkey
dwMaxSubkeyNameLenLocal = dwMaxSubkeyNameLen + 1; lResult = RegEnumKeyEx(hSrcKey, i, lpSubkey, &dwMaxSubkeyNameLenLocal, NULL, NULL, NULL, NULL); if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: Couldnot enum sub key value with error %d"), lResult)); goto Exit; }
// Construct the src and dest subkey
hr = StringCchPrintf(lpSrcSubkey, dwSrcSubkeyLen, TEXT("%s\\%s"), lpSrcKey, lpSubkey); if (FAILED(hr)) { lResult = HRESULT_CODE(hr); goto Exit; }
hr = StringCchPrintf(lpDestSubkey, dwDestSubkeyLen, TEXT("%s\\%s"), lpDestKey, lpSubkey); if (FAILED(hr)) { lResult = HRESULT_CODE(hr); goto Exit; }
// Call this function recursively
lResult = RegRenameKey(hKeyRoot, lpSrcSubkey, lpDestSubkey); if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("RegRenameKey: failed to rename %s to %s, error = %d"), lpSrcSubkey, lpDestSubkey, lResult)); goto Exit; } } Exit:
if (lpSubkey) LocalFree(lpSubkey);
if (lpSrcSubkey) LocalFree(lpSrcSubkey);
if (lpDestSubkey) LocalFree(lpDestSubkey); if (hSrcKey) RegCloseKey(hSrcKey);
if (hDestKey) RegCloseKey(hDestKey);
if (lpData) LocalFree(lpData);
if (lpValueName) LocalFree(lpValueName);
if (pSD) LocalFree(pSD);
if (lResult == ERROR_SUCCESS) lResult = RegDelnode(hKeyRoot, lpSrcKey); else RegDelnode(hKeyRoot, lpDestKey);
return lResult; }
//*************************************************************
//
// CreateSecureAdminDirectory()
//
// Purpose: Creates a secure directory that only the Administrator
// and system have access to.
//
// Parameters: lpDirectory - Directory Name
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/20/95 ericflo Created
//
//*************************************************************
BOOL CreateSecureAdminDirectory (LPTSTR lpDirectory, DWORD dwOtherSids) {
//
// Attempt to create the directory
//
if (!CreateNestedDirectory(lpDirectory, NULL)) { return FALSE; }
//
// Set the security
//
if (!MakeFileSecure (lpDirectory, dwOtherSids)) { RemoveDirectory(lpDirectory); return FALSE; }
return TRUE; }
//*************************************************************
//
// DeleteAllValues ()
//
// Purpose: Deletes all values under specified key
//
// Parameters: hKey - Key to delete values from
//
// Return:
//
// Comments:
//
// History: Date Author Comment
// 9/14/95 ericflo Ported
//
//*************************************************************
BOOL DeleteAllValues(HKEY hKey) { TCHAR ValueName[MAX_PATH+1]; DWORD dwSize = MAX_PATH+1; LONG lResult;
while (RegEnumValue(hKey, 0, ValueName, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
lResult = RegDeleteValue(hKey, ValueName);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("DeleteAllValues: Failed to delete value <%s> with %d."), ValueName, lResult)); return FALSE; } else { DebugMsg((DM_VERBOSE, TEXT("DeleteAllValues: Deleted <%s>"), ValueName)); }
dwSize = MAX_PATH+1; } return TRUE; }
//*************************************************************
//
// MakeFileSecure()
//
// Purpose: Sets the attributes on the file so only Administrators
// and the OS can delete it. Authenticated Users have read
// permission only.
//
// Parameters: lpFile - File to set security on
//
// Return: (BOOL) TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 11/6/95 ericflo Created
// 2/16/99 ushaji Added everyone, pweruser
//
//*************************************************************
BOOL MakeFileSecure (LPTSTR lpFile, DWORD dwOtherSids) { SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; SID_IDENTIFIER_AUTHORITY authWORLD = SECURITY_WORLD_SID_AUTHORITY; PACL pAcl = NULL; PSID psidSystem = NULL, psidAdmin = NULL, psidUsers = NULL, psidPowerUsers = NULL; PSID psidEveryOne = NULL; DWORD cbAcl, aceIndex; ACE_HEADER * lpAceHeader; BOOL bRetVal = FALSE; BOOL bAddPowerUsersAce=TRUE; BOOL bAddEveryOneAce=FALSE; DWORD dwAccMask;
//
// Get the system sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psidSystem)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to initialize system sid. Error = %d"), GetLastError())); goto Exit; }
//
// Get the Admin sid
//
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to initialize admin sid. Error = %d"), GetLastError())); goto Exit; }
//
// Get the users sid
//
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &psidUsers)) {
DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to initialize authenticated users sid. Error = %d"), GetLastError())); goto Exit; }
//
// Allocate space for the ACL
//
cbAcl = (2 * GetLengthSid (psidSystem)) + (2 * GetLengthSid (psidAdmin)) + (2 * GetLengthSid (psidUsers)) + sizeof(ACL) + (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
//
// Get the power users sid, if required.
// Don't fail if you don't get because it might not be available on DCs??
//
bAddPowerUsersAce = TRUE; if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0, 0, &psidPowerUsers)) {
DebugMsg((DM_WARNING, TEXT("AddPowerUserAce: Failed to initialize power users sid. Error = %d"), GetLastError())); bAddPowerUsersAce = FALSE; }
if (bAddPowerUsersAce) cbAcl += (2 * GetLengthSid (psidPowerUsers)) + (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
//
// Get the EveryOne sid, if required.
//
if (dwOtherSids & OTHERSIDS_EVERYONE) { bAddEveryOneAce = TRUE; if (!AllocateAndInitializeSid(&authWORLD, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &psidEveryOne)) {
DebugMsg((DM_WARNING, TEXT("AddPowerUserAce: Failed to initialize everyone sid. Error = %d"), GetLastError())); goto Exit; } }
if (bAddEveryOneAce) cbAcl += (2 * GetLengthSid (psidEveryOne)) + (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl); if (!pAcl) { goto Exit; }
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to initialize acl. Error = %d"), GetLastError())); goto Exit; }
//
// Add Aces. Non-inheritable ACEs first
//
aceIndex = 0; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, psidUsers)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
if (bAddPowerUsersAce) {
//
// By default give read permissions, otherwise give modify permissions
//
dwAccMask = (dwOtherSids & OTHERSIDS_POWERUSERS) ? (FILE_ALL_ACCESS ^ (WRITE_DAC | WRITE_OWNER)): (GENERIC_READ | GENERIC_EXECUTE);
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, dwAccMask, psidPowerUsers)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; } }
if (bAddEveryOneAce) { aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, psidEveryOne)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; } }
//
// Now the inheritable ACEs
//
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, psidUsers)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
if (bAddPowerUsersAce) { aceIndex++; dwAccMask = (dwOtherSids & OTHERSIDS_POWERUSERS) ? (FILE_ALL_ACCESS ^ (WRITE_DAC | WRITE_OWNER)): (GENERIC_READ | GENERIC_EXECUTE);
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, dwAccMask, psidPowerUsers)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE); }
if (bAddEveryOneAce) { aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, psidEveryOne)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError())); goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE); }
//
// Put together the security descriptor
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to initialize security descriptor. Error = %d"), GetLastError())); goto Exit; }
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to set security descriptor dacl. Error = %d"), GetLastError())); goto Exit; }
//
// Set the security
//
if (SetFileSecurity (lpFile, DACL_SECURITY_INFORMATION, &sd)) { bRetVal = TRUE; } else { DebugMsg((DM_WARNING, TEXT("MakeFileSecure: SetFileSecurity failed. Error = %d"), GetLastError())); }
Exit:
if (psidSystem) { FreeSid(psidSystem); }
if (psidAdmin) { FreeSid(psidAdmin); }
if (psidUsers) { FreeSid(psidUsers); }
if ((bAddPowerUsersAce) && (psidPowerUsers)) { FreeSid(psidPowerUsers); }
if ((bAddEveryOneAce) && (psidEveryOne)) { FreeSid(psidEveryOne); }
if (pAcl) { GlobalFree (pAcl); }
return bRetVal; }
//*************************************************************
//
// GetSpecialFolderPath()
//
// Purpose: Gets the path to the requested special folder
//
// Parameters: csid - CSIDL of the special folder
// lpPath - Path to place result in
// assumed to be MAX_PATH in size
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL GetSpecialFolderPath (INT csidl, LPTSTR lpPath) { BOOL bResult = FALSE; PSHELL32_API pShell32Api = NULL; HRESULT hr = E_FAIL;
if (SUCCEEDED(hr = HRESULT_FROM_WIN32(LoadShell32Api( &pShell32Api )))) { //
// Ask the shell for the folder location
//
bResult = pShell32Api->pfnShGetSpecialFolderPath (NULL, lpPath, csidl, TRUE); if (!bResult) { hr = HRESULT_FROM_WIN32(GetLastError()); } } if (!bResult) { DebugMsg((DM_WARNING, TEXT("GetSpecialFolderPath : ShGetSpecialFolderPath failed, hr = %08X\n"), hr)); }
return bResult; }
//*************************************************************
//
// GetFolderPath()
//
// Purpose: Gets the path to the requested special folder
//
// Parameters: csidl - CSIDL of the special folder
// lpPath - Path to place result in
// assumed to be MAX_PATH in size
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL GetFolderPath (INT csidl, HANDLE hToken, LPTSTR lpPath) { BOOL bResult = FALSE; PSHELL32_API pShell32Api = NULL; HRESULT hr = E_FAIL;
if (SUCCEEDED(hr = HRESULT_FROM_WIN32(LoadShell32Api( &pShell32Api )))) { //
// Ask the shell for the folder location
//
hr = pShell32Api->pfnShGetFolderPath (NULL, csidl | CSIDL_FLAG_CREATE, hToken, 0, lpPath); bResult = SUCCEEDED ( hr ); } if (!bResult) { DebugMsg((DM_WARNING, TEXT("GetFolderPath : ShGetFolderPath failed, hr = %08X\n"), hr)); }
return bResult; }
//*************************************************************
//
// SetFolderPath()
//
// Purpose: Sets the path to the requested special folder
//
// Parameters: csidl - CSIDL of the special folder
// lpPath - Path
// assumed to be MAX_PATH in size
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL SetFolderPath (INT csidl, HANDLE hToken, LPTSTR lpPath) { BOOL bResult = FALSE; PSHELL32_API pShell32Api = NULL; HRESULT hr = E_FAIL;
if (SUCCEEDED(hr = HRESULT_FROM_WIN32(LoadShell32Api( &pShell32Api )))) { //
// Set the shell folder location
//
hr = pShell32Api->pfnShSetFolderPath ( csidl | CSIDL_FLAG_DONT_UNEXPAND, hToken, 0, lpPath); bResult = SUCCEEDED ( hr ); } if (!bResult) { DebugMsg((DM_WARNING, TEXT("SetFolderPath : ShSetFolderPath failed, hr = %08X\n"), hr)); }
return bResult; }
//*************************************************************
//
// CenterWindow()
//
// Purpose: Centers a window on the screen
//
// Parameters: hwnd - window handle to center
//
// Return: void
//
// Comments:
//
// History: Date Author Comment
// 2/21/96 ericflo Ported
//
//*************************************************************
void CenterWindow (HWND hwnd) { RECT rect; LONG dx, dy; LONG dxParent, dyParent; LONG Style;
// Get window rect
GetWindowRect(hwnd, &rect);
dx = rect.right - rect.left; dy = rect.bottom - rect.top;
// Get parent rect
Style = GetWindowLong(hwnd, GWL_STYLE); if ((Style & WS_CHILD) == 0) {
// Return the desktop windows size (size of main screen)
dxParent = GetSystemMetrics(SM_CXSCREEN); dyParent = GetSystemMetrics(SM_CYSCREEN); } else { HWND hwndParent; RECT rectParent;
hwndParent = GetParent(hwnd); if (hwndParent == NULL) { hwndParent = GetDesktopWindow(); }
GetWindowRect(hwndParent, &rectParent);
dxParent = rectParent.right - rectParent.left; dyParent = rectParent.bottom - rectParent.top; }
// Centre the child in the parent
rect.left = (dxParent - dx) / 2; rect.top = (dyParent - dy) / 3;
// Move the child into position
SetWindowPos(hwnd, HWND_TOP, rect.left, rect.top, 0, 0, SWP_NOSIZE); }
//*************************************************************
//
// UnExpandSysRoot()
//
// Purpose: Unexpands the given path/filename to have %systemroot%
// if appropriate
//
// Parameters: lpFile - File to check
// lpResult - Result buffer
// cchResult - Result buffer size
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 2/23/96 ericflo Created
//
//*************************************************************
BOOL UnExpandSysRoot(LPCTSTR lpFile, LPTSTR lpResult, DWORD cchResult) { TCHAR szSysRoot[MAX_PATH]; LPTSTR lpFileName; DWORD dwSysLen; HRESULT hr;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("UnExpandSysRoot: Entering with <%s>"), lpFile ? lpFile : TEXT("NULL")));
if (!lpFile || !*lpFile) { DebugMsg((DM_VERBOSE, TEXT("UnExpandSysRoot: lpFile is NULL, setting lpResult to a null string"))); *lpResult = TEXT('\0'); return TRUE; }
//
// If the first part of lpFile is the expanded value of %SystemRoot%
// then we want to un-expand the environment variable.
//
hr = SafeExpandEnvironmentStrings (TEXT("%SystemRoot%"), szSysRoot, ARRAYSIZE(szSysRoot)); if (FAILED(hr)) { DebugMsg((DM_VERBOSE, TEXT("UnExpandSysRoot: ExpandEnvironmentString failed with error %d, setting szSysRoot to %systemroot% "), GetLastError())); StringCchCopy(lpResult, cchResult, lpFile); return FALSE; }
dwSysLen = lstrlen(szSysRoot);
//
// Make sure the source is long enough
//
if ((DWORD)lstrlen(lpFile) < dwSysLen) { StringCchCopy (lpResult, cchResult, lpFile); return TRUE; }
if (CompareString (LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, szSysRoot, dwSysLen, lpFile, dwSysLen) == CSTR_EQUAL) {
//
// The szReturn buffer starts with %systemroot%.
// Actually insert %systemroot% in the result buffer.
//
StringCchCopy (lpResult, cchResult, TEXT("%SystemRoot%")); StringCchCat (lpResult, cchResult, (lpFile + dwSysLen));
} else {
//
// The szReturn buffer does not start with %systemroot%
// just copy in the original string.
//
StringCchCopy (lpResult, cchResult, lpFile); }
DebugMsg((DM_VERBOSE, TEXT("UnExpandSysRoot: Leaving with <%s>"), lpResult));
return TRUE; }
//*************************************************************
//
// AllocAndExpandEnvironmentStrings()
//
// Purpose: Allocates memory for and returns pointer to buffer containing
// the passed string expanded.
//
// Parameters: lpszSrc - unexpanded string
//
// Return: Pointer to expanded string
// NULL if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/21/96 ericflo Ported
//
//*************************************************************
LPTSTR AllocAndExpandEnvironmentStrings(LPCTSTR lpszSrc) { LPTSTR String, Temp; LONG LengthAllocated; LONG LengthCopied;
//
// Pick a random buffer length, if it's not big enough reallocate
// it and try again until it is.
//
LengthAllocated = lstrlen(lpszSrc) + 60;
String = LocalAlloc(LPTR, LengthAllocated * sizeof(TCHAR)); if (String == NULL) { DebugMsg((DM_WARNING, TEXT("AllocAndExpandEnvironmentStrings: Failed to allocate %d bytes for string"), LengthAllocated * sizeof(TCHAR))); return(NULL); }
while (TRUE) {
LengthCopied = ExpandEnvironmentStrings( lpszSrc, String, LengthAllocated ); if (LengthCopied == 0) { DebugMsg((DM_WARNING, TEXT("AllocAndExpandEnvironmentStrings: ExpandEnvironmentStrings failed, error = %d"), GetLastError())); LocalFree(String); String = NULL; break; }
//
// If the buffer was too small, make it bigger and try again
//
if (LengthCopied > LengthAllocated) {
Temp = LocalReAlloc(String, LengthCopied * sizeof(TCHAR), LMEM_MOVEABLE);
if (Temp == NULL) { DebugMsg((DM_WARNING, TEXT("AllocAndExpandEnvironmentStrings: Failed to reallocate %d bytes for string"), LengthAllocated * sizeof(TCHAR))); LocalFree(String); String = NULL; break; }
LengthAllocated = LengthCopied; String = Temp;
//
// Go back and try to expand the string again
//
} else {
//
// Success!
//
break; }
}
return(String); }
//*************************************************************
//
// IntToString
//
// Purpose: TCHAR version of itoa
//
// Parameters: INT i - integer to convert
// LPTSTR sz - pointer where to put the result
//
// Return: void
//
//*************************************************************
void IntToString( INT i, LPTSTR sz) { TCHAR szTemp[CCH_MAX_DEC]; int iChr;
iChr = 0;
do { szTemp[iChr++] = TEXT('0') + (i % 10); i = i / 10; } while (i != 0);
do { iChr--; *sz++ = szTemp[iChr]; } while (iChr != 0);
*sz++ = TEXT('\0'); }
//*************************************************************
//
// IsUserAGuest()
//
// Purpose: Determines if the user is a member of the guest group.
//
// Parameters: hToken - User's token
//
// Return: TRUE if user is a guest
// FALSE if not
// Comments:
//
// History: Date Author Comment
// 7/25/95 ericflo Created
//
//*************************************************************
BOOL IsUserAGuest(HANDLE hToken) { SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; NTSTATUS Status; BOOL FoundGuests=FALSE; PSID pGuestSid=NULL, pDomainGuestSid=NULL, psidUser=NULL; HANDLE hImpToken = NULL;
//
// Create Guests sid.
//
Status = RtlAllocateAndInitializeSid( &authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS, 0, 0, 0, 0, 0, 0, &pGuestSid );
if (Status != STATUS_SUCCESS) { DebugMsg((DM_WARNING, TEXT("IsUserAGuest: RtlAllocateAndInitializeSid failed with error 0x%x"), Status)); goto Exit; }
if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY, NULL, SecurityImpersonation, TokenImpersonation, &hImpToken)) { DebugMsg((DM_WARNING, TEXT("IsUserAGuest: DuplicateTokenEx failed with error %d"), GetLastError())); hImpToken = NULL; goto Exit; }
if (!CheckTokenMembership(hImpToken, pGuestSid, &FoundGuests)) { DebugMsg((DM_WARNING, TEXT("IsUserAGuest: CheckTokenMembership failed for GuestSid with error %d"), GetLastError())); }
if (!FoundGuests) { //
// Get the user's sid
//
psidUser = GetUserSid(hToken);
if (!psidUser) { DebugMsg((DM_WARNING, TEXT("MakeRegKeySecure: Failed to get user sid"))); goto Exit; }
//
// Create Domain Guests sid.
//
Status = GetDomainSidFromDomainRid( psidUser, DOMAIN_GROUP_RID_GUESTS, &pDomainGuestSid);
if (Status != STATUS_SUCCESS) { DebugMsg((DM_WARNING, TEXT("IsUserAGuest: GetDomainSidFromDomainRid failed with error 0x%x"), Status)); goto Exit; }
if (!CheckTokenMembership(hImpToken, pDomainGuestSid, &FoundGuests)) { DebugMsg((DM_WARNING, TEXT("IsUserAGuest: CheckTokenMembership failed for DomainGuestSid with error %d"), GetLastError())); } }
//
// Tidy up
//
Exit:
if (pGuestSid) RtlFreeSid(pGuestSid);
if (pDomainGuestSid) RtlFreeSid(pDomainGuestSid);
if (psidUser) DeleteUserSid (psidUser);
if (hImpToken) CloseHandle(hImpToken);
return(FoundGuests); }
//*************************************************************
//
// IsUserAnAdminMember()
//
// Purpose: Determines if the user is a member of the administrators group.
//
// Parameters: hToken - User's token
//
// Return: TRUE if user is a admin
// FALSE if not
// Comments:
//
// History: Date Author Comment
// 7/25/95 ericflo Created
//
//*************************************************************
BOOL IsUserAnAdminMember(HANDLE hToken) { SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; NTSTATUS Status; BOOL FoundAdmins = FALSE; PSID AdminsDomainSid=NULL; HANDLE hImpToken = NULL;
//
// Create Admins domain sid.
//
Status = RtlAllocateAndInitializeSid( &authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminsDomainSid );
if (Status == STATUS_SUCCESS) {
//
// Test if user is in the Admins domain
//
if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY, NULL, SecurityImpersonation, TokenImpersonation, &hImpToken)) { DebugMsg((DM_WARNING, TEXT("IsUserAnAdminMember: DuplicateTokenEx failed with error %d"), GetLastError())); FoundAdmins = FALSE; hImpToken = NULL; goto Exit; }
if (!CheckTokenMembership(hImpToken, AdminsDomainSid, &FoundAdmins)) { DebugMsg((DM_WARNING, TEXT("IsUserAnAdminmember: CheckTokenMembership failed for AdminsDomainSid with error %d"), GetLastError())); FoundAdmins = FALSE; } }
//
// Tidy up
//
Exit:
if (hImpToken) CloseHandle(hImpToken);
if (AdminsDomainSid) RtlFreeSid(AdminsDomainSid);
return(FoundAdmins); }
//*************************************************************
//
// IsUserALocalSystemMember()
//
// Purpose: Determines if the user is a member of the Local system group.
//
// Parameters: hToken - User's token
//
// Return: TRUE if user is a local system
// FALSE if not
// Comments:
//
// History: Date Author Comment
// 9/22/00 santanuc created
//
//*************************************************************
BOOL IsUserALocalSystemMember(HANDLE hToken) { SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; NTSTATUS Status; BOOL FoundLocalSystem = FALSE; PSID LocalSystemSid=NULL; HANDLE hImpToken = NULL;
//
// Create Local system sid.
//
Status = RtlAllocateAndInitializeSid( &authNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &LocalSystemSid );
if (Status == STATUS_SUCCESS) {
//
// Test if user is in the Local system
//
if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY, NULL, SecurityImpersonation, TokenImpersonation, &hImpToken)) { DebugMsg((DM_WARNING, TEXT("IsUserAGuest: DuplicateTokenEx failed with error %d"), GetLastError())); FoundLocalSystem = FALSE; hImpToken = NULL; goto Exit; }
if (!CheckTokenMembership(hImpToken, LocalSystemSid, &FoundLocalSystem)) { DebugMsg((DM_WARNING, TEXT("IsUserAnAdminmember: CheckTokenMembership failed for LocalSystemSid with error %d"), GetLastError())); FoundLocalSystem = FALSE; } }
//
// Tidy up
//
Exit:
if (hImpToken) CloseHandle(hImpToken);
if (LocalSystemSid) RtlFreeSid(LocalSystemSid);
return(FoundLocalSystem); }
//*************************************************************
//
// IsUserAnInteractiveUser()
//
// Purpose: Determines if the user is interactively logged on.
//
// Parameters: hToken - User's token
//
// Return: TRUE if user is logged on interactively
// FALSE if not
// Comments:
//
//*************************************************************
BOOL IsUserAnInteractiveUser(HANDLE hToken) { SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; BOOL bInteractive = FALSE; PSID pInteractiveSid=NULL; HANDLE hImpToken = NULL;
//
// Create Admins domain sid.
//
if (AllocateAndInitializeSid(&authNT, 1, SECURITY_INTERACTIVE_RID, 0, 0, 0, 0, 0, 0, 0, &pInteractiveSid)) {
//
// Test if user is interactive
//
if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY, NULL, SecurityImpersonation, TokenImpersonation, &hImpToken)) { DebugMsg((DM_WARNING, TEXT("IsUserAnInteractiveUser: DuplicateTokenEx failed with error %d"), GetLastError())); bInteractive = FALSE; hImpToken = NULL; goto Exit; }
if (!CheckTokenMembership(hImpToken, pInteractiveSid, &bInteractive)) { DebugMsg((DM_WARNING, TEXT("IsUserAnInteractiveUser: CheckTokenMembership failed for InteractiveSid with error %d"), GetLastError())); bInteractive = FALSE; } } else { DebugMsg((DM_WARNING, TEXT("IsUserAnInteractiveUser: AllocateAndInitializeSid failed for InteractiveSid with error %d"), GetLastError())); }
//
// Tidy up
//
Exit:
if (hImpToken) CloseHandle(hImpToken);
if (pInteractiveSid) FreeSid(pInteractiveSid);
return(bInteractive); }
//*************************************************************
//
// CheckUserInMachineForest()
//
// Purpose: Determines if the user is from the same forest
// as the computer this code is running on.
//
// Parameters: hToken - User's token
//
// Return: ERROR_SUCCESS if successful
// <error> code if not.
// Comments:
//
//*************************************************************
DWORD CheckUserInMachineForest(HANDLE hToken, BOOL* pbInMachineForest) { DWORD dwResult = ERROR_SUCCESS; HANDLE hOldToken = NULL; LPWSTR szUserDomainName = NULL; PDS_DOMAIN_TRUSTS pDomainTrusts = NULL; ULONG ulDomainCount = 0; ULONG ulCount = 0;
if ( (hToken == NULL) || (pbInMachineForest == NULL) ) { return ERROR_INVALID_PARAMETER; }
// Default to this
*pbInMachineForest = FALSE;
// Query for the user's domain name
if (!ImpersonateUser(hToken, &hOldToken)) { dwResult = GetLastError(); DebugMsg((DM_WARNING, TEXT("CheckUserInMachineForest: Failed to impersonate user with %d."), dwResult)); goto Exit; }
szUserDomainName = MyGetDomainDNSName ();
RevertToUser(&hOldToken);
if ( szUserDomainName == NULL ) { dwResult = GetLastError(); DebugMsg((DM_WARNING, TEXT("CheckUserInMachineForest: MyGetDomainName failed with %d."), dwResult)); goto Exit; }
// Now get the list of trusted domains for this machine
dwResult = DsEnumerateDomainTrusts( NULL, DS_DOMAIN_IN_FOREST, &pDomainTrusts, &ulDomainCount ); if ( dwResult != NO_ERROR ) { pDomainTrusts = NULL; DebugMsg((DM_WARNING, TEXT("CheckUserInMachineForest: Failed to enumerate forest domains with %d."), dwResult)); goto Exit; }
dwResult = ERROR_SUCCESS;
for ( ulCount = 0; ulCount < ulDomainCount; ulCount++ ) { if ( DnsNameCompare_W(szUserDomainName, pDomainTrusts[ulCount].DnsDomainName) ) { *pbInMachineForest = TRUE; goto Exit; } }
Exit: if ( szUserDomainName != NULL ) { LocalFree( szUserDomainName ); }
if ( pDomainTrusts != NULL ) { NetApiBufferFree( pDomainTrusts ); }
return dwResult; }
//*************************************************************
//
// MakeRegKeySecure()
//
// Purpose: Sets the security for the key give so that
// the admin and os having full control with the
// user having read / execute.
//
// Parameters: hToken - User's token or null for "everyone"
// hKeyRoot - Key to the root of the hive
// lpKeyName - Key to secure
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 5/7/97 ericflo Created
//
//*************************************************************
BOOL MakeRegKeySecure(HANDLE hToken, HKEY hKeyRoot, LPTSTR lpKeyName) { DWORD Error, dwDisp; HKEY hSubKey; SECURITY_DESCRIPTOR sd; SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; PACL pAcl = NULL; PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL; DWORD cbAcl, AceIndex; ACE_HEADER * lpAceHeader; BOOL bRetVal = FALSE;
//
// Create the security descriptor that will be applied to the key
//
if (hToken) {
//
// Get the user's sid
//
psidUser = GetUserSid(hToken);
if (!psidUser) { DebugMsg((DM_WARNING, TEXT("MakeRegKeySecure: Failed to get user sid"))); return FALSE; }
} else {
//
// Get the authenticated users sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0, &psidUser)) {
DebugMsg((DM_WARNING, TEXT("MakeRegKeySecure: Failed to initialize authenticated users sid. Error = %d"), GetLastError())); return FALSE; } }
//
// Get the system sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psidSystem)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to initialize system sid. Error = %d"), GetLastError())); goto Exit; }
//
// Get the admin sid
//
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to initialize admin sid. Error = %d"), GetLastError())); goto Exit; }
//
// Allocate space for the ACL
//
cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) + (2 * GetLengthSid (psidAdmin)) + sizeof(ACL) + (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl); if (!pAcl) { goto Exit; }
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to initialize acl. Error = %d"), GetLastError())); goto Exit; }
//
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
//
AceIndex = 0; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidUser)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to add ace for user. Error = %d"), GetLastError())); goto Exit; }
AceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to add ace for system. Error = %d"), GetLastError())); goto Exit; }
AceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to add ace for admin. Error = %d"), GetLastError())); goto Exit; }
//
// Now the inheritable ACEs
//
AceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidUser)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to add ace for user. Error = %d"), GetLastError())); goto Exit; }
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError())); goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
AceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to add ace for system. Error = %d"), GetLastError())); goto Exit; }
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError())); goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
AceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to add ace for admin. Error = %d"), GetLastError())); goto Exit; }
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to get ace (%d). Error = %d"), AceIndex, GetLastError())); goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
//
// Put together the security descriptor
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to initialize security descriptor. Error = %d"), GetLastError())); goto Exit; }
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) { DebugMsg((DM_VERBOSE, TEXT("MakeRegKeySecure: Failed to set security descriptor dacl. Error = %d"), GetLastError())); goto Exit; }
//
// Open the registry key
//
Error = RegCreateKeyEx(hKeyRoot, lpKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, WRITE_DAC, NULL, &hSubKey, &dwDisp);
if (Error == ERROR_SUCCESS) {
Error = RegSetKeySecurity (hSubKey, DACL_SECURITY_INFORMATION, &sd);
if (Error == ERROR_SUCCESS) { bRetVal = TRUE; } else { DebugMsg((DM_WARNING, TEXT("MakeRegKeySecure: Failed to set security, error = %d"), Error)); }
RegCloseKey(hSubKey);
} else { DebugMsg((DM_WARNING, TEXT("MakeRegKeySecure: Failed to open registry key, error = %d"), Error)); }
Exit:
//
// Free the sids and acl
//
if (psidUser) { if (hToken) { DeleteUserSid (psidUser); } else { FreeSid (psidUser); } }
if (psidSystem) { FreeSid(psidSystem); }
if (psidAdmin) { FreeSid(psidAdmin); }
if (pAcl) { GlobalFree (pAcl); }
return(bRetVal); }
//*************************************************************
//
// FlushSpecialFolderCache()
//
// Purpose: Flushes the special folder cache in the shell
//
// Parameters: none
//
// Comments: Shell32.dll caches the special folder pidls
// but since winlogon never goes away, it is possible
// for one user's pidls to be used for another user
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
typedef VOID (*PFNSHFLUSHSFCACHE)(VOID);
BOOL FlushSpecialFolderCache (void) { HINSTANCE hInstDLL; PFNSHFLUSHSFCACHE pfnSHFlushSFCache; BOOL bResult = FALSE;
hInstDLL = LoadLibraryA ("shell32.dll");
if (hInstDLL) {
pfnSHFlushSFCache = (PFNSHFLUSHSFCACHE)GetProcAddress (hInstDLL, MAKEINTRESOURCEA(526));
if (pfnSHFlushSFCache) { pfnSHFlushSFCache(); bResult = TRUE; }
FreeLibrary (hInstDLL); }
return bResult; }
//*************************************************************
//
// CheckForVerbosePolicy()
//
// Purpose: Checks if the user has requested verbose
// output of policy to the eventlog
//
// Parameters: None
//
// Return: TRUE if we should be verbose
// FALSE if not
//
//*************************************************************
BOOL CheckForVerbosePolicy (void) { DWORD dwSize, dwType; BOOL bVerbose = FALSE; HKEY hKey; LONG lResult;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, DIAGNOSTICS_KEY, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
dwSize = sizeof(bVerbose); if (RegQueryValueEx (hKey, DIAGNOSTICS_POLICY_VALUE, NULL, &dwType, (LPBYTE) &bVerbose, &dwSize) != ERROR_SUCCESS) { RegQueryValueEx (hKey, DIAGNOSTICS_GLOBAL_VALUE, NULL, &dwType, (LPBYTE) &bVerbose, &dwSize); }
RegCloseKey (hKey); }
return bVerbose; }
//*************************************************************
//
// int ExtractCSIDL()
//
// Purpose: Extract the CSIDL from the given string which
// should under the form ::0x0000::path1\path2\...\ // pathn\file.ext, where 0x0000 is any valid CSIDL
//
// Parameters: pcszPath - Path containing or not a CSIDL
// ppszUsualPath - pointer to first characvter of
// usual path
//
// Return: CSIDL if successful
// -1 if no CSIDL in path
//
// Comments: The ::0x0000:: must be at the beginning and not
// preceded by any other character and not followed
// by any either (other than the usual path)
//
// History: Date Author Comment
// 6/9/98 stephstm Created
//
//*************************************************************
int ExtractCSIDL(LPCTSTR pcszPath, LPTSTR* ppszUsualPath) { int nRV=-1;
if (NULL != ppszUsualPath) { if (TEXT(':') == *pcszPath && TEXT(':') == *(pcszPath+1) && TEXT(':') == *(pcszPath+8) && TEXT(':') == *(pcszPath+9)) {//looks good
//+4 to skip "::0x"
nRV = HexStringToUInt(pcszPath+4); *ppszUsualPath = (LPTSTR)(pcszPath+10); } else {//no CSIDL in this path
//the whole path is a usual path
*ppszUsualPath = (LPTSTR)pcszPath; } } else { DebugMsg((DM_VERBOSE, TEXT("ExtractCSIDL: ppszUsualPath ptr is NULL."))); } return nRV; }
//*************************************************************
//
// MyGetDomainDNSName()
//
// Purpose: Gets the user's domain dns name
//
// Parameters: void
//
// Return: lpDomain if successful
// NULL if an error occurs
//
//*************************************************************
LPTSTR MyGetDomainDNSName (VOID) { LPTSTR lpTemp, lpDomain;
//
// Get the username in DNS format. It will return it in
// dnsdomainname\username
//
lpDomain = MyGetUserName (NameDnsDomain);
if (!lpDomain) { DebugMsg((DM_WARNING, TEXT("MyGetDomainName: MyGetUserName failed for dns domain name with %d"), GetLastError())); return NULL; }
//
// Look for the \ between the domain and username and replace
// it with a NULL
//
lpTemp = lpDomain;
while (*lpTemp && ((*lpTemp) != TEXT('\\'))) lpTemp++;
if (*lpTemp != TEXT('\\')) { DebugMsg((DM_WARNING, TEXT("GetUserAndDomainNames: Failed to find slash in dns style name: <%s>"), lpDomain)); SetLastError(ERROR_INVALID_DATA); LocalFree (lpDomain); return NULL; }
*lpTemp = TEXT('\0');
return lpDomain; }
//*************************************************************
//
// MyGetUserName()
//
// Purpose: Gets the user name in the requested format
//
// Parameters: NameFormat - GetUserNameEx naming format
//
// Return: lpUserName if successful
// NULL if an error occurs
//
//*************************************************************
LPTSTR MyGetUserName (EXTENDED_NAME_FORMAT NameFormat) { DWORD dwCount = 0, dwError = ERROR_SUCCESS; LPTSTR lpUserName = NULL, lpTemp; ULONG ulUserNameSize; PSECUR32_API pSecur32;
//
// Load secur32.dll
//
pSecur32 = LoadSecur32();
if (!pSecur32) { DebugMsg((DM_WARNING, TEXT("MyGetUserName: Failed to load Secur32."))); return NULL; }
//
// Allocate a buffer for the user name
//
ulUserNameSize = 75;
if (NameFormat == NameFullyQualifiedDN) { ulUserNameSize = 200; }
lpUserName = LocalAlloc (LPTR, ulUserNameSize * sizeof(TCHAR));
if (!lpUserName) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("MyGetUserName: Failed to allocate memory with %d"), dwError)); goto Exit; }
//
// Get the username in the requested format
//
while (TRUE) {
if (pSecur32->pfnGetUserNameEx (NameFormat, lpUserName, &ulUserNameSize)) {
dwError = ERROR_SUCCESS; goto Exit;
} else {
//
// Get the error code
//
dwError = GetLastError();
//
// If the call failed due to insufficient memory, realloc
// the buffer and try again. Otherwise, check the pass
// count and retry if appropriate.
//
if ((dwError == ERROR_INSUFFICIENT_BUFFER) || (dwError == ERROR_MORE_DATA)) {
lpTemp = LocalReAlloc (lpUserName, (ulUserNameSize * sizeof(TCHAR)), LMEM_MOVEABLE);
if (!lpTemp) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("MyGetUserName: Failed to realloc memory with %d"), dwError)); LocalFree (lpUserName); lpUserName = NULL; goto Exit; }
lpUserName = lpTemp;
} else if ((dwError == ERROR_NONE_MAPPED) || (dwError == ERROR_NETWORK_UNREACHABLE)) { LocalFree (lpUserName); lpUserName = NULL; goto Exit;
} else {
DebugMsg((DM_WARNING, TEXT("MyGetUserName: GetUserNameEx failed with %d."), dwError));
dwCount++;
if (dwCount > 3) { LocalFree (lpUserName); lpUserName = NULL; goto Exit; }
DebugMsg((DM_VERBOSE, TEXT("MyGetUserName: Retrying call to GetUserNameEx in 1/2 second.")));
Sleep(500); } } }
Exit:
SetLastError(dwError);
return lpUserName; }
//*************************************************************
//
// MyGetUserNameEx()
//
// Purpose: Gets the user name in the requested format
//
// Parameters: NameFormat - GetUserNameEx naming format
//
// Return: lpUserName if successful
// NULL if an error occurs
//
//*************************************************************
LPTSTR MyGetUserNameEx (EXTENDED_NAME_FORMAT NameFormat) { DWORD dwCount = 0, dwError = ERROR_SUCCESS; LPTSTR lpUserName = NULL, lpTemp; ULONG ulUserNameSize; PSECUR32_API pSecur32;
//
// Load secur32.dll
//
pSecur32 = LoadSecur32();
if (!pSecur32) { DebugMsg((DM_WARNING, TEXT("MyGetUserNameEx: Failed to load Secur32."))); return NULL; }
//
// Allocate a buffer for the user name
//
ulUserNameSize = 75;
if (NameFormat == NameFullyQualifiedDN) { ulUserNameSize = 200; }
lpUserName = LocalAlloc (LPTR, ulUserNameSize * sizeof(TCHAR));
if (!lpUserName) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("MyGetUserNameEx: Failed to allocate memory with %d"), dwError)); goto Exit; }
//
// Get the username in the requested format
//
if (!pSecur32->pfnGetUserNameEx (NameFormat, lpUserName, &ulUserNameSize)) {
//
// If the call failed due to insufficient memory, realloc
// the buffer and try again. Otherwise, exit now.
//
dwError = GetLastError();
if ((dwError != ERROR_INSUFFICIENT_BUFFER) && (dwError != ERROR_MORE_DATA)) { LocalFree (lpUserName); lpUserName = NULL; goto Exit; }
lpTemp = LocalReAlloc (lpUserName, (ulUserNameSize * sizeof(TCHAR)), LMEM_MOVEABLE);
if (!lpTemp) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("MyGetUserNameEx: Failed to realloc memory with %d"), dwError)); LocalFree (lpUserName); lpUserName = NULL; goto Exit; }
lpUserName = lpTemp;
if (!pSecur32->pfnGetUserNameEx (NameFormat, lpUserName, &ulUserNameSize)) { dwError = GetLastError(); LocalFree (lpUserName); lpUserName = NULL; goto Exit; }
dwError = ERROR_SUCCESS; }
Exit:
SetLastError(dwError);
return lpUserName; }
//*************************************************************
//
// MyGetComputerName()
//
// Purpose: Gets the computer name in the requested format
//
// Parameters: NameFormat - GetComputerObjectName naming format
//
// Return: lpComputerName if successful
// NULL if an error occurs
//
//*************************************************************
LPTSTR MyGetComputerName (EXTENDED_NAME_FORMAT NameFormat) { DWORD dwError = ERROR_SUCCESS; LPTSTR lpComputerName = NULL, lpTemp; ULONG ulComputerNameSize; PSECUR32_API pSecur32;
//
// Load secur32.dll
//
pSecur32 = LoadSecur32();
if (!pSecur32) { DebugMsg((DM_WARNING, TEXT("MyGetComputerName: Failed to load Secur32."))); return NULL; }
//
// Allocate a buffer for the computer name
//
ulComputerNameSize = 75;
if (NameFormat == NameFullyQualifiedDN) { ulComputerNameSize = 200; }
lpComputerName = LocalAlloc (LPTR, ulComputerNameSize * sizeof(TCHAR));
if (!lpComputerName) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("MyGetComputerName: Failed to allocate memory with %d"), dwError)); goto Exit; }
//
// Get the computer name in the requested format
//
if (!pSecur32->pfnGetComputerObjectName (NameFormat, lpComputerName, &ulComputerNameSize)) {
//
// If the call failed due to insufficient memory, realloc
// the buffer and try again. Otherwise, exit now.
//
dwError = GetLastError();
if (dwError != ERROR_INSUFFICIENT_BUFFER) { LocalFree (lpComputerName); lpComputerName = NULL; goto Exit; }
lpTemp = LocalReAlloc (lpComputerName, (ulComputerNameSize * sizeof(TCHAR)), LMEM_MOVEABLE);
if (!lpTemp) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("MyGetComputerName: Failed to realloc memory with %d"), dwError)); LocalFree (lpComputerName); lpComputerName = NULL; goto Exit; }
lpComputerName = lpTemp;
if (!pSecur32->pfnGetComputerObjectName (NameFormat, lpComputerName, &ulComputerNameSize)) { dwError = GetLastError(); LocalFree (lpComputerName); lpComputerName = NULL; goto Exit; }
dwError = ERROR_SUCCESS; }
Exit:
SetLastError(dwError);
return lpComputerName; }
//*************************************************************
//
// ImpersonateUser()
//
// Purpose: Impersonates the specified user
//
// Parameters: hToken - user to impersonate
//
// Return: hToken if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL ImpersonateUser (HANDLE hNewUser, HANDLE *hOldUser) { DWORD dwErr; if (!OpenThreadToken (GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_READ, TRUE, hOldUser)) { *hOldUser = NULL; dwErr = GetLastError(); if (dwErr != ERROR_NO_TOKEN) { DebugMsg((DM_VERBOSE, TEXT("ImpersonateUser: Failed to open thread token with %d."), dwErr)); return FALSE; } }
if (!ImpersonateLoggedOnUser(hNewUser)) { if ( *hOldUser ) { CloseHandle( *hOldUser ); *hOldUser = NULL; } DebugMsg((DM_VERBOSE, TEXT("ImpersonateUser: Failed to impersonate user with %d."), GetLastError())); return FALSE; }
return TRUE; }
//*************************************************************
//
// RevertToUser()
//
// Purpose: Revert back to original user
//
// Parameters: hUser - original user token
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL RevertToUser (HANDLE *hUser) { BOOL bRetVal;
bRetVal = SetThreadToken(NULL, *hUser);
if (!bRetVal) { DebugMsg((DM_WARNING, TEXT("RevertToUser: SetThreadToken failed with %d."), GetLastError())); }
if (*hUser) { CloseHandle (*hUser); *hUser = NULL; }
return bRetVal; }
//*************************************************************
//
// GuidToString, StringToGuid, ValidateGuid, CompareGuid()
//
// Purpose: Guid utility functions
//
//*************************************************************
//
// Length in chars of string form of guid {44cffeec-79d0-11d2-a89d-00c04fbbcfa2}
//
#define GUID_LENGTH 38
void GuidToStringEx( const GUID *pGuid, TCHAR * szValue, UINT cchValue) { StringCchPrintf( szValue, cchValue, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"), pGuid->Data1, pGuid->Data2, pGuid->Data3, pGuid->Data4[0], pGuid->Data4[1], pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7] ); }
void GuidToString( const GUID *pGuid, TCHAR * szValue) {
//
// Assume the buffer is big enough (39 chars) to hold the string,
// try to use GuidToStringEx() instead!!!
//
StringCchPrintf( szValue, GUID_LENGTH + 1, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"), pGuid->Data1, pGuid->Data2, pGuid->Data3, pGuid->Data4[0], pGuid->Data4[1], pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7] ); }
void StringToGuid( TCHAR * szValue, GUID * pGuid ) { WCHAR wc; INT i;
//
// If the first character is a '{', skip it
//
if ( szValue[0] == L'{' ) szValue++;
//
// Since szValue may be used again, no permanent modification to
// it is be made.
//
wc = szValue[8]; szValue[8] = 0; pGuid->Data1 = wcstoul( &szValue[0], 0, 16 ); szValue[8] = wc; wc = szValue[13]; szValue[13] = 0; pGuid->Data2 = (USHORT)wcstoul( &szValue[9], 0, 16 ); szValue[13] = wc; wc = szValue[18]; szValue[18] = 0; pGuid->Data3 = (USHORT)wcstoul( &szValue[14], 0, 16 ); szValue[18] = wc;
wc = szValue[21]; szValue[21] = 0; pGuid->Data4[0] = (unsigned char)wcstoul( &szValue[19], 0, 16 ); szValue[21] = wc; wc = szValue[23]; szValue[23] = 0; pGuid->Data4[1] = (unsigned char)wcstoul( &szValue[21], 0, 16 ); szValue[23] = wc;
for ( i = 0; i < 6; i++ ) { wc = szValue[26+i*2]; szValue[26+i*2] = 0; pGuid->Data4[2+i] = (unsigned char)wcstoul( &szValue[24+i*2], 0, 16 ); szValue[26+i*2] = wc; } }
BOOL ValidateGuidPrefix( TCHAR *szValue) // This function is different from ValidateGuid in only one case. szValue is checked to be prefixed with Guid.
{ //
// Check if szValue is of form {19e02dd6-79d2-11d2-a89d-00c04fbbcfa2}
//
// Fixing bug 570352
DWORD i;
if ( lstrlen(szValue) < GUID_LENGTH ) // this function is different from ValidateGuid here.
return FALSE;
if ( szValue[0] != TEXT('{') || szValue[9] != TEXT('-') || szValue[14] != TEXT('-') || szValue[19] != TEXT('-') || szValue[24] != TEXT('-') || szValue[37] != TEXT('}') ) { return FALSE; } for ( i = 0; (i <= 37); i++ ) { if ( i != 0 && i != 9 && i != 14 && i != 19 && i != 24 && i != 37 ) { // it shld be between 0-9 or A-F or a-f
if (szValue[i] >= L'0' && szValue[i] <= L'9') continue;
if (szValue[i] >= L'a' && szValue[i] <= L'f') continue; if (szValue[i] >= L'A' && szValue[i] <= L'F') continue;
return FALSE; // It is here because of invalid character in the string
} } return TRUE; }
BOOL ValidateGuid( TCHAR *szValue ) { //
// Check if szValue is of form {19e02dd6-79d2-11d2-a89d-00c04fbbcfa2}
//
// Fixing bug 570352
DWORD i;
if ( lstrlen(szValue) != GUID_LENGTH ) return FALSE;
return ValidateGuidPrefix(szValue); }
INT CompareGuid( GUID * pGuid1, GUID * pGuid2 ) { INT i;
if ( pGuid1->Data1 != pGuid2->Data1 ) return ( pGuid1->Data1 < pGuid2->Data1 ? -1 : 1 );
if ( pGuid1->Data2 != pGuid2->Data2 ) return ( pGuid1->Data2 < pGuid2->Data2 ? -1 : 1 );
if ( pGuid1->Data3 != pGuid2->Data3 ) return ( pGuid1->Data3 < pGuid2->Data3 ? -1 : 1 );
for ( i = 0; i < 8; i++ ) { if ( pGuid1->Data4[i] != pGuid2->Data4[i] ) return ( pGuid1->Data4[i] < pGuid2->Data4[i] ? -1 : 1 ); }
return 0; }
//*************************************************************
//
// RegCleanUpValue()
//
// Purpose: Removes the target value and if no more values / keys
// are present, removes the key. This function then
// works up the parent tree removing keys if they are
// also empty. If any parent key has a value / subkey,
// it won't be removed.
//
// Parameters: hKeyRoot - Root key
// lpSubKey - SubKey
// lpValueName - Value to remove
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL RegCleanUpValue (HKEY hKeyRoot, LPTSTR lpSubKey, LPTSTR lpValueName) { TCHAR szDelKey[2 * MAX_PATH]; LPTSTR lpEnd; DWORD dwKeys, dwValues; LONG lResult; HKEY hKey;
//
// Make a copy of the subkey so we can write to it.
//
if (FAILED(StringCchCopy (szDelKey, ARRAYSIZE(szDelKey), lpSubKey))) { DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to copy value name."))); return FALSE; }
//
// First delete the value
//
lResult = RegOpenKeyEx (hKeyRoot, szDelKey, 0, KEY_WRITE, &hKey);
if (lResult == ERROR_SUCCESS) { lResult = RegDeleteValue (hKey, lpValueName);
RegCloseKey (hKey);
if (lResult != ERROR_SUCCESS) { if (lResult != ERROR_FILE_NOT_FOUND) { DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to delete value <%s> with %d."), lpValueName, lResult)); return FALSE; } } }
//
// Now loop through each of the parents. If the parent is empty
// eg: no values and no other subkeys, then remove the parent and
// keep working up.
//
lpEnd = szDelKey + lstrlen(szDelKey) - 1;
while (lpEnd >= szDelKey) {
//
// Find the parent key
//
while ((lpEnd > szDelKey) && (*lpEnd != TEXT('\\'))) lpEnd--;
//
// Open the key
//
lResult = RegOpenKeyEx (hKeyRoot, szDelKey, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) { if (lResult == ERROR_FILE_NOT_FOUND) { goto LoopAgain; } else { DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to open key <%s> with %d."), szDelKey, lResult)); return FALSE; } }
//
// See if there any any values / keys
//
lResult = RegQueryInfoKey (hKey, NULL, NULL, NULL, &dwKeys, NULL, NULL, &dwValues, NULL, NULL, NULL, NULL);
RegCloseKey (hKey);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to query key <%s> with %d."), szDelKey, lResult)); return FALSE; }
//
// Exit now if this key has values or keys
//
if ((dwKeys != 0) || (dwValues != 0)) { return TRUE; }
RegDeleteKey (hKeyRoot, szDelKey);
LoopAgain: //
// If we are at the beginning of the subkey, we can leave now.
//
if (lpEnd == szDelKey) { return TRUE; }
//
// There is a parent key. Remove the slash and loop again.
//
if (*lpEnd == TEXT('\\')) { *lpEnd = TEXT('\0'); } }
return TRUE; }
//*************************************************************
//
// InitializePingCritSec()
//
// Purpose: Initializes a CRITICAL_SECTION for pinging
// computers
//
// Parameters: none
//
//
// Return: ERROR_SUCCESS if successful
// An error if it fails.
//
//*************************************************************
DWORD InitializePingCritSec( void ) { CRITICAL_SECTION *pCritSec = NULL; DWORD result = ERROR_SUCCESS; BOOL fInitialized = FALSE; CRITICAL_SECTION *pInitial;
// If the critical section already exists, return.
if (g_PingCritSec != NULL) return ERROR_SUCCESS;
// Allocate memory for the critial section.
pCritSec = (CRITICAL_SECTION *) LocalAlloc( LMEM_FIXED, sizeof(CRITICAL_SECTION) ); if (pCritSec == NULL) { result = ERROR_NOT_ENOUGH_MEMORY; goto Exit; }
// Initialize the critical section. Using the flag 0x80000000
// preallocates the event so that EnterCriticalSection can only
// throw timeout exceptions.
__try { if (!InitializeCriticalSectionAndSpinCount( pCritSec, 0x80000000 )) result = GetLastError(); else fInitialized = TRUE; } __except( EXCEPTION_EXECUTE_HANDLER ) { result = GetExceptionCode(); } if (result != ERROR_SUCCESS) goto Exit;
// Save the critical section.
pInitial = (CRITICAL_SECTION *) InterlockedCompareExchangePointer( (void **) &g_PingCritSec, (void *) pCritSec, NULL );
// If the InterlockedCompareExchange succeeded, don't free the
// critical section just allocated.
if (pInitial == NULL) pCritSec = NULL;
Exit: if (pCritSec != NULL) { if (fInitialized) DeleteCriticalSection( pCritSec ); LocalFree( pCritSec ); } return result; }
//*************************************************************
//
// ClosePingCritSec()
//
// Purpose: Closes the CRITICAL_SECTION for pinging
// computers
//
// Parameters: none
//
//
// Return: none
//
//*************************************************************
void ClosePingCritSec( void ) { if (g_PingCritSec != NULL) { DeleteCriticalSection( g_PingCritSec ); LocalFree( g_PingCritSec ); g_PingCritSec = NULL; } }
#define PING_BUFFER_SIZE 2048
//*************************************************************
//
// PingComputerEx()
//
// Purpose: Pings the specified computer to determine
// what the data transfer rate is
//
// Parameters: ipaddr - IP address of computer
// ulSpeed - Data transfer rate (see Notes below)
// pdwAdapterIndex - index of the adapter that services
// calls to the DC
//
// Return: ERROR_SUCCESS if successful
// Error code otherwise
//
// Notes: For fast connections (eg: LAN), it isn't possible
// to get accurate transfer rates since the response
// time from the computer is less than 10ms. In
// this case, the function returns ERROR_SUCCESS and
// ulSpeed is set to maximum speed of network interface.
//
// This function will ping the computer 3 times with
// no data and 3 times with 4K of data. If the response
// time from any of the pings is less than 10ms, the
// function assumes this is a fast link (eg: LAN) and
// returns with ulSpeed set to maximum speed of network
// interface.
//
// If the pings respond in a time greater than 10ms,
// the time of the second ping is subtracted from
// the time of the first ping to determine the amount
// of time it takes to move just the data. This
// is repeated for the 3 sets of pings. Then the
// average time is computed from the 3 sets of pings.
// From the average time, the kbps is calculated.
//
//*************************************************************
DWORD WINAPI PingComputerEx( ULONG ipaddr, ULONG *ulSpeed, DWORD* pdwAdapterIndex ) { DWORD dwResult = ERROR_SUCCESS; DWORD i; DWORD dwReplySize; HANDLE icmpHandle = NULL; LPBYTE lpReply = NULL; PICMP_ECHO_REPLY pReplyStruct; ULONG ulFirst; ULONG ulSecond; ULONG ulDiff; ULONG ulTotal = 0; ULONG ulCount = 0; PICMP_API pIcmp; HRSRC hJPEG; MIB_IFROW mibIfRow; PIPHLPAPI_API pIpHlpApi; HGLOBAL hGlobalJPEG;
dwResult = InitializePingCritSec(); if (dwResult != ERROR_SUCCESS) return dwResult; EnterCriticalSection( g_PingCritSec );
//
// Load iphlpapi.dll
//
pIpHlpApi = LoadIpHlpApi(); if ( !pIpHlpApi ) { dwResult = GetLastError(); DebugMsg((DM_WARNING, TEXT("PingComputer: iphlpapi.dll is not loaded, %d"), dwResult )); goto Exit; }
//
// Load the icmp api
//
dwResult = LoadIcmp( &pIcmp );
if (dwResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("PingComputer: Failed to load icmp api."))); goto Exit; }
//
// Load the slow link data if appropriate
//
if (!g_lpTestData) {
hJPEG = FindResource (g_hDllInstance, MAKEINTRESOURCE(IDB_SLOWLINK), TEXT("JPEG"));
if (hJPEG) {
hGlobalJPEG = LoadResource (g_hDllInstance, hJPEG);
if (hGlobalJPEG) { g_lpTestData = LockResource (hGlobalJPEG); } } }
if (!g_lpTestData) { dwResult = GetLastError(); DebugMsg((DM_WARNING, TEXT("PingComputer: Failed to load slow link data."))); goto Exit; }
//
// Set default speed
//
ZeroMemory( &mibIfRow, sizeof( mibIfRow ) );
//
// get the interface index corr. to the interface that services traffic to ipaddr ( DC )
//
dwResult = pIpHlpApi->pfnGetBestInterface( ipaddr, &mibIfRow.dwIndex ); if ( dwResult != NO_ERROR ) { DebugMsg((DM_WARNING, TEXT("PingComputer: GetBestInterface with %d"), dwResult)); } else { //
// get information about the interface. We use the dwSpeed as the default speed of the link.
//
dwResult = pIpHlpApi->pfnGetIfEntry( &mibIfRow ); if ( dwResult != NO_ERROR ) { DebugMsg((DM_WARNING, TEXT("PingComputer: GetIfEntry with %d"), dwResult)); } else { DebugMsg((DM_VERBOSE, TEXT("PingComputer: Adapter speed %d bps"), mibIfRow.dwSpeed)); } }
if ( pdwAdapterIndex ) { *pdwAdapterIndex = mibIfRow.dwIndex; } *ulSpeed = mibIfRow.dwSpeed/1024; // In kbps
//
// Allocate space for the receive buffer
//
dwReplySize = PING_BUFFER_SIZE + sizeof(ICMP_ECHO_REPLY) + 8; lpReply = LocalAlloc (LPTR, dwReplySize);
if (!lpReply) { dwResult = GetLastError(); DebugMsg((DM_WARNING, TEXT("PingComputer: Failed to allocate memory with %d"), dwResult)); goto Exit; }
//
// Open the Icmp handle
//
icmpHandle = pIcmp->pfnIcmpCreateFile();
if (icmpHandle == INVALID_HANDLE_VALUE) { dwResult = GetLastError(); DebugMsg((DM_WARNING, TEXT("PingComputer: Failed to open handle with %d"), dwResult)); goto Exit; }
//
// Loop through the 3 sets of pings
//
for (i = 0; i < 3; i++) {
//
// Initialize the return value
//
dwResult = ERROR_SUCCESS;
//
// First ping with no data
//
if (pIcmp->pfnIcmpSendEcho (icmpHandle, ipaddr, g_lpTestData, 0, NULL, lpReply, dwReplySize, 5000) == 0) {
dwResult = GetLastError();
if (dwResult == IP_DEST_HOST_UNREACHABLE) { dwResult = ERROR_BAD_NETPATH; DebugMsg((DM_VERBOSE, TEXT("PingComputer: Target computer 0x%x not found"), (DWORD)ipaddr)); goto Exit;
} else { DebugMsg((DM_VERBOSE, TEXT("PingComputer: First send 0x%x failed with %d"), (DWORD)ipaddr, dwResult)); continue; } }
pReplyStruct = (PICMP_ECHO_REPLY) lpReply;
if (pReplyStruct->Status != IP_SUCCESS) {
if (pReplyStruct->Status == IP_DEST_HOST_UNREACHABLE) {
dwResult = ERROR_BAD_NETPATH; DebugMsg((DM_VERBOSE, TEXT("PingComputer: Target computer not found"))); goto Exit;
} else { DebugMsg((DM_VERBOSE, TEXT("PingComputer: First send has a reply buffer failure of %d"), pReplyStruct->Status)); continue; } }
ulFirst = pReplyStruct->RoundTripTime; DebugMsg((DM_VERBOSE, TEXT("PingComputer: First time: %d"), ulFirst));
if (ulFirst < 10) { DebugMsg((DM_VERBOSE, TEXT("PingComputer: Fast link. Exiting."))); goto Exit; }
//
// Second ping with dwSize data
//
if (pIcmp->pfnIcmpSendEcho (icmpHandle, ipaddr, g_lpTestData, PING_BUFFER_SIZE, NULL, lpReply, dwReplySize, 5000) == 0) {
dwResult = GetLastError();
if (dwResult == IP_DEST_HOST_UNREACHABLE) { dwResult = ERROR_BAD_NETPATH; DebugMsg((DM_VERBOSE, TEXT("PingComputer: Target computer not found"))); goto Exit;
} else { DebugMsg((DM_VERBOSE, TEXT("PingComputer: Second send failed with %d"), dwResult)); continue; } }
pReplyStruct = (PICMP_ECHO_REPLY) lpReply;
if (pReplyStruct->Status != IP_SUCCESS) {
if (pReplyStruct->Status == IP_DEST_HOST_UNREACHABLE) {
dwResult = ERROR_BAD_NETPATH; DebugMsg((DM_VERBOSE, TEXT("PingComputer: Target computer not found"))); goto Exit;
} else { DebugMsg((DM_VERBOSE, TEXT("PingComputer: Second send has a reply buffer failure of %d"), pReplyStruct->Status)); continue; } }
ulSecond = pReplyStruct->RoundTripTime; DebugMsg((DM_VERBOSE, TEXT("PingComputer: Second time: %d"), ulSecond));
if (ulSecond < 10) { DebugMsg((DM_VERBOSE, TEXT("PingComputer: Fast link. Exiting."))); goto Exit; }
//
// Study the results
//
if (ulFirst > ulSecond) { DebugMsg((DM_VERBOSE, TEXT("PingComputer: Second time less than first time.")));
} else if (ulFirst == ulSecond) { DebugMsg((DM_VERBOSE, TEXT("PingComputer: First and second times match.")));
} else { ulTotal += (ulSecond - ulFirst); ulCount++; } }
//
// Study the results
//
if (ulTotal > 0) {
ulTotal = (ulTotal / ulCount); *ulSpeed = ((((PING_BUFFER_SIZE * 2) * 1000) / ulTotal) * 8) / 1024; DebugMsg((DM_VERBOSE, TEXT("PingComputer: Transfer rate: %d Kbps Loop count: %d"),*ulSpeed, ulCount)); dwResult = ERROR_SUCCESS;
} else { DebugMsg((DM_VERBOSE, TEXT("PingComputer: No data available"))); dwResult = ERROR_UNEXP_NET_ERR; }
Exit:
if (icmpHandle) { pIcmp->pfnIcmpCloseHandle (icmpHandle); }
if (lpReply) { LocalFree (lpReply); }
LeaveCriticalSection( g_PingCritSec );
return dwResult; }
DWORD WINAPI PingComputer (ULONG ipaddr, ULONG *ulSpeed) { return PingComputerEx( ipaddr, ulSpeed, 0 ); }
//*************************************************************
//
// GetDomainControllerInfo()
//
// Purpose: Wrapper for DsGetDcName().
//
// Parameters:
// pNetAPI32 - Net API entry points
// szDomainName - domain name
// ulFlags - flags, see DsGetDcName()
// ppInfo - see DOMAIN_CONTROLLER_INFO
// pfSlow - slow link?
//
// Comments:
//
//
// Return: NO_ERROR if successful
// Error code if an error occurs
//
//*************************************************************
DWORD GetDomainControllerInfo( PNETAPI32_API pNetAPI32, LPTSTR szDomainName, ULONG ulFlags, HKEY hKeyRoot, PDOMAIN_CONTROLLER_INFO* ppInfo, BOOL* pfSlow, DWORD* pdwAdapterIndex ) { DWORD dwResult;
//
// get DC info.
//
dwResult = pNetAPI32->pfnDsGetDcName( 0, szDomainName, 0, 0, ulFlags, ppInfo);
if ( dwResult == ERROR_SUCCESS ) {
//
// Check for slow link
//
dwResult = IsSlowLink( hKeyRoot, (*ppInfo)->DomainControllerAddress, pfSlow, pdwAdapterIndex );
if ( dwResult != ERROR_SUCCESS ){
//
// force rediscovery to obtain a live DC
//
dwResult = pNetAPI32->pfnDsGetDcName( 0, szDomainName, 0, 0, ulFlags | DS_FORCE_REDISCOVERY, ppInfo); if ( dwResult == ERROR_SUCCESS ) {
//
// re-evaluate link speed
//
dwResult = IsSlowLink( hKeyRoot, (*ppInfo)->DomainControllerAddress, pfSlow, pdwAdapterIndex ); } } } return dwResult; }
//***************************************************************************
//
// GetUserGuid
//
// Purpose: Allocates and returns a string representing the user guid of
// the current user.
//
// Parameters: hToken - user's token
//
// Return: szUserString is successful
// NULL if an error occurs
//
// Comments: Note, this only works for domain accounts. Local accounts
// do not have GUIDs.
//
// History: Date Author Comment
// 11/14/95 ushaji created
//***************************************************************************
LPTSTR GetUserGuid(HANDLE hToken) { LPTSTR szUserGuid=NULL; HANDLE hOldToken; PSID psidSystem = NULL, psidUser=NULL; SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; BOOL bImpersonated = FALSE;
//
// Get the system sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psidSystem)) { DebugMsg((DM_WARNING, TEXT("GetUserGuid: Failed to initialize system sid. Error = %d"), GetLastError())); goto Exit; }
psidUser = GetUserSid(hToken);
if (!psidUser) { DebugMsg((DM_WARNING, TEXT("GetUserGuid: Couldn't get user sid, Error = %d"), GetLastError())); goto Exit; }
if (EqualSid(psidUser, psidSystem)) { DebugMsg((DM_VERBOSE, TEXT("GetUserGuid: user sid matches local system, returning NULL"), GetLastError())); goto Exit; }
//
// impersonate the user and the get the user guid for this user.
//
if (!ImpersonateUser(hToken, &hOldToken)) { DebugMsg((DM_WARNING, TEXT("GetUserGuid: Failed to impersonate user with %d."), GetLastError())); goto Exit; }
bImpersonated = TRUE;
szUserGuid = MyGetUserNameEx(NameUniqueId);
if (!szUserGuid) { if ((GetLastError() != ERROR_CANT_ACCESS_DOMAIN_INFO) && (GetLastError() != ERROR_NONE_MAPPED)) { DebugMsg((DM_WARNING, TEXT("GetUserGuid: Failed to get user guid with %d."), GetLastError())); } }
Exit: if (bImpersonated) RevertToUser(&hOldToken);
if (psidUser) { DeleteUserSid (psidUser); }
if (psidSystem) FreeSid(psidSystem);
return szUserGuid; }
//***************************************************************************
//
// GetOldSidString
//
// Purpose: Allocates and returns a string representing the old sid of
// the current user by looking at the profile guid in the registry.
//
// Parameters: hToken - user's token
// lpKeyName - key to read
//
// Return: SidString is successful
// NULL if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 11/14/95 ushaji created
//***************************************************************************
LPTSTR GetOldSidString(HANDLE hToken, LPTSTR lpKeyName) { TCHAR szBuffer[MAX_PATH], *lpEnd; LPTSTR szUserGuid; DWORD dwSize=0, dwType; TCHAR *lpSidString = NULL; HKEY hKey = NULL; LONG lResult; DWORD dwErr; HRESULT hr; DWORD cchEnd;
//
// get the prev last error
//
dwErr = GetLastError();
szUserGuid = GetUserGuid(hToken);
if (!szUserGuid) { dwErr = GetLastError(); goto Exit; }
//
// Open the guid->sid mapping
//
hr = StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), lpKeyName);
if (FAILED(hr)) { dwErr = HRESULT_CODE(hr); goto Exit; }
lpEnd = CheckSlashEx (szBuffer, ARRAYSIZE(szBuffer), &cchEnd);
if (!lpEnd) { dwErr = ERROR_INSUFFICIENT_BUFFER; goto Exit; } hr = StringCchCopy(lpEnd, cchEnd, szUserGuid);
if (FAILED(hr)) { dwErr = HRESULT_CODE(hr); goto Exit; }
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) { dwErr = lResult; DebugMsg((DM_VERBOSE, TEXT("GetOldSidString: Failed to open profile profile guid key with error %d"), lResult)); goto Exit; }
//
// Query for the Sid String, (size first)
//
lResult = RegQueryValueEx (hKey, PROFILE_SID_STRING, NULL, &dwType, NULL, &dwSize);
if (lResult != ERROR_SUCCESS) { dwErr = lResult; DebugMsg((DM_WARNING, TEXT("GetOldSidString: Failed to query size of SidString with error %d"), lResult)); goto Exit; }
lpSidString = LocalAlloc(LPTR, dwSize);
if (!lpSidString) { dwErr = lResult; DebugMsg((DM_WARNING, TEXT("GetOldSidString: Failed to allocate memory for SidString"), lResult)); goto Exit; }
lResult = RegQueryValueEx (hKey, PROFILE_SID_STRING, NULL, &dwType, (LPBYTE)lpSidString, &dwSize);
if (lResult != ERROR_SUCCESS) { dwErr = lResult; DebugMsg((DM_WARNING, TEXT("GetOldSidString: Failed to query SidString with error %d"), lResult)); LocalFree(lpSidString); lpSidString = NULL; goto Exit; }
Exit: if (szUserGuid) LocalFree(szUserGuid);
if (hKey) RegCloseKey(hKey);
SetLastError(dwErr);
return lpSidString; }
//***************************************************************************
//
// SetOldSidString
//
// Purpose: Sets the old sid string corresp. to a user for the next domain
// migration
//
// Parameters: hToken - user's token
// lpSidString - user's sid (in a string form)
// lpKeyName - key to store
//
// Return: SidString is successful
// NULL if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 11/14/95 ushaji created
//***************************************************************************
BOOL SetOldSidString(HANDLE hToken, LPTSTR lpSidString, LPTSTR lpKeyName) { TCHAR szBuffer[MAX_PATH+1], *lpEnd; DWORD dwSize=0, dwDisp = 0; HKEY hKey = NULL; BOOL bRetVal = TRUE; LONG lResult = 0; LPTSTR szUserGuid; DWORD dwErr; HRESULT hr; DWORD cchEnd;
//
// get the prev last error
//
dwErr = GetLastError();
szUserGuid = GetUserGuid(hToken);
if (!szUserGuid) { dwErr = GetLastError(); goto Exit; }
//
// Open the guid->sid mapping
//
hr = StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), lpKeyName);
if (FAILED(hr)) { dwErr = HRESULT_CODE(hr); goto Exit; }
lpEnd = CheckSlashEx (szBuffer, ARRAYSIZE(szBuffer), &cchEnd);
if (!lpEnd) { dwErr = ERROR_INSUFFICIENT_BUFFER; goto Exit; } hr = StringCchCopy(lpEnd, cchEnd, szUserGuid);
if (FAILED(hr)) { dwErr = HRESULT_CODE(hr); goto Exit; }
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, 0, 0, KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) { dwErr = GetLastError(); DebugMsg((DM_VERBOSE, TEXT("GetOldSidString: Failed to open profile profile guid key with error %d"), lResult)); goto Exit; }
//
// Set the Sid String
//
lResult = RegSetValueEx (hKey, PROFILE_SID_STRING, 0, REG_SZ, (LPBYTE) lpSidString, (lstrlen(lpSidString) + 1) * sizeof(TCHAR));
if (lResult != ERROR_SUCCESS) { dwErr = GetLastError(); DebugMsg((DM_WARNING, TEXT("SetOldSidString: Failed to set SidString with error %d"), lResult)); goto Exit; }
bRetVal = TRUE;
Exit: if (szUserGuid) LocalFree(szUserGuid);
if (hKey) RegCloseKey(hKey);
SetLastError(dwErr);
return bRetVal; }
//***************************************************************************
//
// GetErrString
//
// Purpose: Calls FormatMessage to Get the error string corresp. to a error
// code
//
//
// Parameters: dwErr - Error Code
// szErr - Buffer to return the error string (MAX_PATH)
// is assumed.!!!
//
// Return: szErr
//
// History: Date Author Comment
// 4/28/99 ushaji created
//***************************************************************************
LPTSTR GetErrString(DWORD dwErr, LPTSTR szErr) { szErr[0] = TEXT('\0');
FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), szErr, MAX_PATH, NULL);
return szErr; }
//*************************************************************
//
// GetMachineToken()
//
// Purpose: Gets the machine token
//
// Parameters: none
//
// Note: This must be called from the LocalSystem context
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
HANDLE GetMachineToken (void) { SECURITY_STATUS SecStatus; SECURITY_STATUS InitStatus; SECURITY_STATUS AcceptStatus; HANDLE hToken = NULL; PSecPkgInfo PackageInfo = NULL; BOOLEAN AcquiredServerCred = FALSE; BOOLEAN AcquiredClientCred = FALSE; BOOLEAN AcquiredClientContext = FALSE; BOOLEAN AcquiredServerContext = FALSE; CredHandle CredentialHandle2; CredHandle ServerCredHandleStorage; CtxtHandle ClientContextHandle; CtxtHandle ServerContextHandle; PCtxtHandle pServerContextHandle = NULL; PCtxtHandle pClientContextHandle = NULL; PCredHandle ServerCredHandle = NULL; TimeStamp Lifetime; DWORD dwSize; TCHAR szComputerName[MAX_PATH]; SecBufferDesc NegotiateDesc; SecBuffer NegotiateBuffer; SecBufferDesc ChallengeDesc; PSecBufferDesc pChallengeDesc = NULL; SecBuffer ChallengeBuffer; LPBYTE pvBuffer = NULL; LPBYTE pvBuffer2 = NULL; ULONG ContextAttributes; PSECUR32_API pSecur32; HRESULT hr;
//
// Load pSecur32->dll
//
if ( !( pSecur32 = LoadSecur32 () ) ) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: Failed to load Secur32."))); SecStatus = GetLastError(); return NULL; }
//
// Get the computer name
//
dwSize = ARRAYSIZE(szComputerName);
if (!GetComputerName (szComputerName, &dwSize)) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: Failed to get the computer name with %d"), GetLastError())); SecStatus = GetLastError(); goto Exit; }
hr = StringCchCat(szComputerName, ARRAYSIZE(szComputerName), TEXT("$"));
if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: Failed to append a '$'. "))); SecStatus = ERROR_INSUFFICIENT_BUFFER; goto Exit; }
//
// Get the kerberos security package
//
SecStatus = pSecur32->pfnQuerySecurityPackageInfo( L"kerberos", &PackageInfo );
if (SecStatus != STATUS_SUCCESS) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: QuerySecurityPackageInfo failed with 0x%x"), SecStatus)); goto Exit; }
//
// Acquire a credential handle for the server side
//
ServerCredHandle = &ServerCredHandleStorage;
SecStatus = pSecur32->pfnAcquireCredentialsHandle( NULL, // New principal
L"kerberos", // Package Name
SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, ServerCredHandle, &Lifetime );
if (SecStatus != STATUS_SUCCESS) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: AcquireCredentialsHandle for server failed with 0x%x"), SecStatus)); goto Exit; }
AcquiredServerCred = TRUE;
//
// Acquire a credential handle for the client side
//
SecStatus = pSecur32->pfnAcquireCredentialsHandle( NULL, // New principal
L"kerberos", // Package Name
SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &CredentialHandle2, &Lifetime );
if (SecStatus != STATUS_SUCCESS) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: AcquireCredentialsHandle for client failed with 0x%x"), SecStatus)); goto Exit; }
AcquiredClientCred = TRUE;
//
// Allocate buffers
//
pvBuffer = LocalAlloc( 0, PackageInfo->cbMaxToken);
if (!pvBuffer) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: LocalAlloc failed with %d"), GetLastError())); SecStatus = GetLastError(); goto Exit; }
pvBuffer2 = LocalAlloc( 0, PackageInfo->cbMaxToken);
if (!pvBuffer2) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: LocalAlloc failed with %d"), GetLastError())); SecStatus = GetLastError(); goto Exit; }
while (TRUE) {
//
// Initialize the security context (client side)
//
NegotiateDesc.ulVersion = 0; NegotiateDesc.cBuffers = 1; NegotiateDesc.pBuffers = &NegotiateBuffer;
NegotiateBuffer.cbBuffer = PackageInfo->cbMaxToken; NegotiateBuffer.BufferType = SECBUFFER_TOKEN; NegotiateBuffer.pvBuffer = pvBuffer;
InitStatus = pSecur32->pfnInitializeSecurityContext( &CredentialHandle2, pClientContextHandle, szComputerName, 0, 0, // Reserved 1
SECURITY_NATIVE_DREP, pChallengeDesc, 0, // Reserved 2
&ClientContextHandle, &NegotiateDesc, &ContextAttributes, &Lifetime );
if ((InitStatus != SEC_E_OK) && (InitStatus != SEC_I_CONTINUE_NEEDED)) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: InitializeSecurityContext failed with 0x%x"), InitStatus)); SecStatus = InitStatus; goto Exit; }
pClientContextHandle = &ClientContextHandle; AcquiredClientContext = TRUE;
//
// Accept the server side context
//
NegotiateBuffer.BufferType |= SECBUFFER_READONLY; ChallengeDesc.ulVersion = 0; ChallengeDesc.cBuffers = 1; ChallengeDesc.pBuffers = &ChallengeBuffer;
ChallengeBuffer.cbBuffer = PackageInfo->cbMaxToken; ChallengeBuffer.BufferType = SECBUFFER_TOKEN; ChallengeBuffer.pvBuffer = pvBuffer2;
AcceptStatus = pSecur32->pfnAcceptSecurityContext( ServerCredHandle, pServerContextHandle, &NegotiateDesc, 0, SECURITY_NATIVE_DREP, &ServerContextHandle, &ChallengeDesc, &ContextAttributes, &Lifetime );
if ((AcceptStatus != SEC_E_OK) && (AcceptStatus != SEC_I_CONTINUE_NEEDED)) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: AcceptSecurityContext failed with 0x%x"), AcceptStatus)); SecStatus = AcceptStatus; goto Exit; }
AcquiredServerContext = TRUE;
if (AcceptStatus == SEC_E_OK) { break; }
pChallengeDesc = &ChallengeDesc; pServerContextHandle = &ServerContextHandle;
DebugMsg((DM_VERBOSE, TEXT("GetMachineToken: Looping for authentication again."))); }
//
// Get the server token
//
SecStatus = pSecur32->pfnQuerySecurityContextToken(&ServerContextHandle, &hToken);
if ( SecStatus != STATUS_SUCCESS ) { DebugMsg((DM_WARNING, TEXT("GetMachineToken: QuerySecurityContextToken failed with 0x%x"), SecStatus)); goto Exit; }
Exit:
if (AcquiredClientContext) { pSecur32->pfnDeleteSecurityContext( &ClientContextHandle ); }
if (AcquiredServerContext) { pSecur32->pfnDeleteSecurityContext( &ServerContextHandle ); }
if (pvBuffer2) { LocalFree (pvBuffer2); }
if (pvBuffer) { LocalFree (pvBuffer); }
if (AcquiredClientCred) { pSecur32->pfnFreeCredentialsHandle(&CredentialHandle2); }
if (AcquiredServerCred) { pSecur32->pfnFreeCredentialsHandle(ServerCredHandle); }
if (PackageInfo) { pSecur32->pfnFreeContextBuffer(PackageInfo); }
if (!hToken) { SetLastError(SecStatus); }
return hToken; }
//*************************************************************
//
// IsNullGUID()
//
// Purpose: Determines if the passed in GUID is all zeros
//
// Parameters: pguid GUID to compare
//
// Return: TRUE if the GUID is all zeros
// FALSE if not
//
//*************************************************************
BOOL IsNullGUID (GUID *pguid) {
return ( (pguid->Data1 == 0) && (pguid->Data2 == 0) && (pguid->Data3 == 0) && (pguid->Data4[0] == 0) && (pguid->Data4[1] == 0) && (pguid->Data4[2] == 0) && (pguid->Data4[3] == 0) && (pguid->Data4[4] == 0) && (pguid->Data4[5] == 0) && (pguid->Data4[6] == 0) && (pguid->Data4[7] == 0) ); }
//*************************************************************
//
// GetMachineRole()
//
// Purpose: Determines the role of the machine
// server vs workstation vs standalone
//
// Parameters: piRole - Receives the simple role number
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL GetMachineRole (LPINT piRole) { PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pBasic; DWORD dwResult; PNETAPI32_API pNetAPI32;
//
// Check the cached value first
//
if (g_iMachineRole != -1) { *piRole = g_iMachineRole; return TRUE; }
//
// Load netapi32
//
pNetAPI32 = LoadNetAPI32();
if (!pNetAPI32) { DebugMsg((DM_WARNING, TEXT("GetMachineRole: Failed to load netapi32 with %d."), GetLastError())); return FALSE; }
//
// Ask for the role of this machine
//
dwResult = pNetAPI32->pfnDsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *)&pBasic);
if (dwResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("GetMachineRole: DsRoleGetPrimaryDomainInformation failed with %d."), dwResult)); return FALSE; }
//
// Convert the role into a simple machine role
//
if ((pBasic->MachineRole == DsRole_RoleStandaloneWorkstation) || (pBasic->MachineRole == DsRole_RoleStandaloneServer)) {
*piRole = 0; // standalone machine not in a DS domain
} else {
if (pBasic->Flags & DSROLE_PRIMARY_DOMAIN_GUID_PRESENT) {
if (!IsNullGUID(&pBasic->DomainGuid)) {
*piRole = 2; // machine is a member of a domain with DS support
if ((pBasic->MachineRole == DsRole_RoleBackupDomainController) || (pBasic->MachineRole == DsRole_RolePrimaryDomainController)) { *piRole = 3; // machine is a domain controller
} } else { *piRole = 1; // machine is a member of a NT4 domain
}
} else { *piRole = 1; // machine is a member of a domain without DS support
} }
pNetAPI32->pfnDsRoleFreeMemory (pBasic);
//
// Save this value in the cache for future use
//
g_iMachineRole = *piRole;
return TRUE; }
//*************************************************************
//
// IsUNCPath()
//
// Purpose: Is the given path a UNC path
//
// Parameters: lpPath - Path to check
//
// Return: TRUE if the path is UNC
// FALSE if not
//
// Comments:
//
// History: Date Author Comment
// 6/21/96 ericflo Ported
//
//*************************************************************
BOOL IsUNCPath(LPCTSTR lpPath) {
if ((!lpPath) || (!lpPath[0]) && (!lpPath[1])) return FALSE;
if (lpPath[0] == TEXT('\\') && lpPath[1] == TEXT('\\')) { return(TRUE); } return(FALSE); }
//*************************************************************
//
// MakePathUNC()
//
// Purpose: Makes the given path UNC s.t. it can be accessed from a remote machine..
// if the path contains %systemroot% expanded then it substitutes
// \\machname\admin$ otherwise \\machname\<driveletter>$
//
// Parameters: lpPath - Input Path (needs to be absolute)
// szComputerName - Name of the computer on which this is the local path
//
// Return: Path if it was fone successfully
// NULL if not
//
// Comments:
//
//
//*************************************************************
LPTSTR MakePathUNC(LPTSTR pwszFile, LPTSTR szComputerName) { LPTSTR szUNCPath=NULL; TCHAR szSysRoot[MAX_PATH]; DWORD dwSysLen; LPTSTR lpEnd = NULL; DWORD cchUNCPath; DWORD cchEnd; HRESULT hr;
DebugMsg((DM_VERBOSE, TEXT("MakePathUNC: Entering with <%s>"), pwszFile ? pwszFile : TEXT("NULL")));
cchUNCPath = lstrlen(pwszFile)+lstrlen(szComputerName)+3+lstrlen(TEXT("admin$"))+1; szUNCPath = LocalAlloc(LPTR, sizeof(TCHAR)*cchUNCPath);
if (!szUNCPath) return NULL;
if (!pwszFile || !*pwszFile) { DebugMsg((DM_VERBOSE, TEXT("MakePathUNC: lpFile is NULL, setting lpResult to a null string"))); *szUNCPath = TEXT('\0'); return szUNCPath; }
if (IsUNCPath(pwszFile)) { StringCchCopy(szUNCPath, cchUNCPath, pwszFile); return szUNCPath; }
StringCchCopy(szUNCPath, cchUNCPath, TEXT("\\\\")); StringCchCat(szUNCPath, cchUNCPath, szComputerName);
//
// If the first part of lpFile is the expanded value of %SystemRoot%
//
if (FAILED(SafeExpandEnvironmentStrings (TEXT("%SystemRoot%"), szSysRoot, MAX_PATH))) { DebugMsg((DM_WARNING, TEXT("MakePathUNC: ExpandEnvironmentString failed with error %d, setting szSysRoot to %systemroot% "), GetLastError())); LocalFree(szUNCPath); return NULL; }
dwSysLen = lstrlen(szSysRoot); lpEnd = CheckSlashEx(szUNCPath, cchUNCPath, &cchEnd);
//
// if the prefix is the same as expanded systemroot then..
//
if (((DWORD)lstrlen(pwszFile) > dwSysLen) && (CompareString (LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, szSysRoot, dwSysLen, pwszFile, dwSysLen) == CSTR_EQUAL)) {
StringCchCat(szUNCPath, cchUNCPath, TEXT("admin$")); StringCchCat(szUNCPath, cchUNCPath, pwszFile+dwSysLen); } else {
if (pwszFile[1] != TEXT(':')) { DebugMsg((DM_WARNING, TEXT("MakePathUNC: Input path %s is not an absolute path"), pwszFile)); StringCchCat(szUNCPath, cchUNCPath, pwszFile); return szUNCPath; }
if (cchEnd > 2) { lpEnd[0] = pwszFile[0]; lpEnd[1] = TEXT('$'); lpEnd[2] = TEXT('\0');
StringCchCat(szUNCPath, cchUNCPath, pwszFile+2); } }
DebugMsg((DM_VERBOSE, TEXT("MakePathUNC: Returning a UNCPath of %s"), szUNCPath));
return szUNCPath; }
//*************************************************************
//
// SupportLongFileName()
//
// Purpose: Prepends lpDir with \\?\UNC\ or \\?\ depending on
// whether lpDir is a UNC path or local path. Before
// prepending this function converts relative path or
// absolute path started with a slash to corresponding
// absolute path containing drive letter.
//
// Parameters: lpDir - Directory
// lpWrkDirSize - Size of the returned buffer in unit
// of TCHAR
//
// Return: LPTSTR pointing to prepended dir/file
// NULL if fail to allocate memory
//
// Comments: Prepending with \\?\UNC\ or \\?\ allows all file api's
// to handle file name > MAX_PATH.
//
// History: Date Author Comment
// 8/8/00 santanuc Created
//
//*************************************************************
LPTSTR SupportLongFileName (LPTSTR lpDir, LPDWORD lpWrkDirSize) { LPTSTR lpWrkDir = NULL;
*lpWrkDirSize = lstrlen(lpDir)+2*MAX_PATH; lpWrkDir = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)**lpWrkDirSize);
if (!lpWrkDir) { DebugMsg((DM_WARNING, TEXT("EnableLongFileNameDeletion: Failed to Allocate memory. Error = %d"), GetLastError())); return NULL; }
if ( IsUNCPath(lpDir) ) { // lpDir is of the form \\computername\...
StringCchCopy(lpWrkDir, *lpWrkDirSize, c_szUNCFilePrefix); StringCchCat(lpWrkDir, *lpWrkDirSize, lpDir+2); }
else if ( *CharNext(lpDir) == TEXT(':') ) { // Local storage specified with drive name
StringCchCopy(lpWrkDir, *lpWrkDirSize, c_szLocalFilePrefix); StringCchCat(lpWrkDir, *lpWrkDirSize, lpDir); }
else if ( *lpDir == TEXT('\\') ) { DWORD dwSize;
// Prepend lpDir with c_szLocalFilePrefix followed by current drive as DeleteFile function requires
// drive name to delete files from local storage with path name > MAX_PATH
StringCchCopy(lpWrkDir, *lpWrkDirSize, c_szLocalFilePrefix); dwSize = GetCurrentDirectory(*lpWrkDirSize-c_dwLocalFilePrefixLen, lpWrkDir+c_dwLocalFilePrefixLen);
if (dwSize == 0) { DebugMsg((DM_VERBOSE, TEXT("DelNode: GetCurrentDirectory failed with error %d"), GetLastError())); // proceed to delete lpDir without long file name deletion feature
StringCchCopy(lpWrkDir, *lpWrkDirSize, lpDir); } else {
if (dwSize > *lpWrkDirSize-c_dwLocalFilePrefixLen) {
// Extend lpWrkDir to accomodate current directory name with drive
LocalFree(lpWrkDir); *lpWrkDirSize = dwSize+c_dwLocalFilePrefixLen; lpWrkDir = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)**lpWrkDirSize); if (!lpWrkDir) { DebugMsg((DM_WARNING, TEXT("Delnode: Failed to Allocate memory. Error = %d"), GetLastError())); return NULL; }
StringCchCopy(lpWrkDir, *lpWrkDirSize, c_szLocalFilePrefix); dwSize = GetCurrentDirectory(*lpWrkDirSize-c_dwLocalFilePrefixLen, lpWrkDir+c_dwLocalFilePrefixLen);
if (dwSize == 0 || dwSize > *lpWrkDirSize-c_dwLocalFilePrefixLen) { DebugMsg((DM_VERBOSE, TEXT("DelNode: GetCurrentDirectory 2nd call failed with error %d"), GetLastError())); // proceed to delete lpDir without long file name deletion feature
StringCchCopy(lpWrkDir, *lpWrkDirSize, lpDir); }
else { // Copy lpDir after c_szLocalFilePrefix and drive name
StringCchCopy(lpWrkDir+c_dwLocalFilePrefixLen+2, *lpWrkDirSize-c_dwLocalFilePrefixLen-2, lpDir); } } else { // Copy lpDir after c_szLocalFilePrefix and drive name
StringCchCopy(lpWrkDir+c_dwLocalFilePrefixLen+2, *lpWrkDirSize-c_dwLocalFilePrefixLen-2, lpDir); } } } else {
LPTSTR szFileName; DWORD dwSize;
// Relative path name specified. So Prepend lpDir with c_szLocalFilePrefix followed by the current directory
StringCchCopy(lpWrkDir, *lpWrkDirSize, c_szLocalFilePrefix); dwSize = GetFullPathName(lpDir, *lpWrkDirSize-c_dwLocalFilePrefixLen, lpWrkDir+c_dwLocalFilePrefixLen, &szFileName); if ( dwSize == 0 ) { DebugMsg((DM_VERBOSE, TEXT("DelNode: GetFullPathName failed with error %d"), GetLastError())); // proceed to delete lpDir without long file name deletion feature
StringCchCopy(lpWrkDir, *lpWrkDirSize, lpDir); } else {
if ( dwSize > *lpWrkDirSize-c_dwLocalFilePrefixLen ) {
// Extend lpWrkDir to accomodate absolute path name
LocalFree(lpWrkDir); *lpWrkDirSize = dwSize+2*MAX_PATH; lpWrkDir = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)**lpWrkDirSize); if (!lpWrkDir) { DebugMsg((DM_WARNING, TEXT("Delnode: Failed to Allocate memory. Error = %d"), GetLastError())); return NULL; }
StringCchCopy(lpWrkDir, *lpWrkDirSize, c_szLocalFilePrefix); dwSize = GetFullPathName(lpDir, *lpWrkDirSize-c_dwLocalFilePrefixLen, lpWrkDir+c_dwLocalFilePrefixLen, &szFileName); if (dwSize == 0 || dwSize > *lpWrkDirSize-c_dwLocalFilePrefixLen) { DebugMsg((DM_VERBOSE, TEXT("DelNode: GetFullPathName 2nd call failed with error %d"), GetLastError())); // proceed to delete lpDir without long file name deletion feature
StringCchCopy(lpWrkDir, *lpWrkDirSize, lpDir); } } } }
return lpWrkDir; }
//*************************************************************
//
// SecureNestedDir_Recurse()
//
// Purpose: Recursive function for securing nested dirs/files
//
// Parameters: lpDir - Full Directory Path.
// dwSize - Allocated size of the working buffer
// pDirSd - Security descriptor to be applied with dirs
// pFileSd - Security descriptor to be applied with files
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
//
//
//*************************************************************
BOOL SecureNestedDir_Recurse (LPTSTR lpDir, DWORD dwSize, PSECURITY_DESCRIPTOR pDirSd, PSECURITY_DESCRIPTOR pFileSd) { BOOL bOwn = FALSE, bRetVal = FALSE; LPTSTR lpEnd = NULL, lpWrkDir = NULL; WIN32_FIND_DATA *pfd = NULL; HANDLE hFile; DWORD dwWrkDirSize; DWORD cchEnd;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("SecureNestedDir_Recurse: Entering, lpDir = <%s>"), lpDir));
//
// Each filename or a directory has to be less than MAX_PATH in the worst case.
// So make sure that we have at least MAX_PATH + 2 (for a slash and '\0'
// space left in the working buffer case.
//
// In the normal case, when we have a path of length ~MAX_PATH it will do only
// 1 allocation
//
if ((DWORD)(lstrlen(lpDir) + MAX_PATH+2) > (dwSize)) { dwWrkDirSize = dwSize+2*MAX_PATH; lpWrkDir = (LPWSTR)LocalAlloc(LPTR, dwWrkDirSize*sizeof(TCHAR)); if (!lpWrkDir) { DebugMsg((DM_WARNING, TEXT("SecureNestedDir_Recurse: Couldn't allocate memory for working buffer. Error - %d"), GetLastError())); goto Exit; }
StringCchCopy(lpWrkDir, dwWrkDirSize, lpDir); bOwn = TRUE;
} else { lpWrkDir = lpDir; dwWrkDirSize = dwSize; }
//
// Allocate WIN32_FIND_DATA in the heap to save stack space
//
pfd = (WIN32_FIND_DATA*) LocalAlloc (LPTR, sizeof(WIN32_FIND_DATA)); if (!pfd) { DebugMsg((DM_WARNING, TEXT("SecureNestedDir_Recurse: Couldn't allocate memory for WIN32_FIND_DATA. Error - %d"), GetLastError())); goto Exit; }
//
// Attach a Slash the end if required
//
lpEnd = CheckSlashEx(lpWrkDir, dwWrkDirSize, &cchEnd); StringCchCopy(lpEnd, cchEnd, c_szStarDotStar);
//
// Find the first file
//
hFile = FindFirstFile(lpWrkDir, pfd);
if (hFile == INVALID_HANDLE_VALUE) {
if ((GetLastError() == ERROR_FILE_NOT_FOUND) || (GetLastError() == ERROR_PATH_NOT_FOUND)) { bRetVal = TRUE; goto Exit; } else { DebugMsg((DM_WARNING, TEXT("SecureNestedDir_Recurse: FindFirstFile failed. Error = %d"), GetLastError())); goto Exit; } }
do { //
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("SecureNestedDir_Recurse: FindFile found: <%s>"), pfd->cFileName));
//
// Check for "." and ".."
//
if (!lstrcmpi(pfd->cFileName, c_szDot)) { continue; }
if (!lstrcmpi(pfd->cFileName, c_szDotDot)) { continue; }
StringCchCopy(lpEnd, cchEnd, pfd->cFileName);
if (pfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
//
// Check for reparse point, don't recurse into it.
//
if (pfd->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { DebugMsg((DM_WARNING, TEXT("SecureNestedDir_Recurse: a reparse point was found: <%s>, will not recurse into it."), lpWrkDir)); } else { SecureNestedDir_Recurse(lpWrkDir, dwWrkDirSize, pDirSd, pFileSd); //
// ignore errors and go ahead..
//
StringCchCopy(lpEnd, cchEnd, pfd->cFileName); }
if (!SetFileSecurity (lpWrkDir, DACL_SECURITY_INFORMATION, pDirSd)) { DebugMsg((DM_WARNING, TEXT("SecureNestedDir_Recurse: Failed to secure directory <%s>. Error = %d"), lpWrkDir, GetLastError())); }
} else {
//
// We found a file. Try to secure it
//
if (!SetFileSecurity (lpWrkDir, DACL_SECURITY_INFORMATION, pFileSd)) { DebugMsg((DM_WARNING, TEXT("SecureNestedDir_Recurse: Failed to secure file <%s>. Error = %d"), pfd->cFileName, GetLastError())); }
}
//
// Find the next entry
//
} while (FindNextFile(hFile, pfd));
//
// Close the search handle
//
FindClose(hFile);
//
// Success.
//
DebugMsg((DM_VERBOSE, TEXT("SecureNestedDir_Recurse: Leaving <%s>"), lpDir));
bRetVal = TRUE;
Exit: if (pfd) LocalFree(pfd); if (bOwn) LocalFree(lpWrkDir); return bRetVal; }
//*************************************************************
//
// SecureNestedDir()
//
// Purpose: Secure the dir and nested dirs(files) with input
// SECURITY_DESCRIPTOR.
//
// Parameters: lpDir - Directory
// pDirSd - Security descriptor to be applied with dirs.
// pFileSd - Security descriptor to be applied with files.
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// History: Date Author Comment
// 8/8/00 santanuc Created
//
//*************************************************************
BOOL SecureNestedDir (LPTSTR lpDir, PSECURITY_DESCRIPTOR pDirSd, PSECURITY_DESCRIPTOR pFileSd) { LPTSTR lpWrkDir = NULL; DWORD dwWrkDirSize; BOOL bRetVal = FALSE;
lpWrkDir = SupportLongFileName(lpDir, &dwWrkDirSize);
if (!lpWrkDir) { DebugMsg((DM_WARNING, TEXT("SecureNestedDir: Failed to Allocate memory. Error = %d"), GetLastError())); goto Exit; }
if (!SecureNestedDir_Recurse (lpWrkDir, dwWrkDirSize, pDirSd, pFileSd)) { DebugMsg((DM_WARNING, TEXT("SecureNestedDir: SecureNestedDir recurse failed with error %d"), GetLastError())); } if (!SetFileSecurity (lpDir, DACL_SECURITY_INFORMATION, pDirSd)) { DebugMsg((DM_WARNING, TEXT("SecureNestedDir: SetFileSecurity failed. Error = %d"), GetLastError())); goto Exit; }
bRetVal = TRUE;
DebugMsg((DM_VERBOSE, TEXT("SecureNestedDir: Secure directory <%s> successfully."), lpDir));
Exit: if (lpWrkDir) { LocalFree(lpWrkDir); }
return bRetVal; }
//*************************************************************
//
// SetEnvironmentVariableInBlock()
//
// Purpose: Sets the environment variable in the given block
//
// Parameters: pEnv - Environment block
// lpVariable - Variables
// lpValue - Value
// bOverwrite - Overwrite
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/21/96 ericflo Ported
//
//*************************************************************
BOOL SetEnvironmentVariableInBlock(PVOID *pEnv, LPTSTR lpVariable, LPTSTR lpValue, BOOL bOverwrite) { NTSTATUS Status; UNICODE_STRING Name, Value; DWORD cb; LPTSTR szValue = NULL;
if (!*pEnv || !lpVariable || !*lpVariable) { return(FALSE); }
RtlInitUnicodeString(&Name, lpVariable);
cb = 1025 * sizeof(WCHAR); Value.Buffer = LocalAlloc(LPTR, cb); if (Value.Buffer) { Value.Length = 0; Value.MaximumLength = (USHORT)cb; Status = RtlQueryEnvironmentVariable_U(*pEnv, &Name, &Value);
LocalFree(Value.Buffer);
if ( NT_SUCCESS(Status) && !bOverwrite) { return(TRUE); } }
szValue = (LPTSTR)LocalAlloc(LPTR, 1024*sizeof(TCHAR)); if (!szValue) { DebugMsg((DM_WARNING, TEXT("SetEnvironmentVariableInBlock: Out of memory"))); return FALSE; }
if (lpValue && *lpValue) {
//
// Special case TEMP and TMP and shorten the path names
//
if ( CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpVariable, -1, TEXT("TEMP"), -1) == CSTR_EQUAL || CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, lpVariable, -1, TEXT("TMP") , -1) == CSTR_EQUAL ) {
DWORD dwLength = GetShortPathName (lpValue, szValue, 1024); if (!dwLength || dwLength > 1024) { StringCchCopy (szValue, 1024, lpValue); } } else { StringCchCopy (szValue, 1024, lpValue); }
RtlInitUnicodeString(&Value, szValue); Status = RtlSetEnvironmentVariable(pEnv, &Name, &Value); } else { Status = RtlSetEnvironmentVariable(pEnv, &Name, NULL); }
LocalFree(szValue); if (NT_SUCCESS(Status)) { return(TRUE); } return(FALSE); }
/***************************************************************************\
* ExpandUserEvironmentVariable * * * History: * 2-28-92 Johannec Created * \***************************************************************************/ DWORD ExpandUserEnvironmentStrings( PVOID pEnv, LPCTSTR lpSrc, LPTSTR lpDst, DWORD nSize ) { NTSTATUS Status; UNICODE_STRING Source, Destination; ULONG Length;
RtlInitUnicodeString( &Source, lpSrc ); Destination.Buffer = lpDst; Destination.Length = 0; Destination.MaximumLength = (USHORT)(nSize*sizeof(WCHAR)); Length = 0; Status = RtlExpandEnvironmentStrings_U( pEnv, (PUNICODE_STRING)&Source, (PUNICODE_STRING)&Destination, &Length ); if (NT_SUCCESS( Status ) || Status == STATUS_BUFFER_TOO_SMALL) { return( Length / sizeof(WCHAR) ); } else { return( 0 ); } }
//*************************************************************
//
// ConvertToShareName()
//
// Purpose: Convert the UNC path of a file\dir to a share
//
// Parameters: lpShare : Full UNC path of file\dir
//
// Return: None.
//
// Comments:
//
// History: Date Author Comment
// 8/21/00 santanuc Created
//
//*************************************************************
LPTSTR ConvertToShareName(LPTSTR lpShare) { BOOL bShareName = FALSE;
lpShare += 2; // Skip initial two slashes
while ((!bShareName || *lpShare != TEXT('\\')) && *lpShare != TEXT('\0')) { if (*lpShare == TEXT('\\')) bShareName = TRUE; lpShare++; }
if (*lpShare == TEXT('\\')) { *lpShare = TEXT('\0'); return lpShare+1; } return NULL; }
//*************************************************************
//
// AbleToBypassCSC()
//
// Purpose: Try to bypass CSC using a secret api.
//
// Parameters: hTokenUser - User's token
// lpDir - Roaming profile dir
// lppCscBypassedPath - Path name with mapped drive (OUT)
// cpDrive - Mapped drive (OUT)
//
// Return: ERROR_SUCCESS if successful
// Error code if an error occurs
//
// Comments: We will always bypass csc for roaming share.
// There are two reason behind this :
// o csc mark entire server offline even if only
// one share goes offline. This is a bad design
// from csc perspective and they need to fix it
// o If csc is turned on in the roaming share server
// then both csc and profile will try to sync files
// on top of one another and we will be in a inconsistent
// state
//
// History: Date Author Comment
// 10/29/00 santanuc Created
//
//*************************************************************
DWORD AbleToBypassCSC(HANDLE hTokenUser, LPCTSTR lpDir, LPTSTR *lppCscBypassedPath, TCHAR *cpDrive) { NETRESOURCE sNR; LPTSTR lpShare = NULL; BOOL bIsDfsConnect = FALSE, bRetValue = FALSE; DWORD dwFlags = 0, dwError; HANDLE hOldToken; WIN32_FIND_DATA fd; HANDLE hResult; LPTSTR lpFileName; BOOL bImpersonated = FALSE; DWORD cchShare; DWORD cchCscBypassedPath; DebugMsg((DM_VERBOSE, TEXT("AbleToBypassCSC: Try to bypass CSC")));
if (!lpDir || !IsUNCPath(lpDir) || !lppCscBypassedPath || !cpDrive) { return ERROR_INVALID_PARAMETER; // Invalid argument
}
// Initialize
*lppCscBypassedPath = NULL; memset(&sNR, 0, sizeof(NETRESOURCE)); if (!ImpersonateUser(hTokenUser, &hOldToken)) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("AbleToBypassCSC: Failed to impersonate user with %d."), dwError)); goto Exit; } bImpersonated = TRUE;
//
// Construct the roaming share name
//
cchShare = lstrlen(lpDir) + 1; lpShare = (LPTSTR)LocalAlloc(LPTR, cchShare * sizeof(TCHAR)); if (!lpShare) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("AbleToBypassCSC: Failed to allocate memory"))); goto Exit; }
StringCchCopy(lpShare, cchShare, lpDir); lpFileName = ConvertToShareName(lpShare);
cchCscBypassedPath = lstrlen(lpDir)+1; *lppCscBypassedPath = (LPTSTR)LocalAlloc(LPTR, cchCscBypassedPath * sizeof(TCHAR)); if (!*lppCscBypassedPath) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("AbleToBypassCSC: Failed to allocate memory"))); goto Exit; }
//
// Initialize NETRESOURCE structure
//
sNR.dwType = RESOURCETYPE_DISK; sNR.lpRemoteName = lpShare; sNR.lpLocalName = (LPTSTR)LocalAlloc(LPTR, 3 * sizeof(TCHAR)); if (!sNR.lpLocalName) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("AbleToBypassCSC: Failed to allocate memory"))); goto Exit; } sNR.lpLocalName[0] = TEXT('E'); sNR.lpLocalName[1] = TEXT(':'); sNR.lpLocalName[2] = TEXT('\0');
do{ __try { dwError = NPAddConnection3ForCSCAgent(NULL, &sNR, NULL, NULL, dwFlags, &bIsDfsConnect); DebugMsg((DM_VERBOSE, TEXT("AbleToBypassCSC: tried NPAddConnection3ForCSCAgent. Error %d"), dwError)); } __except(EXCEPTION_EXECUTE_HANDLER) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("AbleToBypassCSC: Took exception in NPAddConnection3ForCSCAgent. Error %d"), dwError)); }
if (dwError == WN_SUCCESS || dwError == WN_CONNECTED_OTHER_PASSWORD || dwError == WN_CONNECTED_OTHER_PASSWORD_DEFAULT){ dwError = ERROR_SUCCESS; break; } if (sNR.lpLocalName[0]==TEXT('Z')) { goto Exit; } else if ((dwError == WN_BAD_LOCALNAME) || (dwError == WN_ALREADY_CONNECTED)){ ++sNR.lpLocalName[0]; continue; } else{ if (GetNetworkProvider(&sNR) == ERROR_BAD_PROVIDER) { dwError = ERROR_BAD_PROVIDER; } goto Exit; } }while (TRUE);
// Succesfully bypassed CSC. Do not modify dwError in this part.
bRetValue = TRUE;
*cpDrive = sNR.lpLocalName[0]; StringCchCopy(*lppCscBypassedPath, cchCscBypassedPath, sNR.lpLocalName); StringCchCat(*lppCscBypassedPath, cchCscBypassedPath, TEXT("\\")); if (lpFileName) { StringCchCat(*lppCscBypassedPath, cchCscBypassedPath, lpFileName); } DebugMsg((DM_VERBOSE, TEXT("AbleToBypassCSC: Share %s mapped to drive %c. Returned Path %s"), lpShare, sNR.lpLocalName[0], *lppCscBypassedPath));
Exit: if (lpShare) { LocalFree(lpShare); }
if (!bRetValue && *lppCscBypassedPath) { LocalFree(*lppCscBypassedPath); *lppCscBypassedPath = NULL; }
if (sNR.lpLocalName) { LocalFree(sNR.lpLocalName); }
if (bImpersonated) { RevertToUser(&hOldToken); }
return dwError; }
//*************************************************************
//
// CancelCSCBypassedConnection()
//
// Purpose: Release the mapped drive.
//
// Parameters: hTokenUser - User's token
// cDrive - Drive letter to unmap
//
// Return: None
//
// Comments: We will always bypass csc for roaming share.
// There are two reason behind this :
// o csc mark entire server offline even if only
// one share goes offline. This is a bad design
// from csc perspective and they need to fix it
// o If csc is turned on in the roaming share server
// then both csc and profile will try to sync files
// on top of one another and we will be in a inconsistent
// state
//
// History: Date Author Comment
// 10/29/00 santanuc Created
//
//*************************************************************
void CancelCSCBypassedConnection(HANDLE hTokenUser, TCHAR cDrive) { DWORD dwError; TCHAR szDrive[3]; HANDLE hOldToken;
if (!ImpersonateUser(hTokenUser, &hOldToken)) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("CancelCSCBypassedConnection: Failed to impersonate user with %d."), dwError)); return ; }
szDrive[0] = cDrive; szDrive[1] = TEXT(':'); szDrive[2] = TEXT('\0'); DebugMsg((DM_VERBOSE, TEXT("CancelCSCBypassedConnection: Cancelling connection of %s"), szDrive));
__try { dwError = NPCancelConnectionForCSCAgent(szDrive, TRUE); } __except(EXCEPTION_EXECUTE_HANDLER) { dwError = GetLastError(); DebugMsg((DM_WARNING, TEXT("CancelCSCBypassedConnection: Took exception in NPCancelConnectionForCSCAgent. Error %d"), dwError)); }
if (dwError != WN_SUCCESS) { DebugMsg((DM_WARNING, TEXT("CancelCSCBypassedConnection: Fail to delete connection. Error returned %d"), dwError)); } else { DebugMsg((DM_VERBOSE, TEXT("CancelCSCBypassedConnection: Connection deleted."))); }
RevertToUser(&hOldToken);
}
//*************************************************************
//
// GetNetworkProvider()
//
// Purpose: Determine network provider for a share
//
// Parameters:
//
// Return: DWORD
//
// Comments: Returns ERROR_BAD_PROVIDER if provider is other
// than microsoft SMB provider otherwise return
// NO_ERROR.
//
// History: Date Author Comment
// 03/08/01 santanuc Created
//
//*************************************************************
DWORD GetNetworkProvider(NETRESOURCE *psNR) { PFNWNETGETRESOURCEINFORMATION pfnWNetGetResourceInformation; HMODULE hWNetLib = NULL; NETRESOURCE dNR; LPBYTE pbBuffer = (LPBYTE)&dNR; DWORD cbBuffer = sizeof(dNR); DWORD dwError = NO_ERROR; LPTSTR lpSystem = NULL; TCHAR szSMBProvider[100]; HKEY hKeyProvider = NULL; DWORD dwSize, dwType;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_PROVIDER, 0, KEY_READ, &hKeyProvider) != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("GetNetworkProvider: Failed to open network provider key. Error %d"), GetLastError())); goto Exit; } dwSize = ARRAYSIZE(szSMBProvider); if (RegQueryValueEx(hKeyProvider, PROVIDER_NAME, NULL, &dwType, (LPBYTE) szSMBProvider, &dwSize) != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("GetNetworkProvider: Failed to get network provider name. Error %d"), GetLastError())); goto Exit; }
if (!(hWNetLib = LoadLibrary(TEXT("mpr.dll")))) { DebugMsg((DM_WARNING, TEXT("GetNetworkProvider: LoadLibrary failed with %d"), GetLastError())); goto Exit; } pfnWNetGetResourceInformation = (PFNWNETGETRESOURCEINFORMATION)GetProcAddress(hWNetLib, "WNetGetResourceInformationW"); if (!pfnWNetGetResourceInformation) { DebugMsg((DM_WARNING, TEXT("GetNetworkProvider: GetProcAddress failed with %d"), GetLastError())); goto Exit; } dwError = (*pfnWNetGetResourceInformation)(psNR, pbBuffer, &cbBuffer, &lpSystem); if (ERROR_MORE_DATA == dwError) { pbBuffer = LocalAlloc(LPTR, cbBuffer); if (!pbBuffer) { DebugMsg((DM_WARNING, TEXT("AbleToBypassCSC: Failed to impersonate user with %d."), GetLastError())); goto Exit; } dwError = (*pfnWNetGetResourceInformation)(psNR, pbBuffer, &cbBuffer, &lpSystem); }
if (NO_ERROR == dwError) { if (lstrcmpi(((NETRESOURCE *)pbBuffer)->lpProvider, szSMBProvider) != 0) { dwError = ERROR_BAD_PROVIDER; goto Exit; } }
dwError = NO_ERROR;
Exit:
if (hKeyProvider) { RegCloseKey(hKeyProvider); }
if (pbBuffer && (pbBuffer != (LPBYTE)&dNR)) { LocalFree(pbBuffer); }
if (hWNetLib) { FreeLibrary(hWNetLib); }
return dwError; } //*************************************************************
//
// GetUserNameFromSid()
//
// Purpose: Returns the user name in domain\user format
//
// Parameters: lpSidString - User's sid string
//
// Return: LPTSTR : domain\user name if succeeds
// lpSidString if fails
//
// Comments:
//
// History: Date Author Comment
// 10/31/00 santanuc Created
//
//*************************************************************
LPTSTR GetUserNameFromSid(LPTSTR lpSidString) { PSID pSidUser = NULL; LPTSTR lpRetVal = lpSidString; TCHAR szUserName[MAX_PATH], szDomainName[MAX_PATH]; DWORD dwUserSize = MAX_PATH, dwDomainSize = MAX_PATH; SID_NAME_USE TypeOfAccount; DWORD cchRetVal;
//
// Get the user sid
//
if (AllocateAndInitSidFromString(lpSidString, &pSidUser) != STATUS_SUCCESS) { DebugMsg((DM_WARNING, TEXT("GetUserNameFromSid: Failed to create user sid."))); goto Exit; }
//
// Get the user and domain name
//
if (!LookupAccountSid(NULL, pSidUser, szUserName, &dwUserSize, szDomainName, &dwDomainSize, &TypeOfAccount)) { DebugMsg((DM_WARNING, TEXT("GetUserNameFromSid: LookupAccountSid failed with error %d."), GetLastError())); goto Exit; }
cchRetVal = lstrlen(szUserName) + lstrlen(szDomainName) + 2; lpRetVal = (LPTSTR)LocalAlloc(LPTR, cchRetVal * sizeof(TCHAR)); if (!lpRetVal) { DebugMsg((DM_WARNING, TEXT("GetUserNameFromSid: Memory alloaction failure. error %d"), GetLastError())); lpRetVal = lpSidString; goto Exit; } // Construct the return string
StringCchCopy(lpRetVal, cchRetVal, szDomainName); StringCchCat(lpRetVal, cchRetVal, TEXT("\\")); StringCchCat(lpRetVal, cchRetVal, szUserName);
Exit: if (pSidUser) { LocalFree(pSidUser); }
return lpRetVal; }
//*************************************************************
//
// TakeOwnership()
//
// Purpose: Take ownership of a file or directory
//
// Parameters: lpFileName - file or directory name to work on
//
// Return: S_OK for success, else for error
//
// Comments:
//
// History: Date Author Comment
// 04/08/2002 mingzhu Created
//
//*************************************************************
HRESULT TakeOwnership(LPTSTR lpFileName) { HRESULT hr = E_FAIL; DWORD dwErr; PSID pSID = NULL; NTSTATUS status; BOOLEAN bTakeOwnerWasEnabled; BOOL bTakeOwnerEnabled = FALSE; SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
//
// Output a debug message
//
DebugMsg((DM_VERBOSE, TEXT("TakeOwnership : Taking ownership of %s ..."), lpFileName));
//
// Enable SE_TAKE_OWNERSHIP_NAME priviledge
//
status = RtlAdjustPrivilege(SE_TAKE_OWNERSHIP_PRIVILEGE, TRUE, FALSE, &bTakeOwnerWasEnabled);
if(!NT_SUCCESS(status)) { hr = HRESULT_FROM_WIN32(RtlNtStatusToDosError(status)); DebugMsg((DM_WARNING, TEXT("TakeOwnership: RtlAdjustPrivilege failed, error = %08x"), hr)); goto Exit; }
//
// Create a SID for the BUILTIN\Administrators group.
//
if (!AllocateAndInitializeSid(&SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSID)) { hr = HRESULT_FROM_WIN32(GetLastError()); DebugMsg((DM_WARNING, TEXT("TakeOwnership: AllocateAndInitializeSid failed, error = %08x"), hr)); goto Exit; }
//
// Set the owner in the object's security descriptor.
//
dwErr = SetNamedSecurityInfo(lpFileName, // name of the object
SE_FILE_OBJECT, // type of object
OWNER_SECURITY_INFORMATION, // change only the object's owner
pSID, // SID of Administrator group
NULL, NULL, NULL); if (dwErr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(dwErr); DebugMsg((DM_WARNING, TEXT("TakeOwnership: SetNamedSecurityInfo failed, error = %08x"), hr)); goto Exit; }
//
// We're done!
//
DebugMsg((DM_VERBOSE, TEXT("TakeOwnership : Success!"))); hr = S_OK; Exit:
if (bTakeOwnerEnabled && !bTakeOwnerWasEnabled) { status = RtlAdjustPrivilege(SE_TAKE_OWNERSHIP_PRIVILEGE, FALSE, FALSE, &bTakeOwnerWasEnabled); if(!NT_SUCCESS(status)) { DebugMsg((DM_WARNING, TEXT("TakeOwnership: RtlAdjustPrivilege failed, error = %08x"), status)); } }
if (pSID) { FreeSid(pSID); }
return hr; }
//*************************************************************
//
// AddAdminAccess()
//
// Purpose: Add administrators full access to a file or directory
//
// Parameters: lpFileName - file or directory name to work on
//
// Return: S_OK for success, else for error
//
// Comments:
//
// History: Date Author Comment
// 04/08/2002 mingzhu Created
//
//*************************************************************
HRESULT AddAdminAccess(LPTSTR lpFileName) { HRESULT hr = E_FAIL; DWORD dwErr; PSECURITY_DESCRIPTOR pSD = NULL; PACL pOldDACL = NULL; PACL pNewDACL = NULL; EXPLICIT_ACCESS ea;
//
// Output a debug message
//
DebugMsg((DM_VERBOSE, TEXT("AddAdminAccess : Adding administrators access to %s."), lpFileName));
//
// Get the old DACL in the file.
//
dwErr = GetNamedSecurityInfo(lpFileName, // name of the object
SE_FILE_OBJECT, // type of object
DACL_SECURITY_INFORMATION, // change only the object's owner
NULL, NULL, &pOldDACL, NULL, // DACL to get
&pSD); // Security Descriptor of the file
if (dwErr != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("AddAdminAccess : GetNamedSecurityInfo failed with %d"), dwErr)); hr = HRESULT_FROM_WIN32(dwErr); goto Exit; }
//
// Initialize an EXPLICIT_ACCESS structure for the new ACE (admin full access).
//
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = FILE_ALL_ACCESS; ea.grfAccessMode = GRANT_ACCESS; ea.grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea.Trustee.pMultipleTrustee = NULL; ea.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea.Trustee.ptstrName = TEXT("Administrators");
//
// Create a new ACL that merges the new ACE into the existing DACL.
//
dwErr = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL); if (ERROR_SUCCESS != dwErr) { DebugMsg((DM_WARNING, TEXT("AddAdminAccess : SetEntriesInAcl failed. Error = %d"), dwErr)); hr = HRESULT_FROM_WIN32(dwErr); goto Exit; }
//
// Set the owner in the object's security descriptor.
//
dwErr = SetNamedSecurityInfo(lpFileName, // name of the object
SE_FILE_OBJECT, // type of object
DACL_SECURITY_INFORMATION, // change only the object's owner
NULL, NULL, pNewDACL, NULL); // DACL to be set
if (dwErr != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("AddAdminAccess : SetNamedSecurityInfo failed with %d"), dwErr)); hr = HRESULT_FROM_WIN32(dwErr); goto Exit; }
//
// We're done!
//
DebugMsg((DM_VERBOSE, TEXT("AddAdminAccess : Success!"))); hr = S_OK;
Exit:
if(pNewDACL != NULL) LocalFree(pNewDACL);
if(pSD != NULL) LocalFree(pSD); return hr; }
//*************************************************************
//
// Routine Description:
//
// This routine determines if we're doing a gui-mode setup.
//
// This value is retrieved from the following registry location:
//
// \HKLM\System\Setup\ //
// SystemSetupInProgress : REG_DWORD : 0x00 (where nonzero
// means we're doing a gui-setup)
//
// Arguments:
//
// None.
//
// Return Value:
//
// TRUE/FALSE
//
// Note:
//
// This function is courtesy of Andrew Ritz and the Setup API.
// It's copied over from base\pnp\setupapi\dll.c.
//
//***************************************************************
BOOL IsGuiSetupInProgress() { HKEY hKey; DWORD Err, DataType, DataSize = sizeof(DWORD); DWORD Value;
if((Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("System\\Setup"), 0, KEY_READ, &hKey)) == ERROR_SUCCESS) { //
// Attempt to read the the "DriverCachePath" value.
//
Err = RegQueryValueEx( hKey, TEXT("SystemSetupInProgress"), NULL, &DataType, (LPBYTE)&Value, &DataSize);
RegCloseKey(hKey); }
if(Err == NO_ERROR) { if(Value) { return(TRUE); } }
return(FALSE);
}
//*************************************************************
//
// Description:
//
// This function will setup a new key under the ProfileList\{sid}
// entry and give the specified user write permittion to it in order
// to change his/her preference.
//
// Arguments:
//
// lpSidString - String format of the sid indicate which entry we will work on.
//
// Return Value:
//
// S_OK for success, else for failure
//
// Note:
//
// History: Date Author Comment
// 04/19/2002 mingzhu Created
//
//***************************************************************
HRESULT SetupPreferenceKey(LPCTSTR lpSidString) { HRESULT hr = E_FAIL; LONG lResult; DWORD dwResult;
TCHAR szKeyName[MAX_PATH]; HKEY hKey = NULL; PSID psidUser = NULL; PACL pOldDACL = NULL; PACL pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL; EXPLICIT_ACCESS ea;
DebugMsg((DM_VERBOSE, TEXT("SetupPreferenceKey: Setting up the preference key for <%s>"), lpSidString));
//
// Construct the key name
//
hr = StringCchPrintf(szKeyName, ARRAYSIZE(szKeyName), TEXT("%s\\%s\\%s"), PROFILE_LIST_PATH, lpSidString, PREFERENCE_KEYNAME);
if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("SetupPreferenceKey: Failed to make key name, hr = %08X"), hr)); goto Exit; }
//
// Create the "Preference" key, using default security (inherited)
//
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("SetupPreferenceKey: RegCreateKeyEx failed. Error = %d"), lResult)); hr = HRESULT_FROM_WIN32(lResult); goto Exit; }
//
// Get the user's sid from its string form
//
if (!ConvertStringSidToSid(lpSidString, &psidUser)) { dwResult = GetLastError(); DebugMsg((DM_WARNING, TEXT("SetupPreferenceKey: ConvertStringSidToSid failed. Error = %d"), dwResult)); hr = HRESULT_FROM_WIN32(dwResult); goto Exit; }
//
// Get a pointer to the existing DACL and its SD
//
dwResult = GetSecurityInfo(hKey, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, &pSD); if (dwResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("SetupPreferenceKey: GetSecurityInfo failed. Error = %d"), dwResult)); hr = HRESULT_FROM_WIN32(dwResult); goto Exit; }
//
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
//
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = KEY_READ | KEY_SET_VALUE; ea.grfAccessMode = GRANT_ACCESS; ea.grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; ea.Trustee.TrusteeType = TRUSTEE_IS_USER; ea.Trustee.ptstrName = psidUser;
//
// Create a new ACL that merges the new ACE into the existing DACL.
//
dwResult = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL); if (dwResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("SetupPreferenceKey: SetEntriesInAcl failed. Error = %d"), dwResult)); hr = HRESULT_FROM_WIN32(dwResult); goto Exit; }
//
// Attach the new ACL to the key
//
dwResult = SetSecurityInfo(hKey, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL); if (dwResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("SetupPreferenceKey: SetSecurityInfo failed. Error = %d"), dwResult)); hr = HRESULT_FROM_WIN32(dwResult); goto Exit; }
DebugMsg((DM_VERBOSE, TEXT("SetupPreferenceKey: Successfully setup the preference key for <%s>"), lpSidString));
hr = S_OK;
Exit:
if(pSD) LocalFree(pSD);
if(pNewDACL) LocalFree(pNewDACL);
if (psidUser) LocalFree(psidUser);
if (hKey) RegCloseKey(hKey); return hr; }
|