archie/tcl7.6/win/tclWin16.c

435 lines
11 KiB
C
Raw Normal View History

2024-05-27 16:40:40 +02:00
/*
* tclWin16.c --
*
* This file contains code for a 16-bit DLL to handle 32-to-16 bit
* thunking. This is necessary for the Win32s SynchSpawn() call.
*
* Copyright (c) 1994-1996 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tclWin16.c 1.13 96/09/12 15:10:06
*/
#define STRICT
#include <windows.h>
#include <toolhelp.h>
#include <stdio.h>
#include <string.h>
static int WinSpawn(char *command);
static int DosSpawn(char *command, char *fromFileName,
char *toFileName);
static int WaitForExit(int inst);
static char pifData[545] = {
'\000', '\013', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\200', '\000', '\200', '\000', '\103', '\117', '\115', '\115',
'\101', '\116', '\104', '\056', '\103', '\117', '\115', '\000',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\020', '\000', '\000', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\177', '\001', '\000',
'\377', '\031', '\120', '\000', '\000', '\007', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\340',
'\040', '\115', '\111', '\103', '\122', '\117', '\123', '\117',
'\106', '\124', '\040', '\120', '\111', '\106', '\105', '\130',
'\000', '\207', '\001', '\000', '\000', '\161', '\001', '\127',
'\111', '\116', '\104', '\117', '\127', '\123', '\040', '\063',
'\070', '\066', '\040', '\063', '\056', '\060', '\000', '\005',
'\002', '\235', '\001', '\150', '\000', '\200', '\002', '\200',
'\000', '\144', '\000', '\062', '\000', '\000', '\004', '\000',
'\000', '\000', '\004', '\000', '\000', '\002', '\020', '\002',
'\000', '\037', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000',
'\000', '\000', '\000', '\000', '\000', '\057', '\143', '\040',
'\146', '\157', '\157', '\056', '\142', '\141', '\164', '\000',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\040', '\040', '\040',
'\040', '\040', '\040', '\040', '\040', '\127', '\111', '\116',
'\104', '\117', '\127', '\123', '\040', '\062', '\070', '\066',
'\040', '\063', '\056', '\060', '\000', '\377', '\377', '\033',
'\002', '\006', '\000', '\000', '\000', '\000', '\000', '\000',
'\000'
};
BOOL CALLBACK
LibMain(HINSTANCE hinst, WORD wDS, WORD cbHeap, LPSTR unused)
{
// Nothing to do.
hinst = hinst;
wDS = wDS;
cbHeap = cbHeap;
unused = unused;
return TRUE;
}
int WINAPI
UTProc(buf, func)
void *buf;
DWORD func;
{
char **args;
args = (char **) buf;
if (func == 0) {
return DosSpawn(args[0], args[1], args[2]);
} else {
return WinSpawn(args[0]);
}
}
static int
WinSpawn(command)
char *command;
{
return WaitForExit(WinExec(command, SW_SHOW));
}
/*
*---------------------------------------------------------------------------
*
* Spawn --
*
*---------------------------------------------------------------------------
*/
static int
DosSpawn(command, fromFileName, toFileName)
char *command; /* The name of the program, plus any
* arguments, to be run. */
char *fromFileName; /* Standard input for the program is to be
* redirected from this file, or NULL for no
* standard input. */
char *toFileName; /* Standard output for the program is to be
* redirected to this file, or NULL to
* discard standard output. */
{
int result;
HFILE batFile, pifFile;
char batFileName[144], pifFileName[144];
GetTempFileName(0, "tcl", 0, batFileName);
unlink(batFileName);
strcpy(strrchr(batFileName, '.'), ".bat");
batFile = _lcreat(batFileName, 0);
GetTempFileName(0, "tcl", 0, pifFileName);
unlink(pifFileName);
strcpy(strrchr(pifFileName, '.'), ".pif");
pifFile = _lcreat(pifFileName, 0);
_lwrite(batFile, command, strlen(command));
if (fromFileName == NULL) {
_lwrite(batFile, " < nul", 6);
} else {
_lwrite(batFile, " < ", 3);
_lwrite(batFile, fromFileName, strlen(fromFileName));
}
if (toFileName == NULL) {
_lwrite(batFile, " > nul", 6);
} else {
_lwrite(batFile, " > ", 3);
_lwrite(batFile, toFileName, strlen(toFileName));
}
_lwrite(batFile, "\r\n\032", 3);
_lclose(batFile);
strcpy(pifData + 0x1c8, batFileName);
_lwrite(pifFile, pifData, sizeof(pifData));
_lclose(pifFile);
result = WaitForExit(WinExec(pifFileName, SW_MINIMIZE));
unlink(pifFileName);
unlink(batFileName);
return result;
}
/*
* Results:
* The return value is 1 if the process exited successfully,
* or 0 otherwise.
*
* Side effects:
* None.
*
*---------------------------------------------------------------------------
*/
static int
WaitForExit(inst)
int inst; /* Identifies the instance handle of the
* process to wait for. */
{
TASKENTRY te;
MSG msg;
if (inst < 32) {
return 0;
}
te.dwSize = sizeof(te);
te.hInst = 0;
TaskFirst(&te);
do {
if (te.hInst == (HINSTANCE) inst) {
break;
}
} while (TaskNext(&te) != FALSE);
if (te.hInst != (HINSTANCE) inst) {
return 0;
}
while (1) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
TaskFirst(&te);
do {
if (te.hInst == (HINSTANCE) inst) {
break;
}
} while (TaskNext(&te) != FALSE);
if (te.hInst != (HINSTANCE) inst) {
return 1;
}
}
}
#if 0
#ifndef APIENTRY
#define APIENTRY
#endif
#include <windows.h>
#include <malloc.h>
#include <toolhelp.h>
#ifdef _MSC_VER
#include "tclWinInt.h"
#else
#include "tclWinIn.h"
#endif
typedef DWORD (FAR PASCAL * UT16CBPROC)(LPVOID lpBuff, DWORD dwUserDefined,
LPVOID FAR *lpTranslationList);
HINSTANCE hInstance;
/*
*----------------------------------------------------------------------
*
* LibMain --
*
* DLL entry point
*
* Results:
* Returns 1.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int FAR PASCAL
LibMain(instance, dataSeg, heapSize, cmdLine)
HINSTANCE instance;
WORD dataSeg;
WORD heapSize;
LPSTR cmdLine;
{
hInstance = instance;
return 1;
}
/*
*----------------------------------------------------------------------
*
* UTInit --
*
* Universal Thunk initialization procedure.
*
* Results:
* Always returns 1.
*
* Side effects:
* Sets the universal thunk callback procedure.
*
*----------------------------------------------------------------------
*/
DWORD FAR PASCAL _export
UTInit(callback, buf)
UT16CBPROC callback;
LPVOID buf;
{
return 1; /* Return Success */
}
/*
*----------------------------------------------------------------------
*
* UTProc --
*
* Universal Thunk dispatch routine.
*
* Results:
* 1 on success, 0 or -1 on failure.
*
* Side effects:
* Executes 16-bit code.
*
*----------------------------------------------------------------------
*/
DWORD FAR PASCAL _export
UTProc(buf, func)
LPVOID buf;
DWORD func;
{
char **argv;
argv = (char **) buf;
if (func == 0) {
switch (func) {
case TCLSYNCHSPAWN: {
HINSTANCE inst;
LPCSTR cmdLine;
UINT cmdShow;
MSG msg;
TASKENTRY te;
/* Retrieve the command line arguments stored in buffer */
cmdLine = (LPSTR) ((LPDWORD)buf)[0];
cmdShow = (UINT) ((LPDWORD)buf)[1];
/* Start the application with WinExec() */
inst = WinExec(cmdLine, cmdShow);
if ((int) inst < 32) {
return 0;
}
/* Loop until the application is terminated. The Toolhelp API
* ModuleFindHandle() returns NULL when the application is
* terminated. NOTE: PeekMessage() is used to yield the
* processor; otherwise, nothing else could execute on the
* system.
*/
te.dwSize = sizeof(TASKENTRY);
TaskFirst(&te);
do {
if (te.hInst == inst) {
break;
}
} while (TaskNext(&te));
if (te.hInst == inst) {
while (1) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
TaskFirst(&te);
do {
if (te.hInst == inst) {
break;
}
} while (TaskNext(&te));
if (te.hInst != inst) {
break;
}
}
}
return 1;
}
}
return (DWORD)-1L; /* We should never get here. */
}
/*
*----------------------------------------------------------------------
*
* _WEP --
*
* Windows exit procedure
*
* Results:
* Always returns 1.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int FAR PASCAL
_WEP(dummy)
int dummy;
{
return 1;
}
#endif