home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.wwiv.com
/
ftp.wwiv.com.zip
/
ftp.wwiv.com
/
pub
/
INTERNET
/
UPC2S1.ZIP
/
WINUTIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-02
|
12KB
|
331 lines
/*--------------------------------------------------------------------*/
/* 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);
}