|
|
1.1 root 1: /****************************************************************************\
2: ** **
3: ** Microsoft Developer Support **
4: ** Copyright (c) 1992, 1993 Microsoft Corporation **
5: ** **
6: ** MODULE: BOB **
7: ** **
8: ** **
9: ** PURPOSE: Demonstrates the steps needed to programmatically **
10: ** log off/reboot the machine. Note these features should **
11: ** only be used after you've notified the user what you **
12: ** are about to do. Windows itself will not provide any **
13: ** other warnings to the user. **
14: ** **
15: ** **
16: ** **
17: ** **
18: ** COMMENTS: Reads a file asynchronously writes to another synchronously **
19: ** **
20: ** **
21: \***************************************************************************/
22:
23:
24:
25: /* To enable NT's Reboot feature enable the below
26: * manifest constants. By default the program will
27: * log the user off only.
28: */
29:
30: // #define REBOOT
31:
32: #define WIN32S 0x80000000l // no manifest constance yet???
33:
34: #define STRICT
35:
36: #include <stddef.h>
37: #include <stdlib.h>
38:
39:
40: #define OEMRESOURCE
41: #include "windows.h" /* required for all Windows applications */
42:
43: #include "BOB.H" /* specific to this program */
44:
45: HINSTANCE ghInst; /* current instance */
46: HWND ghWnd;
47: WNDPROC OldButtonProc;
48:
49: /****************************************************************************
50:
51: FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
52:
53: PURPOSE: calls initialization function, processes message loop
54:
55: COMMENTS:
56:
57: Windows recognizes this function by name as the initial entry point
58: for the program. This function calls the application initialization
59: routine, if no other instance of the program is running, and always
60: calls the instance initialization routine. It then executes a message
61: retrieval and dispatch loop that is the top-level control structure
62: for the remainder of execution. The loop is terminated when a WM_QUIT
63: message is received, at which time this function exits the application
64: instance by returning the value passed by PostQuitMessage().
65:
66: If this function must abort before entering the message loop, it
67: returns the conventional value NULL.
68:
69: ****************************************************************************/
70:
71: int PASCAL WinMain(HINSTANCE hInstance, /* current instance */
72: HINSTANCE hPrevInstance, /* previous instance */
73: LPSTR lpCmdLine, /* command line */
74: int nCmdShow) /* show-window type (open/icon) */
75: {
76: MSG msg; /* message */
77:
78: if (!hPrevInstance) /* Other instances of app running? */
79: if (!InitApplication(hInstance)) /* Initialize shared things */
80: return (FALSE); /* Exits if unable to initialize */
81:
82: /* Perform initializations that apply to a specific instance */
83:
84: if (!InitInstance(hInstance, nCmdShow))
85: return (FALSE);
86:
87: /* Acquire and dispatch messages until a WM_QUIT message is received. */
88:
89: while (GetMessage(&msg, /* message structure */
90: NULL, /* handle of window receiving the message */
91: 0, /* lowest message to examine */
92: 0)) /* highest message to examine */
93: {
94: TranslateMessage(&msg); /* Translates virtual key codes */
95: DispatchMessage(&msg); /* Dispatches message to window */
96:
97: }
98: return (msg.wParam); /* Returns the value from PostQuitMessage */
99: UNREFERENCED_PARAMETER(lpCmdLine);
100: }
101:
102:
103: /****************************************************************************
104:
105: FUNCTION: InitApplication(HANDLE)
106:
107: PURPOSE: Initializes window data and registers window class
108:
109: COMMENTS:
110:
111: This function is called at initialization time only if no other
112: instances of the application are running. This function performs
113: initialization tasks that can be done once for any number of running
114: instances.
115:
116: In this case, we initialize a window class by filling out a data
117: structure of type WNDCLASS and calling the Windows RegisterClass()
118: function. Since all instances of this application use the same window
119: class, we only need to do this when the first instance is initialized.
120:
121:
122: ****************************************************************************/
123:
124: BOOL InitApplication(HANDLE hInstance) /* current instance */
125: {
126: WNDCLASS wc;
127:
128: /* Fill in window class structure with parameters that describe the */
129: /* main window. */
130:
131: wc.style = 0; /* Class style(s). */
132: wc.lpfnWndProc = (WNDPROC)MainWndProc; /* Function to retrieve messages for */
133: /* windows of this class. */
134: wc.cbClsExtra = 0; /* No per-class extra data. */
135: wc.cbWndExtra = 0; /* No per-window extra data. */
136: wc.hInstance = hInstance; /* Application that owns the class. */
137: wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
138: wc.hCursor = LoadCursor(NULL, IDC_ARROW);
139: wc.hbrBackground = GetStockObject(WHITE_BRUSH);
140: wc.lpszMenuName = "BOBMenu"; /* Name of menu resource in .RC file. */
141: wc.lpszClassName = "BOBWClass"; /* Name used in call to CreateWindow. */
142:
143: /* Register the window class and return success/failure code. */
144:
145:
146: if ( !RegisterClass(&wc) )
147: return( FALSE );
148:
149:
150: }
151:
152:
153: /****************************************************************************
154:
155: FUNCTION: InitInstance(HANDLE, int)
156:
157: PURPOSE: Saves instance handle and creates main window
158:
159: COMMENTS:
160:
161: This function is called at initialization time for every instance of
162: this application. This function performs initialization tasks that
163: cannot be shared by multiple instances.
164:
165: In this case, we save the instance handle in a static variable and
166: create and display the main program window.
167:
168: ****************************************************************************/
169:
170: BOOL InitInstance(HANDLE hInstance, /* Current instance identifier. */
171: int nCmdShow ) /* Param for first ShowWindow() call. */
172: {
173: HWND hWnd; /* Main window handle. */
174: HWND hWndDeskTop;
175: RECT rcDeskTop;
176:
177:
178: /* Save the instance handle in static variable, which will be used in */
179: /* many subsequence calls from this application to Windows. */
180:
181: ghInst = hInstance;
182:
183: /* Create a main window for this application instance. */
184:
185:
186:
187: hWndDeskTop = GetDesktopWindow();
188: GetWindowRect( hWndDeskTop, &rcDeskTop );
189:
190: hWnd = CreateWindow(
191: "BOBWClass", /* See RegisterClass() call. */
192: "BOB", /* Text for window title bar. */
193: WS_OVERLAPPED, /* Window style. */
194: rcDeskTop.left+50, /* horizontal position. */
195: rcDeskTop.bottom-200, /* vertical position. */
196: 150, /* width. */
197: 100, /* height. */
198: NULL, /* Overlapped windows have no parent. */
199: NULL, /* Use the window class menu. */
200: hInstance, /* This instance owns this window. */
201: NULL /* Pointer to Createion Parameters */
202: );
203:
204: /* If window could not be created, return "failure" */
205:
206: if (!hWnd)
207: return (FALSE);
208:
209: ShowWindow(hWnd, nCmdShow); /* Show the window */
210: UpdateWindow(hWnd); /* Sends WM_PAINT message */
211: ghWnd = hWnd;
212:
213: }
214:
215: /****************************************************************************
216:
217: FUNCTION: MainWndProc(HWND, WORD, WPARAM, LPARAM)
218:
219: PURPOSE: Processes messages
220:
221: MESSAGES:
222:
223: WM_COMMAND - application menu (About dialog box)
224: WM_DESTROY - destroy window
225:
226: COMMENTS:
227:
228: To process the IDM_ABOUT message, call MakeProcInstance() to get the
229: current instance address of the About() function. Then call Dialog
230: box which will create the box according to the information in your
231: BOB.RC file and turn control over to the About() function. When
232: it returns, free the intance address.
233:
234: ****************************************************************************/
235:
236: long WINAPI MainWndProc(HWND hWnd, /* window handle */
237: UINT message, /* type of message */
238: WPARAM wParam, /* additional information */
239: LPARAM lParam ) /* additional information */
240: {
241: DLGPROC lpProcAbout;
242: CHAR buffer[80];
243:
244: HANDLE hToken;
245: TOKEN_PRIVILEGES tkp;
246:
247: static CONTROLTEXT CtlText;
248: static TCHAR szTitle[10];
249: static RECT FocusRect, SelectRect;
250:
251: switch (message) {
252:
253: case WM_CREATE: {
254:
255: HWND hWndButton;
256: CREATESTRUCT createStruct;
257: RECT rcClient;
258:
259: int cbTitle;
260: SIZE size;
261: HDC hDC;
262: int nSpaceWidth, nSpaceHeight;
263:
264: createStruct = *(LPCREATESTRUCT)lParam;
265: GetClientRect( hWnd,&rcClient );
266:
267: hWndButton = CreateWindow(
268: "BUTTON", /* See RegisterClass() call. */
269: TEXT("B. O. B."), /* Text for window title bar. */
270: WS_VISIBLE | WS_CHILD |
271: BS_PUSHBUTTON |
272: BS_OWNERDRAW,
273: rcClient.left,
274: rcClient.top,
275: rcClient.right,
276: rcClient.bottom,
277: hWnd, /* Parent */
278: (HMENU)BOB, /* Child ID */
279: createStruct.hInstance, /* This instance owns this window. */
280: NULL /* Pointer to Createion Parameters */
281: );
282:
283: wsprintf( buffer, "hWndButton is %#x and hWnd is %#x\r\n",
284: hWndButton, hWnd );
285: OutputDebugString ( buffer );
286:
287: if ( !hWndButton ) {
288: MessageBox( hWnd, "Error creating Window", NULL, MB_OK );
289: SendMessage( hWnd, WM_DESTROY, 0, 0 );
290: }
291:
292: SetFocus( hWndButton );
293:
294: OldButtonProc = SubclassWindow( hWndButton, ButtonProc );
295:
296: // define size of dashed rectangles around text in both bitmaps
297: hDC = GetDC( hWndButton );
298: cbTitle = SendMessage( hWndButton,
299: WM_GETTEXT,
300: (WPARAM) sizeof(szTitle),
301: (LPARAM)(LPTSTR)szTitle );
302: GetTextExtentPoint( hDC,
303: szTitle,
304: cbTitle,
305: &size );
306: ReleaseDC( hWndButton, hDC);
307:
308: CtlText.ptPosition.x = (rcClient.right - size.cx) >> 1;
309: CtlText.ptPosition.y = (rcClient.bottom - size.cy) >> 1;
310: CtlText.szTitle = szTitle;
311: CtlText.cbTitle = cbTitle;
312:
313: // load bitmap
314:
315: CtlText.hDefaultButton = LoadBitmap(
316: createStruct.hInstance, /* This instance owns this window. */
317: MAKEINTRESOURCE( DEFAULTBUTTON )
318: );
319:
320: if ( !CtlText.hDefaultButton ) {
321: wsprintf( buffer, "Error loading BUTTONBITMAP %d",
322: GetLastError() );
323: MessageBox( hWnd, "Error creating Window", NULL, MB_OK );
324: SendMessage( hWnd, WM_DESTROY, 0, 0 );
325: }
326:
327: CtlText.hSelectButton = LoadBitmap(
328: createStruct.hInstance, /* This instance owns this window. */
329: MAKEINTRESOURCE(SELECTEDBUTTON) // pushed state
330: );
331:
332: if ( !CtlText.hSelectButton ) {
333: wsprintf( buffer, "Error loading BUTTONBITMAP %d",
334: GetLastError() );
335: MessageBox( hWnd, "Error creating Window", NULL, MB_OK );
336: SendMessage( hWnd, WM_DESTROY, 0, 0 );
337: }
338:
339:
340:
341:
342: nSpaceWidth = GetSystemMetrics(SM_CXBORDER) << 1;
343: nSpaceHeight = GetSystemMetrics(SM_CYBORDER) << 1;
344:
345: FocusRect.top = CtlText.ptPosition.y - nSpaceHeight;
346: FocusRect.bottom = FocusRect.top + size.cy + (nSpaceHeight << 1);
347: FocusRect.left = CtlText.ptPosition.x - nSpaceWidth;
348: FocusRect.right = FocusRect.left + size.cx + (nSpaceWidth << 1);
349:
350: SelectRect.top = 2 + FocusRect.top;
351: SelectRect.bottom = 2 + FocusRect.bottom;
352: SelectRect.left = 2 + FocusRect.left;
353: SelectRect.right = 2 + FocusRect.right;
354:
355: return ( TRUE );
356: }
357: case WM_DRAWITEM:
358: {
359: LPDRAWITEMSTRUCT lpdisCtrl;
360:
361: if ( (int)wParam == BOB ) {
362: lpdisCtrl = (LPDRAWITEMSTRUCT)lParam;
363: switch (lpdisCtrl->itemAction)
364: {
365: // handle normal drawing of button, but check if its
366: // selected or focus
367:
368: case ODA_DRAWENTIRE:
369: OutputDebugString("WM_DRAWITEM: Action is ODA_DRAWENTIRE\r\n");
370: // this handles both button down and button up
371: HandleSelectedState(lpdisCtrl, &CtlText);
372:
373: // this handles focus rectangle around Button text
374: HandleFocusState(lpdisCtrl, &FocusRect, &SelectRect);
375: return TRUE;
376:
377: // handle drawing selection if needed
378: // selected is button down, not selected is button up
379: // focus will occur when button is pressed.
380:
381: case ODA_SELECT:
382: OutputDebugString("WM_DRAWITEM: Action is ODA_SELECT\r\n");
383: HandleSelectedState(lpdisCtrl, &CtlText);
384: HandleFocusState(lpdisCtrl, &FocusRect, &SelectRect);
385: return TRUE;
386:
387: // handle focus drawing if needed
388: case ODA_FOCUS:
389: OutputDebugString("WM_DRAWITEM: Action is ODA_FOCUS\r\n");
390: HandleFocusState(lpdisCtrl, &FocusRect, &SelectRect);
391: return TRUE;
392: }
393: }
394: break;
395: }
396: case WM_COMMAND: /* message: command from application menu */
397:
398: if ( HIWORD(wParam) == BN_CLICKED &&
399: LOWORD(wParam) == BOB ) {
400: /*
401: * Below are the steps needed to reboot the machine.
402: */
403: lpProcAbout = (DLGPROC)MakeProcInstance((FARPROC)About, ghInst );
404: #if defined(REBOOT)
405: DialogBox (ghInst, TEXT("AboutBox"), hWnd, lpProcAbout);
406: #else
407: DialogBox (ghInst, TEXT("AboutBox"), hWnd, lpProcAbout);
408: #endif
409:
410: /* Get a token for this process. */
411:
412: if ( !(GetVersion() & WIN32S) )
413: {
414:
415: OutputDebugString("Setting token");
416: // Running on NT so need to change privileges
417:
418: if (!OpenProcessToken(GetCurrentProcess(),
419: TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
420: wsprintf ( buffer, "OpenProcessToken Error #%d", GetLastError ());
421: MessageBox(hWnd, buffer, NULL, MB_OK);
422: }
423: /* Get the LUID for shutdown privilege */
424:
425: LookupPrivilegeValue(NULL, TEXT("SeShutdownPrivilege"),
426: &tkp.Privileges[0].Luid);
427:
428: tkp.PrivilegeCount = 1; /* one privilege to set */
429: tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
430:
431: /* Get shutdown privilege for this process. */
432:
433: if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
434: (PTOKEN_PRIVILEGES)NULL, 0)) {
435: wsprintf ( buffer, "AdjustTokenPrivileges Error #%d", GetLastError ());
436: MessageBox(hWnd, buffer, NULL, MB_OK);
437: }
438: }
439:
440: #if defined(REBOOT)
441: /* Shut down the system, and reboot the system. */
442:
443: if ( !ExitWindowsEx( EWX_REBOOT, 0 )) {
444: wsprintf ( buffer, "Error ExitWindows Error #%d", GetLastError ());
445: MessageBox(hWnd, buffer, NULL, MB_OK);
446: }
447: #else
448: /* Shut down the system, and force all applications closed. */
449:
450: if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0)) {
451: wsprintf ( buffer, "Error ExitWindows Error #%d", GetLastError ());
452: MessageBox(hWnd, buffer, NULL, MB_OK);
453: }
454: #endif
455: break;
456: }
457: else /* Lets Windows process it */
458: return (DefWindowProc(hWnd, message, wParam, lParam));
459:
460: case WM_DESTROY: /* message: window being destroyed */
461: DeleteObject(CtlText.hDefaultButton);
462: DeleteObject(CtlText.hSelectButton);
463: PostQuitMessage(0);
464: break;
465:
466: default: /* Passes it on if unproccessed */
467: return (DefWindowProc(hWnd, message, wParam, lParam));
468: }
469: return ( 0 );
470: }
471:
472:
473: /****************************************************************************
474:
475: FUNCTION: About(HWND, unsigned, WORD, LONG)
476:
477: PURPOSE: Processes messages for "About" dialog box
478:
479: MESSAGES:
480:
481: WM_INITDIALOG - initialize dialog box
482: WM_COMMAND - Input received
483:
484: COMMENTS:
485:
486: No initialization is needed for this particular dialog box, but TRUE
487: must be returned to Windows.
488:
489: Wait for user to click on "Ok" button, then close the dialog box.
490:
491: ****************************************************************************/
492:
493: BOOL WINAPI About(HWND hDlg, /* window handle of the dialog box */
494: UINT message, /* type of message */
495: WPARAM wParam, /* message-specific information */
496: LPARAM lParam )
497: {
498: switch (message) {
499: case WM_INITDIALOG: /* message: initialize dialog box */
500: return (TRUE);
501:
502: case WM_COMMAND: /* message: received a command */
503: if (wParam == IDOK /* "OK" box selected? */
504: || wParam == IDCANCEL) { /* System menu close command? */
505: EndDialog(hDlg, TRUE); /* Exits the dialog box */
506: return (TRUE);
507: }
508: break;
509: }
510: return (FALSE); /* Didn't process a message */
511: UNREFERENCED_PARAMETER(lParam);
512: }
513:
514:
515:
516: /*****************************************************************************
517:
518: FUNCTION: HandleSelectedState
519:
520: PURPOSE: Draw button bitmaps and text:
521: if button selected, draw "down"/pressed button bitmap
522: with text shifted right and down 2 pixels
523: else draw "up"/unpressed button bitmap
524: with text centered in button
525:
526: *****************************************************************************/
527: void HandleSelectedState(LPDRAWITEMSTRUCT lpdisCtrl, LPCONTROLTEXT lpCtlText)
528: {
529:
530: int nOldBkMode;
531:
532: // handle button pressed down select state -- button down bitmap
533: // text is right & down 2 pixels
534: if (lpdisCtrl->itemState & ODS_SELECTED)
535: {
536: DrawBitmap(lpdisCtrl->hDC,
537: lpdisCtrl->rcItem,
538: lpCtlText->hSelectButton,
539: SRCCOPY);
540:
541: // put text 2 pixels right and down of center of bitmap
542: nOldBkMode = SetBkMode(lpdisCtrl->hDC,TRANSPARENT);
543:
544: TextOut( lpdisCtrl->hDC,
545: lpCtlText->ptPosition.x+2,
546: lpCtlText->ptPosition.y+2,
547: lpCtlText->szTitle,
548: lpCtlText->cbTitle );
549:
550: SetBkMode(lpdisCtrl->hDC,nOldBkMode);
551: }
552: // not selected -- button up; text is in normal position
553: else
554: {
555: DrawBitmap(lpdisCtrl->hDC,
556: lpdisCtrl->rcItem,
557: lpCtlText->hDefaultButton,
558: SRCCOPY);
559:
560: // center text in bitmap
561: nOldBkMode = SetBkMode(lpdisCtrl->hDC,TRANSPARENT);
562: TextOut( lpdisCtrl->hDC,
563: lpCtlText->ptPosition.x,
564: lpCtlText->ptPosition.y,
565: lpCtlText->szTitle,
566: lpCtlText->cbTitle );
567:
568: SetBkMode(lpdisCtrl->hDC,nOldBkMode);
569: }
570: }
571:
572: /*****************************************************************************
573:
574: FUNCTION: HandleFocusState
575:
576: PURPOSE: If button has focus, draw dashed rectangle around text in button
577:
578: *****************************************************************************/
579: void HandleFocusState(LPDRAWITEMSTRUCT lpdisCtrl, LPRECT lpFocusRect, LPRECT lpSelectRect )
580: {
581: // if focus state, draw a dashed rect around text
582: if (lpdisCtrl->itemState & ODS_FOCUS)
583: {
584: // if selected, shift focus rect right and down 2 pixels around text
585: if (lpdisCtrl->itemState & ODS_SELECTED) {
586: OutputDebugString("HandleFocusState: State is ODS_SELECTED\r\n");
587: DrawFocusRect(lpdisCtrl->hDC, lpSelectRect);
588: }
589: // else text centered, so focus rect will be too
590: else {
591: DrawFocusRect(lpdisCtrl->hDC, lpFocusRect);
592: OutputDebugString("HandleFocusState: State is ODS_FOCUS\r\n");
593: }
594:
595: }
596: else
597: if (lpdisCtrl->itemState & ODS_SELECTED)
598: OutputDebugString("Error HandleFocusState: State is ODS_SELECTED\r\n");
599: else {
600: char buffer[80];
601: wsprintf(buffer, "HandleFocusState: lpdisCtrl->itemState is %#x\r\n",
602: lpdisCtrl->itemState );
603: OutputDebugString(buffer);
604: }
605: }
606: /****************************************************************************
607:
608: FUNCTION: DrawBitmap
609:
610: PURPOSE: Draw default or pushed button bitmap
611:
612: ****************************************************************************/
613:
614: void DrawBitmap(HDC hDC, RECT rect, HBITMAP hBitmap, DWORD rop)
615: {
616: HDC hMemDC;
617: BITMAP bm;
618: hMemDC = CreateCompatibleDC(hDC);
619: SelectObject(hMemDC, hBitmap);
620: // BitBlt(hDC, rect.left, rect.top, rect.right, rect.bottom, hMemDC, 0, 0, rop);
621: GetObject(hBitmap, sizeof (BITMAP), (LPVOID) &bm);
622: StretchBlt( hDC, rect.left, rect.top, rect.right, rect.bottom,
623: hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, rop);
624: DeleteDC(hMemDC);
625: }
626:
627: long WINAPI ButtonProc(HWND hWnd, /* window handle */
628: UINT message, /* type of message */
629: WPARAM wParam, /* additional information */
630: LPARAM lParam ) /* additional information */
631: {
632:
633: switch ( message )
634: {
635: case WM_CHAR:
636: OutputDebugString("ButtonProc: WM_CHAR received\r\n");
637: SendMessage( ghWnd, WM_COMMAND, MAKEWPARAM(BOB,BN_CLICKED), (LPARAM)(hWnd));
638:
639: default:
640: return CallWindowProc( OldButtonProc, hWnd, message, wParam, lParam );
641:
642: }
643:
644: return ( 0 );
645: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.