summaryrefslogtreecommitdiffstats
path: root/private/windows/gina/userenv/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/windows/gina/userenv/util.c')
-rw-r--r--private/windows/gina/userenv/util.c1645
1 files changed, 1645 insertions, 0 deletions
diff --git a/private/windows/gina/userenv/util.c b/private/windows/gina/userenv/util.c
new file mode 100644
index 000000000..fa9cc8d6f
--- /dev/null
+++ b/private/windows/gina/userenv/util.c
@@ -0,0 +1,1645 @@
+//*************************************************************
+//
+// 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);
+}