Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

2030 lines
55 KiB

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