home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------*/
- /* w i n u t i l . h */
- /* */
- /* Windows 3.1 utility functions for UUPC/extended */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* Copyright (c) Robert Denny, 1993 */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* Changes Copyright (c) 1989-1993 by Kendra Electronic */
- /* Wonderworks. */
- /* */
- /* All rights reserved except those explicitly granted by */
- /* the UUPC/extended license agreement. */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* RCS Information */
- /*--------------------------------------------------------------------*/
-
- /*
- * $Id: winutil.c 1.5 1993/10/02 19:07:49 ahd Exp $
- *
- * Revision history:
- * $Log: winutil.c $
- * Revision 1.5 1993/10/02 19:07:49 ahd
- * Print module name when winexec() fails
- *
- * Revision 1.4 1993/08/03 03:11:49 ahd
- * Further Windows 3.x fixes
- *
- * Revision 1.3 1993/08/02 03:24:59 ahd
- * Further changes in support of Robert Denny's Windows 3.x support
- *
- * Revision 1.2 1993/07/31 16:22:16 ahd
- * Changes in support of Robert Denny's Windows 3.x support
- *
- * Revision 1.1 1993/07/22 23:19:50 ahd
- * Initial revision
- *
- */
-
- /*--------------------------------------------------------------------*/
- /* System include files */
- /*--------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <windows.h>
- #include <toolhelp.h>
-
- /*--------------------------------------------------------------------*/
- /* UUPC/extended include files */
- /*--------------------------------------------------------------------*/
-
- #include "lib.h"
- #include "winutil.h"
-
- /*--------------------------------------------------------------------*/
- /* Local defines */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* Private messages */
- /*--------------------------------------------------------------------*/
-
- #define PM_TASKEND WM_USER
-
- /*--------------------------------------------------------------------*/
- /* Globals needed by callback functions & useful elsewhere */
- /*--------------------------------------------------------------------*/
-
- HTASK hOurTask; // Our task handle
- HWND hOurWindow; // Our EasyWin main window handle
-
- /*--------------------------------------------------------------------*/
- /* Used only locally */
- /*--------------------------------------------------------------------*/
-
- static HINSTANCE hChildInst; // Instance of child proc
- static HWND hTheWindow; // Used by WindCatcher() during enumeration
-
-
- BOOL CALLBACK WindCatcher(HWND hWnd, LPARAM lparam);
- BOOL CALLBACK NotifyCatcher(WORD wID, DWORD dwData);
-
- static LPFNNOTIFYCALLBACK lpfnNotifyCB;
- static FARPROC lpfnEnumWinCB;
-
- void _DoneEasyWin(void); // In TCWIN library
-
- //------------------------------------------------------------------------
- //
- // CloseEasyWin() - Force EasyWin window to close on termination
- //
- // This function should be registered with a call to atexit() if
- // you want to force the EasyWin window to close, permitting the
- // application to exit, automatically. Normally, an EasyWin app
- // hangs out in the "inactive" state until the user manually closes
- // the window. Using an atexit() function assures that the app will
- // exit automatically, regardless of the means of generating the
- // exit action (such as Ctrl-SysReq signal handlers, etc.).
- //
- //------------------------------------------------------------------------
- void CloseEasyWin(void)
- {
- MSG msg;
-
- //
- // This will assure that the EasyWin task yields to the system
- // at least once before exiting. See the comments next to the
- // call to WinExec() below.
- //
- PeekMessage(&msg, hOurWindow, NULL, NULL, PM_NOREMOVE);
- _DoneEasyWin();
- }
-
-
- //------------------------------------------------------------------------
- //
- // SpawnWait() - Spawn a child process, wait for termination
- //
- // Use WinExec() to fire off a child process, then synchronize with
- // its termination. For use with EasyWin applications.
- //
- // Inputs:
- // cmdLine Command line including executable name
- // fuCmdShow How to display new main window (see ShowWindow())
- //
- // Returns:
- // -1 Big Trouble: NotifyRegister or WinExec failed
- // >=0 Exit status of child
- //
- // On Error:
- // Logs and displays an error message using printmsg()
- //
- //------------------------------------------------------------------------
-
- int SpawnWait( const char *command,
- const char *parameters,
- const boolean synchronous,
- const UINT fuCmdShow)
- {
-
- BOOL bChildIsExecuting = TRUE;
- MSG msg;
- int iChildExitStatus = 0;
-
- if ( synchronous )
- {
- lpfnNotifyCB = (LPFNNOTIFYCALLBACK)
- MakeProcInstance((FARPROC) NotifyCatcher,
- _hInstance);
-
- if (!NotifyRegister(hOurTask, lpfnNotifyCB, NF_NORMAL))
- {
- FreeProcInstance(lpfnNotifyCB);
- printmsg(0, "SpawnWait: NotifyRegister() failed.");
- return(-1);
- }
- }
-
- //
- // Start up the child proc with the given command line. To start a DOS
- // box, use a .PIF file as the executable name (1st arg).
- //
- // WARNING! The spawned task MUST give up control to the system at
- // least once before exiting! An EasyWin app that calls _DoneEasyWin()
- // in an atexit() proc may never yiend to the system. In this case
- // WinExec() will not return here before the spawned task terminates.
- // The Notification callback will be called before WinExec() returns,
- // and the hInstChild will not be set yet. Result: This task will never
- // see the termination notfication of the spawned task, and SpawnWait()
- // will wait forever. CAVEAT!
- //
- // (To insure we do yield, banner() has a call to ddelay().)
-
- if ( parameters == NULL )
- hChildInst = WinExec( command , fuCmdShow);
- else {
- char buf[BUFSIZ];
- strcpy( buf, command );
- strcat( buf, " " );
- strcat( buf, parameters );
- hChildInst = WinExec( buf , fuCmdShow);
- }
-
- if ( hChildInst < 32 )
- {
-
- if ( synchronous )
- {
- NotifyUnRegister(hOurTask);
- FreeProcInstance(lpfnNotifyCB);
- }
-
- printmsg(0, "SpawnWait: WinExec(%s %s) failed. Code = %d\n",
- command,
- parameters ? parameters : "",
- (int)hChildInst);
- return(-1);
-
- } /* if */
-
- if ( ! synchronous )
- return 0;
-
- //
- // LOCAL MESSAGE LOOP - Service Windows while waiting for
- // child proc to terminate.
- //
- while(bChildIsExecuting && GetMessage(&msg, NULL, NULL, NULL))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
-
- if (msg.message == PM_TASKEND)
- {
- bChildIsExecuting = FALSE;
- iChildExitStatus = (int)(LOBYTE(msg.lParam));
- } /* while */
-
- } /* while */
-
- NotifyUnRegister(hOurTask);
- FreeProcInstance(lpfnNotifyCB);
-
- return(iChildExitStatus);
-
- } /* SpawnWait */
-
- //------------------------------------------------------------------------
- //
- // NotifyCatcher() - Notification Callback
- //
- //------------------------------------------------------------------------
-
- #ifdef __TURBOC__
- #pragma argsused
- #endif
-
- BOOL CALLBACK NotifyCatcher (WORD wID, DWORD dwData)
- {
- HTASK hCurTask; // handle of the task that called the notification call back
- TASKENTRY te;
-
-
- // Check for task exiting
- switch (wID)
- {
- case NFY_EXITTASK:
- //
- // Obtain info about the task that is terminating
- //
- hCurTask = GetCurrentTask();
- te.dwSize = sizeof(TASKENTRY);
- TaskFindHandle(&te, hCurTask);
- //
- // Check if the task that is terminating is our child task.
- // Also check if the hInstance of the task that is terminating
- // in the same as the hInstance of the task that was WinExec'd
- // by us earlier in this file. This additional check is added
- // because the Task List that is brought up by selecting
- // 'Switch To ...' from the system menu is also run as a child
- // task of the application and consequently the hInstance needs
- // to be checked to determine which child task is terminating.
- // Obviously, the parent may have intentionally WinExec'ed more
- // than one child on purpose as well.
- //
- // Note that the PM_TASKEND message is sent with its LPARAM set
- // to the dwData passed to this callback. The low byte of this
- // is the child's exit status.
- //
- if (te.hTaskParent == hOurTask && te.hInst == hChildInst)
- PostMessage(hOurWindow, PM_TASKEND, (WORD)hOurTask, dwData );
-
- break;
-
- default:
- break;
- }
-
- // Pass notification to other callback functions
- return FALSE;
-
- }
-
- //------------------------------------------------------------------------
- //
- // FindTaskWindow() - Find handle to one of our windows, by name
- //
- //------------------------------------------------------------------------
- HWND FindTaskWindow (HTASK hTask, LPSTR lpszClassName)
- {
-
- hTheWindow = NULL;
-
- lpfnEnumWinCB = MakeProcInstance((FARPROC)WindCatcher, _hInstance);
- EnumTaskWindows(hTask, lpfnEnumWinCB, (LPARAM)lpszClassName);
- FreeProcInstance(lpfnEnumWinCB);
-
- return(hTheWindow);
- }
-
-
- //------------------------------------------------------------------------
- //
- // WindCatcher() - Callback function for EnumTaskWindows(). Passes
- // back a copy of the next window handle.
- //
- //------------------------------------------------------------------------
- #define BUF_LEN 32
- BOOL CALLBACK WindCatcher (HWND hWnd, LPARAM lparam)
- {
- char buf[BUF_LEN+1];
- int i;
-
- if ((i = GetClassName(hWnd, (LPSTR)buf, BUF_LEN)) == 0)
- return(FALSE); // OOPS!
- buf[i] = '\0'; // Make cstr
- if (lstrcmpi((LPCSTR)buf, (LPCSTR)lparam) == 0) // If we found it
- {
- hTheWindow = hWnd; // Save it for called func
- return(FALSE);
- }
- return(TRUE);
- }
-