newlisp/win-util.c

297 lines
6.6 KiB
C

/*
win-util.c, utitity routines for native windows port of newLISP
Copyright (C) 2016 Lutz Mueller
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "newlisp.h"
#include "protos.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#define WIN32_LEAN_AND_MEAN /* exclude rarely-used windows headers */
#include <windows.h>
#include <io.h>
#include <process.h>
/* from newlisp.c */
int init_argv(char * ptr, char *argv[]);
void * callocMemory(size_t nbytes);
WINBASEAPI DWORD WINAPI GetProcessId(HANDLE);
/*
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;
*/
/* kill for MinGW
by Shigeru Kobayashi for v10.4.5
to be used by p_destroyProcess()
see also changes in plainProcess() and winPipedProcess() below
*/
int kill(pid_t pid, int sig)
{
int ret;
HANDLE h;
h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (h == NULL) return -1;
ret = TerminateProcess(h, 0) ? 0 : -1;
CloseHandle(h);
return ret;
}
/* ---------------------------- pipes -------------------------------------- */
UINT plainProcess(char * command, size_t len)
{
char * cPtr;
char * argv[16];
HANDLE hProc;
DWORD pid;
cPtr = callocMemory(len + 1);
memcpy(cPtr, command, len + 1);
init_argv(cPtr, argv);
hProc = (HANDLE)_spawnvp(P_NOWAIT, argv[0], (const char * const *)argv);
free(cPtr);
if(hProc == INVALID_HANDLE_VALUE) return(0);
pid = GetProcessId(hProc);
CloseHandle(hProc);
return(pid);
}
UINT winPipedProcess(char * cmd, int inpipe, int outpipe, int option)
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION process;
int result;
HANDLE fin, fout;
UINT pid;
if(inpipe == -1 && outpipe == -1)
{
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.wShowWindow = option;
memset(&process, 0, sizeof(process));
}
else
{
/* GetStartupInfo(&si); */
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = option; /* SW_SHOW, SW_HIDE get additional user option in Win32 versions */
fin = (HANDLE)_get_osfhandle(inpipe);
fout = (HANDLE)_get_osfhandle(outpipe);
si.hStdInput = (inpipe) ? fin : GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = (outpipe) ? fout : GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = (outpipe) ? fout : GetStdHandle(STD_OUTPUT_HANDLE);
}
if((result = CreateProcess(NULL,cmd,NULL,NULL,TRUE,DETACHED_PROCESS,NULL,NULL,&si, &process)) == 0)
return(0);
pid = GetProcessId(process.hProcess);
CloseHandle(process.hProcess);
return(pid);
}
int winPipe(UINT * inpipe, UINT * outpipe)
{
SECURITY_ATTRIBUTES sa = { 0 };
HANDLE pipe_r, pipe_w;
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
if(!CreatePipe(&pipe_r, &pipe_w, &sa, 0))
return(0);
*inpipe = _open_osfhandle((intptr_t) pipe_r, 0);
*outpipe = _open_osfhandle((intptr_t) pipe_w, 0);
return(1);
}
/* ---------------------------------- semaphores ---------------------------- */
UINT winCreateSemaphore(void)
{
SECURITY_ATTRIBUTES security = { 0 };
HANDLE hSemaphore;
security.nLength = sizeof(security);
security.bInheritHandle = TRUE;
security.lpSecurityDescriptor = NULL; /* default of caller */
hSemaphore = CreateSemaphore(&security, 0, 65536, NULL);
return((UINT)hSemaphore);
}
UINT winWaitSemaphore(UINT hSemaphore)
{
DWORD dwWaitResult;
dwWaitResult = WaitForSingleObject((HANDLE)hSemaphore, INFINITE);
if(dwWaitResult == WAIT_FAILED)
return(FALSE);
return(TRUE);
}
UINT winSignalSemaphore(UINT hSemaphore, int count)
{
return(ReleaseSemaphore((HANDLE)hSemaphore, count, NULL));
}
int winDeleteSemaphore(UINT hSemaphore)
{
return (CloseHandle((HANDLE)hSemaphore));
}
/*
See: http://www.codeguru.com/Cpp/W-P/win32/article.php/c1423/
QuerySemaphore() call
int winGetSemaphoreCount(UINT hSemaphore) {}
*/
/* ---------------------------- shared memory interface -------------------- */
UINT winSharedMemory(int size)
{
SECURITY_ATTRIBUTES sa = { 0 };
HANDLE hMemory;
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL; /* default of caller */
hMemory = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, size, NULL);
return((UINT)hMemory);
}
UINT * winMapView(UINT hMemory, int size)
{
return((UINT *)MapViewOfFile((HANDLE)hMemory, FILE_MAP_WRITE, 0, 0, size));
}
/* ---------------------------- timer -------------------------------------- */
extern SYMBOL * timerEvent;
extern int milliSecTime(void);
extern CELL * getCreateSymbol(CELL * params, SYMBOL * * symbol, char * name);
/*
UINT_PTR SetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
BOOL KillTimer(HWND hWnd, UINT_PTR uIDEvent);
*/
void timerFunc(void * dummy);
int timerDuration = 0;
int rollover = 0;
int start;
CELL * p_timerEvent(CELL * params)
{
CELL * symCell;
double seconds;
int now;
if(params != nilCell)
{
params = getCreateSymbol(params, &timerEvent, "$timer");
if(params != nilCell)
{
getFloat(params, &seconds);
timerDuration = 1000 * seconds;
if(timerDuration > 0)
{
start = milliSecTime();
_beginthread(timerFunc, 0, 0);
seconds = timerDuration/1000.0;
}
}
else
{
/* return the elapsed time */
seconds = ((now = milliSecTime()) < start ?
86400000 - start + now :
now - start)/1000.0;
}
return(stuffFloat(seconds));
}
symCell = getCell(CELL_SYMBOL);
symCell->contents = (UINT)timerEvent;
return(symCell);
}
void timerFunc(void * dummy)
{
if(timerDuration == 0) return;
/* take care of midnight rollover */
if((rollover = start + timerDuration - 86400000) > 0)
{
while(milliSecTime() > start) mySleep(10); /* wait for rollover */
while(milliSecTime() < rollover) mySleep(10);
}
else
while( milliSecTime() < (start + timerDuration) ) mySleep(10);
if(recursionCount)
traceFlag |= TRACE_TIMER;
else /* if idle */
executeSymbol(timerEvent, NULL, NULL);
}
extern STREAM errorStream;
/* eof */