1646 lines
37 KiB
C
1646 lines
37 KiB
C
//*************************************************************
|
|
//
|
|
// Utility functions
|
|
//
|
|
// Microsoft Confidential
|
|
// Copyright (c) Microsoft Corporation 1995
|
|
// All rights reserved
|
|
//
|
|
//*************************************************************
|
|
|
|
#include "uenv.h"
|
|
|
|
#define TYPICAL_STRING_LENGTH 60
|
|
|
|
//*************************************************************
|
|
//
|
|
// 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)
|
|
{
|
|
DWORD dwStrLen;
|
|
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 - Directory
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/10/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL Delnode_Recurse (LPTSTR lpDir)
|
|
{
|
|
WIN32_FIND_DATA fd;
|
|
HANDLE hFile;
|
|
|
|
//
|
|
// Verbose output
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: Entering, lpDir = <%s>"), lpDir));
|
|
|
|
|
|
//
|
|
// Setup the current working dir
|
|
//
|
|
|
|
if (!SetCurrentDirectory (lpDir)) {
|
|
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to set current working directory. Error = %d"), GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Find the first file
|
|
//
|
|
|
|
hFile = FindFirstFile(c_szStarDotStar, &fd);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
|
|
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
|
return TRUE;
|
|
} else {
|
|
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: FindFirstFile failed. Error = %d"),
|
|
GetLastError()));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
do {
|
|
//
|
|
// Verbose output
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: FindFile found: <%s>"),
|
|
fd.cFileName));
|
|
|
|
//
|
|
// Check for "." and ".."
|
|
//
|
|
|
|
if (!lstrcmpi(fd.cFileName, c_szDot)) {
|
|
continue;
|
|
}
|
|
|
|
if (!lstrcmpi(fd.cFileName, c_szDotDot)) {
|
|
continue;
|
|
}
|
|
|
|
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
|
|
//
|
|
// Found a directory.
|
|
//
|
|
|
|
if (!Delnode_Recurse(fd.cFileName)) {
|
|
FindClose(hFile);
|
|
return FALSE;
|
|
}
|
|
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
|
|
fd.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
|
|
SetFileAttributes (fd.cFileName, fd.dwFileAttributes);
|
|
}
|
|
|
|
|
|
if (!RemoveDirectory (fd.cFileName)) {
|
|
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to delete directory <%s>. Error = %d"),
|
|
fd.cFileName, GetLastError()));
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// We found a file. Set the file attributes,
|
|
// and try to delete it.
|
|
//
|
|
|
|
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
|
|
(fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
|
|
SetFileAttributes (fd.cFileName, FILE_ATTRIBUTE_NORMAL);
|
|
}
|
|
|
|
if (!DeleteFile (fd.cFileName)) {
|
|
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to delete <%s>. Error = %d"),
|
|
fd.cFileName, GetLastError()));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Find the next entry
|
|
//
|
|
|
|
} while (FindNextFile(hFile, &fd));
|
|
|
|
|
|
//
|
|
// Close the search handle
|
|
//
|
|
|
|
FindClose(hFile);
|
|
|
|
|
|
//
|
|
// Reset the working directory
|
|
//
|
|
|
|
if (!SetCurrentDirectory (c_szDotDot)) {
|
|
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to reset current working directory. Error = %d"), GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Success.
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: Leaving <%s>"), lpDir));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// 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
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL Delnode (LPTSTR lpDir)
|
|
{
|
|
TCHAR szCurWorkingDir[MAX_PATH];
|
|
|
|
if (GetCurrentDirectory(MAX_PATH, szCurWorkingDir)) {
|
|
|
|
Delnode_Recurse (lpDir);
|
|
|
|
SetCurrentDirectory (szCurWorkingDir);
|
|
|
|
if (!RemoveDirectory (lpDir)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("Delnode: Failed to delete directory <%s>. Error = %d"),
|
|
lpDir, GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("Delnode: Failed to get current working directory. Error = %d"), GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// CreateNestedDirectory()
|
|
//
|
|
// Purpose: Creates a subdirectory and all it's parents
|
|
// if necessary.
|
|
//
|
|
// Parameters: lpDirectory - Directory name
|
|
// lpSecurityAttributes - Security Attributes
|
|
//
|
|
// Return: > 0 if successful
|
|
// 0 if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/08/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
UINT CreateNestedDirectory(LPCTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
|
{
|
|
TCHAR szDirectory[MAX_PATH];
|
|
LPTSTR lpEnd;
|
|
|
|
//
|
|
// Check for NULL pointer
|
|
//
|
|
|
|
if (!lpDirectory || !(*lpDirectory)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: Received a NULL pointer.")));
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// First, see if we can create the directory without having
|
|
// to build parent directories.
|
|
//
|
|
|
|
if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// If this directory exists already, this is OK too.
|
|
//
|
|
|
|
if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
|
return ERROR_ALREADY_EXISTS;
|
|
}
|
|
|
|
|
|
//
|
|
// No luck, copy the string to a buffer we can munge
|
|
//
|
|
|
|
lstrcpy (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 (!CreateDirectory (szDirectory, NULL)) {
|
|
|
|
if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: CreateDirectory failed with %d."), GetLastError()));
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
*lpEnd = TEXT('\\');
|
|
lpEnd++;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Create the final directory
|
|
//
|
|
|
|
if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
|
|
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)
|
|
{
|
|
TCHAR szDirectory[MAX_PATH];
|
|
DWORD dwLength;
|
|
BOOL bRetVal = FALSE;
|
|
|
|
ExpandEnvironmentStrings(PROFILES_DIR, szDirectory, MAX_PATH);
|
|
dwLength = lstrlen(szDirectory) + 1;
|
|
|
|
if (lpProfilesDir) {
|
|
|
|
if (*lpcchSize >= dwLength) {
|
|
lstrcpy (lpProfilesDir, szDirectory);
|
|
bRetVal = TRUE;
|
|
|
|
} else {
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
}
|
|
}
|
|
|
|
|
|
*lpcchSize = dwLength;
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// 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;
|
|
|
|
|
|
//
|
|
// Parameter check
|
|
//
|
|
|
|
if (!hToken) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Retrieve the user's sid string
|
|
//
|
|
|
|
lpSidString = GetSidString(hToken);
|
|
|
|
if (!lpSidString) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Check the registry
|
|
//
|
|
|
|
lstrcpy(szBuffer, PROFILE_LIST_PATH);
|
|
lstrcat(szBuffer, TEXT("\\"));
|
|
lstrcat(szBuffer, lpSidString);
|
|
|
|
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ,
|
|
&hKey);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DeleteSidString(lpSidString);
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegQueryValueEx(hKey,
|
|
PROFILE_IMAGE_VALUE_NAME,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE) szBuffer,
|
|
&dwLength);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
RegCloseKey (hKey);
|
|
DeleteSidString(lpSidString);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Clean up
|
|
//
|
|
|
|
RegCloseKey(hKey);
|
|
DeleteSidString(lpSidString);
|
|
|
|
|
|
|
|
//
|
|
// Expand and get the length of string
|
|
//
|
|
|
|
ExpandEnvironmentStrings(szBuffer, szDirectory, MAX_PATH);
|
|
|
|
dwLength = lstrlen(szDirectory) + 1;
|
|
|
|
|
|
//
|
|
// Save the string if appropriate
|
|
//
|
|
|
|
if (lpProfileDir) {
|
|
|
|
if (*lpcchSize >= dwLength) {
|
|
lstrcpy (lpProfileDir, szDirectory);
|
|
bRetVal = TRUE;
|
|
|
|
} else {
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
}
|
|
}
|
|
|
|
|
|
*lpcchSize = dwLength;
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// RegDelnodeRecurse()
|
|
//
|
|
// Purpose: Deletes a registry key and all it's subkeys / values.
|
|
// Called by RegDelnode
|
|
//
|
|
// Parameters: hKeyRoot - Root key
|
|
// lpSubKey - SubKey to delete
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/3/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL RegDelnodeRecurse (HKEY hKeyRoot, LPTSTR lpSubKey)
|
|
{
|
|
LPTSTR lpEnd;
|
|
LONG lResult;
|
|
DWORD dwSize;
|
|
TCHAR szName[MAX_PATH];
|
|
HKEY hKey;
|
|
FILETIME ftWrite;
|
|
|
|
//
|
|
// First, see if we can delete the key without having
|
|
// to recurse.
|
|
//
|
|
|
|
|
|
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
lpEnd = CheckSlash(lpSubKey);
|
|
|
|
//
|
|
// Enumerate the keys
|
|
//
|
|
|
|
dwSize = MAX_PATH;
|
|
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
|
NULL, NULL, &ftWrite);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
|
|
do {
|
|
|
|
lstrcpy (lpEnd, szName);
|
|
|
|
if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Enumerate again
|
|
//
|
|
|
|
dwSize = MAX_PATH;
|
|
|
|
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
|
NULL, NULL, &ftWrite);
|
|
|
|
|
|
} while (lResult == ERROR_SUCCESS);
|
|
}
|
|
|
|
lpEnd--;
|
|
*lpEnd = TEXT('\0');
|
|
|
|
|
|
RegCloseKey (hKey);
|
|
|
|
|
|
//
|
|
// Try again to delete the key
|
|
//
|
|
|
|
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// RegDelnode()
|
|
//
|
|
// Purpose: Deletes a registry key and all it's subkeys / values
|
|
//
|
|
// Parameters: hKeyRoot - Root key
|
|
// lpSubKey - SubKey to delete
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/3/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL RegDelnode (HKEY hKeyRoot, LPTSTR lpSubKey)
|
|
{
|
|
TCHAR szDelKey[2 * MAX_PATH];
|
|
|
|
|
|
lstrcpy (szDelKey, lpSubKey);
|
|
|
|
return RegDelnodeRecurse(hKeyRoot, szDelKey);
|
|
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// 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
|
|
//
|
|
//*************************************************************
|
|
|
|
VOID DeleteAllValues(HKEY hKey)
|
|
{
|
|
TCHAR ValueName[MAX_PATH+1];
|
|
DWORD dwSize = MAX_PATH+1;
|
|
|
|
while (RegEnumValue(hKey, 0, ValueName, &dwSize,
|
|
NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
|
|
|
|
if (RegDeleteValue(hKey, ValueName) != ERROR_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
dwSize = MAX_PATH+1;
|
|
}
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// OpenHKeyCurrentUser()
|
|
//
|
|
// Purpose: Opens HKEY_CURRENT_USER to point at the current logged
|
|
// on user's profile.
|
|
//
|
|
// Parameters: lpProfile - Profile Information
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/13/95 ericflo Ported
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL OpenHKeyCurrentUser(LPPROFILE lpProfile)
|
|
{
|
|
|
|
//
|
|
// Make sure HKEY_CURRENT_USER is closed before
|
|
// remapping it.
|
|
//
|
|
|
|
try {
|
|
|
|
RegCloseKey(HKEY_CURRENT_USER);
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {};
|
|
|
|
|
|
//
|
|
// Impersonate the user
|
|
//
|
|
|
|
if (!ImpersonateLoggedOnUser(lpProfile->hToken)) {
|
|
DebugMsg((DM_WARNING, TEXT("OpenHKeyCurrentUser: Failed to impersonate user")));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Access the registry to force HKEY_CURRENT_USER to be re-opened
|
|
//
|
|
|
|
RegEnumKey(HKEY_CURRENT_USER, 0, NULL, 0);
|
|
|
|
|
|
//
|
|
// Revert to being 'ourself'
|
|
//
|
|
|
|
if (!RevertToSelf()) {
|
|
DebugMsg((DM_WARNING, TEXT("OpenHKeyCurrentUser: Failed to revert to self")));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// CloseHKeyCurrentUser()
|
|
//
|
|
// Purpose: Closes HKEY_CURRENT_USER
|
|
//
|
|
// Parameters: lpProfile - Profile Information
|
|
//
|
|
// Return: void
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/13/95 ericflo Ported
|
|
//
|
|
//*************************************************************
|
|
|
|
VOID CloseHKeyCurrentUser(LPPROFILE lpProfile)
|
|
{
|
|
RegCloseKey(HKEY_CURRENT_USER);
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// MakeFileSecure()
|
|
//
|
|
// Purpose: Sets the attributes on the file so only Administrators
|
|
// and the OS can delete it. Everyone else has 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
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL MakeFileSecure (LPTSTR lpFile)
|
|
{
|
|
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, psidEveryone = NULL;
|
|
DWORD cbAcl, aceIndex;
|
|
ACE_HEADER * lpAceHeader;
|
|
BOOL bRetVal = 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("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 World sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authWorld, 1, SECURITY_WORLD_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidEveryone)) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("MakeFileSecure: Failed to initialize world sid. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate space for the ACL
|
|
//
|
|
|
|
cbAcl = (3 * GetLengthSid (psidSystem)) +
|
|
(3 * 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_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, 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, 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 (psidEveryone) {
|
|
FreeSid(psidEveryone);
|
|
}
|
|
|
|
|
|
if (pAcl) {
|
|
GlobalFree (pAcl);
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetProgramsDirectory()
|
|
//
|
|
// Purpose: Retrieves the programs directory for the current
|
|
// user, or returns Default User's if not found.
|
|
//
|
|
// Parameters: bCommonGroup - Common or personal
|
|
// lpDirectory - Result
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments: lpDirectory is assumed to be MAX_PATH chars long
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/20/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL GetProgramsDirectory (BOOL bCommonGroup, LPTSTR lpDirectory)
|
|
{
|
|
LONG lResult;
|
|
HKEY hKey;
|
|
DWORD dwType, dwSize;
|
|
TCHAR szDirectory[MAX_PATH];
|
|
UINT uID;
|
|
BOOL bRetVal = FALSE;
|
|
|
|
|
|
//
|
|
// Open the User Shell Folders in the registry
|
|
//
|
|
|
|
|
|
lResult = RegOpenKeyEx (HKEY_CURRENT_USER, USER_SHELL_FOLDER, 0,
|
|
KEY_READ, &hKey);
|
|
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("GetProgramsDirectory: Failed to open registry. %d"), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Now query for the programs directory
|
|
//
|
|
|
|
dwSize = MAX_PATH * sizeof(TCHAR);
|
|
szDirectory[0] = TEXT('\0');
|
|
|
|
if (bCommonGroup) {
|
|
|
|
lResult = RegQueryValueEx (hKey, c_CommonShellFolders[2].lpFolderName,
|
|
NULL, &dwType, (LPBYTE) szDirectory, &dwSize);
|
|
} else {
|
|
|
|
lResult = RegQueryValueEx (hKey, c_ShellFolders[10].lpFolderName,
|
|
NULL, &dwType, (LPBYTE) szDirectory, &dwSize);
|
|
}
|
|
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("GetProgramsDirectory: Failed to query for registry value. %d"), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Did we find anything?
|
|
//
|
|
|
|
if (szDirectory[0] == TEXT('\0')) {
|
|
DebugMsg((DM_WARNING, TEXT("GetProgramsDirectory: NULL special folder name")));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Save the result
|
|
//
|
|
|
|
|
|
if (ExpandEnvironmentStrings(szDirectory, lpDirectory, MAX_PATH)) {
|
|
bRetVal = TRUE;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if (!bRetVal) {
|
|
|
|
//
|
|
// Load the default programs location
|
|
//
|
|
|
|
if (bCommonGroup) {
|
|
uID = IDS_COMMON_PROGRAMS;
|
|
} else {
|
|
uID = IDS_DEFAULT_PROGRAMS;
|
|
}
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("GetProgramsDirectory: Loading Default User programs dir !!!")));
|
|
|
|
if (LoadString(g_hDllInstance, uID, szDirectory, MAX_PATH)) {
|
|
|
|
if (ExpandEnvironmentStrings(szDirectory, lpDirectory, MAX_PATH)) {
|
|
bRetVal = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return bRetVal;
|
|
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetDesktopDirectory()
|
|
//
|
|
// Purpose: Retrieves the Desktop directory for the current
|
|
// user, or returns Default User's if not found.
|
|
//
|
|
// Parameters: bCommonGroup - Common or personal
|
|
// lpDirectory - Result
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments: lpDirectory is assumed to be MAX_PATH chars long
|
|
//
|
|
// History: Date Author Comment
|
|
// 4/2/96 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL GetDesktopDirectory (BOOL bCommonGroup, LPTSTR lpDirectory)
|
|
{
|
|
LONG lResult;
|
|
HKEY hKey;
|
|
DWORD dwType, dwSize;
|
|
TCHAR szDirectory[MAX_PATH];
|
|
UINT uID;
|
|
BOOL bRetVal = FALSE;
|
|
|
|
|
|
//
|
|
// Open the User Shell Folders in the registry
|
|
//
|
|
|
|
|
|
lResult = RegOpenKeyEx (HKEY_CURRENT_USER, USER_SHELL_FOLDER, 0,
|
|
KEY_READ, &hKey);
|
|
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Now query for the Desktop directory
|
|
//
|
|
|
|
dwSize = MAX_PATH * sizeof(TCHAR);
|
|
szDirectory[0] = TEXT('\0');
|
|
|
|
if (bCommonGroup) {
|
|
|
|
lResult = RegQueryValueEx (hKey, c_CommonShellFolders[0].lpFolderName,
|
|
NULL, &dwType, (LPBYTE) szDirectory, &dwSize);
|
|
} else {
|
|
|
|
lResult = RegQueryValueEx (hKey, c_ShellFolders[1].lpFolderName,
|
|
NULL, &dwType, (LPBYTE) szDirectory, &dwSize);
|
|
}
|
|
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Did we find anything?
|
|
//
|
|
|
|
if (szDirectory[0] == TEXT('\0')) {
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Save the result
|
|
//
|
|
|
|
|
|
if (ExpandEnvironmentStrings(szDirectory, lpDirectory, MAX_PATH)) {
|
|
bRetVal = TRUE;
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if (!bRetVal) {
|
|
|
|
//
|
|
// Load the default Desktop location
|
|
//
|
|
|
|
if (bCommonGroup) {
|
|
uID = IDS_COMMON_DESKTOP;
|
|
} else {
|
|
uID = IDS_DEFAULT_DESKTOP;
|
|
}
|
|
|
|
if (LoadString(g_hDllInstance, uID, szDirectory, MAX_PATH)) {
|
|
|
|
if (ExpandEnvironmentStrings(szDirectory, lpDirectory, MAX_PATH)) {
|
|
bRetVal = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return bRetVal;
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// 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_TOPMOST, 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 (MAX_PATH chars in 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)
|
|
{
|
|
TCHAR szSysRoot[MAX_PATH];
|
|
LPTSTR lpFileName;
|
|
DWORD dwSysLen;
|
|
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
ExpandEnvironmentStrings (TEXT("%SystemRoot%"), szSysRoot, MAX_PATH);
|
|
dwSysLen = lstrlen(szSysRoot);
|
|
|
|
|
|
//
|
|
// Make sure the source is long enough
|
|
//
|
|
|
|
if ((DWORD)lstrlen(lpFile) < dwSysLen) {
|
|
lstrcpy (lpResult, lpFile);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
if (CompareString (LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
|
|
szSysRoot, dwSysLen,
|
|
lpFile, dwSysLen) == 2) {
|
|
|
|
//
|
|
// The szReturn buffer starts with %systemroot%.
|
|
// Actually insert %systemroot% in the result buffer.
|
|
//
|
|
|
|
lstrcpy (lpResult, TEXT("%SystemRoot%"));
|
|
lstrcat (lpResult, (lpFile + dwSysLen));
|
|
|
|
|
|
} else {
|
|
|
|
//
|
|
// The szReturn buffer does not start with %systemroot%
|
|
// just copy in the original string.
|
|
//
|
|
|
|
lstrcpy (lpResult, 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;
|
|
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) + TYPICAL_STRING_LENGTH;
|
|
|
|
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()));
|
|
Free(String);
|
|
String = NULL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If the buffer was too small, make it bigger and try again
|
|
//
|
|
|
|
if (LengthCopied > LengthAllocated) {
|
|
|
|
String = LocalReAlloc(String, LengthCopied * sizeof(TCHAR), LMEM_MOVEABLE);
|
|
LengthAllocated = LengthCopied;
|
|
if (String == NULL) {
|
|
DebugMsg((DM_WARNING, TEXT("AllocAndExpandEnvironmentStrings: Failed to reallocate %d bytes for string"), LengthAllocated * sizeof(TCHAR)));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Go back and try to expand the string again
|
|
//
|
|
|
|
} else {
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return(String);
|
|
}
|