· last year · May 04, 2024, 10:00 PM
1/*++
2
3Copyright (c) 1992 Microsoft Corporation
4
5Module Name:
6
7 taskman.c
8
9Abstract:
10
11 This file contains the source for the windows Task Manager.
12 Taskman basically is a dialog box, which enumerates active windows
13 keep in the user window manager, then sets active focus to the selected
14 dialog box element(ie active window).
15
16--*/
17
18#define UNICODE
19
20#include "taskman.h"
21#include <port1632.h>
22#include <shellapi.h>
23#include <shlapip.h>
24
25//LATER find correct define for NT
26#if !defined(NTWIN) && !defined(DOSWIN32) && !defined(WIN16)
27#define NTWIN 1
28#endif
29
30#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
31
32#define MAXPATHFIELD 260
33
34#define INIT_MAX_FILES 4
35#define FILES_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager\\Recent File List"
36#define MAXFILES_ENTRY L"Max Files"
37#define FILE_ENTRY L"File%lu"
38
39#define WM_CONTENTSCHANGED (WM_USER+5)
40
41TCHAR szPathField[MAXPATHFIELD];
42TCHAR szDirField[MAXPATHFIELD];
43TCHAR szTitle[MAXPATHFIELD];
44TCHAR szMessage[MAXMSGBOXLEN];
45
46TCHAR szUserHomeDir[MAXPATHFIELD];
47TCHAR szWindowsDirectory[MAXPATHFIELD];
48
49TCHAR szOOMExitMsg[64] = TEXT("Close an application and try again."); // 64
50TCHAR szOOMExitTitle[32] = TEXT("Extremely Low on Memory"); // 32
51
52TCHAR szNoRun[] = TEXT("NoRun");
53// registry key for groups
54
55HANDLE hInst;
56
57BOOL bChangedDefaultButton;
58
59INT_PTR APIENTRY TaskmanDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
60
61WORD APIENTRY ExecProgram(LPTSTR lpszPath,LPTSTR lpDir,LPTSTR lpTitle);
62void APIENTRY SaveRecentFileList (HWND, LPTSTR);
63
64VOID GetPathInfo(PTSTR szPath,PTSTR *pszFileName,PTSTR *pszExt,WORD *pich,BOOL *pfUnc);
65VOID GetFilenameFromPath(PTSTR szPath, PTSTR szFilename);
66VOID GetDirectoryFromPath(PTSTR szFilePath, PTSTR szDir);
67BOOL IsUserAdmin();
68BOOL OKToExec();
69BOOL TestTokenForAdmin(HANDLE Token);
70VOID SetDefButton(HWND hwndDlg, INT idButton);
71
72WINUSERAPI VOID SwitchToThisWindow(HWND, BOOL);
73INT MyMessageBox(HWND hWnd,WORD idTitle,WORD idMessage,PWSTR psz,WORD wStyle);
74
75INT MyX = 0;
76INT MyY = 0;
77INT dxTaskman;
78INT dyTaskman;
79INT dxScreen;
80INT dyScreen;
81
82HWND ghwndDialog;
83BOOL fExecOK = TRUE;
84BOOL fMsgBox = FALSE;
85
86
87PVOID Alloc(
88 DWORD Bytes)
89{
90 HANDLE hMem;
91 PVOID Buffer;
92
93 hMem = LocalAlloc(LMEM_MOVEABLE, Bytes + sizeof(hMem));
94
95 if (hMem == NULL) {
96 return(NULL);
97 }
98
99 Buffer = LocalLock(hMem);
100 if (Buffer == NULL) {
101 LocalFree(hMem);
102 return(NULL);
103 }
104
105 *((PHANDLE)Buffer) = hMem;
106
107 return (PVOID)(((PHANDLE)Buffer)+1);
108}
109
110
111BOOL Free(
112 PVOID Buffer)
113{
114 HANDLE hMem;
115
116 hMem = *(((PHANDLE)Buffer) - 1);
117
118 LocalUnlock(hMem);
119
120 return(LocalFree(hMem) == NULL);
121}
122
123
124VOID
125HideWindow(HWND hwnd)
126{
127 if (!fMsgBox) {
128
129 if (fExecOK) {
130 SetDlgItemText(ghwndDialog, IDD_PATH, TEXT(""));
131 }
132
133 // redundant? why do they do the reverse twice for show below?
134 ShowWindow(ghwndDialog, SW_HIDE);
135
136 SetWindowPos(ghwndDialog, HWND_NOTOPMOST, 0, 0, 0, 0,
137 SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
138 }
139
140 // Erase dark border from depressed pushbuttons
141 SendMessage(GetDlgItem(hwnd, IDCANCEL), // IDCANCEL
142 BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
143 SendMessage(GetDlgItem(hwnd, IDD_TERMINATE),
144 BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
145 SendMessage(GetDlgItem(hwnd, IDD_CASCADE),
146 BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
147 SendMessage(GetDlgItem(hwnd, IDD_TILE),
148 BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
149 SendMessage(GetDlgItem(hwnd, IDD_ARRANGEICONS),
150 BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
151}
152
153/*
154 * We call HideTasklist() when we want to remove the tasklist window
155 * from the screen but not select another window (ie. when we're about
156 * to select another app. We call ShowWindow(SW_HIDE) directly when
157 * we're doing something like tiling or cascading so a window other than
158 * the tasklist will become the foreground window.
159 */
160VOID HideTasklist(VOID)
161{
162 if (fExecOK) {
163 SetDlgItemText(ghwndDialog, IDD_PATH, TEXT(""));
164 }
165
166 SetWindowPos(ghwndDialog, HWND_TOP, 0, 0, 0, 0, SWP_HIDEWINDOW |
167 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
168
169}
170
171
172VOID ShowTasklist(
173 POINT pt)
174{
175 /*
176 * Retract the drop down listbox.
177 */
178
179 if (fExecOK) {
180 SendDlgItemMessage(ghwndDialog, IDD_PATH,
181 CB_SHOWDROPDOWN,0,0);
182 }
183
184 SetWindowPos(ghwndDialog, HWND_TOPMOST, pt.x, pt.y, 0, 0,
185 SWP_NOSIZE | SWP_NOACTIVATE );
186 SetForegroundWindow(ghwndDialog);
187
188 ShowWindow(ghwndDialog, SW_NORMAL);
189}
190
191
192/*** ActivateSelectedWindow -- Calls user, to set active window, selected
193 * by the user.
194 *
195 *
196 * ActivateSelectedWindow(HWND hwndLB)
197 *
198 * ENTRY - HWND hwndLB - handle to window, which is to become the active
199 * window, with focus.
200 * EXIT -
201 * SYNOPSIS - This function takes the hwnd passed into it, calls user
202 * to set active focus to that window.
203 * WARNINGS -
204 * EFFECTS -
205 *
206 */
207
208VOID ActivateSelectedWindow(
209 HWND hwndLB)
210{
211 INT nIndex;
212 HWND hwndT;
213 HWND hwndLastActive;
214 DWORD lTemp;
215
216 /*
217 * Get the hwnd of the item which was selected.
218 */
219 nIndex = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0);
220 hwndT = (HWND)SendMessage(hwndLB, LB_GETITEMDATA, nIndex, 0);
221
222 if (!IsWindow(hwndT)) {
223 /*
224 * We gotta make sure the window is valid before doing stuff with it.
225 * An app may terminate itself in the background rendering these
226 * window handles invalid.
227 */
228 goto Beep;
229 }
230
231 /*
232 * Switch to that task.
233 * HACK! Activate the window in the hwndLastActive field of the WndStruct.
234 */
235 hwndLastActive = GetLastActivePopup(hwndT);
236
237 if (!IsWindow(hwndLastActive)) {
238 goto Beep;
239 }
240
241 /*
242 * But only if it isn't disabled.
243 */
244 lTemp = GetWindowLong(hwndLastActive, GWL_STYLE);
245 if (!(lTemp & WS_DISABLED)) {
246 /*
247 * HACK!! Use SwitchToThisWindow() to bring dialog parents as well.
248 */
249 SwitchToThisWindow(hwndLastActive, TRUE);
250
251 } else {
252Beep:
253 MessageBeep(0);
254 }
255}
256
257#ifdef NTWIN
258/*** DoEndTask --
259 *
260 * void DoEndTask( HWND hwnd )
261 */
262VOID DoEndTask(
263 HWND hwnd )
264{
265 TCHAR szMsgBoxText[MAXMSGBOXLEN];
266 TCHAR szTempField[MAXTASKNAMELEN];
267 INT nch;
268
269
270 if (!EndTask(hwnd, FALSE, FALSE)) {
271 /* App does not want to close, ask user if
272 * he wants to blow it away
273 */
274
275 InternalGetWindowText(hwnd, (LPTSTR)szTempField, MAXTASKNAMELEN);
276
277 /* Load the message box string, it is very long (greater than 255 chars
278 * which is why we load it in two pieces
279 */
280 nch = LoadString(NULL, IDS_MSGBOXSTR1, szMsgBoxText, MAXMSGBOXLEN);
281 LoadString(NULL, IDS_MSGBOXSTR2, &szMsgBoxText[nch], MAXMSGBOXLEN-nch);
282
283 if( MessageBox( NULL, szMsgBoxText, szTempField,
284 MB_SETFOREGROUND | MB_SYSTEMMODAL | MB_YESNO ) == IDYES) {
285 EndTask(hwnd, FALSE, TRUE);
286 }
287 }
288}
289
290
291/*** CallEndTask -- A separate thread to instigate EndTask
292 *
293 * CallEndTask( HWND hwnd );
294 *
295 * ENTRY - HWND hwnd - window handle for the task to be killed
296 * EXIT -
297 * SYNOPSIS - This function calls EndTask on the given window to kill the
298 * task that owns that window.
299 *
300 * WARNINGS -
301 * EFFECTS - Kills the task that owns hwnd.
302 *
303 */
304
305DWORD CallEndTask(
306 HWND hwnd)
307{
308 DoEndTask(hwnd);
309
310 ExitThread(0);
311 return 0; /* placate compiler */
312}
313#endif
314
315
316/*** TaskmanDlgProc -- Dialog Procedure for Taskman Window
317 *
318 *
319 *
320 * TaskmanDlgProc(HWND hDlg, WORD wMSG, DWORD wParam, LPARAM lParam)
321 *
322 * ENTRY - HWND hhDlg - handle to dialog box.
323 * WORD wMsg - message to be acted upon.
324 * DWORD wParam - value specific to wMsg.
325 * LPARAM lParam - value specific to wMsg.
326 *
327 * EXIT - True if success, False if not.
328 * SYNOPSIS - Dialog box message processing function.
329 *
330 * WARNINGS -
331 * EFFECTS -
332 *
333 */
334
335INT_PTR TaskmanDlgProc(
336 HWND hwnd,
337 UINT wMsg,
338 WPARAM wParam,
339 LPARAM lParam)
340{
341 int nIndex;
342 RECT rc;
343 HWND hwndLB;
344 HWND hwndNext;
345 TCHAR szTempField[MAXTASKNAMELEN];
346 POINT pt;
347 HKEY hKey;
348 DWORD dwDisp;
349 DWORD dwDataType, dwMaxFiles=INIT_MAX_FILES, dwMaxFilesSize, dwCount;
350 TCHAR szFileEntry[20];
351 TCHAR szFullPath[MAXPATHFIELD];
352#ifndef NTWIN
353 LONG lTemp;
354#endif
355
356 hwndLB = GetDlgItem(hwnd, IDD_TASKLISTBOX);
357
358 switch (wMsg) {
359
360 case WM_INITDIALOG:
361 /*
362 * call private api to mark task man as a system app. This causes
363 * it to be killed after all other non-system apps during shutdown.
364 */
365// MarkProcess(MP_SYSTEMAPP);
366 GetWindowRect(hwnd, &rc);
367 dxTaskman = rc.right - rc.left;
368 dyTaskman = rc.bottom - rc.top;
369 dxScreen = GetSystemMetrics(SM_CXSCREEN);
370 dyScreen = GetSystemMetrics(SM_CYSCREEN);
371
372 pt.x = (dxScreen - dxTaskman) / 2;
373 pt.y = (dyScreen - dyTaskman) / 2;
374
375 SetWindowPos(hwnd, HWND_NOTOPMOST, pt.x, pt.y, 0, 0,
376 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
377
378 SendDlgItemMessage(hwnd, IDD_PATH, EM_LIMITTEXT, MAXPATHFIELD-4, 0L);
379 szPathField[0] = TEXT('\0');
380
381 bChangedDefaultButton = FALSE;
382
383 return FALSE;
384
385 case WM_SHOWWINDOW:
386 /*
387 * If we're being shown fill in the listbox. We do this here
388 * rather than in WM_ACTIVATE process so we can do it while the
389 * dialog is still invisible.
390 */
391 if (wParam != 0) {
392 DWORD pidTaskMan = GetCurrentProcessId();
393
394 /*
395 * First delete any previous entries.
396 */
397 while ((int)SendMessage(hwndLB, LB_DELETESTRING, 0, 0) != LB_ERR);
398
399 /*
400 * Search the window list for enabled top level windows.
401 */
402 hwndNext = GetWindow(hwnd, GW_HWNDFIRST);
403 while (hwndNext) {
404
405 /*
406 * Only add non-owned, visible, non-Taskman, Top Level Windows.
407 */
408 if ((hwndNext != hwnd) && (IsWindowVisible(hwndNext)) &&
409 (!GetWindow(hwndNext, GW_OWNER))) {
410 DWORD pidNext;
411 GetWindowThreadProcessId(hwndNext, &pidNext);
412 if (pidNext != pidTaskMan) {
413 if (InternalGetWindowText(hwndNext, (LPTSTR)szTempField,
414 MAXTASKNAMELEN)) {
415 nIndex = (int)SendMessage(hwndLB, LB_ADDSTRING, 0,
416 (DWORD_PTR)(LPTSTR)szTempField);
417 SendMessage(hwndLB, LB_SETITEMDATA, nIndex,
418 (DWORD_PTR)hwndNext);
419 }
420 }
421 }
422
423 hwndNext = GetWindow(hwndNext, GW_HWNDNEXT);
424 }
425 SendMessage(hwndLB, LB_SETCURSEL, 0, 0);
426
427 //
428 // Set the default button to "Switch To"
429 //
430
431 SetDefButton(hwnd,IDD_SWITCH);
432
433 //
434 // Load the combobox with the recently used files.
435 //
436
437 if (GetDlgItem(hwnd, IDD_PATH)) {
438
439 //
440 // FIrst empty the combo box from the last time.
441 //
442
443 SendDlgItemMessage (hwnd, IDD_PATH,
444 CB_RESETCONTENT, 0, 0);
445
446
447 //
448 // Load the combobox with recently used files from the registry.
449 //
450 // Query the max number of files first.
451 //
452
453 if (RegCreateKeyEx (HKEY_CURRENT_USER, FILES_KEY, 0, 0,
454 REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
455 NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
456
457 if (dwDisp == REG_OPENED_EXISTING_KEY) {
458
459 //
460 // Query the max number of entries
461 //
462
463 dwMaxFilesSize = sizeof (DWORD);
464
465 if (RegQueryValueEx (hKey, MAXFILES_ENTRY, NULL, &dwDataType,
466 (LPBYTE)&dwMaxFiles, &dwMaxFilesSize) == ERROR_SUCCESS) {
467
468 //
469 // Now Query each entry and add it to the list box.
470 //
471
472 for (dwCount=0; dwCount < dwMaxFiles; dwCount++) {
473
474 wsprintf (szFileEntry, FILE_ENTRY, dwCount);
475 dwMaxFilesSize = MAXPATHFIELD+1;
476
477 if (RegQueryValueEx (hKey, szFileEntry, NULL, &dwDataType,
478 (LPBYTE) szFullPath, &dwMaxFilesSize) == ERROR_SUCCESS) {
479
480 //
481 // Found an entry. Add it to the combo box.
482 //
483
484 SendDlgItemMessage (hwnd, IDD_PATH,
485 CB_ADDSTRING, 0,
486 (LPARAM)szFullPath);
487
488 } else {
489 break;
490 }
491 }
492 }
493 } else {
494 //
495 // We are working with a new key, so we need to
496 // set the default number of files.
497 //
498
499 RegSetValueEx (hKey, MAXFILES_ENTRY, 0, REG_DWORD,
500 (CONST BYTE *) &dwMaxFiles, sizeof (DWORD));
501 }
502
503 //
504 // Close the registry key
505 //
506
507 RegCloseKey (hKey);
508
509 }
510 }
511
512 //
513 // Disable the Run button and set the focus to the
514 // listbox.
515 //
516
517 EnableWindow(GetDlgItem(hwnd, IDD_RUN), FALSE);
518 SetFocus(hwndLB);
519 }
520 break;
521
522 case WM_ACTIVATE:
523 /*
524 * If we're being deactivated clear the listbox so we
525 * can fill it in afresh when we're re-activated.
526 */
527 if (wParam == 0) {
528 /*
529 * If we're not already invisible, hide ourself.
530 */
531 if (IsWindowVisible(hwnd)) {
532 HideWindow(hwnd);
533 }
534 }
535
536 if (!bChangedDefaultButton) {
537 SetDefButton(hwnd,IDD_SWITCH);
538 }
539
540 break;
541
542 case WM_ACTIVATEAPP:
543 if (wParam)
544 return FALSE;
545
546 /*
547 * If we are not visible when we get this message it is because
548 * we are already in the process of terminating. If we don't
549 * ignore this we get into a weird race condition and the frame
550 * of the window being activated doesn't get fully drawn. (BG)
551 */
552 if (IsWindowVisible(hwnd)) {
553 HideWindow(hwnd);
554 }
555 break;
556
557#ifdef JAPAN // bug fix
558 //
559 // Do nothing. Let the progman main thread do the work.
560 //
561#else // not JAPAN
562 case WM_WININICHANGE:
563 //
564 // Check if the user's environment variables have changed, if so
565 // regenerate the environment, so that new apps started from
566 // taskman will have the latest environment.
567 //
568 if (lParam && (!lstrcmpi((LPTSTR)lParam, (LPTSTR) TEXT("Environment")))) {
569 PVOID pEnv;
570
571 RegenerateUserEnvironment(&pEnv, TRUE);
572 break;
573 }
574 else {
575 return FALSE;
576 }
577#endif // JAPAN
578
579 case WM_CONTENTSCHANGED:
580 if (fExecOK) {
581 if (GetDlgItemText(hwnd, IDD_PATH, (LPTSTR)szPathField, MAXPATHFIELD)) {
582 EnableWindow(GetDlgItem(hwnd, IDD_RUN), TRUE);
583 if (!bChangedDefaultButton) {
584 SetDefButton(hwnd,IDD_RUN);
585 bChangedDefaultButton = TRUE;
586 }
587 } else {
588 EnableWindow(GetDlgItem(hwnd, IDD_RUN), FALSE);
589 if (bChangedDefaultButton) {
590 SetDefButton(hwnd,IDD_SWITCH);
591 bChangedDefaultButton = FALSE;
592 }
593 }
594 }
595
596 break;
597
598
599 case WM_COMMAND:
600 switch(LOWORD(wParam)) {
601
602 case IDD_TASKLISTBOX:
603
604 switch(HIWORD(wParam)) {
605
606 case LBN_DBLCLK:
607 HideTasklist();
608 ActivateSelectedWindow(hwndLB);
609 break;
610
611 default:
612 return FALSE;
613 }
614 break;
615
616 case IDD_PATH:
617 PostMessage (hwnd, WM_CONTENTSCHANGED, 0, 0);
618 break;
619
620
621 case IDOK:
622 if (!bChangedDefaultButton) {
623 goto Switchem;
624 }
625
626 case IDD_RUN:
627 if (fExecOK) {
628 TCHAR szFilename[MAXPATHFIELD+4];
629 WORD ret;
630
631 GetDlgItemText(hwnd, IDD_PATH, szPathField, MAXPATHFIELD);
632 DoEnvironmentSubst(szPathField, MAXPATHFIELD);
633 GetDirectoryFromPath(szPathField, szDirField);
634 if (*szDirField) {
635 // Convert path into a .\foo.exe style thing.
636 lstrcpy(szFilename, L".\\");
637 // Tag the filename and params on to the end of the dot slash.
638 GetFilenameFromPath(szPathField, szFilename+2);
639 if (*(szFilename+2) == L'"' ) {
640 SheRemoveQuotes(szFilename+2);
641 CheckEscapes(szFilename, ARRAYSIZE(szFilename));
642 }
643 }
644 else {
645 GetFilenameFromPath(szPathField, szFilename);
646 }
647
648 ret = ExecProgram(szFilename, szDirField, szFilename);
649
650 if (ret) {
651 fMsgBox = TRUE;
652 MyMessageBox( hwnd, IDS_EXECERRTITLE, ret, szPathField,
653 MB_SYSTEMMODAL | MB_OK | MB_ICONEXCLAMATION );
654 fMsgBox = FALSE;
655
656 SetFocus(GetDlgItem(hwnd, IDD_PATH));
657 } else {
658 GetDlgItemText(hwnd, IDD_PATH, szPathField, MAXPATHFIELD);
659 SaveRecentFileList (hwnd, szPathField);
660 HideWindow(hwnd);
661 }
662
663 }
664 break;
665
666Switchem:
667
668 case IDD_SWITCH:
669 HideTasklist();
670 ActivateSelectedWindow(hwndLB);
671 break;
672
673 case IDCANCEL:
674 HideWindow(hwnd);
675 break;
676
677 case IDD_TERMINATE:
678 /*
679 * Get the hwnd of the item which was selected.
680 */
681 nIndex = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0);
682 hwndNext = (HWND)SendMessage(hwndLB, LB_GETITEMDATA, nIndex, 0);
683
684 if (!IsWindow(hwndNext)) {
685 HideWindow(hwnd);
686 MessageBeep(0);
687 break;
688 }
689
690#ifndef NTWIN /* Since NTWIN uses WM_ENDSESSION to kill the app,
691 * It is OK to kill it when it is disabled
692 */
693 /*
694 * Test if the toplevel window is disabled. If it is
695 * diabled, we don't want to send a WM_CLOSE message to
696 * the parent. This is because the app could have a dialog
697 * box up and it's not expecting a CLOSE message...
698 * Nasty rips can happen... Instead, active the window so
699 * that the user can dismis any dialog box or fix whatever
700 * is causing the top level window to be disabled...
701 */
702 lTemp = GetWindowLong(hwndNext, GWL_STYLE);
703 if (lTemp & WS_DISABLED) {
704 HideTasklist();
705 MessageBeep(0);
706 ActivateSelectedWindow(hwndLB);
707
708 } else
709#endif
710 {
711 /* Always activate the window first. This prevents
712 * apps from going to Beep mode. Failing to do this
713 * can cause re-entrancy problems in the app if we
714 * do this again before activating the app.
715 *
716 * However, don't do this if it is a old app task.
717 */
718
719#ifdef WIN16 /* if NTWIN, then always do this, as is no winoldapp */
720 if (!IsWinoldapTask(GetTaskFromHwnd(hwndNext)))
721#endif
722 HideWindow(hwnd);
723 ActivateSelectedWindow(hwndLB);
724#ifdef NTWIN
725 {
726 DWORD idt;
727 HANDLE hThread;
728
729 hThread = CreateThread(NULL, 0,
730 (LPTHREAD_START_ROUTINE)CallEndTask,
731 (LPVOID)hwndNext, 0,
732 &idt);
733
734 if (hThread == NULL) {
735 /*
736 * Can not create thread, just call EndTask
737 * syncronously
738 */
739 DoEndTask( hwndNext );
740 } else {
741 CloseHandle(hThread);
742 }
743 }
744#else
745 EndTask(hwndNext, FALSE, FALSE);
746#endif
747 }
748
749 break;
750
751 case IDD_TILE:
752 case IDD_CASCADE:
753 {
754 HWND hwndDesktop;
755
756 HideWindow(hwnd);
757
758 hwndDesktop = GetDesktopWindow();
759
760 if (wParam == IDD_CASCADE) {
761 CascadeChildWindows(hwndDesktop, 0);
762
763 } else {
764 /*
765 * If shift is down, tile vertically, else horizontally.
766 */
767 TileChildWindows(hwndDesktop, ((GetKeyState(VK_SHIFT) &
768 0x8000) ? MDITILE_HORIZONTAL : MDITILE_VERTICAL));
769 }
770 break;
771 }
772
773 case IDD_ARRANGEICONS:
774 /*
775 * Let's restore the saved bits before ArrangeIcons
776 * FIX for Bug #4884; --SANKAR-- 10-02-89
777 */
778 HideWindow(hwnd);
779 ArrangeIconicWindows(GetDesktopWindow());
780 break;
781 }
782
783 break;
784
785
786 case WM_CLOSE:
787 /*
788 * If wParam != 0, this is a shutdown request, so exit.
789 */
790 if (wParam != 0)
791 ExitProcess(0);
792 return FALSE;
793 break;
794
795 case WM_HOTKEY:
796 if (wParam == 1) {
797 pt.x = (dxScreen - dxTaskman) / 2;
798 pt.y = (dyScreen - dyTaskman) / 2;
799 ShowTasklist(pt);
800 }
801 break;
802
803 case WM_LOGOFF:
804 PostQuitMessage(0);
805 break;
806
807 default:
808 return FALSE;
809 }
810
811 return TRUE;
812
813 lParam;
814}
815
816//*************************************************************
817//
818// SetDefButton()
819//
820// Purpose: Sets the default button
821//
822// Parameters: HWND hDlg - Window handle of dialog box
823// INT idButton - ID of button
824//
825// Return: void
826//
827//*************************************************************
828
829VOID SetDefButton(HWND hwndDlg, INT idButton)
830{
831 LRESULT lr;
832
833 if (HIWORD(lr = SendMessage(hwndDlg, DM_GETDEFID, 0, 0)) == DC_HASDEFID)
834 {
835 HWND hwndOldDefButton = GetDlgItem(hwndDlg, LOWORD(lr));
836
837 SendMessage (hwndOldDefButton,
838 BM_SETSTYLE,
839 MAKEWPARAM(BS_PUSHBUTTON, 0),
840 MAKELPARAM(TRUE, 0));
841 }
842
843 SendMessage( hwndDlg, DM_SETDEFID, idButton, 0L );
844 SendMessage( GetDlgItem(hwndDlg, idButton),
845 BM_SETSTYLE,
846 MAKEWPARAM( BS_DEFPUSHBUTTON, 0 ),
847 MAKELPARAM( TRUE, 0 ));
848
849}
850
851
852/*** SaveRecentFileList -- Save the list of recently used files
853 *
854 * void APIENTRY SaveRecentFileList (HWND hwnd, LPTSTR szCurrentFile);
855 *
856 *
857 *
858 * ENTRY - HWND hwnd - handle to dialog box.
859 * LPTSTR szCurrentFile - pointer to selected filename
860 *
861 * EXIT -
862 * SYNOPSIS -
863 *
864 * WARNINGS -
865 * EFFECTS -
866 *
867 */
868
869
870void APIENTRY SaveRecentFileList (HWND hwnd, LPTSTR szCurrentFile)
871{
872 HKEY hKey;
873 DWORD dwDisp;
874 DWORD dwDataType, dwMaxFiles=INIT_MAX_FILES, dwMaxFilesSize, dwCount;
875 TCHAR szFileEntry[20];
876 DWORD dwEnd=0;
877 DWORD dwFileNum=0;
878 DWORD dwDup;
879 static TCHAR szRecentFilePath[MAXPATHFIELD+1];
880
881 //
882 // Open registry key
883 //
884
885 if ( RegCreateKeyEx (HKEY_CURRENT_USER, FILES_KEY, 0, 0,
886 REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
887 NULL, &hKey, &dwDisp) != ERROR_SUCCESS) {
888 return;
889 }
890
891
892 //
893 // Query the max number of files to save first.
894 //
895
896 dwMaxFilesSize = sizeof (DWORD);
897
898 RegQueryValueEx (hKey, MAXFILES_ENTRY, NULL, &dwDataType,
899 (LPBYTE)&dwMaxFiles, &dwMaxFilesSize);
900
901 //
902 // If the user request 0 entries, then exit now.
903 //
904 if (dwMaxFiles == 0) {
905 RegCloseKey (hKey);
906 return;
907 }
908
909 //
910 // Find out how many items are in the list box.
911 //
912
913 dwEnd = (DWORD)SendDlgItemMessage (hwnd, IDD_PATH, CB_GETCOUNT, 0, 0);
914
915 //
916 // If the max number of items we want to save is less than the
917 // number of entries, then change the ending point.
918 //
919
920 if (dwMaxFiles < dwEnd) {
921 dwEnd = dwMaxFiles;
922 }
923
924 //
925 // Add the first entry (the current file)
926 //
927
928 wsprintf (szFileEntry, FILE_ENTRY, dwFileNum++);
929 dwMaxFilesSize = MAXPATHFIELD+1;
930
931 RegSetValueEx (hKey, szFileEntry, 0, REG_SZ, (CONST BYTE *)szCurrentFile,
932 sizeof (TCHAR) * (lstrlen (szCurrentFile)+1));
933
934
935 //
936 // Check for a duplicate string.
937 //
938
939 dwDup = (DWORD)SendDlgItemMessage (hwnd, IDD_PATH, CB_FINDSTRING,
940 (WPARAM) -1, (LPARAM) szCurrentFile);
941
942 //
943 // If we already have dwMaxFiles in the list and we don't have any
944 // duplicates, then we only want to save dwMaxFiles - 1 entries
945 // (drop the last entry).
946 //
947 //
948
949 if ( (dwEnd == dwMaxFiles) && (dwDup == CB_ERR) ) {
950 dwEnd--;
951 }
952
953 //
954 // Now loop through the remaining entries
955 //
956
957 for (dwCount=0; dwCount < dwEnd; dwCount++) {
958
959 //
960 // Check to see if we are at the duplicate entry. If
961 // so skip on to the next item.
962 //
963
964 if ((dwDup != CB_ERR) && (dwCount == dwDup)) {
965 continue;
966 }
967
968 //
969 // Get an entry out of the listbox.
970 //
971
972 SendDlgItemMessage (hwnd, IDD_PATH, CB_GETLBTEXT, (WPARAM) dwCount,
973 (LPARAM) szRecentFilePath);
974
975 //
976 // If we get a NULL string, break out of the loop.
977 //
978
979 if (!(*szRecentFilePath) || !szRecentFilePath) {
980 break;
981 }
982
983 //
984 // Build the entry name
985 //
986
987 wsprintf (szFileEntry, FILE_ENTRY, dwFileNum);
988 dwMaxFilesSize = MAXPATHFIELD+1;
989
990 //
991 // Save the entry
992 //
993
994 RegSetValueEx (hKey, szFileEntry, 0, REG_SZ,(CONST BYTE *) szRecentFilePath,
995 sizeof (TCHAR) * (lstrlen (szRecentFilePath)+1));
996
997 //
998 // Increment our current file number
999 //
1000
1001 dwFileNum++;
1002 }
1003
1004 //
1005 // Close the key
1006 //
1007
1008 RegCloseKey (hKey);
1009
1010}
1011
1012
1013
1014/*** Main -- Program entry point (was WinMain).
1015 *
1016 *
1017 *
1018 * Main(int argc, char *argv[], char *envp[])
1019 *
1020 * ENTRY - int argc - argument count.
1021 * char *argv[] - argument list.
1022 * char *envp[] - environment.
1023 *
1024 * EXIT - TRUE if success, FALSE if not.
1025 * SYNOPSIS - Parses command line, for position to place dialog box, if no
1026 * position (came from ctl/esc) then center on screen.
1027 * Also make sure only one instance of taskman.
1028 *
1029 * WARNINGS -
1030 * EFFECTS -
1031 */
1032
1033INT __cdecl main(
1034 INT argc,
1035 CHAR *argv[],
1036 CHAR *envp[])
1037{
1038 MSG msg;
1039
1040 /*
1041 * First set the priority of taskman so it is higher than foreground apps
1042 * that spin in loops - this way it'll always come up when you hit
1043 * ctrl-esc.
1044 */
1045 hInst = GetModuleHandle(NULL);
1046
1047 SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
1048
1049 {
1050 //
1051 // Set the working set size to 200k.
1052 //
1053
1054 QUOTA_LIMITS QuotaLimits;
1055 NTSTATUS status;
1056
1057 status = NtQueryInformationProcess( NtCurrentProcess(),
1058 ProcessQuotaLimits,
1059 &QuotaLimits,
1060 sizeof(QUOTA_LIMITS),
1061 NULL );
1062 if (NT_SUCCESS(status)) {
1063 QuotaLimits.MinimumWorkingSetSize = 300 * 1024;
1064 QuotaLimits.MaximumWorkingSetSize = 372 * 1024;
1065
1066 NtSetInformationProcess( NtCurrentProcess(),
1067 ProcessQuotaLimits,
1068 &QuotaLimits,
1069 sizeof(QUOTA_LIMITS) );
1070 }
1071 }
1072
1073 /*
1074 * Taskman will work in the windows directory, and switch to the
1075 * original directory (home directory) before execing programs.
1076 * This is to prevent weird popups if a UNC original directory is
1077 * disconnected.
1078 */
1079
1080 GetCurrentDirectory(MAXPATHFIELD, szUserHomeDir);
1081 GetWindowsDirectory(szWindowsDirectory, MAXPATHFIELD);
1082 SetCurrentDirectory(szWindowsDirectory);
1083
1084 fExecOK = OKToExec();
1085 if (!IsUserAdmin() && !fExecOK) {
1086 ghwndDialog = CreateDialog(hInst, MAKEINTRESOURCE(WMPTASKMANDLG), NULL,
1087 TaskmanDlgProc);
1088 } else {
1089 ghwndDialog = CreateDialog(hInst, MAKEINTRESOURCE(PWRTASKMANDLG), NULL,
1090 TaskmanDlgProc);
1091 }
1092
1093 if (ghwndDialog == NULL)
1094 return 0;
1095
1096 LoadString(hInst, IDS_OOMEXITTITLE, szOOMExitTitle, 32);
1097 LoadString(hInst, IDS_OOMEXITMSG, szOOMExitMsg, 64);
1098
1099 if (!RegisterHotKey(ghwndDialog, 1, MOD_CONTROL, VK_ESCAPE) ||
1100 !RegisterTasklist(ghwndDialog)) {
1101 goto exit;
1102 }
1103
1104 while (GetMessage(&msg, (HWND)NULL, (UINT)0, (UINT)0)) {
1105 if (!IsDialogMessage(ghwndDialog, &msg)) {
1106 if ((msg.message == WM_SYSCOMMAND) && (msg.wParam == SC_TASKLIST)) {
1107 POINT pt;
1108
1109 GetCursorPos(&pt);
1110 pt.x = max(pt.x - (dyTaskman / 2), 0);
1111 pt.x = min(pt.x, dxScreen - dxTaskman);
1112 pt.y = max(pt.y - (GetSystemMetrics(SM_CYCAPTION) * 2), 0);
1113 pt.y = min(pt.y, dyScreen - dyTaskman);
1114
1115 ShowTasklist(pt);
1116 } else {
1117
1118 //
1119 // We need to have a regular message loop in order
1120 // to handle the DDE messages generated by spawning
1121 // an application via an association.
1122 //
1123
1124 TranslateMessage (&msg);
1125 DispatchMessage (&msg);
1126 }
1127
1128 }
1129 }
1130
1131exit:
1132 DestroyWindow(ghwndDialog);
1133 return 0;
1134
1135 argc;
1136 argv;
1137 envp;
1138}
1139
1140
1141WORD APIENTRY
1142ExecProgram(
1143 LPTSTR lpszPath,
1144 LPTSTR lpDir,
1145 LPTSTR lpTitle
1146 )
1147{
1148 WORD ret;
1149 HCURSOR hCursor;
1150 LPTSTR lpP;
1151 TCHAR cSeparator;
1152 TCHAR lpReservedFormat[] = TEXT("dde.%d,hotkey.%d");
1153 TCHAR lpReserved[100]; // used for DDE request of icons from console apps
1154 // add for passing the hotkey associated with an item.
1155 HANDLE hProcess;
1156
1157 ret = 0;
1158
1159 /*
1160 * Set the current directory to the user's home directory if possible.
1161 */
1162 SetCurrentDirectory(szUserHomeDir);
1163
1164 hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
1165
1166 /* Don't mess with the mouse state; unless we're on a mouseless system.
1167 */
1168 if (!GetSystemMetrics(SM_MOUSEPRESENT))
1169 ShowCursor(TRUE);
1170
1171 /* skip leading spaces
1172 */
1173 while (*lpszPath == TEXT(' '))
1174 lpszPath++;
1175
1176 /* skip past path
1177 */
1178 lpP = lpszPath;
1179 if (*lpszPath == TEXT('"')) {
1180 cSeparator = TEXT('"');
1181 lpP++;
1182 }
1183 else {
1184 cSeparator = TEXT(' ');
1185 }
1186
1187 for (; *lpP && *lpP != cSeparator; lpP = CharNext(lpP))
1188 ;
1189 if (*lpP == TEXT('"')) {
1190 lpP++;
1191 }
1192
1193 /* if stuff on end, separate it
1194 */
1195 if (*lpP)
1196 *lpP++ = 0;
1197
1198
1199 /* Try to exec 'szCommandLine'. */
1200
1201 /*changed order, since wPendINstance is a 32b HANDLE, and ret is WORD*/
1202 if (!lpP)
1203 lpP = TEXT("");
1204
1205 wsprintf(lpReserved, lpReservedFormat, 0, 0);
1206
1207 ret = (WORD)RealShellExecute(ghwndDialog, NULL, lpszPath, lpP,
1208 lpDir, NULL, lpTitle, lpReserved,
1209 (WORD)SW_SHOWNORMAL, &hProcess);
1210
1211 /*BUG BUG these are DOS exec function return codes, no map yet to NT return codes!*/
1212 switch (ret) {
1213 case 0:
1214 case SE_ERR_OOM: // 8
1215 ret = IDS_NOMEMORYMSG;
1216 break;
1217
1218 case SE_ERR_FNF: // 2
1219 ret = IDS_FILENOTFOUNDMSG;
1220 break;
1221
1222 case SE_ERR_PNF: // 3
1223 ret = IDS_BADPATHMSG;
1224 break;
1225
1226 case 4:
1227 ret = IDS_MANYOPENFILESMSG;
1228 break;
1229
1230 case 5:
1231 ret = IDS_ACCESSDENIED;
1232 break;
1233
1234 case 10:
1235 ret = IDS_NEWWINDOWSMSG;
1236 break;
1237
1238 case 12:
1239 ret = IDS_OS2APPMSG;
1240 break;
1241
1242 case 15:
1243 /* KERNEL has already put up a messagebox for this one. */
1244 ret = 0;
1245 break;
1246
1247 case 16:
1248 ret = IDS_MULTIPLEDSMSG;
1249 break;
1250
1251 case 18:
1252 ret = IDS_PMODEONLYMSG;
1253 break;
1254
1255 case 19:
1256 ret = IDS_COMPRESSEDEXE;
1257 break;
1258
1259 case 20:
1260 ret = IDS_INVALIDDLL;
1261 break;
1262
1263 case SE_ERR_SHARE:
1264 ret = IDS_SHAREERROR;
1265 break;
1266
1267 case SE_ERR_ASSOCINCOMPLETE:
1268 ret = IDS_ASSOCINCOMPLETE;
1269 break;
1270
1271 case SE_ERR_DDETIMEOUT:
1272 case SE_ERR_DDEFAIL:
1273 case SE_ERR_DDEBUSY:
1274 ret = IDS_DDEFAIL;
1275 break;
1276
1277 case SE_ERR_NOASSOC:
1278 ret = IDS_NOASSOCMSG;
1279 break;
1280
1281 default:
1282 ret = 0;
1283 break;
1284 }
1285
1286 if (!GetSystemMetrics(SM_MOUSEPRESENT)) {
1287 /*
1288 * We want to turn the mouse off here on mouseless systems, but
1289 * the mouse will already have been turned off by USER if the
1290 * app has GP'd so make sure everything's kosher.
1291 */
1292 if (ShowCursor(FALSE) != -1)
1293 ShowCursor(TRUE);
1294 }
1295
1296 SetCursor(hCursor);
1297
1298 /*
1299 * Reset the working directory to the windows directory.
1300 */
1301 SetCurrentDirectory(szWindowsDirectory);
1302
1303 return(ret);
1304}
1305
1306
1307VOID
1308GetDirectoryFromPath(
1309 PTSTR szFilePath,
1310 PTSTR szDir)
1311{
1312 PTSTR pFileName;
1313 PTSTR pExt;
1314 WORD ich;
1315 BOOL fUnc;
1316
1317 *szDir = TEXT('\0');
1318
1319 /* Get info about file path. */
1320 GetPathInfo(szFilePath, &pFileName, &pExt, &ich, &fUnc);
1321
1322 /* UNC paths don't (conceptually to Progman) have a directory component. */
1323 if (fUnc)
1324 return;
1325
1326 /* Does it have a directory component ? */
1327 if (pFileName != szFilePath) { // Yep.
1328 /* copy path to temp. */
1329 if (*szFilePath == TEXT('"')) {
1330 szFilePath++;
1331 }
1332 lstrcpy(szDir, szFilePath);
1333 /* check path style. */
1334 if (ich <= 3 && *(szDir+1) == TEXT(':')) {
1335 /*
1336 * The path is "c:\foo.c" or "c:foo.c" style.
1337 * Don't remove the last slash/colon, just the filename.
1338 */
1339 szDir[pFileName-szFilePath] = TEXT('\0');
1340 }
1341
1342 else if (ich == 1) {
1343 /*
1344 * something like "\foo.c"
1345 * Don't remove the last slash/colon, just the filename.
1346 */
1347 szDir[pFileName-szFilePath] = TEXT('\0');
1348 }
1349 else {
1350 /*
1351 * The filepath is a full normal path.
1352 * Could be something like "..\foo.c" or ".\foo.c" though.
1353 * Stomp on the last slash to get just the path.
1354 */
1355 szDir[pFileName-szFilePath-1] = TEXT('\0');
1356 }
1357 }
1358
1359 /* else just a filename with no path. */
1360}
1361
1362VOID
1363GetFilenameFromPath(
1364 PTSTR szPath,
1365 PTSTR szFilename)
1366{
1367 DWORD dummy;
1368 PTSTR pFileName;
1369 BOOL fUNC;
1370
1371 GetPathInfo(szPath, &pFileName, (PTSTR*) &dummy, (WORD*) &dummy,
1372 &fUNC);
1373
1374 /* If it's a UNC then the 'filename' part is the whole thing. */
1375 if (fUNC || (szPath == pFileName))
1376 lstrcpy(szFilename, szPath);
1377 else {
1378 if (*szPath == TEXT('"')) {
1379 *szFilename++ = TEXT('"');
1380 }
1381 lstrcpy(szFilename, pFileName);
1382 }
1383}
1384
1385
1386VOID
1387GetPathInfo(
1388 PTSTR szPath,
1389 PTSTR *pszFileName,
1390 PTSTR *pszExt,
1391 WORD *pich,
1392 BOOL *pfUnc)
1393{
1394 TCHAR *pch; // Temp variable.
1395 WORD ich = 0; // Temp.
1396 BOOL InQuotes;
1397
1398 *pszExt = NULL; // If no extension, return NULL.
1399 *pszFileName = szPath; // If no seperate filename component, return path.
1400 *pich = 0;
1401 *pfUnc = FALSE; // Default to not UNC style.
1402
1403 //
1404 // Check if path is in quotes.
1405 //
1406 if (InQuotes = (*szPath == TEXT('"'))) {
1407 szPath++;
1408 }
1409
1410 // Check for UNC style paths.
1411 if (*szPath == TEXT('\\') && *(szPath+1) == TEXT('\\'))
1412 *pfUnc = TRUE;
1413
1414 // Search forward to find the last backslash or colon in the path.
1415 // While we're at it, look for the last dot.
1416 for (pch = szPath; *pch; pch = CharNext(pch)) {
1417
1418 if ((*pch == TEXT(' ')) && (!InQuotes)) {
1419 // Found a space - stop here.
1420 break;
1421 }
1422 if (*pch == TEXT('"')) {
1423 // Found a the second quote - stop here.
1424 pch++;
1425 break;
1426 }
1427 if (*pch == TEXT('\\') || *pch == TEXT(':')) {
1428 // Found it, record ptr to it and it's index.
1429 *pszFileName = pch+1;
1430 *pich = ich + (WORD)1;
1431 }
1432 if (*pch == TEXT('.')) {
1433 // Found a dot.
1434 *pszExt = pch;
1435 }
1436 ich++;
1437 }
1438
1439 /* Check that the last dot is part of the last filename. */
1440 if (*pszExt < *pszFileName)
1441 *pszExt = NULL;
1442}
1443
1444
1445BOOL
1446IsUserAdmin()
1447{
1448 BOOL UserIsAdmin = FALSE;
1449 HANDLE Token;
1450 PSID AdminAliasSid = NULL;
1451 SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
1452
1453 //
1454 // Get the token of the current process.
1455 //
1456
1457 if (!OpenProcessToken(
1458 GetCurrentProcess(),
1459 TOKEN_QUERY,
1460 &Token) ) {
1461 return(FALSE);
1462 }
1463
1464 UserIsAdmin = TestTokenForAdmin(Token);
1465
1466
1467 CloseHandle(Token);
1468
1469 return(UserIsAdmin);
1470}
1471
1472BOOL
1473TestTokenForAdmin(
1474 HANDLE Token
1475 )
1476{
1477 NTSTATUS Status;
1478 DWORD InfoLength;
1479 PTOKEN_GROUPS TokenGroupList;
1480 DWORD GroupIndex;
1481 PSID AdminSid;
1482 BOOL FoundAdmin;
1483 SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
1484
1485 //
1486 // Get a list of groups in the token
1487 //
1488
1489 Status = NtQueryInformationToken(
1490 Token, // Handle
1491 TokenGroups, // TokenInformationClass
1492 NULL, // TokenInformation
1493 0, // TokenInformationLength
1494 &InfoLength // ReturnLength
1495 );
1496
1497 if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_TOO_SMALL)) {
1498 return(FALSE);
1499 }
1500
1501 TokenGroupList = Alloc(InfoLength);
1502
1503 if (TokenGroupList == NULL) {
1504 return(FALSE);
1505 }
1506
1507 Status = NtQueryInformationToken(
1508 Token, // Handle
1509 TokenGroups, // TokenInformationClass
1510 TokenGroupList, // TokenInformation
1511 InfoLength, // TokenInformationLength
1512 &InfoLength // ReturnLength
1513 );
1514
1515 if (!NT_SUCCESS(Status)) {
1516 LocalFree(TokenGroupList);
1517 return(FALSE);
1518 }
1519
1520 //
1521 // Create the admin sid
1522 //
1523 Status = RtlAllocateAndInitializeSid(
1524 &SystemSidAuthority, 2,
1525 SECURITY_BUILTIN_DOMAIN_RID,
1526 DOMAIN_ALIAS_RID_ADMINS,
1527 0, 0, 0, 0, 0, 0,
1528 &AdminSid);
1529
1530 if (!NT_SUCCESS(Status)) {
1531 Free(TokenGroupList);
1532 return(FALSE);
1533 }
1534
1535 //
1536 // Search group list for admin alias
1537 //
1538 FoundAdmin = FALSE;
1539
1540 for (GroupIndex=0; GroupIndex < TokenGroupList->GroupCount; GroupIndex++ ) {
1541 if (RtlEqualSid(TokenGroupList->Groups[GroupIndex].Sid, AdminSid)) {
1542 FoundAdmin = TRUE;
1543 break;
1544 }
1545 }
1546
1547 //
1548 // Tidy up
1549 //
1550
1551 RtlFreeSid(AdminSid);
1552 Free(TokenGroupList);
1553
1554 return(FoundAdmin);
1555}
1556
1557BOOL
1558OKToExec()
1559{
1560 TCHAR szRestrict[] = TEXT("Restrictions");
1561 TCHAR szProgramManager[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager");
1562 HKEY hkeyProgramManager = NULL; // progman.ini key
1563 HKEY hkeyPMRestrict = NULL;
1564 DWORD cbData, dwType;
1565 BOOL fNoRun = FALSE;
1566
1567 /*
1568 * Create/Open the registry keys corresponding to progman.ini sections.
1569 */
1570 if (!RegCreateKeyEx(HKEY_CURRENT_USER, szProgramManager, 0, szProgramManager, 0,
1571 KEY_READ | KEY_WRITE, NULL, &hkeyProgramManager, NULL)) {
1572
1573 RegCreateKeyEx(hkeyProgramManager, szRestrict, 0, szProgramManager, 0,
1574 KEY_READ, NULL, &hkeyPMRestrict, NULL);
1575
1576 } else {
1577 return(FALSE);
1578 }
1579
1580 if (hkeyPMRestrict) {
1581 cbData = sizeof(fNoRun);
1582 RegQueryValueEx(hkeyPMRestrict, szNoRun, 0, &dwType, (LPBYTE)&fNoRun,
1583 &cbData);
1584 }
1585
1586 if (hkeyPMRestrict) {
1587 RegCloseKey(hkeyPMRestrict);
1588 hkeyPMRestrict = NULL;
1589 }
1590
1591 RegCloseKey(hkeyProgramManager);
1592
1593 return(!fNoRun);
1594
1595}
1596
1597INT
1598MyMessageBox(
1599 HWND hWnd,
1600 WORD idTitle,
1601 WORD idMessage,
1602 PWSTR psz,
1603 WORD wStyle)
1604{
1605 WCHAR szTempField[MAXMSGBOXLEN];
1606 INT iMsgResult;
1607
1608 if (!LoadString(hInst, idTitle, szTitle, ARRAYSIZE(szTitle))){
1609 goto MessageBoxOOM;
1610 }
1611 if (idMessage < 32){
1612 if (!LoadString(hInst, IDS_UNKNOWNMSG, szTempField, ARRAYSIZE(szTempField))){
1613 goto MessageBoxOOM;
1614 }
1615 wsprintf(szMessage, szTempField, idMessage);
1616 }
1617 else{
1618 if (!LoadString(hInst, idMessage, szTempField, ARRAYSIZE(szTempField)))
1619 goto MessageBoxOOM;
1620
1621 if (psz) {
1622 wsprintf(szMessage, szTempField, (LPTSTR)psz);
1623 }
1624 else
1625 lstrcpy(szMessage, szTempField);
1626 }
1627
1628 iMsgResult = MessageBox(hWnd, szMessage, szTitle, wStyle );
1629
1630 if (iMsgResult == -1){
1631
1632MessageBoxOOM:
1633 MessageBox(hWnd, szOOMExitMsg, szOOMExitTitle, MB_SYSTEMMODAL | MB_ICONHAND | MB_OK);
1634 }
1635
1636 return(iMsgResult);
1637}
1638