home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES1.ZIP / LIB / winutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-16  |  15.3 KB  |  362 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       w i n u t i l . c                                            */
  3. /*                                                                    */
  4. /*       Windows 3.1 utility functions for UUPC/extended              */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*       Copyright (c) Robert Denny, 1993                             */
  9. /*--------------------------------------------------------------------*/
  10.  
  11. /*--------------------------------------------------------------------*/
  12. /*       Changes Copyright (c) 1989-1993 by Kendra Electronic         */
  13. /*       Wonderworks.                                                 */
  14. /*                                                                    */
  15. /*       All rights reserved except those explicitly granted by       */
  16. /*       the UUPC/extended license agreement.                         */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*--------------------------------------------------------------------*/
  20. /*                          RCS Information                           */
  21. /*--------------------------------------------------------------------*/
  22.  
  23. /*
  24.  *    $Id: winutil.c 1.8 1993/10/16 15:13:17 ahd Exp $
  25.  *
  26.  *    Revision history:
  27.  *    $Log: winutil.c $
  28.  * Revision 1.8  1993/10/16  15:13:17  ahd
  29.  * Add _export keywords per Paul Steckler to fix system crashes
  30.  *
  31.  * Revision 1.7  1993/10/12  01:20:43  ahd
  32.  * Normalize comments to PL/I style
  33.  *
  34.  * Revision 1.6  1993/10/12  00:48:44  ahd
  35.  * Normalize comments
  36.  *
  37.  * Revision 1.5  1993/10/02  19:07:49  ahd
  38.  * Print module name when winexec() fails
  39.  *
  40.  * Revision 1.4  1993/08/03  03:11:49  ahd
  41.  * Further Windows 3.x fixes
  42.  *
  43.  * Revision 1.3  1993/08/02  03:24:59  ahd
  44.  * Further changes in support of Robert Denny's Windows 3.x support
  45.  *
  46.  * Revision 1.2  1993/07/31  16:22:16  ahd
  47.  * Changes in support of Robert Denny's Windows 3.x support
  48.  *
  49.  * Revision 1.1  1993/07/22  23:19:50  ahd
  50.  * Initial revision
  51.  *
  52.  */
  53.  
  54. /*--------------------------------------------------------------------*/
  55. /*                        System include files                        */
  56. /*--------------------------------------------------------------------*/
  57.  
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include <windows.h>
  62. #include <toolhelp.h>
  63.  
  64. /*--------------------------------------------------------------------*/
  65. /*                    UUPC/extended include files                     */
  66. /*--------------------------------------------------------------------*/
  67.  
  68. #include "lib.h"
  69. #include "winutil.h"
  70.  
  71. /*--------------------------------------------------------------------*/
  72. /*                           Local defines                            */
  73. /*--------------------------------------------------------------------*/
  74.  
  75. /*--------------------------------------------------------------------*/
  76. /*                          Private messages                          */
  77. /*--------------------------------------------------------------------*/
  78.  
  79. #define PM_TASKEND WM_USER
  80.  
  81. /*--------------------------------------------------------------------*/
  82. /*      Globals needed by callback functions & useful elsewhere       */
  83. /*--------------------------------------------------------------------*/
  84.  
  85. HTASK hOurTask;               /* Our task handle                      */
  86. HWND hOurWindow;              /* Our EasyWin main window handle       */
  87.  
  88. /*--------------------------------------------------------------------*/
  89. /*                         Used only locally                          */
  90. /*--------------------------------------------------------------------*/
  91.  
  92. static HINSTANCE hChildInst;            /* Instance of child proc     */
  93. static HWND hTheWindow;                 /* Used by WindCatcher()
  94.                                            during enumeration         */
  95.  
  96. BOOL CALLBACK _export WindCatcher(HWND hWnd, LPARAM lparam);
  97. BOOL CALLBACK _export NotifyCatcher(WORD wID, DWORD dwData);
  98.  
  99. static LPFNNOTIFYCALLBACK lpfnNotifyCB;
  100. static FARPROC lpfnEnumWinCB;
  101.  
  102. void _DoneEasyWin(void);      /* In TCWIN library                     */
  103.  
  104. /*--------------------------------------------------------------------*/
  105. /*       C l o s e E a s y W i n                                      */
  106. /*                                                                    */
  107. /*       Force EasyWin window to close on termination                 */
  108. /*                                                                    */
  109. /*       This function should be registered with a call to            */
  110. /*       atexit() if you want to force the EasyWin window to          */
  111. /*       close, permitting the application to exit, automatically.    */
  112. /*       Normally, an EasyWin app hangs out in the "inactive"         */
  113. /*       state until the user manually closes the window.  Using      */
  114. /*       an atexit() function assures that the app will exit          */
  115. /*       automatically, regardless of the means of generating the     */
  116. /*       exit action (such as Ctrl-SysReq signal handlers, etc.).     */
  117. /*--------------------------------------------------------------------*/
  118.  
  119. void CloseEasyWin(void)
  120. {
  121.    MSG msg;
  122.  
  123. /*--------------------------------------------------------------------*/
  124. /*       This will assure that the EasyWin task yields to the         */
  125. /*       system at least once before exiting.  See the comments       */
  126. /*       next to the call to WinExec() below.                         */
  127. /*--------------------------------------------------------------------*/
  128.  
  129.    PeekMessage(&msg, hOurWindow, NULL, NULL, PM_NOREMOVE);
  130.    _DoneEasyWin();
  131. }
  132.  
  133. /*--------------------------------------------------------------------*/
  134. /*       S p a w n W a i t                                            */
  135. /*                                                                    */
  136. /*       Spawn a child process, wait for termination                  */
  137. /*                                                                    */
  138. /*       Use WinExec() to fire off a child process, then              */
  139. /*       synchronize with its termination.  For use with EasyWin      */
  140. /*       applications.                                                */
  141. /*                                                                    */
  142. /*       Inputs:                                                      */
  143. /*          cmdLine     Command line including executable name        */
  144. /*          fuCmdShow   How to display new main window (see           */
  145. /*                      ShowWindow())                                 */
  146. /*                                                                    */
  147. /*       Returns:                                                     */
  148. /*          -1          Big Trouble: NotifyRegister or WinExec        */
  149. /*          failed                                                    */
  150. /*          >=0         Exit status of child                          */
  151. /*                                                                    */
  152. /*       On Error:                                                    */
  153. /*          Logs and displays an error message using printmsg()       */
  154. /*--------------------------------------------------------------------*/
  155.  
  156. int SpawnWait( const char *command,
  157.                const char *parameters,
  158.                const boolean synchronous,
  159.                const UINT fuCmdShow)
  160. {
  161.  
  162.    BOOL bChildIsExecuting = TRUE;
  163.    MSG msg;
  164.    int iChildExitStatus = 0;
  165.  
  166.    if ( synchronous )
  167.    {
  168.       lpfnNotifyCB = (LPFNNOTIFYCALLBACK)
  169.                            MakeProcInstance((FARPROC) NotifyCatcher,
  170.                                              _hInstance);
  171.  
  172.       if (!NotifyRegister(hOurTask, lpfnNotifyCB, NF_NORMAL))
  173.       {
  174.            FreeProcInstance(lpfnNotifyCB);
  175.            printmsg(0, "SpawnWait: NotifyRegister() failed.");
  176.            return(-1);
  177.       }
  178.    }
  179.  
  180. /*--------------------------------------------------------------------*/
  181. /*       Start up the child proc with the given command line.  To     */
  182. /*       start a DOS box, use a .PIF file as the executable name      */
  183. /*       (1st arg).                                                   */
  184. /*                                                                    */
  185. /*       WARNING!  The spawned task MUST give up control to the       */
  186. /*       system at least once before exiting!  An EasyWin app that    */
  187. /*       calls _DoneEasyWin() in an atexit() proc may never yiend     */
  188. /*       to the system.  In this case WinExec() will not return       */
  189. /*       here before the spawned task terminates.  The                */
  190. /*       Notification callback will be called before WinExec()        */
  191. /*       returns, and the hInstChild will not be set yet.  Result:    */
  192. /*       This task will never see the termination notfication of      */
  193. /*       the spawned task, and SpawnWait() will wait forever.         */
  194. /*       CAVEAT!                                                      */
  195. /*                                                                    */
  196. /*       (To insure we do yield, banner() has a call to ddelay().)    */
  197. /*--------------------------------------------------------------------*/
  198.  
  199.    if ( parameters == NULL )
  200.       hChildInst = WinExec( command , fuCmdShow);
  201.    else {
  202.       char buf[BUFSIZ];
  203.       strcpy( buf, command );
  204.       strcat( buf, " " );
  205.       strcat( buf, parameters );
  206.       hChildInst = WinExec( buf , fuCmdShow);
  207.    }
  208.  
  209.    if ( hChildInst < 32 )
  210.    {
  211.  
  212.       if ( synchronous )
  213.       {
  214.          NotifyUnRegister(hOurTask);
  215.          FreeProcInstance(lpfnNotifyCB);
  216.       }
  217.  
  218.       printmsg(0, "SpawnWait: WinExec(%s %s) failed. Code = %d\n",
  219.                   command,
  220.                   parameters ? parameters : "",
  221.                   (int)hChildInst);
  222.       return(-1);
  223.  
  224.    }  /* if */
  225.  
  226.    if ( ! synchronous )
  227.       return 0;
  228.  
  229. /*--------------------------------------------------------------------*/
  230. /*       LOCAL MESSAGE LOOP - Service Windows while waiting for       */
  231. /*       child proc to terminate.                                     */
  232. /*--------------------------------------------------------------------*/
  233.  
  234.    while(bChildIsExecuting && GetMessage(&msg, NULL, NULL, NULL))
  235.    {
  236.       TranslateMessage(&msg);
  237.       DispatchMessage(&msg);
  238.  
  239.       if (msg.message == PM_TASKEND)
  240.       {
  241.          bChildIsExecuting = FALSE;
  242.          iChildExitStatus = (int)(LOBYTE(msg.lParam));
  243.       } /* while */
  244.  
  245.    } /* while */
  246.  
  247.    NotifyUnRegister(hOurTask);
  248.    FreeProcInstance(lpfnNotifyCB);
  249.  
  250.    return(iChildExitStatus);
  251.  
  252. } /* SpawnWait */
  253.  
  254. /*--------------------------------------------------------------------*/
  255. /*       N o t i f y C a t c h e r                                    */
  256. /*                                                                    */
  257. /*       Notification Callback                                        */
  258. /*--------------------------------------------------------------------*/
  259.  
  260. #ifdef __TURBOC__
  261. #pragma argsused
  262. #endif
  263.  
  264. BOOL CALLBACK _export NotifyCatcher (WORD wID, DWORD dwData)
  265. {
  266.    HTASK hCurTask;                     /* handle of the task that     */
  267.                                        /* called notification call    */
  268.                                        /* back                        */
  269.    TASKENTRY te;
  270.  
  271. /*--------------------------------------------------------------------*/
  272. /*                        Check for task exiting                      */
  273. /*--------------------------------------------------------------------*/
  274.  
  275.    switch (wID)
  276.    {
  277.       case NFY_EXITTASK:
  278. /*--------------------------------------------------------------------*/
  279. /*            Obtain info about the task that is terminating          */
  280. /*--------------------------------------------------------------------*/
  281.          hCurTask = GetCurrentTask();
  282.          te.dwSize = sizeof(TASKENTRY);
  283.          TaskFindHandle(&te, hCurTask);
  284.  
  285. /*--------------------------------------------------------------------*/
  286. /*       Check if the task that is terminating is our child task.     */
  287. /*       Also check if the hInstance of the task that is              */
  288. /*       terminating in the same as the hInstance of the task that    */
  289. /*       was WinExec'd by us earlier in this file.  This              */
  290. /*       additional check is added because the Task List that is      */
  291. /*       brought up by selecting 'Switch To ...' from the system      */
  292. /*       menu is also run as a child task of the application and      */
  293. /*       consequently the hInstance needs to be checked to            */
  294. /*       determine which child task is terminating.  Obviously,       */
  295. /*       the parent may have intentionally WinExec'ed more than       */
  296. /*       one child on purpose as well.                                */
  297. /*                                                                    */
  298. /*       Note that the PM_TASKEND message is sent with its LPARAM     */
  299. /*       set to the dwData passed to this callback.  The low byte     */
  300. /*       of this is the child's exit status.                          */
  301. /*--------------------------------------------------------------------*/
  302.  
  303.          if (te.hTaskParent == hOurTask && te.hInst == hChildInst)
  304.             PostMessage(hOurWindow, PM_TASKEND, (WORD)hOurTask, dwData );
  305.  
  306.          break;
  307.  
  308.          default:
  309.             break;
  310.    }
  311.  
  312. /*--------------------------------------------------------------------*/
  313. /*             Pass notification to other callback functions          */
  314. /*--------------------------------------------------------------------*/
  315.  
  316.    return FALSE;
  317.  
  318. }
  319.  
  320. /*--------------------------------------------------------------------*/
  321. /*       F i n d T a s k W i n d o w                                  */
  322. /*                                                                    */
  323. /*       Find handle to one of our windows, by name                   */
  324. /*--------------------------------------------------------------------*/
  325.  
  326. HWND FindTaskWindow (HTASK hTask, LPSTR lpszClassName)
  327. {
  328.  
  329.    hTheWindow = NULL;
  330.  
  331.    lpfnEnumWinCB = MakeProcInstance((FARPROC)WindCatcher, _hInstance);
  332.    EnumTaskWindows(hTask, lpfnEnumWinCB, (LPARAM)lpszClassName);
  333.    FreeProcInstance(lpfnEnumWinCB);
  334.  
  335.    return(hTheWindow);
  336. }
  337.  
  338. /*--------------------------------------------------------------------*/
  339. /*       W i n d C a t c h e r                                        */
  340. /*                                                                    */
  341. /*       Callback function for EnumTaskWindows().  Passes back a      */
  342. /*       copy of the next window handle.                              */
  343. /*--------------------------------------------------------------------*/
  344.  
  345. #define BUF_LEN 32
  346. BOOL CALLBACK _export WindCatcher (HWND hWnd, LPARAM lparam)
  347. {
  348.     char buf[BUF_LEN+1];
  349.     int i;
  350.  
  351.     if ((i = GetClassName(hWnd, (LPSTR)buf, BUF_LEN)) == 0)
  352.        return(FALSE);                      /* OOPS!                   */
  353.  
  354.     buf[i] = '\0';                         /* Make cstr               */
  355.     if (lstrcmpi((LPCSTR)buf, (LPCSTR)lparam) == 0) /* If we found it */
  356.     {
  357.         hTheWindow = hWnd;                 /* Save it for called func */
  358.         return(FALSE);
  359.     }
  360.     return(TRUE);
  361. }
  362.