435 lines
11 KiB
C
435 lines
11 KiB
C
|
/*
|
|||
|
* 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
|