home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 35 Internet
/
35-Internet.zip
/
portwin.zip
/
portwin.c
next >
Wrap
C/C++ Source or Header
|
1996-04-15
|
25KB
|
834 lines
/* portwin.c */
/* This program maintains a small number of buttons as a
management gadget for UUPC/Extended.
A button is provided to suspend/resume the use of the comport
and show its current status.
A 2nd button displays the contents of a profile-specified log file,
via a profile-specified display program (needs to give list).
Another button is provided that displays the spool status in a
list box, allowing deletions of individual spool files.
*/
#include "portwin.h"
static HWND hwndBase; /* invisible frame */
static HWND hwndDlg; /* Button dialog */
static HWND hwndObject; /* Object window for util_task */
static HWND hwndSpool; /* Spool dialog */
static HAB hab; /* PM anchor */
static TID util_thread; /* utility task ID */
static FILE *errf; /* error file handle */
static HINI prfinit; /* profile handle */
static BOOL portfree; /* COMx available? */
static char comstr[5]; /* COMx string */
static char *qprocbuf; /* DosQProcStatus buffer ptr */
PROF_INI globals; /* portwin.ini globals */
SWP buttonpos; /* window positions */
SWP spoolpos; /* window positions */
BOOL buttonsaved, spoolsaved; /* positions saved ? */
/* declare mystery API */
extern unsigned _Far16 _Pascal DosQProcStatus( ULONG * _Seg16 buffer,
USHORT buffer_size );
/* check for SLIP.EXE or PPP.EXE running: returns TRUE if one is */
BOOL query_tcp( void )
{
APIRET rc;
rc = DosQProcStatus( (ULONG * _Seg16 )qprocbuf, 64*1024 );
if ( rc != 0 ) return FALSE;
return FALSE;
}
/*------------------- log PM error code to pmastro.err -----------------*/
static VOID logWinErr( void )
{
USHORT sev, id;
ERRORID ecode;
ecode = WinGetLastError( hab );
id = ERRORIDERROR( ecode );
sev = ERRORIDSEV( ecode );
if ( errf == NULL )
errf = fopen( "portwin.err", "w" );
fprintf( errf, "PM Window error %x severity %x \n", id, sev );
}
/*-------------------- issue message box ------------------------------*/
USHORT message( PSZ text, PSZ label, ULONG mstyle )
{
USHORT tmpret;
tmpret =
WinMessageBox(HWND_DESKTOP, /* Parent window is desk top */
hwndBase, /* Owner window is our frame */
text, /* PMWIN Error message */
label, /* Title bar message */
MSGBOXID, /* Message identifier */
MB_MOVEABLE | MB_CUACRITICAL | mstyle ); /* Flags */
if (tmpret == MBID_ERROR)
logWinErr();
return tmpret;
}
/* see if specified com port is available or not;
just open it exclusive */
int check_com_port( void )
{
HFILE hfCom;
ULONG ulAction;
APIRET retc;
BOOL retval;
RGB color;
strcpy( comstr, "COMx" );
/* make the com num into an ascii char */
comstr[3] = globals.comport | 0x30;
retc = DosOpen( comstr, &hfCom, &ulAction, 0, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
(PEAOP2)NULL );
if ( retc == 0 )
{
DosClose( hfCom );
retval = 0; /* says port is free */
color.bGreen = 255;
color.bBlue = 0;
color.bRed = 0;
}
else
{
char tcpath[128];
char *cp;
retval = 2; /* says port has tcpip connect */
color.bGreen = 0;
color.bBlue = 255; /* assume tcpip has it */
color.bRed = 0;
cp = getenv("ETC");
if ( cp != NULL )
{
/* determine if SLIP.EXE or PPP.EXE are running.
If so, change color to Blue */
strcpy( tcpath, cp );
cp = strrchr( tcpath, '\\' );
if ( cp == NULL )
cp = strrchr( tcpath, ':' );
cp++;
*cp = '\0'; /* terminate string */
strcat( tcpath, "bin\\slip.exe" );
retc = DosOpen( tcpath, &hfCom, &ulAction,
0, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_READONLY | OPEN_SHARE_DENYREADWRITE,
(PEAOP2)NULL );
if ( retc == 0 )
{ /* we were able to open it, so it's not in use */
DosClose( hfCom );
*cp = '\0'; /* reset to path */
strcat( tcpath, "bin\\ppp.exe" );
retc = DosOpen( tcpath, &hfCom, &ulAction,
0, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_READONLY | OPEN_SHARE_DENYREADWRITE,
(PEAOP2)NULL );
if ( retc == 0 )
{ /* both pgms not in use, must be UUPC */
DosClose( hfCom );
retval = 1; /* says port in use by uupc */
color.bGreen = 0;
color.bBlue = 0;
color.bRed = 255;
}
}
}
}
/* set button background */
WinSetPresParam( WinWindowFromID( hwndDlg, BID_COM2 ),
PP_BACKGROUNDCOLOR, (ULONG)sizeof(RGB),
(PVOID)&color);
return retval;
}
static UU_JOB *jobanc;
void insert_spool_line( HWND lbox, char * dline, UU_JOB * njob )
{
MRESULT res;
USHORT itx;
/* add the spool status line to listbox,
save the result which contains index num */
res = WinSendMsg( lbox, LM_INSERTITEM,
MPFROM2SHORT( LIT_SORTASCENDING, 0 ),
MPFROMP( dline ) );
itx = SHORT1FROMMR( res );
/* push the rest of the data onto a linked-list */
njob->next = jobanc;
jobanc = njob;
/* now save this address with the dialog item */
WinSendMsg( lbox, LM_SETITEMHANDLE,
MPFROMSHORT( itx ),
MPFROMP( njob ) );
return;
}
static HAB uhab; /* hab for utility task */
/* Client Window for util_task */
static
MRESULT EXPENTRY UtilWinProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
{
ULONG retc;
BOOL prevfree;
char cmd[80];
switch( msg )
{
case WM_CREATE:
/* send a WM_TIMER message for 10 sec. interval */
retc = WinStartTimer( uhab, hwnd, 1L, 10000UL );
return (MRESULT) 0;
case WM_TIMER:
prevfree = portfree;
portfree = check_com_port();
break;
case WM_USER_TOGGLE_PORT:
{
/* obtain the current state of the port */
prevfree = portfree;
portfree = check_com_port();
/* suspend or resume the COM port as required */
if ( portfree == 1 )
{ /* held by uupc, so suspend it */
sprintf( cmd, "uuport -s %s", comstr );
system( cmd );
}
else
if ( portfree == 0 )
{ sprintf( cmd, "uuport -r %s", comstr );
system( cmd );
}
else
message( "COM port in use by Network", "UUPC",
MB_CANCEL );
portfree = check_com_port();
WinPostMsg( hwndBase, WM_USER_ENABLE, 0, 0 );
return (MRESULT) 0;
}
case WM_USER_DISPLAY_LOG:
sprintf( cmd, "start /f %s %s", globals.disp_pgm, globals.log_file );
system(cmd);
/* no Ack required */
WinPostMsg( hwndBase, WM_USER_ENABLE, 0, 0 );
return (MRESULT) 0;
/* for display run the uustat to a tmp file,
and read it into a listbox */
case WM_USER_DISPLAY_SPOOL:
{
HWND lbox;
FILE *uustat;
char *uutarg, *uusize;
char cbuf[128];
char dline[128];
sprintf( cmd, "uustat -sall > %s 2>NUL", globals.tmp_file );
retc = system(cmd);
/* if ok return msg to open the listbox dialog */
if ( retc != 0 )
{
WinPostMsg( hwndBase, WM_USER_ENABLE, 0, 0 );
message("Unable to run uustat", "Error", MB_OK );
WinDismissDlg( hwndSpool, 0L );
return (MRESULT) 0;
}
lbox = WinWindowFromID( hwndSpool, DID_SPOOL_BOX );
uustat = fopen( globals.tmp_file, "r" );
jobanc = NULL;
while ( fgets( cbuf, sizeof(cbuf)-1, uustat ) != NULL )
{
char *cp, *datime;
UU_JOB *njob;
if ( strncmp( cbuf, "uustat: No jobs", 15 ) == 0 )
{
fclose( uustat );
message( "Spool is empty", "UUPC", MB_OK );
WinPostMsg( hwndBase, WM_USER_ENABLE, 0, 0 );
WinDismissDlg( hwndSpool, 0L );
return (MRESULT)0;
}
/* parse the line(s) and build 1 display line */
cp = strtok( cbuf, " \n" );
if ( cbuf[0] > ' ' ) /* has jobID */
{
njob = (UU_JOB *)malloc( sizeof(UU_JOB) );
strcpy( njob->jobid, cp );
datime = strtok( NULL, " \n" );
strtok( NULL, " \n" ); /* skip field */
uutarg = strtok( NULL, " \n" );
strtok( NULL, " \n" ); /* skip field */
uusize = strtok( NULL, " \n" );
cp = strtok( NULL, " \n" );
sprintf( dline, "%-9s %-12s %-8s ", uutarg, datime, uusize );
/* 2-liner has chars 'x.' to begin this token */
if ( ( cp != NULL ) && ( *(cp+1) == '.' ) ) /* 2-liner */
strncpy( njob->uufile, cp, sizeof(njob->uufile)-1 );
else /* 1-liner */
{ if ( cp != NULL )
strcat( dline, cp ); /* add UUCP file to copy */
njob->uufile[0] = '\0';
insert_spool_line( lbox, dline, njob );
}
}
else
{
/* skip to 5th and 6th tokens */
strtok( NULL, " \n" ); /* skip field */
strtok( NULL, " \n" ); /* skip field */
strtok( NULL, " \n" ); /* skip field */
uutarg = strtok( NULL, " \n" ); /* command */
cp = strtok( NULL, " \n" ); /* mail addr */
strcat( dline, uutarg );
strcat( dline, " " );
strcat( dline, cp );
insert_spool_line( lbox, dline, njob );
}
} /* end while fgets() */
/* close the temp file */
fclose(uustat);
/* send msg to SpoolDlg to continue */
WinEnableWindow( hwndSpool, TRUE );
return (MRESULT) 0;
}
/* if user chooses to delete a spool file */
case WM_USER_DELETE_SPOOL:
{
/* use pointer in mp1 */
UU_JOB *jp;
jp = (UU_JOB *)mp1;
sprintf( cmd, "uustat -k %s >NUL 2>NUL", jp->jobid );
system( cmd );
WinEnableWindow( hwndSpool, TRUE );
return (MRESULT) 0;
}
}
return WinDefWindowProc( hwnd, msg, mp1, mp2 );
}
/* Utility Thread */
void util_task( void * parm )
{
BOOL fSuccess;
HMQ uhmq;
QMSG uqmsg;
/* thread initialization */
uhab = WinInitialize( 0 );
uhmq = WinCreateMsgQueue( uhab, 0 );
/* prevent system from posting object window a WM_QUIT
I'll post WM_QUIT when it's time. */
fSuccess = WinCancelShutdown( uhmq, TRUE );
pmassert( uhab, fSuccess );
fSuccess = WinRegisterClass( uhab, UTIL_OBJECT,
(PFNWP)UtilWinProc, 0, 0 );
pmassert( uhab, fSuccess );
hwndObject = WinCreateWindow( HWND_OBJECT, UTIL_OBJECT, "",
0, 0, 0, 0, 0, HWND_OBJECT, HWND_BOTTOM, 0, NULL, NULL );
/* created OK, ack Client to start Dlg */
WinPostMsg( hwndBase, WM_USER_ENABLE, 0, 0 );
/* get/dispatch messages; user messages, for the most part */
while( WinGetMsg ( uhab, &uqmsg, 0, 0, 0 ) )
{
WinDispatchMsg ( uhab, &uqmsg );
}
/* tell client window to quit */
WinPostMsg( hwndDlg, WM_QUIT, 0, 0 );
/* clean up */
WinDestroyWindow( hwndObject );
WinDestroyMsgQueue( uhmq );
WinTerminate( uhab );
return;
}
MRESULT EXPENTRY SpoolDlg( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
USHORT command;
command = (COMMANDMSG(&msg)->cmd);
switch( msg )
{
case WM_INITDLG:
{
/* send msg to object window to fill the listbox */
hwndSpool = hwnd;
WinPostMsg( hwndObject, WM_USER_DISPLAY_SPOOL, 0, 0 );
if ( spoolsaved )
{ WinSetWindowPos( hwnd, HWND_TOP, spoolpos.x, spoolpos.y,
0, 0, SWP_MOVE | SWP_ZORDER );
}
WinEnableWindow( hwnd, FALSE ); /* disable this dialog until
we fill the box */
return (MRESULT)FALSE;
}
case WM_CLOSE:
command = DID_SPOOL_DISMISS;
case WM_COMMAND:
{
HWND lbox; /* listbox handle */
SHORT spfile, numitem; /* item index, count */
UU_JOB *fjob;
lbox = WinWindowFromID( hwnd, DID_SPOOL_BOX );
switch( command )
{
case DID_SPOOL_DELETE:
spfile = WinQueryLboxSelectedItem( lbox );
numitem = 1;
if ( spfile >= 0 )
{ /* retrieve pointer to job */
fjob = (UU_JOB *) WinSendMsg( lbox,
LM_QUERYITEMHANDLE,
MPFROMSHORT( spfile ), NULL );
/* remove entry from list */
numitem = WinDeleteLboxItem( lbox, spfile );
/* post msg to util-task to delete this one */
WinPostMsg( hwndObject, WM_USER_DELETE_SPOOL, fjob, 0 );
}
if ( numitem != 0 )
return (MRESULT)FALSE;
case DID_SPOOL_DISMISS:
/* free the chain of jobs */
fjob = jobanc;
while ( fjob != NULL )
{ jobanc = fjob;
fjob = fjob->next;
free(jobanc);
}
spoolsaved = WinQueryWindowPos( hwnd, &spoolpos );
WinDismissDlg( hwnd, 0L );
return (MRESULT)FALSE;
}
return (MRESULT)FALSE;
}
}
return WinDefDlgProc( hwnd, msg, mp1, mp2 );
}
MRESULT EXPENTRY ButtonDlg( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
switch( msg )
{
case WM_INITDLG:
{
/* attach utility task to be used by object window for long-running
activity */
util_thread = _beginthread( util_task, NULL, 16384, NULL );
WinSetDlgItemText( hwnd, BID_COM2, comstr );
if ( buttonsaved )
{ WinSetWindowPos( hwnd, HWND_TOP, buttonpos.x, buttonpos.y,
0, 0, SWP_MOVE | SWP_ZORDER );
}
return (MRESULT)FALSE;
}
case WM_COMMAND:
{
switch (COMMANDMSG(&msg)->cmd)
{
/**********************************/
/* Process Button requests */
/**********************************/
case BID_COM2:
{ /* request to toggle COM2 port state */
WinEnableWindow( hwndDlg, FALSE );
WinPostMsg( hwndObject, WM_USER_TOGGLE_PORT, 0, 0 );
break;
}
case BID_LOG:
{ /* request to display UUCP log */
WinEnableWindow( hwndDlg, FALSE );
WinPostMsg( hwndObject, WM_USER_DISPLAY_LOG, 0, 0 );
break;
}
case BID_SPOOL:
{ /* request to display UUCP spool in listbox */
WinDlgBox( HWND_DESKTOP, hwndBase, SpoolDlg,
NULLHANDLE, DID_SPOOL, NULL );
break;
}
}
return (MRESULT)TRUE;
}
/* if we get a close, tell object to go away, then
tell the frame to hike out */
case WM_CLOSE:
/* save the window position */
buttonsaved = WinQueryWindowPos( hwnd, &buttonpos );
/* tell object window to quit, then exit its thread */
WinPostMsg( hwndObject, WM_QUIT, 0, 0 );
/* may need to send ourselves a WM_QUIT here */
WinSendMsg( hwndBase, WM_CLOSE, 0L, 0L );
}
return WinDefDlgProc( hwnd, msg, mp1, mp2 );
}
BOOL verify_file( char * fname )
{
return TRUE;
}
/* Profile initialization dialog */
MRESULT EXPENTRY prof_init_dlg( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
USHORT fld, act;
LONG portn;
BOOL tst;
char texta[PATH_LEN];
static PROF_INI temprof;
switch( msg )
{
case WM_INITDLG:
/* setup COM port spin button values */
WinSendMsg( WinWindowFromID( hwnd, DID_UUPC_COM_PORT ),
SPBM_SETLIMITS, MPFROMLONG(4), MPFROMLONG(1) );
/* set text length limits */
WinSendMsg( WinWindowFromID( hwnd, DID_TMP_FILE ), EM_SETTEXTLIMIT,
MPFROMLONG( PATH_LEN - 1 ), MPFROMLONG( 0 ) );
WinSendMsg( WinWindowFromID( hwnd, DID_LOG_FILE ), EM_SETTEXTLIMIT,
MPFROMLONG( PATH_LEN - 1 ), MPFROMLONG( 0 ) );
WinSendMsg( WinWindowFromID( hwnd, DID_DISPLAY_PGM ), EM_SETTEXTLIMIT,
MPFROMLONG( PATH_LEN - 1 ), MPFROMLONG( 0 ) );
/* setup temp file path */
WinSetDlgItemText( hwnd, DID_TMP_FILE, globals.tmp_file );
/* setup log file path */
WinSetDlgItemText( hwnd, DID_LOG_FILE, globals.log_file );
/* setup display pgm path */
WinSetDlgItemText( hwnd, DID_DISPLAY_PGM, globals.disp_pgm );
/* setup COM port spin button current value */
portn = (LONG)globals.comport;
tst = (BOOL)WinSendMsg( WinWindowFromID(hwnd, DID_UUPC_COM_PORT),
SPBM_SETCURRENTVALUE, MPFROMLONG( portn ), 0L );
pmassert( hab, tst );
memcpy( &temprof, &globals, sizeof(PROF_INI) );
return (MRESULT)FALSE;
/*----------------------------------------------------------------*/
case WM_CONTROL:
fld = SHORT1FROMMP( mp1 ); /* file resource ID */
act = SHORT2FROMMP( mp1 ); /* event */
switch ( act )
{
case EN_KILLFOCUS:
{ /* verify the current field contents */
WinQueryDlgItemText( hwnd, fld,
PATH_LEN, texta );
if ( texta[0] == '\0' )
break;
switch ( fld )
{
case DID_TMP_FILE:
if ( verify_file( texta ) )
strcpy( temprof.tmp_file, texta );
break;
case DID_LOG_FILE:
if ( verify_file( texta ) )
strcpy( temprof.log_file, texta );
break;
case DID_DISPLAY_PGM:
if ( verify_file( texta ) )
strcpy( temprof.disp_pgm, texta );
break;
default: break;
}
break;
}
}
break;
/*----------------------------------------------------------------*/
case WM_COMMAND:
{
switch (COMMANDMSG(&msg)->cmd)
{
case DID_PROF_OK:
{ /* user accepts profile change */
ULONG fx;
/* pick up spin button value */
fx = 0;
WinSendMsg( WinWindowFromID( hwnd, DID_UUPC_COM_PORT ),
SPBM_QUERYVALUE, MPFROMP(&fx), 0 );
memcpy( &globals, &temprof, sizeof(PROF_INI) );
globals.comport = fx;
/* save the profile */
PrfWriteProfileData( prfinit,
"portwin", "profini", &(globals), sizeof(PROF_INI) );
WinDismissDlg(hwnd, (ULONG)sizeof(PROF_INI) );
return(MRESULT)TRUE;
}
case DID_PROF_CANCEL:
{ /* ignore profile change */
WinDismissDlg(hwnd, FALSE);
return(MRESULT)TRUE;
}
}
break;
}
/*----------------------------------------------------------------*/
case WM_CLOSE:
{
WinDismissDlg(hwnd, FALSE);
return(MRESULT)TRUE;
}
}
return WinDefDlgProc( hwnd, msg, mp1, mp2 );
}
BOOL portwin_profile( void )
{
ULONG lsize;
if ( ( prfinit = PrfOpenProfile( hab, "uucppm.ini" ) ) == (HINI)0L )
{
message( "Unable to open portwin.ini", "Sorry", MB_CANCEL );
return FALSE;
}
/* load .ini data */
PrfQueryProfileSize( prfinit, "portwin", "profini", &lsize );
if ( lsize != sizeof(PROF_INI) ) return FALSE;
PrfQueryProfileSize( prfinit, "portwin", "buttonpos", &lsize );
if ( lsize == sizeof(SWP) )
{ PrfQueryProfileData( prfinit, "portwin", "buttonpos",
&buttonpos, &lsize );
buttonsaved = TRUE;
}
PrfQueryProfileSize( prfinit, "portwin", "spoolpos", &lsize );
if ( lsize == sizeof(SWP) )
{ PrfQueryProfileData( prfinit, "portwin", "spoolpos",
&spoolpos, &lsize );
spoolsaved = TRUE;
}
/* load globals with profile values */
lsize = sizeof(PROF_INI);
PrfQueryProfileData( prfinit, "portwin", "profini", &globals, &lsize );
return TRUE;
}
MRESULT EXPENTRY UUPCbuttonWndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
{
switch( msg )
{
case WM_CREATE:
{
/* If profile is not present schedule dialog */
if (!(portwin_profile()) )
{ /* set default profile data */
strcpy( globals.tmp_file, "C:\\TMP" );
strcpy( globals.tmp_file, getenv( "TMP" ) );
strcpy( globals.log_file, "c:\\uupc\\spool\\rmail.log" );
strcpy( globals.disp_pgm, "c:\\os2\\e.exe" );
globals.comport = 1;
WinPostMsg( hwnd, WM_USER_PROFILE, 0, 0 );
}
else
{
portfree = check_com_port();
}
hwndDlg = WinLoadDlg( HWND_DESKTOP, hwnd, ButtonDlg, NULLHANDLE,
FID_UUPC, NULL );
pmassert( hab, hwndDlg );
return (MRESULT)0;
}
case WM_USER_PROFILE:
{
if ( WinDlgBox( HWND_DESKTOP, hwndBase, prof_init_dlg,
NULLHANDLE, DID_PROF, NULL ) != sizeof(PROF_INI) )
{ WinPostMsg( hwndDlg, WM_CLOSE, 0, 0 );
}
return (MRESULT)TRUE;
}
case WM_USER_ENABLE:
{ /* util thread is ready for work */
WinEnableWindow( hwndDlg, TRUE );
return (MRESULT)TRUE;
}
case WM_USER_DISABLE:
{ /* util thread is ready for work */
WinEnableWindow( hwndDlg, FALSE );
return (MRESULT)TRUE;
}
}
return WinDefWindowProc( hwnd, msg, mp1, mp2 );
}
/* Start here. */
int main (void)
{
ULONG flFrameFlags;
HMQ hmq;
QMSG qmsg;
APIRET retc;
errf = NULL;
portfree = FALSE;
buttonsaved = FALSE;
spoolsaved = FALSE;
/* obtain DosQProcStatus 64k buffer */
retc = DosAllocMem( (PVOID *) &(qprocbuf), 64*1024,
OBJ_TILE | PAG_READ | PAG_WRITE );
if ( retc != 0 )
exit( 0x7A );
/* Initialize Presentation Manager. */
hab = WinInitialize (0);
hmq = WinCreateMsgQueue (hab, 0);
/* Create client window class. */
WinRegisterClass (hab, szUUPCbuttonClass, UUPCbuttonWndProc,
CS_SIZEREDRAW, 0);
/* Create the frame to hold the buttons.
Window is initially invisible. */
flFrameFlags = (FCF_TITLEBAR | FCF_SYSMENU );
/* Create and the frame window. */
hwndBase = WinCreateStdWindow (HWND_DESKTOP, 0,
&flFrameFlags, szUUPCbuttonClass,
"UUPC Status",
0L, 0, 1, NULL);
pmassert( hab, hwndBase );
/* The message loop. */
while (WinGetMsg (hab, &qmsg, 0L, 0, 0))
WinDispatchMsg (hab, &qmsg);
/* Clean up. */
if ( buttonsaved )
{
PrfWriteProfileData( prfinit,
"portwin", "buttonpos", &(buttonpos), sizeof(SWP) );
}
if ( spoolsaved )
{
PrfWriteProfileData( prfinit,
"portwin", "spoolpos", &(spoolpos), sizeof(SWP) );
}
WinDestroyWindow (hwndBase);
WinDestroyMsgQueue (hmq);
WinTerminate (hab);
retc = DosWaitThread( &util_thread, DCWW_WAIT );
if ( errf != NULL ) fclose( errf );
DosFreeMem( qprocbuf );
return retc;
}