/* --- Copyright University of Sussex 1998. All rights reserved. ----------
 * File:			C.win32/extern/src/popcore.h
 * Purpose:			Header file for Poplog --> Win32 interface
 * Author:			Robert John Duncan, Jun 14 1994 (see revisions)
 * Documentation:
 * Related Files:
 */

#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>

#ifdef __NUTC__
#include <unistd.h>
#include <nutc.h>
#include <winnutc.h>
#define ExitProcess		_exit
#endif
#define GET_ERRNO 		errno
#define SET_ERRNO(n)	(errno = (n))

typedef struct _POP_AST
{
	DWORD	type;
	DWORD	data;
} POP_AST;
	/* ASynchronous Trap */

#define POP_AST_SIGNAL      0	/* Unix-style signal */
#define POP_AST_TIMER       1	/* timer */
#define POP_AST_APP_PENDING 2	/* events pending for Xt appcontext */
#define POP_AST_QUEUE_CHECK 3	/* dummy to check AST queue */
#define POP_AST_HANDLE		4	/* Win32 HANDLE signaled */
#define POP_AST_DEV         5	/* condition on device */
	/* AST types (cf. "signals.ph") */

#define POP_SIG_HUP		1
#define POP_SIG_INT		2
#define POP_SIG_QUIT	3
#define POP_SIG_ILL		4
#define POP_SIG_EXN		5
#define POP_SIG_CHLD	6
#define POP_SIG_ALRM	7
#define POP_SIG_FPE		8
#define POP_SIG_BUS		10
#define POP_SIG_SEGV	11
#define POP_SIG_TERM	15
	/* signal numbers for AST_SIGNAL, cf. "sigdefs.ph" */

typedef struct _POP_SIGNAL_CONTEXT /* psc */
{
	DWORD	SignalNumber;
	DWORD	ExceptionCode;
	PVOID	ExceptionAddress;
	PVOID	FaultAddress;
	DWORD	ReadWriteFlag;
} POP_SIGNAL_CONTEXT;
	/* same as struct PSC in "signal.p" */

#define POP_EXCEPTION(n) (0xefefbe60|(n))

#define POP_EXCEPTION_INIT_FAILED	POP_EXCEPTION(1)
	/* indicates some initialisation step failed */

typedef struct _POP_FILE {	/* pf */
	HANDLE	handle;			/* file handle */
	DWORD	flags;			/* status flags */
	DWORD	error;			/* last error code */
	void*	encoding;		/* character encoding */
	UINT	istate;			/* input (decode) state */
	UINT	ostate;			/* output (encode) state */
	DWORD	timeout;		/* timeout in milliseconds */
	BYTE*	buffer;			/* I/O buffer */
	DWORD	size;			/* buffer size */
	DWORD	nbytes;			/* chars in the buffer */
	BYTE*	ptr;			/* file pointer */
	HANDLE	thread;			/* I/O thread */
	HANDLE	io_todo;		/* I/O ready event */
	HANDLE	io_done;		/* I/O completed event */
	HANDLE	io_wait[2];		/* I/O wait events */
	OVERLAPPED*
			overlapped;		/* overlapped I/O structure */
} POP_FILE;

enum {
	/* File types */
	POP_FILE_TYPE_OTHER	   = 0,	/* unknown */
	POP_FILE_TYPE_DISK	   = 1,	/* disk file */
	POP_FILE_TYPE_CHAR	   = 2,	/* comms, printer, etc. */
	POP_FILE_TYPE_PIPE	   = 3,	/* named or anonymous pipe */
	POP_FILE_TYPE_CONSOLE  = 4,	/* console input or screen buffer */

	/* I/O modes */
	POP_FILE_MODE_TEXT	= 0x01,	/* convert NL <--> CR/NL */
	POP_FILE_MODE_LINE	= 0x02,	/* stop at NL */
	POP_FILE_MODE_RAW	= 0x04,	/* raw mode (console only) */
	POP_FILE_MODE_16BIT	= 0x08,	/* 16-bit (Unicode) output */

	/* POP_FILE flags */
	POP_FILE_READY		= 0x01,	/* initialised */
	POP_FILE_OUTPUT		= 0x02,	/* set for output */
	POP_FILE_READING	= 0x04,	/* read in progress */
	POP_FILE_WRITING	= 0x08,	/* write in progress */
	POP_FILE_INTERRUPT	= 0x10,	/* operation interrupted */
	POP_FILE_TIMEOUT	= 0x20,	/* operation timed out */
	POP_FILE_ERROR		= 0x40,	/* operation failed */

	POP_FILE_INPUT_READY  = POP_FILE_READY,
	POP_FILE_OUTPUT_READY = POP_FILE_OUTPUT|POP_FILE_READY,

	/* Character signalling EOF in TEXT mode */
	POP_FILE_EOF_CHAR	= '\x1a',	/* ^Z */
};

#define POP_M_PROT_NONE		0x0
#define POP_M_PROT_EXEC		0x1
#define POP_M_PROT_WRITE	0x2
#define POP_M_PROT_READ		0x4
#define POP_M_PROT_ALL		0x7
	/* bit masks for memory protection */

typedef struct _POP_PROCESS_INFO
{
	DWORD	dwProcessId;
	HANDLE	hProcess;
	HANDLE	hThread;
	HANDLE	hStdInput;
	HANDLE	hStdOutput;
	HANDLE	hStdError;
} POP_PROCESS_INFO;
	/* params/results for process creation */

#define POP_TIME_ERROR (DWORD)-1
#define POP_MAX_HANDLES	32


extern DWORD _pop_signals_pending;
	/* Poplog _trap flag defined in "initial.p" */

extern void __pop_errsig(void);
	/* system error routine defined in "asignals.s" */

extern int (*_WEAK_pop_external_callback)(void *);
	/* weak reference to _external_callback_func defined in "asignals.s" */

extern int pop_main(void);
	/* entry point to Poplog defined in "amain.s" */

extern HANDLE pop_ast_queue_non_empty;

extern void _pop_add_ast(DWORD type, DWORD data);
extern BOOL _pop_rem_ast(DWORD *type, DWORD *data);
extern void _pop_timer_trap(DWORD ident);
extern void pop_signal(DWORD);
extern void pause_popintr(void);
extern void pop_init_ast(void);
	/* from "ast.c" */

extern void pop_init_console(void);
	/* from "console.c" */

extern BOOL pop_init_registry(
	LPCTSTR company,
	LPCTSTR product,
	LPCTSTR version);
extern BOOL pop_get_registry_value(
	LPCTSTR key_name,
	LPCTSTR value_name,
	DWORD flags,
	DWORD* type,
	BYTE data[],
	DWORD* len);
extern BOOL pop_set_registry_value(
	LPCTSTR key_name,
	LPCTSTR value_name,
	DWORD flags,
	DWORD type,
	const BYTE data[],
	DWORD len);
BOOL pop_delete_registry_value(
	LPCTSTR key_name,
	LPCTSTR value_name,
	DWORD flags);
extern DWORD pop_get_environment_variable(
	LPCTSTR var,
	LPTSTR value,
	DWORD nchars);
extern BOOL pop_set_environment_variable(
	LPCTSTR var,
	LPCTSTR value);
extern DWORD pop_expand_environment_strings(
	LPCTSTR string,
	LPTSTR value,
	DWORD nchars);
extern void pop_init_environment(const TCHAR** env);
	/* from "environment.c" */

extern POP_SIGNAL_CONTEXT __pop_sigcontext;
extern DWORD __pop_fpe_handler;

extern LONG pop_exception_filter(LPEXCEPTION_POINTERS exp);
	/* from "exception.c" */

extern int __pop_in_user_extern;

extern HINSTANCE pop_load_library(TCHAR *name);
extern BOOL pop_free_library(HINSTANCE handle);
extern FARPROC pop_get_proc_address(HINSTANCE handle, LPCSTR symbol);
extern DWORD _pop_exfunc_callback(DWORD arg, ...);
	/* from "external.c" */

extern HANDLE pop_get_console_handle(BOOL output);
extern HANDLE pop_get_std_handle(DWORD fd, BOOL create);
extern BOOL pop_set_std_handle(DWORD fd, HANDLE handle);
extern HANDLE pop_create_file(
		TCHAR *name,
		DWORD access,
		DWORD share,
		LPSECURITY_ATTRIBUTES security,
		DWORD create,
		DWORD attributes,
		HANDLE tmplate);
extern BOOL pop_create_pipe(HANDLE *ihandle, HANDLE *ohandle);
extern DWORD pop_get_file_size(HANDLE handle, DWORD *size_hi);
extern DWORD pop_get_file_attributes(TCHAR *path);
extern DWORD pop_get_file_type(HANDLE handle);
extern DWORD pop_get_file_time(HANDLE handle);
extern BOOL pop_get_file_id(
		HANDLE handle,
		DWORD *volume,
		DWORD *index_hi,
		DWORD *index_lo);
extern DWORD pop_get_full_pathname(TCHAR *file, TCHAR *buffer, DWORD len);
extern DWORD pop_get_current_directory(TCHAR *buffer, DWORD len);
extern BOOL pop_set_current_directory(TCHAR *path);
extern DWORD pop_start_file_search(
		TCHAR *pattern,
		TCHAR *buffer,
		DWORD len,
		DWORD *attrs,
		HANDLE *handle);
extern DWORD pop_file_search(
		HANDLE handle,
		TCHAR *buffer,
		DWORD len,
		DWORD *attrs);
extern BOOL pop_end_file_search(HANDLE handle);
extern BOOL pop_move_file(TCHAR *from_name, TCHAR *to_name, BOOL replace_existing);
extern BOOL pop_copy_file(TCHAR *from_name, TCHAR *to_name, BOOL replace_existing);
extern BOOL pop_delete_file(TCHAR *name);
	/* from "file.c" */

extern BOOL pop_add_async_object(HANDLE obj);
extern BOOL pop_close_handle(HANDLE handle);
extern BOOL pop_rem_async_object(HANDLE obj);
extern int pop_wait_for_objects(DWORD n, HANDLE *hndv[], DWORD timeout);
	/* from "handle.c" */

extern HANDLE pop_in_console_read;
extern POP_FILE* pop_file_create(HANDLE* handle, BOOL overlapped);
extern BOOL pop_file_flush(POP_FILE* pf);
extern BOOL pop_file_close(POP_FILE* pf);
extern DWORD pop_file_seek(POP_FILE* pf, LONG nbytes, DWORD method);
extern int pop_file_test_input(POP_FILE* pf);
extern void pop_file_clear_input(POP_FILE* pf);
extern DWORD pop_file_read(POP_FILE* pf, BYTE* addr, DWORD nbytes);
extern DWORD pop_file_special_read(POP_FILE* pf, BYTE* addr, DWORD nbytes,
								   DWORD mode, int timeout);
extern DWORD pop_file_console_read(POP_FILE* pf, BYTE* addr, DWORD nbytes,
								   DWORD mode, int timeout, TCHAR* prompt);
extern DWORD pop_file_write(POP_FILE* pf, BYTE* addr, DWORD nbytes, DWORD mode);
extern DWORD pop_file_special_write(POP_FILE* pf, BYTE* addr, DWORD nbytes,
									DWORD mode, int timeout);
extern DWORD pop_file_console_write(POP_FILE* pf, BYTE* addr, DWORD nbytes,
									DWORD mode, int timeout);
extern BOOL pop_file_start_overlapped_read(POP_FILE* pf);
extern HANDLE pop_file_is_overlapped(POP_FILE* pf);
	/* from "io.c" */

extern DWORD __pop_nr_seg[];
extern DWORD __pop_nr_seg_nbytes;

extern void pop_init_heap(void);
extern void *pop_alloc(DWORD nbytes);
extern void *pop_realloc(void *ptr, DWORD nbytes);
extern BOOL pop_free(void *ptr);
extern BYTE *pop_get_heap_ptr(void);
extern BYTE *pop_set_heap_ptr(BYTE *hi, BYTE *lo);
extern PVOID pop_get_callstack_base(void);
extern BOOL pop_virtual_protect(BYTE *base, BYTE *limit, DWORD prot);
extern BOOL pop_has_read_access(VOID *address);
	/* from "memory.c" */

extern DWORD pop_get_last_error();
extern DWORD pop_get_oem_id(void);
extern DWORD pop_get_computer_name(TCHAR *buffer, DWORD len);
extern DWORD pop_get_user_name(TCHAR *buffer, DWORD len);
extern DWORD pop_get_current_process_id(void);
extern TCHAR *pop_get_command_line(void);
	/* from "misc.c" */

extern BOOL pop_get_exit_code_process(HANDLE proc, DWORD* status);
extern BOOL pop_create_process(
		TCHAR *path,
		TCHAR *command_line,
		DWORD flags,
		BOOL useStdHandles,
		POP_PROCESS_INFO *proc
	);
extern BOOL pop_terminate_process(HANDLE proc);
extern BOOL pop_close_process_windows(HANDLE proc, DWORD pid);
extern DWORD pop_suspend_thread(HANDLE thread);
extern DWORD pop_resume_thread(HANDLE thread);
	/* from "process.c" */

OSVERSIONINFO pop_os_version_info;
extern void pop_init(void);
extern BOOL pop_start(BOOL bMainThread, UINT* exitCode);
extern void pop_exit(UINT exitCode);
	/* from "start.c" */

extern DWORD pop_counter_start(void);
extern DWORD pop_counter_diff(DWORD *count);
extern DWORD pop_get_process_time(void);
extern DWORD pop_get_real_time(DWORD *usecs);
extern DWORD pop_convert_date(BOOL local, DWORD time, TCHAR *buffer, DWORD len);
extern void pop_sleep(DWORD millisecs);
	/* from "time.c" */

extern DWORD pop_time_from_file_time(DWORD *popTime, FILETIME *fileTime);
extern void pop_time_to_file_time(DWORD popTime, FILETIME *fileTime);
extern DWORD pop_sum_process_times(FILETIME *kernelTime, FILETIME *userTime);
	/* from "util.asm" */


/* --- Revision History ---------------------------------------------------
--- Robert Duncan, Aug 11 1998
		Changes for NuTCRACKER 4.0
--- Robert Duncan, Apr  3 1997
		New overlapped I/O functions from "io.c"
--- Robert Duncan, Feb 27 1997
		Changes for device encoding
--- Robert Duncan, Jan 24 1997
		Corrections for UNICODE compilation
--- Robert Duncan, Jul 24 1996
		New registry functions from "environment.c"
--- Robert Duncan, Jun  4 1996
		New initialisation stuff in "start.c"
--- Robert Duncan, May 24 1996
		Additions for "handle.c" plus new process stuff
--- Robert Duncan, May 14 1996
		Added special case for Win32 + NuTCRACKER
--- Robert Duncan, Mar 29 1996
		Extra declarations for improved console control-handling
--- Robert John Duncan, Feb  7 1996
		Added pop_start/pop_exit from new "start.c".
--- Robert John Duncan, Jan  8 1996
		Added new FILE stuff from "io.c" in place of the previous device
		interface. Other minor mods from "console.c" and "file.c".
--- Robert John Duncan, Sep 13 1995
		Change to type of _pop_signals_pending
 */
