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

1494 lines
34 KiB

//*************************************************************
//
// SETUP.C - API's used by setup to create groups/items
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1995
// All rights reserved
//
//*************************************************************
#include <uenv.h>
BOOL AppendCommonExtension(LPTSTR lpName);
BOOL PrependPath(LPCTSTR szFile, LPTSTR szResult);
//*************************************************************
//
// CreateGroup()
//
// Purpose: Creates a program group (sub-directory)
//
// Parameters: lpGroupName - Name of group
// bCommonGroup - Common or Personal group
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 8/08/95 ericflo Created
//
//*************************************************************
BOOL WINAPI CreateGroup(LPCTSTR lpGroupName, BOOL bCommonGroup)
{
TCHAR szDirectory[MAX_PATH];
LPTSTR lpEnd;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("CreateGroup: Entering with <%s>."), lpGroupName));
//
// Validate parameters
//
if (!lpGroupName || !(*lpGroupName)) {
return TRUE;
}
//
// Get the profile directory
//
if (!GetProgramsDirectory (bCommonGroup, szDirectory)) {
return FALSE;
}
//
// Now append the requested directory
//
lpEnd = CheckSlash (szDirectory);
lstrcpy (lpEnd, lpGroupName);
if (bCommonGroup) {
AppendCommonExtension(szDirectory);
}
//
// Create the group (directory)
//
if (!CreateNestedDirectory(szDirectory, NULL)) {
DebugMsg((DM_VERBOSE, TEXT("CreateGroup: CreatedNestedDirectory failed.")));
return FALSE;
}
//
// Success
//
SHChangeNotify (SHCNE_MKDIR, SHCNF_PATH, szDirectory, NULL);
DebugMsg((DM_VERBOSE, TEXT("CreateGroup: Leaving successfully.")));
return TRUE;
}
//*************************************************************
//
// DeleteGroup()
//
// Purpose: Deletes a program group (sub-directory)
//
// Parameters: lpGroupName - Name of group
// bCommonGroup - Common or Personal group
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 8/10/95 ericflo Created
//
//*************************************************************
BOOL WINAPI DeleteGroup(LPCTSTR lpGroupName, BOOL bCommonGroup)
{
TCHAR szDirectory[MAX_PATH];
LPTSTR lpEnd;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Entering with <%s>."), lpGroupName));
//
// Validate parameters
//
if (!lpGroupName || !(*lpGroupName)) {
return TRUE;
}
//
// Get the profile directory
//
if (!GetProgramsDirectory (bCommonGroup, szDirectory)) {
return FALSE;
}
//
// Now append the requested directory
//
lpEnd = CheckSlash (szDirectory);
lstrcpy (lpEnd, lpGroupName);
if (bCommonGroup) {
AppendCommonExtension(szDirectory);
}
//
// Delete the group (directory)
//
if (!Delnode(szDirectory)) {
DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Delnode failed.")));
return FALSE;
}
//
// Success
//
SHChangeNotify (SHCNE_RMDIR, SHCNF_PATH, szDirectory, NULL);
DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Leaving successfully.")));
return TRUE;
}
//*************************************************************
//
// AddItem()
//
// Purpose: Adds a item to the specified group
//
// Parameters: lpGroupName - Destination group
// bCommonGroup - Common vs Personal
// lpDescription - Description of the item
// lpCommandLine - Command line (including args)
// lpIconPath - Icon path (can be NULL)
// iIconIndex - Index of icon in icon path
// lpWorkingDir - Working directory
// wHotKey - Hot key
// iShowCmd - ShowWindow flag
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 8/09/95 ericflo Created
//
//*************************************************************
BOOL WINAPI AddItem(LPCTSTR lpGroupName, BOOL bCommonGroup,
LPCTSTR lpDescription, LPCTSTR lpCommandLine,
LPCTSTR lpIconPath, int iIconIndex,
LPCTSTR lpWorkingDirectory, WORD wHotKey,
int iShowCmd)
{
HANDLE hFile;
WIN32_FIND_DATA fd;
TCHAR szItem[MAX_PATH];
TCHAR szArgs[MAX_PATH];
TCHAR szLinkName[MAX_PATH];
TCHAR szPath[MAX_PATH];
LPTSTR lpArgs, lpEnd;
LPUNKNOWN pUnkOuter = NULL;
IShellLink *psl;
IPersistFile *ppf;
BOOL bRetVal = FALSE;
//
// Verbose output
//
#if DBG
DebugMsg((DM_VERBOSE, TEXT("AddItem: Entering.")));
if (lpGroupName && *lpGroupName) {
DebugMsg((DM_VERBOSE, TEXT("AddItem: lpGroupName = <%s>."), lpGroupName));
DebugMsg((DM_VERBOSE, TEXT("AddItem: bCommonGroup = <%d>."), bCommonGroup));
}
DebugMsg((DM_VERBOSE, TEXT("AddItem: lpDescription = <%s>."), lpDescription));
DebugMsg((DM_VERBOSE, TEXT("AddItem: lpCommandLine = <%s>."), lpCommandLine));
if (lpIconPath) {
DebugMsg((DM_VERBOSE, TEXT("AddItem: lpIconPath = <%s>."), lpIconPath));
DebugMsg((DM_VERBOSE, TEXT("AddItem: iIconIndex = <%d>."), iIconIndex));
}
if (lpWorkingDirectory) {
DebugMsg((DM_VERBOSE, TEXT("AddItem: lpWorkingDirectory = <%s>."), lpWorkingDirectory));
} else {
DebugMsg((DM_VERBOSE, TEXT("AddItem: Null working directory. Setting to %%HOMEDRIVE%%%%HOMEPATH%%")));
}
DebugMsg((DM_VERBOSE, TEXT("AddItem: wHotKey = <%d>."), wHotKey));
DebugMsg((DM_VERBOSE, TEXT("AddItem: iShowCmd = <%d>."), iShowCmd));
#endif
//
// Get the profile directory
//
if (!GetProgramsDirectory (bCommonGroup, szLinkName)) {
return FALSE;
}
if (lpGroupName && *lpGroupName) {
lpEnd = CheckSlash (szLinkName);
lstrcpy (lpEnd, lpGroupName);
if (bCommonGroup) {
AppendCommonExtension(szLinkName);
}
//
// Test if the program group (sub directory) exists.
// If not, create it.
//
hFile = FindFirstFile (szLinkName, &fd);
if (hFile == INVALID_HANDLE_VALUE) {
if (!CreateGroup (lpGroupName, bCommonGroup)) {
DebugMsg((DM_WARNING, TEXT("AddItem: CreateGroup failed.")));
return FALSE;
}
} else {
FindClose (hFile);
}
}
//
// Now tack on the filename and extension.
//
lpEnd = CheckSlash (szLinkName);
lstrcpy (lpEnd, lpDescription);
lstrcat (lpEnd, c_szLNK);
//
// Split the command line into the executable name
// and arguments.
//
lstrcpy (szItem, lpCommandLine);
lpArgs = PathGetArgs(szItem);
if (*lpArgs) {
lstrcpy (szArgs, lpArgs);
lpArgs--;
while (*lpArgs == TEXT(' ')) {
lpArgs--;
}
lpArgs++;
*lpArgs = TEXT('\0');
} else {
szArgs[0] = TEXT('\0');
}
PathUnquoteSpaces (szItem);
//
// Create an IShellLink object
//
if (FAILED(SHCoCreateInstance(NULL, &CLSID_ShellLink, pUnkOuter,
&IID_IShellLink,
(LPVOID)&psl)))
{
DebugMsg((DM_WARNING, TEXT("AddItem: Could not create instance of IShellLink .")));
goto ExitNoFree;
}
//
// Query for IPersistFile
//
if (FAILED(psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf)))
{
DebugMsg((DM_WARNING, TEXT("AddItem: QueryInterface of IShellLink failed.")));
goto ExitFreePSL;
}
//
// Set the item information
//
psl->lpVtbl->SetDescription(psl, lpDescription);
PrependPath(szItem, szPath);
psl->lpVtbl->SetPath(psl, szPath);
psl->lpVtbl->SetArguments(psl, szArgs);
if (lpWorkingDirectory) {
psl->lpVtbl->SetWorkingDirectory(psl, lpWorkingDirectory);
} else {
psl->lpVtbl->SetWorkingDirectory(psl, TEXT("%HOMEDRIVE%%HOMEPATH%"));
}
PrependPath(lpIconPath, szPath);
psl->lpVtbl->SetIconLocation(psl, szPath, iIconIndex);
psl->lpVtbl->SetHotkey(psl, wHotKey);
psl->lpVtbl->SetShowCmd(psl, iShowCmd);
//
// Save the item to disk
//
bRetVal = SUCCEEDED(ppf->lpVtbl->Save(ppf, szLinkName, TRUE));
if (bRetVal) {
SHChangeNotify (SHCNE_CREATE, SHCNF_PATH, szLinkName, NULL);
}
//
// Release the IPersistFile object
//
ppf->lpVtbl->Release(ppf);
ExitFreePSL:
//
// Release the IShellLink object
//
psl->lpVtbl->Release(psl);
ExitNoFree:
//
// Finished.
//
DebugMsg((DM_VERBOSE, TEXT("AddItem: Leaving with status of %d."), bRetVal));
return bRetVal;
}
//*************************************************************
//
// DeleteItem()
//
// Purpose: Deletes an item from the specified group
//
// Parameters: lpGroupName - Destination group
// bCommonGroup - Common vs Personal
// lpDescription - Description of the item
// bDeleteGroup - Delete the group if possible
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 8/10/95 ericflo Created
//
//*************************************************************
BOOL WINAPI DeleteItem(LPCTSTR lpGroupName, BOOL bCommonGroup,
LPCTSTR lpDescription, BOOL bDeleteGroup)
{
TCHAR szLinkName[MAX_PATH];
LPTSTR lpEnd;
//
// Verbose output
//
#if DBG
DebugMsg((DM_VERBOSE, TEXT("DeleteItem: Entering.")));
if (lpGroupName && *lpGroupName) {
DebugMsg((DM_VERBOSE, TEXT("DeleteItem: lpGroupName = <%s>."), lpGroupName));
DebugMsg((DM_VERBOSE, TEXT("DeleteItem: bCommonGroup = <%d>."), bCommonGroup));
}
DebugMsg((DM_VERBOSE, TEXT("DeleteItem: lpDescription = <%s>."), lpDescription));
#endif
//
// Get the profile directory
//
if (!GetProgramsDirectory (bCommonGroup, szLinkName)) {
return FALSE;
}
if (lpGroupName && *lpGroupName) {
lpEnd = CheckSlash (szLinkName);
lstrcpy (lpEnd, lpGroupName);
if (bCommonGroup) {
AppendCommonExtension(szLinkName);
}
}
//
// Now tack on the filename and extension.
//
lpEnd = CheckSlash (szLinkName);
lstrcpy (lpEnd, lpDescription);
lstrcat (lpEnd, c_szLNK);
//
// Delete the file
//
if (!DeleteFile (szLinkName)) {
DebugMsg((DM_VERBOSE, TEXT("DeleteItem: Failed to delete <%s>. Error = %d"),
szLinkName, GetLastError()));
return FALSE;
}
SHChangeNotify (SHCNE_DELETE, SHCNF_PATH, szLinkName, NULL);
//
// Delete the group if appropriate (and possible).
//
if (bDeleteGroup) {
*(lpEnd-1) = TEXT('\0');
if (RemoveDirectory(szLinkName)) {
SHChangeNotify (SHCNE_RMDIR, SHCNF_PATH, szLinkName, NULL);
}
}
//
// Success
//
DebugMsg((DM_VERBOSE, TEXT("DeleteItem: Leaving successfully.")));
return TRUE;
}
//*************************************************************
//
// PrependPath()
//
// Purpose: Expands the given 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
// 10/11/95 ericflo Created
//
//*************************************************************
BOOL PrependPath(LPCTSTR lpFile, LPTSTR lpResult)
{
TCHAR szReturn [MAX_PATH];
TCHAR szSysRoot[MAX_PATH];
LPTSTR lpFileName;
DWORD dwSysLen;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("PrependPath: Entering with <%s>"),
lpFile ? lpFile : TEXT("NULL")));
if (!lpFile || !*lpFile) {
DebugMsg((DM_VERBOSE, TEXT("PrependPath: lpFile is NULL, setting lpResult to a null string")));
*lpResult = TEXT('\0');
return TRUE;
}
//
// Call SearchPath to find the filename
//
if (!SearchPath (NULL, lpFile, TEXT(".exe"), MAX_PATH, szReturn, &lpFileName)) {
DebugMsg((DM_VERBOSE, TEXT("PrependPath: SearchPath failed with error %d. Using input string"), GetLastError()));
lstrcpy (lpResult, lpFile);
return TRUE;
}
UnExpandSysRoot(szReturn, lpResult);
DebugMsg((DM_VERBOSE, TEXT("PrependPath: Leaving with <%s>"), lpResult));
return TRUE;
}
//*************************************************************
//
// AppendCommonExtension()
//
// Purpose: Appends " (Common)" to the directory name
// if it does not exist already.
//
// Parameters: lpName - Name to work with
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: lpName is assumed to be MAX_PATH chars long
//
// History: Date Author Comment
// 10/2/95 ericflo Created
//
//*************************************************************
BOOL AppendCommonExtension(LPTSTR lpName)
{
LPTSTR lpEnd;
//
// Verbose Output
//
DebugMsg((DM_VERBOSE, TEXT("AppendCommonExtension: Entering with <%s>"), lpName));
lpEnd = lpName + lstrlen(lpName) - g_cchCommon;
if (lstrcmpi(lpEnd, g_szCommon) == 0) {
return TRUE;
}
lstrcat (lpName, g_szCommon);
//
// Success
//
DebugMsg((DM_VERBOSE, TEXT("AppendCommonExtension: Leaving successfully.")));
return TRUE;
}
//*************************************************************
//
// CreateSecureAdminDirectory()
//
// Purpose: Creates a secure directory that only the Administrator
// and system have access to.
//
// Parameters: lpDirectory - Directory Name
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/20/95 ericflo Created
//
//*************************************************************
BOOL CreateSecureAdminDirectory (LPTSTR lpDirectory)
{
//
// Attempt to create the directory
//
if (!CreateNestedDirectory(lpDirectory, NULL)) {
return FALSE;
}
//
// Set the security
//
if (!MakeFileSecure (lpDirectory)) {
RemoveDirectory(lpDirectory);
return FALSE;
}
return TRUE;
}
//*************************************************************
//
// ConvertCommonGroups()
//
// Purpose: Calls grpconv.exe to convert progman common groups
// to Explorer common groups, and create floppy links.
//
// Parameters: none
//
// Return: TRUE if successful
// FALSE if an error occurs
// Comments:
//
// History: Date Author Comment
// 10/1/95 ericflo Created
//
//*************************************************************
BOOL ConvertCommonGroups (void)
{
STARTUPINFO si;
PROCESS_INFORMATION ProcessInformation;
BOOL Result;
TCHAR szCmdLine[MAX_PATH];
DWORD dwType, dwSize, dwConvert;
BOOL bRunGrpConv = TRUE;
LONG lResult;
HKEY hKey;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Entering.")));
//
// Check if we have run grpconv before.
//
lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
TEXT("Software\\Program Groups"),
0,
KEY_ALL_ACCESS,
&hKey);
if (lResult == ERROR_SUCCESS) {
dwSize = sizeof(dwConvert);
lResult = RegQueryValueEx (hKey,
TEXT("ConvertedToLinks"),
NULL,
&dwType,
(LPBYTE)&dwConvert,
&dwSize);
if (lResult == ERROR_SUCCESS) {
//
// If dwConvert is 1, then grpconv has run before.
// Don't run it again.
//
if (dwConvert) {
bRunGrpConv = FALSE;
}
}
//
// Now set the value to prevent grpconv from running in the future
//
dwConvert = 1;
RegSetValueEx (hKey,
TEXT("ConvertedToLinks"),
0,
REG_DWORD,
(LPBYTE) &dwConvert,
sizeof(dwConvert));
RegCloseKey (hKey);
}
if (bRunGrpConv) {
//
// Initialize process startup info
//
si.cb = sizeof(STARTUPINFO);
si.lpReserved = NULL;
si.lpDesktop = NULL;
si.lpTitle = NULL;
si.dwFlags = 0;
si.lpReserved2 = NULL;
si.cbReserved2 = 0;
//
// Spawn grpconv
//
lstrcpy (szCmdLine, TEXT("grpconv -n"));
Result = CreateProcess(
NULL,
szCmdLine,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&si,
&ProcessInformation
);
if (!Result) {
DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: grpconv failed to start due to error %d."), GetLastError()));
return FALSE;
} else {
//
// Wait for up to 2 minutes
//
WaitForSingleObject(ProcessInformation.hProcess, 120000);
//
// Close our handles to the process and thread
//
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
}
}
//
// Success
//
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Leaving Successfully.")));
return TRUE;
}
//*************************************************************
//
// InitializeProfiles()
//
// Purpose: Confirms / Creates the profile, Default User,
// and All Users directories, and converts any
// existing common groups.
//
// Parameters:
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments: This should only be called by GUI mode setup!
//
// History: Date Author Comment
// 8/08/95 ericflo Created
//
//*************************************************************
BOOL WINAPI InitializeProfiles (void)
{
TCHAR szDirectory[MAX_PATH];
LPTSTR lpEnd;
INT i;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Entering.")));
//
// Step 1: Check if the profiles directory exists.
//
ExpandEnvironmentStrings(PROFILES_DIR, szDirectory, MAX_PATH);
if (!CreateNestedDirectory(szDirectory, NULL)) {
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create profiles subdirectory <%s>. Error = %d."),
szDirectory, GetLastError()));
return FALSE;
}
//
// Step 2: Check if the profiles\Default User directory exists.
//
ExpandEnvironmentStrings(DEFAULT_PROFILE, szDirectory, MAX_PATH);
if (!CreateSecureAdminDirectory (szDirectory)) {
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create Default User subdirectory <%s>. Error = %d."),
szDirectory, GetLastError()));
return FALSE;
}
//
// Step 3: Set the USERPROFILE environment variable
//
SetEnvironmentVariable (TEXT("USERPROFILE"), szDirectory);
//
// Step 4: Create all the folders (sub-directories) under Default User
//
lpEnd = CheckSlash (szDirectory);
//
// Loop through the shell folders
//
for (i=0; i < NUM_SHELL_FOLDERS; i++) {
lstrcpy (lpEnd, c_ShellFolders[i].lpFolderLocation);
if (!CreateNestedDirectory(szDirectory, NULL)) {
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create the destination directory <%s>. Error = %d"),
szDirectory, GetLastError()));
return FALSE;
}
if (c_ShellFolders[i].bHidden) {
SetFileAttributes(szDirectory, FILE_ATTRIBUTE_HIDDEN);
}
}
//
// Step 5: Check if the profiles\All Users directory exists.
//
ExpandEnvironmentStrings(COMMON_PROFILE, szDirectory, MAX_PATH);
if (!CreateSecureAdminDirectory (szDirectory)) {
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create All Users subdirectory <%s>. Error = %d."),
szDirectory, GetLastError()));
return FALSE;
}
//
// Step 6: Create all the folders (sub-directories) under All Users
//
lpEnd = CheckSlash (szDirectory);
//
// Loop through the shell folders
//
for (i=0; i < NUM_COMMON_SHELL_FOLDERS; i++) {
lstrcpy (lpEnd, c_CommonShellFolders[i].lpFolderLocation);
if (!CreateNestedDirectory(szDirectory, NULL)) {
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create the destination directory <%s>. Error = %d"),
szDirectory, GetLastError()));
return FALSE;
}
if (c_CommonShellFolders[i].bHidden) {
SetFileAttributes(szDirectory, FILE_ATTRIBUTE_HIDDEN);
}
}
//
// Step 7: Convert any common groups
//
if (!ConvertCommonGroups()) {
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: ConvertCommonGroups failed.")));
}
//
// Success
//
DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Leaving successfully.")));
return TRUE;
}
//*************************************************************
//
// CreateUserProfile()
//
// Purpose: Creates a new user profile, but does not load
// the hive.
//
// Parameters: pSid - SID pointer
// lpUserName - User name
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 9/12/95 ericflo Created
//
//*************************************************************
BOOL WINAPI CreateUserProfile (PSID pSid, LPCTSTR lpUserName)
{
TCHAR szProfileDir[MAX_PATH];
TCHAR szExpProfileDir[MAX_PATH];
TCHAR szDefaultUser[MAX_PATH];
TCHAR LocalProfileKey[MAX_PATH];
UNICODE_STRING UnicodeString;
LPTSTR lpSidString, lpEnd, lpSave;
NTSTATUS NtStatus;
LONG lResult;
DWORD dwDisp;
HKEY hKey;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Entering with <%s>."), lpUserName));
//
// Check parameters
//
if (!lpUserName || !lpUserName[0]) {
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Null username.")));
return FALSE;
}
//
// Make / Confirm the user's directory exists
//
lstrcpy (szProfileDir, CONFIG_FILE_PATH);
lstrcat (szProfileDir, lpUserName);
ExpandEnvironmentStrings(szProfileDir, szExpProfileDir, MAX_PATH);
if (!CreateSecureDirectory(NULL, szExpProfileDir, pSid)) {
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to create user directory <%s>."), szExpProfileDir));
return FALSE;
}
//
// Copy the default user profile into this directory
//
ExpandEnvironmentStrings(DEFAULT_PROFILE, szDefaultUser, MAX_PATH);
if (!CopyProfileDirectory (szDefaultUser, szExpProfileDir, CPD_IGNORECOPYERRORS)) {
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: CopyProfileDirectory failed with error %d."), GetLastError()));
return FALSE;
}
//
// Save the user's profile in the registry.
// First, convert the sid to a text string
//
NtStatus = RtlConvertSidToUnicodeString(&UnicodeString, pSid, (BOOLEAN)TRUE);
if (!NT_SUCCESS(NtStatus)) {
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: RtlConvertSidToUnicodeString failed, status = 0x%x"),
NtStatus));
return FALSE;
}
lpSidString = UnicodeString.Buffer;
//
// Part B: Open the new registry key
//
lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
lstrcat(LocalProfileKey, TEXT("\\"));
lstrcat(LocalProfileKey, lpSidString);
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed trying to create the local profile key <%s>, error = %d."), LocalProfileKey, lResult));
RtlFreeUnicodeString(&UnicodeString);
return FALSE;
}
//
// Add the profile directory
//
lResult = RegSetValueEx(hKey, PROFILE_IMAGE_VALUE_NAME, 0,
REG_EXPAND_SZ,
(LPBYTE)szProfileDir,
sizeof(TCHAR)*(lstrlen(szProfileDir) + 1));
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: First RegSetValueEx failed, error = %d."), lResult));
RegCloseKey (hKey);
RtlFreeUnicodeString(&UnicodeString);
return FALSE;
}
//
// Add the users's SID
//
lResult = RegSetValueEx(hKey, TEXT("Sid"), 0,
REG_BINARY, pSid, RtlLengthSid(pSid));
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Second RegSetValueEx failed, error = %d."), lResult));
}
//
// Close the registry key
//
RegCloseKey (hKey);
//
// Now load the hive temporary so the security can be fixed
//
lpEnd = CheckSlash (szExpProfileDir);
lpSave = lpEnd - 1;
lstrcpy (lpEnd, c_szNTUserDat);
lResult = MyRegLoadKey(NULL, HKEY_USERS, lpSidString, szExpProfileDir);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to load hive, error = %d."), lResult));
*lpSave = TEXT('\0');
DeleteProfile (lpSidString, szExpProfileDir, FALSE);
RtlFreeUnicodeString(&UnicodeString);
return FALSE;
}
if (!SetupNewHive(NULL, lpSidString, pSid)) {
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: SetupNewHive failed.")));
*lpSave = TEXT('\0');
MyRegUnLoadKey(HKEY_USERS, lpSidString);
DeleteProfile (lpSidString, szExpProfileDir, FALSE);
RtlFreeUnicodeString(&UnicodeString);
return FALSE;
}
//
// Unload the hive
//
MyRegUnLoadKey(HKEY_USERS, lpSidString);
//
// Free the sid string
//
RtlFreeUnicodeString(&UnicodeString);
//
// Success
//
DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Leaving successfully.")));
return TRUE;
}
//*************************************************************
//
// AddDesktopItem()
//
// Purpose: Adds a item to the desktop
//
// Parameters: bCommonItem - Common vs Personal
// lpDescription - Description of the item
// lpCommandLine - Command line (including args)
// lpIconPath - Icon path (can be NULL)
// iIconIndex - Index of icon in icon path
// lpWorkingDir - Working directory
// wHotKey - Hot key
// iShowCmd - ShowWindow flag
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 4/02/96 ericflo Created
//
//*************************************************************
BOOL WINAPI AddDesktopItem(BOOL bCommonItem,
LPCTSTR lpDescription, LPCTSTR lpCommandLine,
LPCTSTR lpIconPath, int iIconIndex,
LPCTSTR lpWorkingDirectory, WORD wHotKey,
int iShowCmd)
{
HANDLE hFile;
WIN32_FIND_DATA fd;
TCHAR szItem[MAX_PATH];
TCHAR szArgs[MAX_PATH];
TCHAR szLinkName[MAX_PATH];
TCHAR szPath[MAX_PATH];
LPTSTR lpArgs, lpEnd;
LPUNKNOWN pUnkOuter = NULL;
IShellLink *psl;
IPersistFile *ppf;
BOOL bRetVal = FALSE;
//
// Verbose output
//
#if DBG
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: Entering.")));
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: bCommonItem = <%d>."), bCommonItem));
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: lpDescription = <%s>."), lpDescription));
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: lpCommandLine = <%s>."), lpCommandLine));
if (lpIconPath) {
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: lpIconPath = <%s>."), lpIconPath));
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: iIconIndex = <%d>."), iIconIndex));
}
if (lpWorkingDirectory) {
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: lpWorkingDirectory = <%s>."), lpWorkingDirectory));
} else {
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: Null working directory. Setting to %%HOMEDRIVE%%%%HOMEPATH%%")));
}
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: wHotKey = <%d>."), wHotKey));
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: iShowCmd = <%d>."), iShowCmd));
#endif
//
// Get the desktop directory
//
if (!GetDesktopDirectory (bCommonItem, szLinkName)) {
return FALSE;
}
//
// Test if the sub directory exists.
// If not, create it.
//
hFile = FindFirstFile (szLinkName, &fd);
if (hFile == INVALID_HANDLE_VALUE) {
if (!CreateNestedDirectory(szLinkName, NULL)) {
DebugMsg((DM_WARNING, TEXT("AddDesktopItem: CreateNestedDirectory failed.")));
return FALSE;
}
} else {
FindClose (hFile);
}
//
// Now tack on the filename and extension.
//
lpEnd = CheckSlash (szLinkName);
lstrcpy (lpEnd, lpDescription);
lstrcat (lpEnd, c_szLNK);
//
// Split the command line into the executable name
// and arguments.
//
lstrcpy (szItem, lpCommandLine);
lpArgs = PathGetArgs(szItem);
if (*lpArgs) {
lstrcpy (szArgs, lpArgs);
lpArgs--;
while (*lpArgs == TEXT(' ')) {
lpArgs--;
}
lpArgs++;
*lpArgs = TEXT('\0');
} else {
szArgs[0] = TEXT('\0');
}
//
// Create an IShellLink object
//
if (FAILED(SHCoCreateInstance(NULL, &CLSID_ShellLink, pUnkOuter,
&IID_IShellLink,
(LPVOID)&psl)))
{
DebugMsg((DM_WARNING, TEXT("AddDesktopItem: Could not create instance of IShellLink .")));
goto ExitNoFree;
}
//
// Query for IPersistFile
//
if (FAILED(psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf)))
{
DebugMsg((DM_WARNING, TEXT("AddDesktopItem: QueryInterface of IShellLink failed.")));
goto ExitFreePSL;
}
//
// Set the item information
//
psl->lpVtbl->SetDescription(psl, lpDescription);
PrependPath(szItem, szPath);
psl->lpVtbl->SetPath(psl, szPath);
psl->lpVtbl->SetArguments(psl, szArgs);
if (lpWorkingDirectory) {
psl->lpVtbl->SetWorkingDirectory(psl, lpWorkingDirectory);
} else {
psl->lpVtbl->SetWorkingDirectory(psl, TEXT("%HOMEDRIVE%%HOMEPATH%"));
}
PrependPath(lpIconPath, szPath);
psl->lpVtbl->SetIconLocation(psl, szPath, iIconIndex);
psl->lpVtbl->SetHotkey(psl, wHotKey);
psl->lpVtbl->SetShowCmd(psl, iShowCmd);
//
// Save the item to disk
//
bRetVal = SUCCEEDED(ppf->lpVtbl->Save(ppf, szLinkName, TRUE));
//
// Release the IPersistFile object
//
ppf->lpVtbl->Release(ppf);
ExitFreePSL:
//
// Release the IShellLink object
//
psl->lpVtbl->Release(psl);
ExitNoFree:
//
// Finished.
//
DebugMsg((DM_VERBOSE, TEXT("AddDesktopItem: Leaving with status of %d."), bRetVal));
return bRetVal;
}
//*************************************************************
//
// DeleteDesktopItem()
//
// Purpose: Deletes an item from the desktop
//
// Parameters: bCommonItem - Common vs Personal
// lpDescription - Description of the item
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 4/02/96 ericflo Created
//
//*************************************************************
BOOL WINAPI DeleteDesktopItem(BOOL bCommonItem, LPCTSTR lpDescription)
{
TCHAR szLinkName[MAX_PATH];
LPTSTR lpEnd;
//
// Verbose output
//
#if DBG
DebugMsg((DM_VERBOSE, TEXT("DeleteDesktopItem: Entering.")));
DebugMsg((DM_VERBOSE, TEXT("DeleteDesktopItem: bCommonItem = <%d>."), bCommonItem));
DebugMsg((DM_VERBOSE, TEXT("DeleteDesktopItem: lpDescription = <%s>."), lpDescription));
#endif
//
// Get the desktop directory
//
if (!GetDesktopDirectory (bCommonItem, szLinkName)) {
return FALSE;
}
//
// Now tack on the filename and extension.
//
lpEnd = CheckSlash (szLinkName);
lstrcpy (lpEnd, lpDescription);
lstrcat (lpEnd, c_szLNK);
//
// Delete the file
//
if (!DeleteFile (szLinkName)) {
DebugMsg((DM_VERBOSE, TEXT("DeleteDesktopItem: Failed to delete <%s>. Error = %d"),
szLinkName, GetLastError()));
return FALSE;
}
//
// Success
//
DebugMsg((DM_VERBOSE, TEXT("DeleteDesktopItem: Leaving successfully.")));
return TRUE;
}