|
|
/*
* pminit.c - program manager * * Copyright (c) 1991, Microsoft Corporation * * DESCRIPTION * * This file is for support of program manager under NT Windows. * This file is/was ported from pminit.c (program manager). * * MODIFICATION HISTORY * Initial Version: x/x/90 Author Unknown, since he didn't feel * like commenting the code... * * NT 32b Version: 1/25/91 Jeff Pack * Intitial port to begin. * * */
#include "progman.h"
#include "util.h"
#include "commdlg.h"
//#ifdef FE_IME
#include "winnls32.h"
//#endif
#include "uniconv.h"
#include "security.h"
#define MAX_USERNAME_LENGTH 256
#define PROGMAN_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager"
#define WINDOWS_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
//#define MYDEBUG 1
SECURITY_ATTRIBUTES SecurityAttributes; SECURITY_ATTRIBUTES AdminSecAttr; // security attributes for common groups
BOOL bInitialArrange; BOOL bInNtSetup; TCHAR szProgramGroups[] = TEXT("UNICODE Program Groups"); // registry key for groups
TCHAR szRestrict[] = TEXT("Restrictions"); TCHAR szNoRun[] = TEXT("NoRun"); TCHAR szNoClose[] = TEXT("NoClose"); TCHAR szEditLevel[] = TEXT("EditLevel"); TCHAR szNoFileMenu[] = TEXT("NoFileMenu"); TCHAR szNoSave[] = TEXT("NoSaveSettings"); TCHAR szShowCommonGroups[]= TEXT("ShowCommonGroups"); TCHAR szSettings[] = TEXT("Settings"); TCHAR szGroups[] = TEXT("UNICODE Groups"); TCHAR szAnsiGroups[] = TEXT("Groups"); TCHAR szCommonGroups[] = TEXT("Common Groups"); TCHAR szSystemBoot[] = TEXT("Boot"); TCHAR szSystemDisplay[] = TEXT("display.drv"); TCHAR szDefPrograms[] = TEXT("EXE COM BAT PIF"); TCHAR szSystemIni[] = TEXT("system.ini"); TCHAR szWindows[] = TEXT("Windows"); TCHAR szCheckBinaryType[] = TEXT("CheckBinaryType"); TCHAR szCheckBinaryTimeout[] = TEXT("CheckBinaryTimeout"); TCHAR szMigrateAnsi[] = TEXT("Migrate ANSI");
BOOL bDisableDDE = FALSE;
/* in hotkey.c */ BOOL APIENTRY RegisterHotKeyClass(HANDLE hInstance); /* in pmgseg.c */ HWND NEAR PASCAL IsGroupAlreadyLoaded(LPTSTR lpGroupKey, BOOL bCommonGroup);
/*---------------------------------------------------------------------------
* * A fixed buffer case and space insensative compare... * Returns true if they compare the same. * *--------------------------------------------------------------------------*/
BOOL NEAR PASCAL StartupCmp(LPTSTR szSrc1, LPTSTR szSrc2) { TCHAR sz1[MAXGROUPNAMELEN+1]; TCHAR sz2[MAXMESSAGELEN+1]; LPTSTR lp1, lp2;
lstrcpy(sz1, szSrc1); CharUpper(sz1); lstrcpy(sz2, szSrc2); CharUpper(sz2); lp1 = sz1; lp2 = sz2;
for (;;) { while(*lp1 == TEXT(' ')) lp1++; while(*lp2 == TEXT(' ')) lp2++; if (*lp1 != *lp2) return FALSE; if (!*lp1) break; while (*lp1 == *lp2 && *lp1) lp1++, lp2++; } return TRUE; }
/*---------------------------------------------------------------------------
* * Handles finding and execing the items in the startup group. * *--------------------------------------------------------------------------*/
VOID NEAR PASCAL HandleStartupGroup(int nCmdShow) { TCHAR szGroupTitle[MAXGROUPNAMELEN+1]; HWND hwndT; DWORD cbData = sizeof(TCHAR)*(MAXGROUPNAMELEN+1); PGROUP pGroup; LPGROUPDEF lpgd; TCHAR szCommonStartupGroup[MAXGROUPNAMELEN+1]; TCHAR szDefaultStartup[MAXGROUPNAMELEN+1] = TEXT("startup");
TCHAR szStartupKana[] = TEXT("^?X^?^^?[^?g^?A^?b^?v");
if (nCmdShow != SW_SHOWMINNOACTIVE) { //
// Daytona security weenies decreed that GetAsyncKeyState only work
// if threads window is foreground, so make it so.
//
hwndT = GetForegroundWindow(); if (hwndProgman != hwndT) SetForegroundWindow( hwndProgman ); if (GetAsyncKeyState(VK_SHIFT) < 0) // SHIFT will cancel the startup group
return; }
//
// The Default startup group name is "Startup", for personal and common
// groups.
//
LoadString(hAppInstance,IDS_DEFAULTSTARTUP,szDefaultStartup,CharSizeOf(szDefaultStartup)); lstrcpy(szGroupTitle, szDefaultStartup); lstrcpy(szCommonStartupGroup, szDefaultStartup);
//
// Get the Personal startup group name.
//
if (hkeyPMSettings) { if ( RegQueryValueEx(hkeyPMSettings, szStartup, 0, 0, (LPBYTE)szGroupTitle, &cbData) != ERROR_SUCCESS ) { lstrcpy(szGroupTitle, szDefaultStartup); } }
// Search for the startup group.
hwndT = GetWindow(hwndMDIClient, GW_CHILD); while (hwndT) { //
// Skip icon titles.
//
if (!GetWindow(hwndT, GW_OWNER)) {
/* Compare the group name with the startup. */ pGroup = (PGROUP)GetWindowLongPtr(hwndT, GWLP_PGROUP); if (lpgd = (LPGROUPDEF)GlobalLock(pGroup->hGroup)) { // ToddB: We want to check for three things here:
// 1.) A common group with the name szCommonStartupGroup
// 2.) Any group with the name szGroupTitle (which is a copy of szDefaultStartup)
// 3.) If we are in Japan then we also search for two hardcoded strings,
// szStartupKana AND szStartup. I think this special Japanese
// check is a bug and should be removed.
if (pGroup->fCommon) { if (StartupCmp(szCommonStartupGroup, (LPTSTR) PTR(lpgd, lpgd->pName))) StartupGroup(hwndT); } else if (StartupCmp(szGroupTitle, (LPTSTR) PTR(lpgd, lpgd->pName))) { StartupGroup(hwndT); } #ifdef JAPAN_HACK_WHICH_TODDB_THINKS_IS_A_BUG
else if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) == LANG_JAPANESE) { if (StartupCmp(szStartupKana,(LPTSTR)PTR(lpgd,lpgd->pName)) || // search for hardcoded localized startup
StartupCmp(szStartup,(LPTSTR)PTR(lpgd,lpgd->pName))) // search for hardcoded non-localized "startup"
{ StartupGroup( hwndT ); } } #endif
GlobalUnlock(pGroup->hGroup); } } hwndT = GetWindow(hwndT, GW_HWNDNEXT); } }
/*** BoilThatDustSpec -- strips string to program name
* * * VOID APIENTRY BoilThatDustSpec(PSTR pStart, BOOL bLoadIt) * * ENTRY - PSTR pStart - Program to exec, and possible parameters * BOOL LoadIt - * * EXIT - VOID * * SYNOPSIS - strips everything after program name, then exec's program. * * WARNINGS - * EFFECTS - * */
VOID APIENTRY BoilThatDustSpec(LPTSTR pStart, BOOL bLoadIt) { register LPTSTR pEnd; WORD ret; BOOL bFinished; TCHAR szText[MAXMESSAGELEN+1]; TCHAR szExtra[MAXMESSAGELEN+1]; TCHAR szFilename[MAXITEMPATHLEN+1]; TCHAR szWindowsDirectory2[MAXITEMPATHLEN+1];
if (*pStart == TEXT('\0')) { /*test for null string*/ return; }
// Used to massage any errors.
LoadString(hAppInstance,IDS_WININIERR,szExtra, CharSizeOf(szExtra));
// skip first spaces
while (*pStart == ' ') { pStart = CharNext(pStart); } bFinished = !*pStart;
GetWindowsDirectory(szWindowsDirectory2, CharSizeOf(szWindowsDirectory2));
while (!bFinished){ pEnd = pStart; /* strip anything after execprogram name*/ while ((*pEnd) && (*pEnd != TEXT(' ')) && (*pEnd != TEXT(','))){ pEnd = CharNext(pEnd); } if (*pEnd == TEXT('\0')) bFinished = TRUE; else *pEnd = TEXT('\0');
if (!*pStart) { pStart = pEnd+1; continue; }
if (GetFreeSpace(GMEM_NOT_BANKED) < 65535L) break;
GetDirectoryFromPath(pStart, szDirField);
// Load and Run lines are done relative to windows directory.
SetCurrentDirectory(szWindowsDirectory2);
GetFilenameFromPath(pStart, szFilename); ret = ExecProgram(szFilename, szDirField, NULL, bLoadIt, 0, 0, 0); if (ret) { // Insert a phrase mentioning win.ini after the file name.
szText[0] = TEXT('\''); lstrcpy(&szText[1], pStart); lstrcat(szText, szExtra); MyMessageBox(NULL, IDS_APPTITLE, ret, szText, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL); }
pStart = pEnd+1; }
SetCurrentDirectory(szWindowsDirectory); // in fact system32 directory
}
/*** DoRunEquals --
* * * VOID APIENTRY DoRunEquals(PINT pnCmdShow) * * ENTRY - PINT pnCmdShow - point to cmdshow * * EXIT - VOID * * SYNOPSIS - ??? * * WARNINGS - * EFFECTS - * */
VOID APIENTRY DoRunEquals(PINT pnCmdShow) { TCHAR szBuffer[MAX_PATH]; DWORD dwType; DWORD cbData; HKEY hkeyWindows;
/* "Load" apps before "Run"ning any. */ if (RegOpenKeyEx(HKEY_CURRENT_USER, WINDOWS_KEY, 0, KEY_READ, &hkeyWindows) != ERROR_SUCCESS) { return; }
*szBuffer = 0; cbData = sizeof(szBuffer); RegQueryValueEx(hkeyWindows, L"Load", 0, &dwType, (LPBYTE)szBuffer, &cbData); if (*szBuffer) BoilThatDustSpec(szBuffer, TRUE);
*szBuffer = 0; cbData = sizeof(szBuffer); RegQueryValueEx(hkeyWindows, L"Run", 0, &dwType, (LPBYTE)szBuffer, &cbData); if (*szBuffer) { BoilThatDustSpec(szBuffer, FALSE); *pnCmdShow = SW_SHOWMINNOACTIVE; }
RegCloseKey(hkeyWindows); }
/*** GetSettings --
* * * PSTR APIENTRY GetSettings(VOID) * * ENTRY - VOID * * EXIT - PSTR - if NULL then error. * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
LPTSTR APIENTRY GetSettings() { LPTSTR pszT; TCHAR szGroups[32]; TCHAR szAppTitle[MAXKEYLEN + 1]; DWORD cbData; DWORD dwType; DWORD rc; DWORD dwBinaryInfo;
#define SETTING_SIZE 160
/* Get the flags out of the INI file. */ LoadString(hAppInstance, IDS_GROUPS, szGroups, CharSizeOf(szGroups)); LoadString(hAppInstance, IDS_APPTITLE, szAppTitle, CharSizeOf(szAppTitle));
/*
* Use direct registry call. */ if (hkeyPMSettings) { cbData = sizeof(bMinOnRun); RegQueryValueEx(hkeyPMSettings, szMinOnRun, 0, &dwType, (LPBYTE)&bMinOnRun, &cbData); cbData = sizeof(bAutoArrange); RegQueryValueEx(hkeyPMSettings, szAutoArrange, 0, &dwType, (LPBYTE)&bAutoArrange, &cbData); cbData = sizeof(bSaveSettings); RegQueryValueEx(hkeyPMSettings, szSaveSettings, 0, &dwType, (LPBYTE)&bSaveSettings, &cbData); cbData = sizeof(bInitialArrange); bInitialArrange = FALSE; rc = RegQueryValueEx(hkeyPMSettings, TEXT("InitialArrange"), 0, &dwType, (LPBYTE)&bInitialArrange, &cbData); if (bInitialArrange) { RegDeleteValue(hkeyPMSettings, TEXT("InitialArrange")); }
//
// Check if the binary type checking information exists. If not,
// add it.
//
// First check for the enabled / disabled entry.
//
cbData = sizeof(dwBinaryInfo); if (RegQueryValueEx(hkeyPMSettings, szCheckBinaryType, 0, &dwType, (LPBYTE)&dwBinaryInfo, &cbData) == ERROR_FILE_NOT_FOUND) { //
// Key doesn't exist, so create the default case.
//
dwBinaryInfo = BINARY_TYPE_DEFAULT; RegSetValueEx (hkeyPMSettings, szCheckBinaryType, 0, REG_DWORD, (LPBYTE) &dwBinaryInfo, cbData); }
//
// Now check for the timeout value. This is the number of milliseconds
// of delay after the lastkeystroke and before the background thread
// is signaled to check the type.
//
cbData = sizeof(dwBinaryInfo); if (RegQueryValueEx(hkeyPMSettings, szCheckBinaryTimeout, 0, &dwType, (LPBYTE)&dwBinaryInfo, &cbData) == ERROR_FILE_NOT_FOUND) { //
// Key doesn't exist, so create the default case.
//
dwBinaryInfo = BINARY_TIMEOUT_DEFAULT; RegSetValueEx (hkeyPMSettings, szCheckBinaryTimeout, 0, REG_DWORD, (LPBYTE) &dwBinaryInfo, cbData); }
} if (hkeyPMRestrict && !UserIsAdmin) { cbData = sizeof(fNoRun); RegQueryValueEx(hkeyPMRestrict, szNoRun, 0, &dwType, (LPBYTE)&fNoRun, &cbData); cbData = sizeof(fNoClose); RegQueryValueEx(hkeyPMRestrict, szNoClose, 0, &dwType, (LPBYTE)&fNoClose, &cbData); cbData = sizeof(fNoSave); RegQueryValueEx(hkeyPMRestrict, szNoSave, 0, &dwType, (LPBYTE)&fNoSave, &cbData); cbData = sizeof(dwEditLevel); RegQueryValueEx(hkeyPMRestrict, szEditLevel, 0, &dwType, (LPBYTE)&dwEditLevel, &cbData); }
pszT = (LPTSTR)LocalAlloc(LPTR, SETTING_SIZE); if (!pszT) return(NULL);
/*
* Use direct registry call. */ if (hkeyPMSettings) { cbData = SETTING_SIZE; if (RegQueryValueEx(hkeyPMSettings, szWindow, 0, &dwType, (LPBYTE)pszT, &cbData)) { LocalFree((HANDLE)pszT); return NULL; } } else { return(NULL); }
return pszT; }
//#if 0
BOOL GetUserAndDomainName(LPTSTR lpBuffer, DWORD cb) { HANDLE hToken; DWORD cbTokenBuffer = 0; PTOKEN_USER pUserToken; LPTSTR lpUserName = NULL; LPTSTR lpUserDomain = NULL; DWORD cbAccountName = 0; DWORD cbUserDomain = 0; SID_NAME_USE SidNameUse;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) ){ return(FALSE); }
//
// Get space needed for token information
//
if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &cbTokenBuffer) ) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { return(FALSE); } }
//
// Get the actual token information
//
pUserToken = (PTOKEN_USER)Alloc(cbTokenBuffer); if (pUserToken == NULL) { return(FALSE); } if (!GetTokenInformation(hToken, TokenUser, pUserToken, cbTokenBuffer, &cbTokenBuffer) ) { Free(pUserToken); return(FALSE); }
//
// Get the space needed for the User name and the Domain name
//
if (!LookupAccountSid(NULL, pUserToken->User.Sid, NULL, &cbAccountName, NULL, &cbUserDomain, &SidNameUse ) ) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { Free(pUserToken); return(FALSE); } } lpUserName = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(cbAccountName+1)); if (!lpUserName) { Free(pUserToken); return(FALSE); } lpUserDomain = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(1+cbUserDomain)); if (!lpUserDomain) { LocalFree(lpUserName); Free(pUserToken); return(FALSE); }
//
// Now get the user name and domain name
//
if (!LookupAccountSid(NULL, pUserToken->User.Sid, lpUserName, &cbAccountName, lpUserDomain, &cbUserDomain, &SidNameUse ) ) {
LocalFree(lpUserName); LocalFree(lpUserDomain); Free(pUserToken); return(FALSE); }
if (*lpUserName && ((int)sizeof(TCHAR)*(lstrlen(lpBuffer) + lstrlen(lpUserName) + lstrlen(lpUserDomain)) < (int)(cb+4)) ) {
lstrcat(lpBuffer, TEXT(" - ")); lstrcat(lpBuffer, lpUserDomain); lstrcat(lpBuffer, TEXT("\\")); lstrcat(lpBuffer, lpUserName); } Free(pUserToken); LocalFree(lpUserName); LocalFree(lpUserDomain); return(TRUE); } //#endif
/*** CreateFrameWindow --
* * * HWND APIENTRY CreateFrameWindow(register PRECT prc, WORD nCmdShow) * * ENTRY - PRECT prc - * WORD nCmdShow - * * EXIT - HWND - (NULL = Error) * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
HWND APIENTRY CreateFrameWindow(register PRECT prc, WORD nCmdShow) { HDC hdc; HBRUSH hbr; HMENU hMenu; HMENU hSystemMenu; TCHAR szBuffer[40 + MAX_USERNAME_LENGTH]; TCHAR szProgmanClass[16]; TCHAR szUserName[MAX_USERNAME_LENGTH + 1] = TEXT(""); TCHAR szUserDomain[MAX_USERNAME_LENGTH + 1] = TEXT(""); DWORD dwType, cbData;
/* Create the Desktop Manager window. */ LoadString(hAppInstance, IDS_APPTITLE, szBuffer, CharSizeOf(szBuffer)); LoadString(hAppInstance, IDS_PMCLASS, szProgmanClass, CharSizeOf(szProgmanClass)); #if 1
GetUserAndDomainName(szBuffer,sizeof(szBuffer)); #else
cbData = CharSizeOf(szUserName); GetUserName(szUserName, &cbData) ; cbData = CharSizeOf(szUserDomain); GetEnvironmentVariable(TEXT("USERDOMAIN"), szUserDomain, cbData); if (*szUserName){ lstrcat(szBuffer, TEXT(" - ")); lstrcat(szBuffer, szUserDomain); lstrcat(szBuffer, TEXT("\\")); lstrcat(szBuffer, szUserName); } #endif
hwndProgman = CreateWindow(szProgmanClass, szBuffer, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, prc->left, prc->top, prc->right-prc->left, prc->bottom-prc->top, NULL, /* No Parent */ NULL, /* Use Class Menu */ hAppInstance, NULL);
if (!hwndProgman) return NULL;
SetWindowLong (hwndProgman, GWL_EXITING, 0);
hMenu = GetMenu(hwndProgman); hSystemMenu = GetSystemMenu(hwndProgman, FALSE);
if (!bExitWindows) { LoadString(hAppInstance,IDS_EXIT,szBuffer,CharSizeOf(szBuffer)); ModifyMenu(hMenu,IDM_EXIT,MF_BYCOMMAND|MF_STRING,IDM_EXIT,szBuffer); DeleteMenu(hMenu,IDM_SHUTDOWN,MF_BYCOMMAND); } else { // replace Close menu item with Logoff and Shutdown
LoadString(hAppInstance,IDS_LOGOFF,szBuffer,CharSizeOf(szBuffer)); InsertMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND|MF_STRING, SC_CLOSE, szBuffer); LoadString(hAppInstance,IDS_SHUTDOWN,szBuffer,CharSizeOf(szBuffer)); ModifyMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND|MF_STRING, IDM_SHUTDOWN, szBuffer); }
if (hkeyPMRestrict && !UserIsAdmin) { cbData = sizeof(fNoFileMenu); RegQueryValueEx(hkeyPMRestrict, szNoFileMenu, 0, &dwType, (LPBYTE)&fNoFileMenu, &cbData); }
if (fNoFileMenu) { DeleteMenu(hMenu, IDM_FILE, MF_BYPOSITION); }
if (fNoSave) { bSaveSettings = FALSE; EnableMenuItem(hMenu, IDM_SAVESETTINGS, MF_BYCOMMAND|MF_GRAYED|MF_DISABLED); EnableMenuItem(hMenu, IDM_SAVENOW, MF_BYCOMMAND|MF_GRAYED|MF_DISABLED); }
/* Update the menu items here (no maximized kids to deal with). */ if (bMinOnRun) CheckMenuItem(hMenu, IDM_MINONRUN, MF_CHECKED); if (bAutoArrange) CheckMenuItem(hMenu, IDM_AUTOARRANGE, MF_CHECKED); if (bSaveSettings) CheckMenuItem(hMenu, IDM_SAVESETTINGS, MF_CHECKED);
if (bInNtSetup) { EnableWindow(hwndProgman, FALSE); } ShowWindow(hwndProgman, nCmdShow); UpdateWindow(hwndProgman);
/* fake-paint the client area with the color of the MDI client so users
* have something pleasent to stare at while we hit the disk for the * group files */ hdc = GetDC(hwndProgman); GetClientRect(hwndProgman, prc); hbr = CreateSolidBrush(GetSysColor(COLOR_APPWORKSPACE)); if (hbr) { FillRect(hdc, prc, hbr); DeleteObject(hbr); } ReleaseDC(hwndProgman, hdc);
return hwndProgman; }
/*** IsGroup --
* * * BOOL APIENTRY IsGroup(PSTR p) * * ENTRY - PSTR p - * * EXIT - BOOL - (FALSE == ERROR) * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
BOOL PASCAL IsGroup(LPTSTR p) { if (_wcsnicmp(p, TEXT("GROUP"), CCHGROUP) != 0) { return FALSE; }
/*
* Can't have 0 for first digit */ if (p[5] == TEXT('0')) { return FALSE; }
/*
* Everything else must be a number */ for (p += CCHGROUP; *p; p++) { if (*p != TEXT('C') && (*p < TEXT('0') || *p > TEXT('9'))) { return FALSE; } }
return TRUE; }
/*** RemoveString --
* * * VOID APIENTRY RemoveString(PSTR pString) * * ENTRY - PSTR pString - * * EXIT - VOID * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
VOID APIENTRY RemoveString(LPTSTR pString) {
LPTSTR pT = pString + lstrlen(pString) + 1;
while (*pT) { while (*pString++ = *pT++) ; } *pString = 0; }
/*** StringToEnd --
* * * VOID APIENTRY StringToEnd(PSTR pString) * * ENTRY - PSTR pString - * * EXIT - VOID * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
VOID PASCAL StringToEnd(LPTSTR pString) { TCHAR *pT,*pTT;
for (pT = pString; *pT; ) //go to end of strings
while (*pT++) ; for (pTT = pString; *pT++ = *pTT++;) // copy first string to the end
; *pT = 0;
RemoveString(pString); // remove first string
}
/*** GetGroupList --
* * * VOID APIENTRY GetGroupList(PSTR szList) * * ENTRY - PSTR szList - * * EXIT - VOID * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
VOID PASCAL GetGroupList(LPTSTR szList, HKEY hkeyPMGroups) { TCHAR szOrd[CGROUPSMAX*8+7]; TCHAR szT[20]; LPTSTR pT, pTT, pS; INT cGroups; // The number of Groups= lines.
LPTSTR lpList; DWORD dwType; DWORD dwIndex = 0; DWORD cbValueName = 8; DWORD cbData; INT cbList = (CGROUPSMAX+1)*18; LPTSTR lpOrder;
lpList = szList; //
// Get the user's list of personal groups.
//
if (hkeyPMGroups) { cbValueName = cbList; while (!RegEnumValue(hkeyPMGroups, dwIndex, lpList, &cbValueName, 0, 0, 0, 0)) { dwIndex++; cbValueName++; lpList += cbValueName; cbList -= cbValueName; cbValueName = cbList; } } //
// Now get the user's list of common groups.
//
if (hkeyPMCommonGroups) { cbValueName = cbList; dwIndex = 0; while (!RegEnumValue(hkeyPMCommonGroups, dwIndex, lpList, &cbValueName, 0, 0, 0, 0)) { dwIndex++; cbValueName++; lpList += cbValueName; cbList -= cbValueName; cbValueName = cbList; } } *lpList = TEXT('\0');
cbData = sizeof(szOrd); if (bUseANSIGroups) lpOrder = szAnsiOrder; else lpOrder = szOrder;
if (!hkeyPMSettings || RegQueryValueEx(hkeyPMSettings, lpOrder, 0, &dwType, (LPBYTE)szOrd, &cbData)) *szOrd = TEXT('\0');
cGroups = 0;
/*
* Filter out anything that isn't group#. */ for (pT = szList; *pT; ) { CharUpper(pT);
if (IsGroup(pT)) { pT += lstrlen(pT) + 1; cGroups++; } else { RemoveString(pT); } }
/*
* Sort the groups */ lstrcpy(szT, TEXT("Group")); for (pT = szOrd; *pT; ) { while (*pT == TEXT(' ')) { pT++; }
if ((*pT == TEXT('C') && (*(pT+1) < TEXT('0') || *(pT+1) > TEXT('9'))) || (*pT != TEXT('C') && (*pT < TEXT('0') || *pT > TEXT('9'))) ) { break; }
pTT = szT + CCHGROUP; while (*pT == TEXT('C') || (*pT >= TEXT('0') && *pT <= TEXT('9'))) { *pTT++ = *pT++; } *pTT=0;
for (pS = szList; *pS; pS += lstrlen(pS) + 1) { if (!lstrcmpi(pS,szT)) { StringToEnd(pS); cGroups--; break; } } }
/*
* Move any remaining groups to the end of the list so that they load * last and appear on top of everything else - keeps DOS based install * programs happy. * If bInitialArrange is set then the remaining groups come from the * Windows 3.1 migration and we want these groups to be loaded before * the remaining groups so they appear below the regular groups. * 10-15-93 johannec */ if (!bInitialArrange) { while (cGroups>0) { StringToEnd(szList); cGroups--; } }
}
/*** LoadCommonGroups --
* * * VOID APIENTRY LoadCommonGroups(LPTSTR) * * ENTRY - LPTSTR the key name of the common group that should have the focus. * * EXIT - HWND hwnd of the common group which should have the focus. * * SYNOPSIS - * * WARNINGS - * EFFECTS - * */
HWND LoadCommonGroups(LPTSTR lpFocusGroup) { int i = 0; TCHAR szGroupKey[MAXKEYLEN]; DWORD cchGroupKey = CharSizeOf(szGroupKey); BOOL bRealArrange; FILETIME ft; HWND hwnd;
if (!hkeyCommonGroups) { // cannot access registry.
return(NULL); }
/*
* Set global to note that we haven't run out of memory yet. */ fLowMemErrYet = FALSE; /*
* Flag for extraction problems. */ fErrorOnExtract = FALSE;
// REVIEW - Why stop AutoArrange on load ? Switch it off for now.
bRealArrange = bAutoArrange;
//
// For mow, just load the groups in whatever order they are enumerated
// in the registry.
//
while (!RegEnumKeyEx(hkeyCommonGroups, i, szGroupKey, &cchGroupKey, 0, 0, 0, &ft)) { if (cchGroupKey) { hwnd = LoadGroupWindow(szGroupKey, 0, TRUE); } cchGroupKey = CharSizeOf(szGroupKey); i++; }
bAutoArrange = bRealArrange;
/*
* Check to see if there was any trouble. */ if (fErrorOnExtract) { /*
* On observed problem with icon extraction has been to do * with a low memory. */ MyMessageBox(hwndProgman, IDS_OOMEXITTITLE, IDS_LOWMEMONEXTRACT, NULL, MB_OK|MB_ICONHAND|MB_SYSTEMMODAL); } return(hwnd); }
/*** LoadAllGroups --
* * * VOID APIENTRY LoadAllGroups(VOID) * * ENTRY - VOID * * EXIT - VOID * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
VOID PASCAL LoadAllGroups() { LPTSTR pT, pszT; TCHAR szGroupList[(CGROUPSMAX+1)*18]; WORD wIndex; TCHAR szPath[120]; TCHAR szGroupKey[MAXKEYLEN]; BOOL bRealArrange; DWORD cbData; DWORD dwType; BOOL fShowCommonGrps = TRUE; HKEY hkeyPMAnsiGroups = NULL; HKEY hkeyGroups; TCHAR szCommonGrpInfo[MAXKEYLEN]; INT i; BOOL bDefaultPosition = FALSE; INT rgiPos[7]; HWND hwndGroup;
if (bUseANSIGroups) { RegCreateKeyEx(hkeyProgramManager, szAnsiGroups, 0, szProgman, 0, KEY_READ | KEY_WRITE, pSecurityAttributes, &hkeyPMAnsiGroups, NULL); hkeyGroups = hkeyPMAnsiGroups; } else { hkeyGroups = hkeyPMGroups; } if (!hkeyGroups) { // cannot access registry.
return; }
/*
* Set global to note that we haven't run out of memory yet. */ fLowMemErrYet = FALSE; /*
* Flag for extraction problems. */ fErrorOnExtract = FALSE;
// REVIEW - Why stop AutoArrange on load ? Switch it off for now.
bRealArrange = bAutoArrange;
//
// If the user is allowed to see the common program groups, load them.
//
if (hkeyPMRestrict) { cbData = sizeof(fShowCommonGrps); RegQueryValueEx(hkeyPMRestrict, szShowCommonGroups, 0, &dwType, (LPBYTE)&fShowCommonGrps, &cbData); } if (fShowCommonGrps || AccessToCommonGroups) {
RegCreateKeyEx(hkeyProgramManager, szCommonGroups, 0, szProgman, 0, KEY_READ | KEY_WRITE, pSecurityAttributes, &hkeyPMCommonGroups, NULL); //
// Load all common program groups
//
LoadCommonGroups(szNULL); }
//
// Now load the user's personal program groups.
//
pT = szGroupList; for (GetGroupList(pT, hkeyGroups); *pT; pT += (lstrlen(pT) + 1)) {
*szGroupKey = TEXT('\0'); cbData = sizeof(szCommonGrpInfo); //
// If we're loading a common group...
//
if (*(pT+CCHGROUP) == TEXT('C') && hkeyPMCommonGroups) { if (RegQueryValueEx(hkeyPMCommonGroups, pT, 0, 0, (LPBYTE)szCommonGrpInfo, &cbData)) continue; wIndex = 0; for (pszT = pT + CCHCOMMONGROUP; *pszT; pszT++) { wIndex *= 10; wIndex += *pszT - TEXT('0'); } //
// Get the window coordinates of this common group.
//
pszT = szCommonGrpInfo; for (i=0; i < 7; i++) { rgiPos[i] = 0; while (*pszT && !((*pszT >= TEXT('0') && *pszT <= TEXT('9')) || *pszT == TEXT('-'))) pszT++;
if (!*pszT) { bDefaultPosition = TRUE; break; } rgiPos[i] = MyAtoi(pszT);
while (*pszT && ((*pszT >= TEXT('0') && *pszT <= TEXT('9')) || *pszT == TEXT('-'))) pszT++; } //
// Now get the common group's name.
//
if (*pszT) { while(*pszT && *pszT == TEXT(' ')) pszT++; lstrcpy(szGroupKey, pszT); }
hwndGroup = IsGroupAlreadyLoaded(szGroupKey, TRUE); if (!hwndGroup) { //
// The common group no longer exists, remove this entry from
// the user's list.
//
RegDeleteValue(hkeyPMCommonGroups, pT); } if (hwndGroup && !bDefaultPosition) { //
// Position the common group according to the user's choice.
//
SetInternalWindowPos(hwndGroup, (UINT)rgiPos[6], (LPRECT)&rgiPos[0], (LPPOINT)&rgiPos[4]); }
} else { if (RegQueryValueEx(hkeyGroups, pT, 0, 0, (LPBYTE)szGroupKey, &cbData)) continue; wIndex = 0; for (pszT = pT + CCHGROUP; *pszT; pszT++) { wIndex *= 10; wIndex += *pszT - TEXT('0'); }
LoadGroupWindow(szGroupKey, wIndex, FALSE); } } bAutoArrange = bRealArrange;
//
// If we started with ANSI groups, save the newly converted unicode
// groups now.
//
if (bUseANSIGroups) { WriteINIFile(); }
if (hkeyPMAnsiGroups) { RegCloseKey(hkeyPMAnsiGroups); }
/*
* Record the current display driver. */ GetPrivateProfileString(szSystemBoot, szSystemDisplay, szPath, szPath, CharSizeOf(szPath), szSystemIni); RegSetValueEx(hkeyPMSettings, szSystemDisplay, 0, REG_SZ, (LPBYTE)szPath, sizeof(TCHAR)*(lstrlen(szPath)+1));
/*
* Check to see if there was any trouble. */ if (fErrorOnExtract) { /*
* On observed problem with icon extraction has been to do * with a low memory. */ MyMessageBox(hwndProgman, IDS_OOMEXITTITLE, IDS_LOWMEMONEXTRACT, NULL, MB_OK|MB_ICONHAND|MB_SYSTEMMODAL); } }
//*************************************************************
//
// UseAnsiGroups()
//
// Purpose: Determine if we should convert the ANSI groups
// to Unicode groups.
//
// Parameters: DWORD dwDisp - disposition from RegCreateKeyEx
// on UNICODE Program Groups
//
// Return: BOOL TRUE if the groups should be converted
// FALSE if not
//
//*************************************************************
BOOL UseAnsiGroups(DWORD dwDisp) { DWORD dwType, dwMigrateValue, dwSize, dwAnsiValue = 0; LONG lResult; BOOL bRet = FALSE; HKEY hKeyAnsiPG;
//
// If the dwDisp is a new key, then we return immediately and use
// the ANSI groups if they exist.
//
if (dwDisp == REG_CREATED_NEW_KEY) { return TRUE; }
//
// dwDisp is an existing key.
// If the "Migrate Ansi" value exist and the ANSI groups exist,
// then use them otherwise use the current UNICODE information.
//
dwSize = sizeof (DWORD); lResult = RegQueryValueEx (hkeyProgramGroups, szMigrateAnsi, NULL, &dwType, (LPBYTE) &dwMigrateValue, &dwSize);
//
// Check the return value of registry call. If it fails
// then we are working with a machine that has UNICODE Program
// Groups, and does not need to be updated from the ANSI groups.
// Most of the time, we will exit here.
//
if (lResult != ERROR_SUCCESS) { return FALSE; }
//
// Now we need to know if any ANSI groups exist.
//
lResult = RegOpenKeyEx (HKEY_CURRENT_USER, szAnsiProgramGroups, 0, KEY_READ, &hKeyAnsiPG);
if (lResult == ERROR_SUCCESS) { TCHAR szName[MAX_PATH]; DWORD dwNameSize = MAX_PATH; FILETIME ft;
//
// The "Program Groups" key exists, check to see if there is
// really something in it.
//
lResult = RegEnumKeyEx (hKeyAnsiPG, 0, szName, &dwNameSize, NULL, NULL, NULL, &ft);
//
// If the return value is success, then there is one or more
// items in the ANSI key.
//
if (lResult == ERROR_SUCCESS) { dwAnsiValue = 1; } else { dwAnsiValue = 0; }
//
// Close the key
//
RegCloseKey (hKeyAnsiPG); }
//
// If the MigrateValue is set, then we want to delete this entry
// so the next time the user logs we don't try to convert the ANSI
// groups again (and this function will execute faster).
//
if (dwMigrateValue) { RegDeleteValue (hkeyProgramGroups, szMigrateAnsi); }
//
// Determine the return value.
//
if (dwMigrateValue && dwAnsiValue) { bRet = TRUE; } else { bRet = FALSE; }
return (bRet);
}
/*** ReadConfigFile --
* * * BOOL APIENTRY ReadConfigFile(int nCmdShow) * * ENTRY - int CmdShow - * * EXIT - void * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
VOID NEAR PASCAL ReadConfigFile(int nCmdShow) { int j; int rgiPos[5]; LPTSTR pszT, pT; HCURSOR hCursor; BOOL bErrorMsgDisplayed = FALSE; TCHAR szCommonGroupsKey[MAXKEYLEN]; DWORD dwDisposition; HKEY hkey = NULL;
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); ShowCursor(TRUE);
/*
* Create/Open the registry keys corresponding to progman.ini sections. */ if (!RegCreateKeyEx(HKEY_CURRENT_USER, PROGMAN_KEY, 0, szProgman, 0, KEY_READ | KEY_WRITE, pSecurityAttributes, &hkeyProgramManager, NULL)) {
RegCreateKeyEx(hkeyProgramManager, szSettings, 0, szProgman, 0, KEY_READ | KEY_WRITE, pSecurityAttributes, &hkeyPMSettings, NULL);
RegCreateKeyEx(hkeyProgramManager, szRestrict, 0, szProgman, 0, KEY_READ, pSecurityAttributes, &hkeyPMRestrict, NULL);
RegCreateKeyEx(hkeyProgramManager, szGroups, 0, szProgman, 0, KEY_READ | KEY_WRITE, pSecurityAttributes, &hkeyPMGroups, NULL); } else { MyMessageBox(NULL, IDS_APPTITLE, IDS_REGISTRYERROR, NULL, MB_OK | MB_ICONEXCLAMATION); bErrorMsgDisplayed = TRUE; }
/* Get the global variable settings out of the INI file. */ if (pszT = GetSettings()) { /* Get the window coordinates for PROGMAN's main window. */ pT = pszT; for (j=0; j < 5; j++) { rgiPos[j] = 0; while (*pT && !((*pT >= TEXT('0') && *pT <= TEXT('9')) || *pT == TEXT('-'))) pT++;
if (!*pT) { LocalFree((HANDLE)pszT); goto DefaultPosition; }
rgiPos[j] = MyAtoi(pT);
while (*pT && ((*pT >= TEXT('0') && *pT <= TEXT('9')) || *pT == TEXT('-'))) pT++; } LocalFree((HANDLE)pszT); } else {
DefaultPosition: /* NOTE: cx = 0 - CW_USEDEFAULT == CW_USEDEFAULT (0x8000) */ rgiPos[0] = rgiPos[1] = CW_USEDEFAULT; rgiPos[2] = rgiPos[3] = 0; rgiPos[4] = SW_SHOWNORMAL; }
if (nCmdShow != SW_SHOWNORMAL) rgiPos[4] = nCmdShow;
/*
* We don't want an invisible Program Manager! */ if (!(rgiPos[4])) rgiPos[4] = SW_SHOWNORMAL;
/* Create and paint the top-level frame window. */ if (!CreateFrameWindow((PRECT)rgiPos, (WORD)rgiPos[4])) goto RCFErrExit;
/*
* Will create/open the key Program Groups, parent of all groups. */ if (RegCreateKeyEx(HKEY_CURRENT_USER, szProgramGroups, 0, szGroups, 0, KEY_READ | KEY_WRITE, pSecurityAttributes, &hkeyProgramGroups, &dwDisposition)) { if (!bErrorMsgDisplayed) { MyMessageBox(NULL, IDS_APPTITLE, IDS_REGISTRYERROR, NULL, MB_OK | MB_ICONEXCLAMATION); } goto RCFErrExit; } if (UseAnsiGroups(dwDisposition)) { //
// There are no UNICODE groups, so convert the ANSI groups and save
// them as UNICODE groups.
//
bUseANSIGroups = TRUE; if (RegCreateKeyEx(HKEY_CURRENT_USER, szAnsiProgramGroups, 0, szGroups, 0, KEY_READ, pSecurityAttributes, &hkeyAnsiProgramGroups, &dwDisposition)) { if (!bErrorMsgDisplayed) { MyMessageBox(NULL, IDS_APPTITLE, IDS_REGISTRYERROR, NULL, MB_OK | MB_ICONEXCLAMATION); } goto RCFErrExit; } }
/*
* Will create/open the key Program Groups for common groups on the local * machine. */
lstrcpy(szCommonGroupsKey, TEXT("SOFTWARE\\")); lstrcat(szCommonGroupsKey, szAnsiProgramGroups);
//
// Try opening/creating the common groups key with Write access
//
OpenCommonGroupsKey:
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szCommonGroupsKey, 0, szGroups, 0, KEY_READ | KEY_WRITE | DELETE, pAdminSecAttr, &hkeyCommonGroups, &dwDisposition) == ERROR_SUCCESS) { if (dwDisposition == REG_CREATED_NEW_KEY) { //
// need to close and reopen the key to make sure we have the
// right access
//
RegCloseKey(hkeyCommonGroups); goto OpenCommonGroupsKey; } AccessToCommonGroups = TRUE;
} else {
RegOpenKeyEx(HKEY_LOCAL_MACHINE, szCommonGroupsKey, 0, KEY_READ, &hkeyCommonGroups); }
//
// If we have Ansi groups in the profile, add a menu item under the Options menu
// to remove the old NT1.0 ANSI groups. This menu item will be deleted we the
// user selects to remove the old groups
//
if (!fNoSave && (bUseANSIGroups || !RegOpenKeyEx(HKEY_CURRENT_USER, szAnsiProgramGroups, 0, DELETE | KEY_READ | KEY_WRITE, &hkey))){
HMENU hMenu = GetSubMenu(GetMenu(hwndProgman), 1);
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); LoadString(hAppInstance, IDS_ANSIGROUPSMENU, szMessage, CharSizeOf(szMessage)); AppendMenu(hMenu, MF_STRING | MF_ENABLED, IDM_ANSIGROUPS, szMessage); if (hkey) { RegCloseKey(hkey); } }
/* The main frame window's been created, shown, and filled.
* It's time to read the various group files, by enumerating group# * lines in PROGMAN.INI */ LoadAllGroups();
/*
* Restriction key is no longer needed. */ if (hkeyPMRestrict) { RegCloseKey(hkeyPMRestrict); hkeyPMRestrict = NULL; }
RCFErrExit: //
// We've got the Ansi groups, reset this value.
//
bUseANSIGroups = FALSE; RegCloseKey(hkeyAnsiProgramGroups); hkeyAnsiProgramGroups = NULL;
ShowCursor(FALSE); SetCursor(hCursor); ShowWindow(hwndMDIClient,SW_SHOWNORMAL); }
/****************************************************************************
* * FUNCTION: ParseReserved(LPTSTR lpReserved, LPDWORD lpDdeId, LPDWORD lpHotKey) * * PURPOSE: Parses the lpReserved field of the StartupInfo structure to * get the Progman's new instance DDE id and its Hot key. * The lpReserved field is a string of thee following format: * "dde.%d,hotkey.%d" * * Returns the dde id and hotkey. * * COMMENTS: This is to be compatible with Win3.1 by allowing users to * set a hotkey for Progman, and to allow them to change * Progman's icon and window title (see SetProgmanProperties in * pmwprocs.c) * * * HISTORY: 08-28-92 JohanneC Created. * ****************************************************************************/
void ParseReserved(LPTSTR lpReserved, LPDWORD lpDdeId, LPDWORD lpHotKey) { TCHAR *pch, *pchT, ch;
//
// The string will be of the format "dde.%d,hotkey.%d"
//
//
// Get the DDE id.
//
if ((pch = wcsstr(lpReserved, TEXT("dde."))) != NULL) { pch += 4;
pchT = pch; while (*pchT >= TEXT('0') && *pchT <= TEXT('9')) pchT++;
ch = *pchT; *pchT = 0; *lpDdeId = MyAtoi(pch); *pchT = ch;
}
//
// Get the hot key.
//
if ((pch = wcsstr(lpReserved, TEXT("hotkey."))) != NULL) { pch += 7;
pchT = pch; while (*pchT >= TEXT('0') && *pchT <= TEXT('9')) pchT++;
ch = *pchT; *pchT = 0; *lpHotKey = MyAtoi(pch); *pchT = ch;
} }
/*** IsHandleReallyProgman --
* * * BOOL IsHandleReallyProgman (HWND hProgman, LPTSTR lpClassName) * * ENTRY - HWND hProgman * * EXIT - BOOL TRUE if it is progman * FALSE if not * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
BOOL IsHandleReallyProgman(HWND hwndProgman) {
//
// Test to see if we found Progman or Explorer.
//
if ((GetClassLong (hwndProgman, GCL_STYLE) == 0) && (GetClassLongPtr (hwndProgman, GCLP_HICON) != 0) && (GetClassLongPtr (hwndProgman, GCLP_MENUNAME) != 0)) {
return TRUE; }
return FALSE; }
/*** AppInit --
* * * BOOL APIENTRY AppInit(HANDLE hInstance, HANDLE hPrevInstance, * LPTSTR lpszCmdLine, int nCmdShow) * * ENTRY - HANDLE hInstance * HANDLE hPrevInstance * LPTSTR lpszCmdLine * int nCmdSHow * * EXIT - BOOL xxx - (FALSE == ERROR) * * SYNOPSIS - ?? * * WARNINGS - * EFFECTS - * */
BOOL APIENTRY AppInit(HANDLE hInstance, LPTSTR lpszCmdLine, int nCmdShow) { WORD ret; WNDCLASS wndClass; TCHAR szClass[16]; TCHAR szBuffer[MAX_PATH]; LOGFONT lf; TCHAR szText[MAXMESSAGELEN+1]; STARTUPINFO si; HWND hwndPrev; INT nTempCmdShow = nCmdShow;
#ifdef DEBUG_PROGMAN_DDE
{ TCHAR szDebug[300];
wsprintf (szDebug, TEXT("%d PROGMAN: Enter AppInit\r\n"), GetTickCount()); OutputDebugString(szDebug); } #endif
//
// Preserve this instance's module handle.
//
hAppInstance = hInstance;
//
// Specify the shutdown order of the progman process.
// 2 means Porgman will shutdown before taskman (level = 1) and
// ntsd or windbg (level = 0)
//
SetProcessShutdownParameters(2,0);
#ifndef MYDEBUG
LoadString(hAppInstance, IDS_PMCLASS, szClass, CharSizeOf(szClass)); if (hwndPrev = FindWindow(szClass, NULL)) {
bDisableDDE = TRUE; // Only 1 "PROGMAN" should respond to dde
if (IsHandleReallyProgman(hwndPrev)) { DWORD dwDdeId = 0; DWORD dwHotKey = 0; LONG lExiting;
GetStartupInfo(&si); if (si.lpReserved) { ParseReserved(si.lpReserved, &dwDdeId, &dwHotKey); }
PostMessage(hwndPrev, WM_EXECINSTANCE, (WPARAM)dwDdeId, dwHotKey);
//
// Need to check the other progman to see if it is exiting currently.
// If so, then we will continue. GetWindowLong returns 0 as a
// failure case and as the "Not exiting" case (1 if we are exiting),
// so we need to confirm that the last error is also
// zero.
//
lExiting = GetWindowLong (hwndPrev, GWL_EXITING);
if (lExiting != 1) { return FALSE; } } } #endif
/*
* Compute general constants. */ dyBorder = GetSystemMetrics(SM_CYBORDER); hItemIcon = LoadIcon(hAppInstance, (LPTSTR) MAKEINTRESOURCE(ITEMICON)); if (!hItemIcon) { return FALSE; }
/*
* Load the accelerator table. */ hAccel = LoadAccelerators(hAppInstance, (LPTSTR) MAKEINTRESOURCE(PMACCELS)); if (!hAccel) return FALSE;
cxIcon = GetSystemMetrics(SM_CXICON); cyIcon = GetSystemMetrics(SM_CYICON);
cxOffset = 2 * GetSystemMetrics(SM_CXBORDER); cyOffset = 2 * GetSystemMetrics(SM_CYBORDER);
cxIconSpace = cxIcon + 2 * cxOffset; cyIconSpace = cyIcon + 2 * cyOffset;
SystemParametersInfo(SPI_ICONHORIZONTALSPACING, 0, (PVOID)(LPINT)&cxArrange, FALSE); SystemParametersInfo(SPI_ICONVERTICALSPACING, 0, (PVOID)(LPINT)&cyArrange, FALSE); SystemParametersInfo(SPI_GETICONTITLEWRAP, 0, (PVOID)(LPWORD)&bIconTitleWrap, FALSE); SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), (PVOID)(LPLOGFONT)&lf, FALSE);
// lhb tracks check this out !!!! save this one for later! 1/21/93
//lf.lfCharSet = ANSI_CHARSET ;
//lstrcpy (lf.lfFaceName, TEXT("Lucida Sans Unicode"));
hFontTitle = CreateFontIndirect(&lf);
if (!hFontTitle) return FALSE;
hIconGlobal = LoadIcon(hAppInstance,(LPTSTR) MAKEINTRESOURCE(WORDICON)); if (!hIconGlobal) { return FALSE; }
/*
* Remember the original directory. */ GetCurrentDirectory(MAXITEMPATHLEN+1, szOriginalDirectory);
//
// Set Progman's working directory to system32 directory instead of the
// windows directory. johannec 5-4-93 bug 8364
//
//GetWindowsDirectory(szWindowsDirectory, MAXITEMPATHLEN+1);
GetSystemDirectory(szWindowsDirectory, MAXITEMPATHLEN+1);
/*
* Make sure drive letter is upper case. */ CharUpperBuff(szWindowsDirectory, 1);
bInNtSetup = FALSE;
if (lpszCmdLine && *lpszCmdLine && !lstrcmpi(lpszCmdLine, TEXT("/NTSETUP"))) { //
// Progman was started from ntsetup.exe, so it can be exited
// without causing NT Windows to exit.
//
bExitWindows = FALSE; bInNtSetup = TRUE; *lpszCmdLine = 0;
} else { HKEY hkeyWinlogon; DWORD dwType; DWORD cbBuffer; LPTSTR lpt;
/* Check if we should be the shell by looking at shell= line for WInlogon
*/ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), 0, KEY_READ, &hkeyWinlogon) == ERROR_SUCCESS) { cbBuffer = sizeof(szBuffer); if (RegQueryValueEx(hkeyWinlogon, TEXT("Shell"), 0, &dwType, (LPBYTE)szBuffer, &cbBuffer) == ERROR_SUCCESS) { CharLower(szBuffer); lpt = szBuffer; while (lpt = wcsstr(lpt, szProgman)) { //
// we probably found progman
//
lpt += lstrlen(szProgman); if (*lpt == TEXT(' ') || *lpt == TEXT('.') || *lpt == TEXT(',') || !*lpt) bExitWindows = TRUE; } } else { //
// assume that progman is the shell.
//
bExitWindows = TRUE; } RegCloseKey(hkeyWinlogon); } else { //
// assume that progman is the shell.
//
bExitWindows = TRUE; }
}
if (lpszCmdLine && *lpszCmdLine) { nCmdShow = SW_SHOWMINNOACTIVE; }
/*
* call private api to mark task man as a system app. This causes * it to be killed after all other non-system apps during shutdown. */ // MarkProcess(MP_SYSTEMAPP);
/*
* Load these strings now. If we need them later, * we won't be able to load them at that time. */ LoadString(hAppInstance, IDS_OOMEXITTITLE, szOOMExitTitle, CharSizeOf(szOOMExitTitle)); LoadString(hAppInstance, IDS_OOMEXITMSG, szOOMExitMsg, CharSizeOf(szOOMExitMsg));
LoadString(hAppInstance, IDS_PMCLASS, szClass, CharSizeOf(szClass));
SetCurrentDirectory(szWindowsDirectory);
SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); // Bounce errors to us, not fs.
// Set global exit flag.
fExiting = FALSE;
uiHelpMessage = RegisterWindowMessage(TEXT("ShellHelp")); uiBrowseMessage = RegisterWindowMessage(HELPMSGSTRING); uiActivateShellWindowMessage = RegisterWindowMessage(TEXT("ACTIVATESHELLWINDOW")); uiConsoleWindowMessage = RegisterWindowMessage(TEXT("ConsoleProgmanHandle")); uiSaveSettingsMessage = RegisterWindowMessage(TEXT("SaveSettings")); // for UPEDIT.exe : User Profile Editor
hhkMsgFilter = SetWindowsHook(WH_MSGFILTER, MessageFilter); if (hhkMsgFilter == 0) { GetLastError(); } /*
* Register the Frame window class. */ wndClass.lpszClassName = szClass; wndClass.style = 0; wndClass.lpfnWndProc = ProgmanWndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = sizeof(LONG); wndClass.hInstance = hAppInstance; wndClass.hIcon = hProgmanIcon = LoadIcon(hAppInstance, (LPTSTR) MAKEINTRESOURCE(PROGMANICON)); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = NULL; wndClass.lpszMenuName = (LPTSTR) MAKEINTRESOURCE(PROGMANMENU);
if (!RegisterClass(&wndClass)) return(FALSE);
/*
* Register the Program Group window class. */ LoadString(hAppInstance, IDS_GROUPCLASS, szClass, 16); wndClass.lpszClassName = szClass; wndClass.style = CS_DBLCLKS; wndClass.lpfnWndProc = GroupWndProc; /*wndClass.cbClsExtra = 0;*/ wndClass.cbWndExtra = sizeof(PGROUP); /* <== PGROUP */ /*wndClass.hInstance = hAppInstance;*/ wndClass.hIcon = NULL; /*wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);*/ wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wndClass.lpszMenuName = NULL;
if (!RegisterClass(&wndClass)) return(FALSE);
{ //
// Set the working set size to 300k.
//
QUOTA_LIMITS QuotaLimits; NTSTATUS status;
status = NtQueryInformationProcess( NtCurrentProcess(), ProcessQuotaLimits, &QuotaLimits, sizeof(QUOTA_LIMITS), NULL ); if (NT_SUCCESS(status)) { QuotaLimits.MinimumWorkingSetSize = 400 * 1024; QuotaLimits.MaximumWorkingSetSize = 508 * 1024;
NtSetInformationProcess( NtCurrentProcess(), ProcessQuotaLimits, &QuotaLimits, sizeof(QUOTA_LIMITS) ); } }
hGroupIcon = LoadIcon(hAppInstance, (LPTSTR) MAKEINTRESOURCE(PERSGROUPICON)); hCommonGrpIcon = LoadIcon(hAppInstance, (LPTSTR) MAKEINTRESOURCE(COMMGROUPICON));
if (!RegisterHotKeyClass((HANDLE)hAppInstance)) return FALSE;
RegisterDDEClasses((HANDLE)hAppInstance);
/*
* Initialize the security descriptor for the registry keys that * will be added to the user's personal profile. */ pSecurityAttributes = &SecurityAttributes; if (!InitializeSecurityAttributes(pSecurityAttributes, TRUE)) pSecurityAttributes = NULL;
/*
* Initialize the security descriptor for the registry keys that * will be added to the local machine program groups. Only * Administrators, Power Users and Server Operators * have all access to these keys, other users have only read access. */ pAdminSecAttr = &AdminSecAttr; if (!InitializeSecurityAttributes(pAdminSecAttr, FALSE)) pAdminSecAttr = NULL;
/*
* Test if the current user is an admin. If so, ignore restrictions * from the profile. */
UserIsAdmin = TestUserForAdmin();
/*
* Read in the Group/Item data structures and create the windows. */ #ifdef DEBUG_PROGMAN_DDE
{ TCHAR szDebug[300];
wsprintf (szDebug, TEXT("%d PROGMAN: Before ReadConfigFile\r\n"), GetTickCount()); OutputDebugString(szDebug); } #endif
ReadConfigFile(nCmdShow);
#ifdef DEBUG_PROGMAN_DDE
{ TCHAR szDebug[300];
wsprintf (szDebug, TEXT("%d PROGMAN: After ReadConfigFile\r\n"), GetTickCount()); OutputDebugString(szDebug); } #endif
if (hwndProgman == NULL) return FALSE;
/*
* NOTE: the nCmdShow stuff from here down is bogus * * Do load/run lines, then the command line, then the startup group... */ if (bExitWindows) DoRunEquals(&nCmdShow);
/* Process the Command Line */ if (lpszCmdLine && *lpszCmdLine) { WORD cbText; TCHAR szFilename[MAXITEMPATHLEN+1];
lstrcpy(szPathField, lpszCmdLine); // win foo.bar is done relative to the original directory.
SetCurrentDirectory(szOriginalDirectory); GetDirectoryFromPath(szPathField, szDirField);
// now kernel converts the DOS cmd line to Ansi for us!
GetFilenameFromPath(szPathField, szFilename); ret = ExecProgram(szFilename, szDirField, NULL, FALSE, 0, 0, 0); if (ret) { szText[0] = TEXT('\''); lstrcpy(&szText[1],szPathField); cbText = (WORD)lstrlen(szText); LoadString(hAppInstance,IDS_CMDLINEERR,&szText[cbText],CharSizeOf(szText)-cbText); MyMessageBox(NULL, IDS_APPTITLE, ret, szText, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL); } else nCmdShow = SW_SHOWMINNOACTIVE; SetCurrentDirectory(szWindowsDirectory); }
/*
* See if we have a startup group last. */ #ifndef MYDEBUG
if (bExitWindows || GetAsyncKeyState(VK_CONTROL) < 0) #endif
HandleStartupGroup(nTempCmdShow);
/*
* create an event for monitoring the ProgramGroups key. */ InitializeGroupKeyNotification();
if (bInitialArrange) { PostMessage(hwndMDIClient, WM_MDIICONARRANGE, 0, 0L); PostMessage(hwndProgman, WM_COMMAND, IDM_SAVENOW, 0L); }
#ifdef DEBUG_PROGMAN_DDE
{ TCHAR szDebug[300];
wsprintf (szDebug, TEXT("%d PROGMAN: Leave AppInit\r\n"), GetTickCount()); OutputDebugString(szDebug); } #endif
return TRUE; }
|