|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 Microsoft Corporation
4:
5: Module Name:
6:
7: browse.c
8:
9: Abstract:
10: This file implements the functions that make use of the common
11: file open dialogs for browsing for files/directories.
12:
13: Author:
14:
15: Wesley Witt (wesw) 1-May-1993
16:
17: Environment:
18:
19: User Mode
20:
21: --*/
22:
23: #include <windows.h>
24: #include <stdlib.h>
25: #include <stdio.h>
26: #include <string.h>
27: #include <commdlg.h>
28: #include <mmsystem.h>
29: #include <direct.h>
30:
31: #include "drwatson.h"
32: #include "proto.h"
33: #include "resource.h"
34: #include "messages.h"
35:
36:
37: //
38: // defines
39: //
40: #define DEFAULT_WAIT_TIME (1000 * 60 * 5) // wait for 5 minutes
41:
42: //
43: // static global variables
44: //
45: static HANDLE hThreadDebug;
46: static PDEBUGPACKET dp;
47:
48:
49: DWORD TimerKillThread( HWND hwnd );
50: LRESULT NotifyWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
51: BOOL CALLBACK UsageDialogProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
52:
53:
54: void
55: NotifyWinMain ( void )
56:
57: /*++
58:
59: Routine Description:
60:
61: This is the entry point for DRWTSN32
62:
63: Arguments:
64:
65: None.
66:
67: Return Value:
68:
69: None.
70:
71: --*/
72:
73: {
74: MSG msg;
75: WNDCLASS wndclass;
76: DWORD dwThreadId;
77: HINSTANCE hInst;
78:
79:
80: dp = (PDEBUGPACKET) malloc( sizeof(DEBUGPACKET) );
81: memset( dp, 0, sizeof(DEBUGPACKET) );
82: GetCommandLineArgs( &dp->dwPidToDebug, &dp->hEventToSignal );
83:
84: RegInitialize( &dp->options );
85:
86: if (dp->options.fVisual) {
87: hInst = GetModuleHandle( NULL );
88: wndclass.style = CS_HREDRAW | CS_VREDRAW;
89: wndclass.lpfnWndProc = NotifyWndProc;
90: wndclass.cbClsExtra = 0;
91: wndclass.cbWndExtra = DLGWINDOWEXTRA;
92: wndclass.hInstance = hInst;
93: wndclass.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(APPICON) );
94: wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
95: wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
96: wndclass.lpszMenuName = NULL;
97: wndclass.lpszClassName = "NotifyDialog";
98: RegisterClass( &wndclass );
99:
100: dp->hwnd = CreateDialog( hInst,
101: MAKEINTRESOURCE( NOTIFYDIALOG ),
102: 0,
103: NotifyWndProc );
104: }
105:
106: hThreadDebug = CreateThread( NULL,
107: 16000,
108: (LPTHREAD_START_ROUTINE)DispatchDebugEventThread,
109: dp,
110: THREAD_SET_INFORMATION,
111: (LPDWORD)&dwThreadId
112: );
113:
114: if (dp->options.fSound) {
115: if ((waveOutGetNumDevs() == 0) || (!strlen(dp->options.szWaveFile))) {
116: MessageBeep( MB_ICONHAND );
117: MessageBeep( MB_ICONHAND );
118: }
119: else {
120: PlaySound( dp->options.szWaveFile, NULL, SND_FILENAME );
121: }
122: }
123:
124: if (dp->options.fVisual) {
125: ShowWindow( dp->hwnd, SW_SHOWNORMAL );
126: while (GetMessage (&msg, NULL, 0, 0)) {
127: if (!IsDialogMessage( dp->hwnd, &msg )) {
128: TranslateMessage (&msg) ;
129: DispatchMessage (&msg) ;
130: }
131: }
132: }
133: else {
134: WaitForSingleObject( hThreadDebug, INFINITE );
135: }
136:
137: return;
138: }
139:
140: LRESULT
141: NotifyWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
142:
143: /*++
144:
145: Routine Description:
146:
147: Window procedure for the DRWTSN32.EXE popup. This is the popup
148: that is displayed when an application error occurs.
149:
150: Arguments:
151:
152: hwnd - window handle to the dialog box
153: message - message number
154: wParam - first message parameter
155: lParam - second message parameter
156:
157: Return Value:
158:
159: TRUE - did not process the message
160: FALSE - did process the message
161:
162: --*/
163:
164: {
165: DWORD dwThreadId;
166: DWORD dwSize;
167: HANDLE hThread;
168: char szTaskName[MAX_PATH];
169: char szHelpFileName[MAX_PATH];
170:
171: switch (message) {
172: case WM_CREATE:
173: return FALSE;
174:
175: case WM_INITDIALOG:
176: //
177: // OK is not enabled until the debugger thread finishes
178: //
179: EnableWindow( GetDlgItem( hwnd, IDOK ), FALSE );
180:
181: //
182: // CANCEL is not enabled until debugactiveprocess is finished
183: //
184: EnableWindow( GetDlgItem( hwnd, IDCANCEL ), FALSE );
185:
186: //
187: // make sure that the user can see the dialog box
188: //
189: SetForegroundWindow( hwnd );
190:
191: //
192: // get the task name and display it on the dialog box
193: //
194: dwSize = sizeof(szTaskName);
195: GetTaskName( dp->dwPidToDebug, szTaskName, &dwSize );
196: SetDlgItemText( hwnd, ID_TEXT1, szTaskName);
197:
198: //
199: // create a thread to terminate DrWatson if the user does
200: // not push the OK putton
201: //
202: CreateThread( NULL,
203: 16000,
204: (LPTHREAD_START_ROUTINE)TimerKillThread,
205: (LPVOID)hwnd,
206: THREAD_SET_INFORMATION,
207: (LPDWORD)&dwThreadId
208: );
209: return TRUE;
210:
211: case WM_COMMAND:
212: switch (wParam) {
213: case IDOK:
214: PostQuitMessage( 0 );
215: break;
216:
217: case IDCANCEL:
218: //
219: // terminate the debugger thread
220: //
221: TerminateThread( hThreadDebug, 0 );
222:
223: //
224: // create a thread to terminate the debuggee
225: // this is necessary if cancel is pressed before the
226: // debugger thread finishes the postmortem dump
227: //
228: hThread = CreateThread( NULL,
229: 16000,
230: (LPTHREAD_START_ROUTINE)TerminationThread,
231: dp,
232: THREAD_SET_INFORMATION,
233: (LPDWORD)&dwThreadId
234: );
235:
236: //
237: // wait for the termination thread to kill the debuggee
238: //
239: WaitForSingleObject( hThread, 30000 );
240:
241: //
242: // now post a quit message so that DrWatson will go away
243: //
244: PostQuitMessage( 0 );
245: break;
246:
247: case ID_HELP:
248: //
249: // call winhelp
250: //
251: GetHelpFileName( szHelpFileName, sizeof(szHelpFileName) );
252: WinHelp( hwnd, szHelpFileName, HELP_CONTEXT, IDH_WHAT );
253: break;
254: }
255: break;
256:
257: case WM_DUMPCOMPLETE:
258:
259: //
260: // the message is received from the debugger thread
261: // when the postmortem dump is finished. all we need to do
262: // is enable the OK button and wait for the user to press the
263: // OK button or for the timer to expire. in either case
264: // DrWatson will terminate.
265: //
266: EnableWindow( GetDlgItem( hwnd, IDOK ), TRUE );
267: return 0;
268:
269: case WM_ATTACHCOMPLETE:
270:
271: //
272: // the message is received from the debugger thread when
273: // the debugactiveprocess() is completed
274: //
275: EnableWindow( GetDlgItem( hwnd, IDCANCEL ), TRUE );
276: return 0;
277:
278: case WM_EXCEPTIONINFO:
279:
280: SetDlgItemText( hwnd, ID_TEXT2, (char *) lParam);
281: break;
282:
283: case WM_DESTROY:
284: PostQuitMessage( 0 );
285: return 0;
286: }
287:
288: return DefWindowProc( hwnd, message, wParam, lParam );
289: }
290:
291: DWORD
292: TimerKillThread( HWND hwnd )
293:
294: /*++
295:
296: Routine Description:
297:
298: This function executes in its own thread. The purpose is to wait
299: dwMilliseconds and notify the hwndMain window by destroting it.
300: This thread is used to terminate DRWTSN32 when the use does not
301: respond to the application error popup.
302:
303: Arguments:
304:
305: dwMilliseconds - amount of time to wait
306:
307: Return Value:
308:
309: Zero.
310:
311: --*/
312:
313: {
314: //
315: // wait as long as i'm told to
316: //
317: Sleep( DEFAULT_WAIT_TIME );
318:
319: //
320: // tell the popup that its time to go away
321: //
322: SendMessage( hwnd, WM_DESTROY, 0, 0 );
323:
324: return 0;
325: }
326:
327: BOOLEAN
328: GetCommandLineArgs( LPDWORD dwPidToDebug, LPHANDLE hEventToSignal )
329:
330: /*++
331:
332: Routine Description:
333:
334: Parses the command line for the 3 possible command lines
335: arguments:
336:
337: -p %ld process id
338: -e %ld event id
339: -g go
340:
341: Arguments:
342:
343: dp - pointer to a debug packet
344:
345: Return Value:
346:
347: None.
348:
349: --*/
350:
351: {
352: char *lpstrCmd = GetCommandLine();
353: UCHAR ch;
354: char buf[4096];
355: BOOLEAN rval = FALSE;
356:
357: // skip over program name
358: do {
359: ch = *lpstrCmd++;
360: }
361: while (ch != ' ' && ch != '\t' && ch != '\0');
362:
363: // skip over any following white space
364: while (ch == ' ' || ch == '\t') {
365: ch = *lpstrCmd++;
366: }
367:
368: // process each switch character '-' as encountered
369:
370: while (ch == '-') {
371: ch = *lpstrCmd++;
372: // process multiple switch characters as needed
373: do {
374: switch (ch) {
375: case 'e':
376: case 'E':
377: // event to signal takes decimal argument
378: // skip whitespace
379: do {
380: ch = *lpstrCmd++;
381: }
382: while (ch == ' ' || ch == '\t');
383: while (ch >= '0' && ch <= '9') {
384: (DWORD)*hEventToSignal =
385: (DWORD)*hEventToSignal * 10 + ch - '0';
386: ch = *lpstrCmd++;
387: }
388: rval = TRUE;
389: break;
390:
391: case 'p':
392: case 'P':
393: // pid debug takes decimal argument
394:
395: do
396: ch = *lpstrCmd++;
397: while (ch == ' ' || ch == '\t');
398:
399: if ( ch == '-' ) {
400: ch = *lpstrCmd++;
401: if ( ch == '1' ) {
402: *dwPidToDebug = 0xffffffff;
403: ch = *lpstrCmd++;
404: }
405: }
406: else {
407: while (ch >= '0' && ch <= '9') {
408: *dwPidToDebug =
409: *dwPidToDebug * 10 + ch - '0';
410: ch = *lpstrCmd++;
411: }
412: }
413: rval = TRUE;
414: break;
415:
416: case 'g':
417: case 'G':
418: ch = *lpstrCmd++;
419: break;
420:
421: case '?':
422: DialogBox( GetModuleHandle(NULL),
423: MAKEINTRESOURCE(USAGEDIALOG),
424: NULL,
425: UsageDialogProc
426: );
427: rval = TRUE;
428: ch = *lpstrCmd++;
429: break;
430:
431: case 'i':
432: case 'I':
433: FormatMessage(
434: FORMAT_MESSAGE_FROM_HMODULE,
435: NULL,
436: MSG_INSTALL_NOTIFY,
437: 0, // GetUserDefaultLangID(),
438: buf,
439: sizeof(buf),
440: NULL
441: );
442: RegInstallDrWatson();
443: MessageBox( NULL,
444: buf,
445: "Dr. Watson for Windows NT",
446: MB_ICONINFORMATION | MB_OK |
447: MB_SETFOREGROUND );
448: rval = TRUE;
449: ch = *lpstrCmd++;
450: break;
451:
452: default:
453: return rval;
454: }
455: }
456: while (ch != ' ' && ch != '\t' && ch != '\0');
457:
458: while (ch == ' ' || ch == '\t') {
459: ch = *lpstrCmd++;
460: }
461: }
462: return rval;
463: }
464:
465: BOOL CALLBACK
466: UsageDialogProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
467:
468: /*++
469:
470: Routine Description:
471:
472: This is the dialog procedure for the assert dialog box. Normally
473: an assertion box is simply a message box but in this case a Help
474: button is desired so a dialog box is used.
475:
476: Arguments:
477:
478: hDlg - window handle to the dialog box
479: message - message number
480: wParam - first message parameter
481: lParam - second message parameter
482:
483: Return Value:
484:
485: TRUE - did not process the message
486: FALSE - did process the message
487:
488: --*/
489:
490: {
491: char buf[4096];
492:
493: switch (message) {
494: case WM_INITDIALOG:
495: FormatMessage(
496: FORMAT_MESSAGE_FROM_HMODULE,
497: NULL,
498: MSG_USAGE,
499: 0, // GetUserDefaultLangID(),
500: buf,
501: sizeof(buf),
502: NULL
503: );
504: SetDlgItemText( hDlg, ID_USAGE, buf );
505: break;
506:
507: case WM_COMMAND:
508: switch (wParam) {
509: case IDOK:
510: EndDialog( hDlg, 0 );
511: break;
512: }
513: break;
514: }
515:
516: return FALSE;
517: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.