/* * 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; }