|
|
//*************************************************************
//
// Userdiff.c
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1995
// All rights reserved
//
//*************************************************************
#include "uenv.h"
#define MAX_KEY_NAME MAX_PATH
BOOL AddUDNode (LPUDNODE *lpList, LPTSTR lpBuildNumber); BOOL FreeUDList (LPUDNODE lpList); BOOL ProcessBuild(LPPROFILE lpProfile, LPUDNODE lpItem, LPVOID pEnv); BOOL ProcessHive(LPPROFILE lpProfile, LPUDNODE lpItem, HKEY hKey); BOOL ProcessFiles(LPPROFILE lpProfile, LPUDNODE lpItem, HKEY hKey); BOOL ProcessPrograms(LPPROFILE lpProfile, LPUDNODE lpItem, HKEY hKey, LPVOID pEnv); BOOL OkToProcessItem(DWORD dwProductType);
//*************************************************************
//
// ProcessUserDiff()
//
// Purpose: Processes the userdiff hive
//
// Parameters: lpProfile - Profile information
// dwBuildNumber - profile build #
// pEnv - Environment block
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/2/95 ericflo Created
//
//*************************************************************
BOOL ProcessUserDiff (LPPROFILE lpProfile, DWORD dwBuildNumber, LPVOID pEnv) { TCHAR szUserDiff[MAX_PATH] = {0}; TCHAR szName[MAX_KEY_NAME]; HANDLE hFile; WIN32_FIND_DATA fd; LPUDNODE lpList = NULL, lpItem; LONG lResult; HKEY hKeyUserDiff; UINT Index = 0; DWORD dwSize; FILETIME ftWrite;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("ProcessUserDiff: Entering.")));
//
// Test if the hive exists, first look for USERDIFR
//
ExpandUserEnvironmentStrings(pEnv, USERDIFR_LOCATION, szUserDiff, MAX_PATH); hFile = FindFirstFile (szUserDiff, &fd);
if (hFile == INVALID_HANDLE_VALUE) { DebugMsg((DM_VERBOSE, TEXT("ProcessUserDiff: userdifr hive doesn't exist. Trying userdiff.")));
ExpandUserEnvironmentStrings(pEnv, USERDIFF_LOCATION, szUserDiff, MAX_PATH); hFile = FindFirstFile (szUserDiff, &fd);
if (hFile == INVALID_HANDLE_VALUE) { DebugMsg((DM_WARNING, TEXT("ProcessUserDiff: userdiff hive doesn't exist. Leaving."))); return TRUE; } }
FindClose (hFile);
//
// Load the hive
//
if (MyRegLoadKey(HKEY_USERS, USERDIFF, szUserDiff) != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessUserDiff: Failed to load userdiff."))); return FALSE; }
//
// Open the key
//
lResult = RegOpenKeyEx(HKEY_USERS, USERDIFF, 0, KEY_READ, &hKeyUserDiff);
if (lResult != ERROR_SUCCESS) { MyRegUnLoadKey(HKEY_USERS, USERDIFF); DebugMsg((DM_WARNING, TEXT("ProcessUserDiff: failed to open registry root (%d)"), lResult)); return FALSE; }
//
// Enumerate the build numbers
//
dwSize = MAX_KEY_NAME; lResult = RegEnumKeyEx(hKeyUserDiff, Index, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
if (lResult == ERROR_SUCCESS) {
do {
//
// Add the node
//
if (!AddUDNode (&lpList, szName)) { break; }
Index++; dwSize = MAX_KEY_NAME;
lResult = RegEnumKeyEx(hKeyUserDiff, Index, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
} while (lResult == ERROR_SUCCESS); }
//
// Close the open key
//
RegCloseKey(hKeyUserDiff);
//
// Process the builds
//
lpItem = lpList;
while (lpItem) {
//
// Only want to apply changes that occurred in
// builds after the one the user is running.
//
if ( (lpItem->dwBuildNumber > dwBuildNumber) && (lpItem->dwBuildNumber <= g_dwBuildNumber) ) { ProcessBuild(lpProfile, lpItem, pEnv); }
lpItem = lpItem->pNext; }
//
// Free the link list
//
FreeUDList (lpList);
//
// Unload the hive
//
MyRegUnLoadKey(HKEY_USERS, USERDIFF);
//
// Success
//
DebugMsg((DM_VERBOSE, TEXT("ProcessUserDiff: Leaving successfully.")));
return TRUE;
}
//*************************************************************
//
// AddUDNode()
//
// Purpose: Adds a build node to the link listed
// sorted by build number
//
// Parameters: lpList - Link list of nodes
// lpBuildNumber - New node name
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
BOOL AddUDNode (LPUDNODE *lpList, LPTSTR lpBuildNumber) { LPUDNODE lpNewItem; LPUDNODE lpHead, lpPrev;
if (!lpBuildNumber || !*lpBuildNumber) { return TRUE; }
//
// Setup the new node
//
lpNewItem = (LPUDNODE) LocalAlloc(LPTR, sizeof(UDNODE));
if (!lpNewItem) { return FALSE; }
lstrcpy (lpNewItem->szBuildNumber, lpBuildNumber); lpNewItem->dwBuildNumber = StringToInt(lpBuildNumber); lpNewItem->pNext = NULL;
//
// Now add it to the list sorted
//
lpHead = *lpList; lpPrev = NULL;
if (!lpHead) {
//
// First item in the list
//
*lpList = lpNewItem;
return TRUE; }
//
// If we made it here, there is one or more items in the list
//
while (lpHead) {
if (lpNewItem->dwBuildNumber <= lpHead->dwBuildNumber) {
if (lpPrev) {
//
// Insert the item
//
lpPrev->pNext = lpNewItem; lpNewItem->pNext = lpHead; return TRUE;
} else {
//
// Head of the list
//
lpNewItem->pNext = lpHead; *lpList = lpNewItem; return TRUE;
}
}
lpPrev = lpHead; lpHead = lpHead->pNext; }
//
// Add node to the end of the list
//
lpPrev->pNext = lpNewItem;
return TRUE; }
//*************************************************************
//
// FreeUDList()
//
// Purpose: Free's a UDNODE link list
//
// Parameters: lpList - List to be freed
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
BOOL FreeUDList (LPUDNODE lpList) { LPUDNODE lpNext;
if (!lpList) { return TRUE; }
lpNext = lpList->pNext;
while (lpList) { LocalFree (lpList); lpList = lpNext;
if (lpList) { lpNext = lpList->pNext; } }
return TRUE; }
//*************************************************************
//
// ProcessBuild()
//
// Purpose: Processes the changes for a specific build
//
// Parameters: lpProfile - Profile information
// lpItem - Build item to process
// pEnv - Environment block
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
BOOL ProcessBuild(LPPROFILE lpProfile, LPUDNODE lpItem, LPVOID pEnv) { TCHAR szSubKey[MAX_PATH]; LONG lResult; HKEY hKey;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("ProcessBuild: Entering with build <%s>."), lpItem->szBuildNumber));
//
// Open "Hive" subkey
//
wsprintf (szSubKey, TEXT("%s\\%s\\Hive"), USERDIFF, lpItem->szBuildNumber); lResult = RegOpenKeyEx (HKEY_USERS, szSubKey, 0, KEY_READ, &hKey);
if (lResult == ERROR_SUCCESS) { ProcessHive(lpProfile, lpItem, hKey); RegCloseKey (hKey); }
//
// Open "Files" subkey
//
wsprintf (szSubKey, TEXT("%s\\%s\\Files"), USERDIFF, lpItem->szBuildNumber); lResult = RegOpenKeyEx (HKEY_USERS, szSubKey, 0, KEY_READ, &hKey);
if (lResult == ERROR_SUCCESS) { ProcessFiles(lpProfile, lpItem, hKey); RegCloseKey (hKey); }
//
// Open "Execute" subkey
//
wsprintf (szSubKey, TEXT("%s\\%s\\Execute"), USERDIFF, lpItem->szBuildNumber); lResult = RegOpenKeyEx (HKEY_USERS, szSubKey, 0, KEY_READ, &hKey);
if (lResult == ERROR_SUCCESS) { ProcessPrograms(lpProfile, lpItem, hKey, pEnv); RegCloseKey (hKey); }
//
// Success
//
DebugMsg((DM_VERBOSE, TEXT("ProcessBuild: Leaving successfully.")));
return TRUE;
}
//*************************************************************
//
// ProcessHive()
//
// Purpose: Processes the Hive entry for a build
//
// Parameters: lpProfile - Profile information
// lpItem - Build item
// hKey - Registry key to enumerate
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
BOOL ProcessHive(LPPROFILE lpProfile, LPUDNODE lpItem, HKEY hKey) { TCHAR szSubKey[MAX_PATH]; TCHAR szValueName[MAX_KEY_NAME]; DWORD dwSize, dwType, dwAction, dwDisp, dwFlags, dwProductType; LPBYTE lpValueData; LONG lResult; UINT Index = 1; FILETIME ftWrite; HKEY hKeyEntry, hKeyTemp; LPTSTR lpName;
DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Entering.")));
//
// Process the entry
//
wsprintf (szSubKey, TEXT("%s\\%s\\Hive\\%d"), USERDIFF, lpItem->szBuildNumber, Index); lResult = RegOpenKeyEx (HKEY_USERS, szSubKey, 0, KEY_READ, &hKeyEntry);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("ProcessHive: No hive entries."))); goto Exit; }
do {
//
// Query for the product type
//
dwSize = sizeof(dwProductType); lResult = RegQueryValueEx(hKeyEntry, UD_PRODUCTTYPE, NULL, &dwType, (LPBYTE)&dwProductType, &dwSize);
//
// It's ok to not have a product type listed in userdiff.ini.
// In this case, we always apply the change regardless of the
// platform.
//
if (lResult == ERROR_SUCCESS) {
//
// A specific product was listed. Check if
// we can process this entry.
//
if (!OkToProcessItem(dwProductType)) { DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Skipping Item %d due to product type mismatch."), Index)); goto LoopAgain; } }
//
// Query for the action type
//
dwSize = sizeof(dwAction); lResult = RegQueryValueEx(hKeyEntry, UD_ACTION, NULL, &dwType, (LPBYTE)&dwAction, &dwSize);
if (lResult == ERROR_SUCCESS) {
switch (dwAction) {
DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Item %d has an action of %d."), Index, dwAction));
case 1: { //
// Add New Key
//
// Get the key name
//
dwSize = MAX_PATH * sizeof(TCHAR); lResult = RegQueryValueEx(hKeyEntry, UD_KEYNAME, NULL, &dwType, (LPBYTE)szSubKey, &dwSize);
if (lResult == ERROR_SUCCESS) {
lResult = RegCreateKeyEx (lpProfile->hKeyCurrentUser, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyTemp, &dwDisp);
if (lResult == ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Created subkey <%s>."), szSubKey));
RegCloseKey(hKeyTemp); } else {
DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to create subkey <%s> with error %d."), szSubKey, lResult)); } }
} break;
case 2: { //
// Delete a key and all it's subkeys
//
// Get the key name
//
dwSize = MAX_PATH * sizeof(TCHAR); lResult = RegQueryValueEx(hKeyEntry, UD_KEYNAME, NULL, &dwType, (LPBYTE)szSubKey, &dwSize);
if (lResult == ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Calling RegDelnode on <%s>."), szSubKey));
RegDelnode (lpProfile->hKeyCurrentUser, szSubKey); }
} break;
case 3: { //
// Add a new value
//
// Get the key name
//
DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Adding a new value.")));
dwSize = MAX_PATH * sizeof(TCHAR); lResult = RegQueryValueEx(hKeyEntry, UD_KEYNAME, NULL, &dwType, (LPBYTE)szSubKey, &dwSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to get UD_KEYNAME with error %d."), lResult)); goto LoopAgain; }
lResult = RegCreateKeyEx (lpProfile->hKeyCurrentUser, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyTemp, &dwDisp);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to create UD_KEYNAME with error %d."), lResult)); goto LoopAgain; }
//
// Query for the value name
//
dwSize = MAX_KEY_NAME * sizeof(TCHAR); lResult = RegQueryValueEx(hKeyEntry, UD_VALUENAME, NULL, &dwType, (LPBYTE)szValueName, &dwSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to query UD_VALUENAME with error %d."), lResult)); RegCloseKey(hKeyTemp); goto LoopAgain; }
//
// Query for the value data size
//
dwSize = 0; lResult = RegQueryValueEx(hKeyEntry, UD_VALUE, NULL, &dwType, NULL, &dwSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to query UD_VALUE with error %d."), lResult)); RegCloseKey(hKeyTemp); goto LoopAgain; }
//
// Allocate space for the data
//
lpValueData = LocalAlloc (LPTR, dwSize);
if (!lpValueData) { DebugMsg((DM_WARNING, TEXT("ProcessHive: LocalAlloc failed (%d)."), GetLastError())); RegCloseKey(hKeyTemp); goto LoopAgain; }
//
// Query for the value data
//
lResult = RegQueryValueEx(hKeyEntry, UD_VALUE, NULL, &dwType, lpValueData, &dwSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to query value data with error %d."), lResult)); LocalFree (lpValueData); RegCloseKey(hKeyTemp); goto LoopAgain; }
//
// Set the new value
//
RegSetValueEx(hKeyTemp, szValueName, 0, dwType, lpValueData, dwSize);
//
// Clean up
//
LocalFree (lpValueData);
RegCloseKey(hKeyTemp);
DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Finished adding value <%s>."), szValueName)); } break;
case 4: { //
// Delete value(s)
//
// Get the key name
//
DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Entering delete a value.")));
dwSize = ARRAYSIZE(szSubKey); lResult = RegQueryValueEx(hKeyEntry, UD_KEYNAME, NULL, &dwType, (LPBYTE)szSubKey, &dwSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to query for value to delete (%d)."), lResult)); goto LoopAgain; }
lResult = RegCreateKeyEx (lpProfile->hKeyCurrentUser, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyTemp, &dwDisp);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to create key (%s) for value to delete (%d)."), szSubKey, lResult)); goto LoopAgain; }
//
// Query for the flags
//
dwSize = sizeof(dwFlags); lResult = RegQueryValueEx(hKeyEntry, UD_FLAGS, NULL, &dwType, (LPBYTE)&dwFlags, &dwSize);
if (lResult != ERROR_SUCCESS) { dwFlags = 0; }
//
// Process the flags
//
if (dwFlags == 2) { DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Calling DeleteAllValues."))); DeleteAllValues (hKeyTemp); RegCloseKey(hKeyTemp); goto LoopAgain; }
//
// Query for the value names size
//
dwSize = 0; lResult = RegQueryValueEx(hKeyEntry, UD_VALUENAMES, NULL, &dwType, NULL, &dwSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to query for value names to delete (%d)."), lResult)); RegCloseKey(hKeyTemp); goto LoopAgain; }
//
// Allocate space for the data
//
lpValueData = LocalAlloc (LPTR, dwSize);
if (!lpValueData) { DebugMsg((DM_WARNING, TEXT("ProcessHive: LocalAlloc failed (%d)."), GetLastError())); RegCloseKey(hKeyTemp); goto LoopAgain; }
//
// Query for the value data
//
lResult = RegQueryValueEx(hKeyEntry, UD_VALUENAMES, NULL, &dwType, lpValueData, &dwSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessHive: Failed to query for value data to delete (%d)."), lResult)); LocalFree (lpValueData); RegCloseKey(hKeyTemp); goto LoopAgain; }
//
// Delete the values
//
lpName = (LPTSTR) lpValueData;
while (*lpName) { DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Deleting (%s)."), lpName)); RegDeleteValue (hKeyTemp, lpName); lpName += lstrlen(lpName) + 1; }
//
// Delete the no-name value if appropriate
//
if (dwFlags == 1) { DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Deleting no name value."))); RegDeleteValue (hKeyTemp, NULL); }
//
// Clean up
//
LocalFree (lpValueData); RegCloseKey(hKeyTemp);
DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Leaving deletion code."))); }
break; }
}
LoopAgain:
//
// Close the registry key
//
RegCloseKey(hKeyEntry);
//
// Enumerate again
//
Index++;
wsprintf (szSubKey, TEXT("%s\\%s\\Hive\\%d"), USERDIFF, lpItem->szBuildNumber, Index); lResult = RegOpenKeyEx (HKEY_USERS, szSubKey, 0, KEY_READ, &hKeyEntry);
} while (lResult == ERROR_SUCCESS);
Exit:
DebugMsg((DM_VERBOSE, TEXT("ProcessHive: Leaving.")));
return TRUE; }
//*************************************************************
//
// ProcessFiles()
//
// Purpose: Processes the Files entry for a build
//
// Parameters: lpProfile - Profile information
// lpItem - Build item
// hKey - Registry key to enumerate
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
BOOL ProcessFiles(LPPROFILE lpProfile, LPUDNODE lpItem, HKEY hKey) { TCHAR szSubKey[MAX_PATH]; TCHAR szSrc[MAX_PATH]; TCHAR szDest[MAX_PATH]; TCHAR szItem[MAX_PATH]; LPTSTR lpEnd, lpTemp; DWORD dwSize, dwType, dwAction, dwProductType; LONG lResult; UINT Index = 1; FILETIME ftWrite; HKEY hKeyEntry; HANDLE hOldToken; BOOL bImpersonateUser = FALSE;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: Entering.")));
//
// Process the entry
//
wsprintf (szSubKey, TEXT("%s\\%s\\Files\\%d"), USERDIFF, lpItem->szBuildNumber, Index); lResult = RegOpenKeyEx (HKEY_USERS, szSubKey, 0, KEY_READ, &hKeyEntry);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: No Files entries."))); goto Exit; }
do { //
// Query for the product type
//
dwSize = sizeof(dwProductType); lResult = RegQueryValueEx(hKeyEntry, UD_PRODUCTTYPE, NULL, &dwType, (LPBYTE)&dwProductType, &dwSize);
//
// It's ok to not have a product type listed in userdiff.ini.
// In this case, we always apply the change regardless of the
// platform.
//
if (lResult == ERROR_SUCCESS) {
//
// A specific product was listed. Check if
// we can process this entry.
//
if (!OkToProcessItem(dwProductType)) { DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: Skipping Item %d due to product type mismatch."), Index)); goto LoopAgain; } }
//
// Query for the action type
//
dwSize = sizeof(dwAction); lResult = RegQueryValueEx(hKeyEntry, UD_ACTION, NULL, &dwType, (LPBYTE)&dwAction, &dwSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessFiles: Failed to query action type (%d)."), lResult)); goto LoopAgain; }
//
// Query for the item
//
dwSize = ARRAYSIZE(szItem); lResult = RegQueryValueEx(hKeyEntry, UD_ITEM, NULL, &dwType, (LPBYTE)szItem, &dwSize);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("ProcessFiles: Failed to query UD_ITEM type (%d)."), lResult)); goto LoopAgain; }
DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: Item %d has an action of %d."), Index, dwAction));
//
// Impersonate the user
//
if (!ImpersonateUser(lpProfile->hTokenUser, &hOldToken)) { DebugMsg((DM_WARNING, TEXT("ProcessFiles: Failed to impersonate user"))); RegCloseKey(hKeyEntry); goto Exit; } bImpersonateUser = TRUE;
switch (dwAction) {
case 1:
//
// Create new program group
//
GetSpecialFolderPath (CSIDL_PROGRAMS, szDest); lpEnd = CheckSlash(szDest); lstrcpy (lpEnd, szItem);
if (CreateNestedDirectory(szDest, NULL)) { DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: Created new group (%s)."), szDest)); } else { DebugMsg((DM_WARNING, TEXT("ProcessFiles: Failed to created new group (%s) with (%d)."), szDest, GetLastError())); }
break;
case 2: //
// Delete a program group
//
GetSpecialFolderPath (CSIDL_PROGRAMS, szDest); lpEnd = CheckSlash(szDest); lstrcpy (lpEnd, szItem);
Delnode(szDest);
DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: Deleted group (%s)."), szDest));
break;
case 3: { TCHAR szStartMenu [MAX_FOLDER_SIZE]; DWORD dwSize;
//
// Add a new item
//
dwSize = ARRAYSIZE(szSrc); if (!GetDefaultUserProfileDirectory(szSrc, &dwSize)) { DebugMsg((DM_WARNING, TEXT("ProcessFiles: Failed to get default user profile."))); goto LoopAgain; }
lpEnd = CheckSlash(szSrc);
if (LoadString (g_hDllInstance, IDS_SH_PROGRAMS, szStartMenu, MAX_FOLDER_SIZE)) {
lstrcpy (lpEnd, szStartMenu); lpEnd = CheckSlash(szSrc); lstrcpy (lpEnd, szItem);
GetSpecialFolderPath (CSIDL_PROGRAMS, szDest); lpEnd = CheckSlash(szDest); lstrcpy (lpEnd, szItem);
if (CopyFile (szSrc, szDest, FALSE)) { DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: <%s> ==> <%s> [OK]."), szSrc, szDest)); } else { DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: <%s> ==> <%s> [FAILED %d]."), szSrc, szDest, GetLastError())); } } }
break;
case 4: //
// Delete a program item
//
GetSpecialFolderPath (CSIDL_PROGRAMS, szDest); lpEnd = CheckSlash(szDest); lstrcpy (lpEnd, szItem);
if (DeleteFile(szDest)) { DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: Deleted <%s>"), szDest)); } else { DebugMsg((DM_WARNING, TEXT("ProcessFiles: Failed to deleted <%s> with %d"), szDest, GetLastError())); }
//
// Attempt to delete the directory
//
lpTemp = szDest + lstrlen(szDest) - 1; lpEnd--;
while ((*lpTemp != TEXT('\\')) && lpTemp > lpEnd) { lpTemp--; }
if (lpTemp == lpEnd) { break; }
*lpTemp = TEXT('\0');
if (RemoveDirectory(szDest)) { DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: Deleted directory <%s>"), szDest)); } else { DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: Failed to delete directory <%s> with %d"), szDest, GetLastError())); }
break; }
LoopAgain:
if (bImpersonateUser) { //
// Revert to being 'ourself'
//
if (!RevertToUser(&hOldToken)) { DebugMsg((DM_WARNING, TEXT("ProcessFiles: Failed to revert to self"))); } bImpersonateUser = FALSE; }
//
// Close the registry key
//
RegCloseKey(hKeyEntry);
//
// Enumerate again
//
Index++;
wsprintf (szSubKey, TEXT("%s\\%s\\Files\\%d"), USERDIFF, lpItem->szBuildNumber, Index); lResult = RegOpenKeyEx (HKEY_USERS, szSubKey, 0, KEY_READ, &hKeyEntry);
} while (lResult == ERROR_SUCCESS);
Exit:
DebugMsg((DM_VERBOSE, TEXT("ProcessFiles: Leaving.")));
return TRUE; }
//*************************************************************
//
// ProcessPrograms()
//
// Purpose: Processes the Execute entry for a build
//
// Parameters: lpProfile - Profile information
// lpItem - Build item
// hKey - Registry key to enumerate
// pEnv - Environment block
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 11/16/95 ericflo Created
//
//*************************************************************
BOOL ProcessPrograms (LPPROFILE lpProfile, LPUDNODE lpItem, HKEY hKey, LPVOID pEnv) { TCHAR szSubKey[MAX_PATH]; TCHAR szCmdLine[MAX_PATH]; TCHAR szFullPath[MAX_PATH]; DWORD dwSize, dwType, dwProductType; LONG lResult; UINT Index = 1; HKEY hKeyEntry; STARTUPINFO si; PROCESS_INFORMATION ProcessInformation; BOOL Result;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("ProcessPrograms: Entering.")));
//
// Process the entry
//
wsprintf (szSubKey, TEXT("%s\\%s\\Execute\\%d"), USERDIFF, lpItem->szBuildNumber, Index); lResult = RegOpenKeyEx (HKEY_USERS, szSubKey, 0, KEY_READ, &hKeyEntry);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_VERBOSE, TEXT("ProcessPrograms: No execute entries."))); goto Exit; }
do {
//
// Query for the product type
//
dwSize = sizeof(dwProductType); lResult = RegQueryValueEx(hKeyEntry, UD_PRODUCTTYPE, NULL, &dwType, (LPBYTE)&dwProductType, &dwSize);
//
// It's ok to not have a product type listed in userdiff.ini.
// In this case, we always apply the change regardless of the
// platform.
//
if (lResult == ERROR_SUCCESS) {
//
// A specific product was listed. Check if
// we can process this entry.
//
if (!OkToProcessItem(dwProductType)) { DebugMsg((DM_VERBOSE, TEXT("ProcessPrograms: Skipping Item %d due to product type mismatch."), Index)); goto LoopAgain; } }
//
// Query for the command line
//
dwSize = MAX_PATH * sizeof(TCHAR); lResult = RegQueryValueEx(hKeyEntry, UD_COMMANDLINE, NULL, &dwType, (LPBYTE)szCmdLine, &dwSize);
if (lResult != ERROR_SUCCESS) { goto LoopAgain; }
//
// If we have a NULL path, loop again.
//
if (szCmdLine[0] == TEXT('\0')) { goto LoopAgain; }
//
// Expand the command line
//
ExpandUserEnvironmentStrings(pEnv, szCmdLine, szFullPath, MAX_PATH);
//
// Initialize process startup info
//
si.cb = sizeof(STARTUPINFO); si.lpReserved = NULL; si.lpTitle = NULL; si.lpDesktop = NULL; si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWNORMAL; si.lpReserved2 = NULL; si.cbReserved2 = 0;
//
// Start the app
//
Result = CreateProcessAsUser(lpProfile->hTokenUser, NULL, szFullPath, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, pEnv, NULL, &si, &ProcessInformation);
if (Result) {
DebugMsg((DM_VERBOSE, TEXT("ProcessPrograms: Spawned <%s>. Waiting for it to complete."), szFullPath));
//
// Wait for the app to complete (3 minutes max)
//
WaitForSingleObject(ProcessInformation.hProcess, 180000);
DebugMsg((DM_VERBOSE, TEXT("ProcessPrograms: Finished waiting for <%s>."), szFullPath));
//
// Close our handles to the process and thread
//
CloseHandle(ProcessInformation.hProcess); CloseHandle(ProcessInformation.hThread);
} else { DebugMsg((DM_WARNING, TEXT("ProcessPrograms: Failed to execute <%s>, error = %d"), szFullPath, GetLastError())); }
LoopAgain:
//
// Close the registry key
//
RegCloseKey(hKeyEntry);
//
// Enumerate again
//
Index++;
wsprintf (szSubKey, TEXT("%s\\%s\\Execute\\%d"), USERDIFF, lpItem->szBuildNumber, Index); lResult = RegOpenKeyEx (HKEY_USERS, szSubKey, 0, KEY_READ, &hKeyEntry);
} while (lResult == ERROR_SUCCESS);
Exit:
DebugMsg((DM_VERBOSE, TEXT("ProcessPrograms: Leaving.")));
return TRUE; }
//*************************************************************
//
// OkToProcessItem()
//
// Purpose: Determines if the platform currently running
// on should have the change in userdiff.ini applied.
//
// Parameters: dwProductType - ProductType for a specific entry
// in userdiff.ini
//
// Return: TRUE if change should be applied
// FALSE if not
//
// Comments: dwProductType can be one of these values:
//
// 0 = All platforms
// 1 = All server platforms
// 2 = Workstation
// 3 = Server
// 4 = Domain Controller
//
// History: Date Author Comment
// 4/08/96 ericflo Created
//
//*************************************************************
BOOL OkToProcessItem(DWORD dwProductType) { BOOL bRetVal = FALSE;
switch (g_ProductType) {
case PT_WORKSTATION:
if ( (dwProductType == 0) || (dwProductType == 2) ) {
bRetVal = TRUE; }
break;
case PT_SERVER:
if ( (dwProductType == 0) || (dwProductType == 1) || (dwProductType == 3) ) {
bRetVal = TRUE; }
break;
case PT_DC: if ( (dwProductType == 0) || (dwProductType == 1) || (dwProductType == 4) ) {
bRetVal = TRUE; }
break;
}
return bRetVal; }
|