1 /*
2  * Include file for WIN32_NATIVE version of CLISP
3  * Bruno Haible 1997-2008, 2017
4  * Sam Steingold 1999-2011, 2017
5  */
6 
7 /* control characters constants */
8 
9 #define BEL  7                  /* bell */
10 /* define NL  10             -- new line, see LISPBIBL.D */
11 #define RUBOUT 127              /* Rubout = Delete */
12 #define CRLFstring  "\r\n"      /* C-String - CR/LF */
13 
14 /* Declaration of operating system functions */
15 #define WIN32_LEAN_AND_MEAN  /* avoid including junk */
16 #undef unused /* `unused' is used in function declarations. */
17 #ifdef __MINGW32__
18   #define ULONGLONG OS_ULONGLONG
19   #define ULONG OS_ULONG
20   #include <windows.h>
21   #undef ULONG
22   #undef ULONGLONG
23   #define unused_void (void)
24 #else
25   #include <windows.h>
26   #define unused_void
27 #endif
28 
29 /* Shell object handling for shell link resolution */
30 #include <objbase.h>
31 #include <shlobj.h>
32 
33 /* ShellExecute declaration */
34 #include <shellapi.h>
35 #define unused unused_void      /* restore the unused declaration */
36 
37 /* NtQueryInformationFile http://msdn.microsoft.com/en-us/library/ff567052.aspx
38    It uses IO_STATUS_BLOCK http://msdn.microsoft.com/en-us/library/ff567052.aspx
39    which uses NTSTATUS https://msdn.microsoft.com/en-us/library/ff565436.aspx */
40 #include <winternl.h>
41 #include <ntstatus.h>
42 
43 /* Table of system error messages */
44 #include <winerror.h>
45 /* extern DWORD GetLastError (void);
46    extern void SetLastError (DWORD ErrCode);
47    extern DWORD FormatMessage (DWORD Flags, LPCVOID Source, DWORD MessageId, DWORD LanguageId, LPTSTR Buffer, DWORD Size, va_list* Arguments);
48    extern int WSAGetLastError (void); */
49 #define OS_errno GetLastError()
50 #define OS_set_errno(e) SetLastError(e)
51 /* used by error.d, spvw.d, stream.d, pathname.d, socket.d */
52 
53 #define HAVE_STRERROR 1
54 /* used by errunix.d */
55 
56 /* Getting memory. */
57 #include <malloc.h>
58 extern void* malloc (size_t size);
59 extern void free (void* memblock);
60 /* used by spvw.d */
61 
62 /* Abrupt program termination */
63 /* win32aux.d overwrites abort() */
64 extern _Noreturn void abort (void);
65 /* used by spvw.d, debug.d, eval.d, io.d */
66 
67 /* Type of a file handle */
68 #define Handle  HANDLE
69 #define INVALID_HANDLE  INVALID_HANDLE_VALUE
70 #define FOREIGN_HANDLE          /* box them */
71 
72 /* File handles of standard input, standard output, standard error */
73 extern Handle stdin_handle;
74 extern Handle stdout_handle;  /* see win32aux.d */
75 extern Handle stderr_handle;
76 extern void init_win32 (void);
77 extern void done_win32 (void);
78 /* used by spvw.d, stream.d */
79 
80 /* Signal handling
81    extern BOOL SetConsoleCtrlHandler (BOOL (*) (DWORD CtrlType), BOOL add);
82    extern HANDLE CreateEvent (SECURITY_ATTRIBUTES* EventAttributes, BOOL ManualReset, BOOL InitialState, LPCTSTR Name);
83    extern BOOL PulseEvent (HANDLE Event);
84    extern HANDLE CreateThread (SECURITY_ATTRIBUTES* ThreadAttributes, DWORD StackSize, THREAD_START_ROUTINE* StartAddress, void* Parameter, DWORD CreationFlags, DWORD* ThreadId);
85    extern DWORD WaitForSingleObject (HANDLE Handle, DWORD Milliseconds);
86    extern DWORD WaitForMultipleObjects (DWORD Count, CONST HANDLE * Handles, BOOL WaitAll, DWORD Milliseconds);
87    extern BOOL TerminateThread (HANDLE Thread, DWORD ExitCode);
88    extern BOOL GetExitCodeThread (HANDLE Thread, DWORD* ExitCode);
89    extern DWORD SuspendThread (HANDLE Thread);
90    extern DWORD ResumeThread (HANDLE Thread);
91    extern BOOL GetThreadContext (HANDLE Thread, LPCONTEXT Context);
92    extern BOOL SetThreadContext (HANDLE Thread, CONST CONTEXT * Context);
93    extern HANDLE GetCurrentProcess (void);
94    extern HANDLE GetCurrentThread (void);
95    extern BOOL DuplicateHandle (HANDLE SourceProcessHandle, HANDLE SourceHandle, HANDLE TargetProcessHandle, LPHANDLE TargetHandle, DWORD DesiredAccess, BOOL InheritHandle, DWORD Options);
96  used by win32aux.d
97    This is the Ctrl-C handler. It is executed in the main thread and must
98    not return! */
99 extern void interrupt_handler (void);
100 /* Install our intelligent Ctrl-C handler.
101    This should be called only once, and only from the main thread. */
102 extern void install_sigint_handler (void);
103 /* used by spvw.d */
104 
105 /* Locale definition function */
106 extern_C char *setlocale (int category, const char *locale);
107 /* used by spvw_ctype.d */
108 
109 /* Character set conversion
110    extern BOOL CharToOem (LPCTSTR Str, LPSTR Dst);
111    extern BOOL OemToChar (LPCTSTR Str, LPSTR Dst);
112  used by win32aux.d */
113 
114 /* Set working directory
115    extern BOOL SetCurrentDirectory (LPCTSTR PathName);
116  used by pathname.d */
117 
118 /* Retrieve working directory
119    extern DWORD GetCurrentDirectory (DWORD BufferLength, LPTSTR Buffer);
120    extern DWORD GetFullPathName (LPCTSTR FileName, DWORD BufferLength, LPTSTR Buffer, LPTSTR* FilePart);
121    The actual value of _MAX_PATH is irrelevant, because we retry the calls to
122    GetCurrentDirectory() and GetFullPathName() if the buffer is too small. */
123 #ifndef _MAX_PATH
124   #define _MAX_PATH 1024
125 #endif
126 #ifndef MAXPATHLEN
127   #define MAXPATHLEN _MAX_PATH
128 #endif
129 /* used by pathname.d */
130 
131 /* Retrieve information about a file
132    extern DWORD GetLogicalDrives (void); // broken!
133    extern UINT GetDriveType (LPCTSTR RootPathName);
134    extern DWORD GetFileAttributes (LPCTSTR FileName);
135    extern DWORD GetFileType (HANDLE File);
136    extern DWORD GetFileSize (HANDLE File, LPDWORD FileSizeHigh);
137    extern BOOL GetFileInformationByHandle (HANDLE File, BY_HANDLE_FILE_INFORMATION* FileInformation);
138  used by pathname.d, stream.d */
139 
140 struct file_id {        /* Unique ID for an open file on this machine */
141   DWORD nFileIndexHigh;
142   DWORD nFileIndexLow;
143 };
144 typedef DWORD os_error_code_t;
145 /* fill FI for an exiting namestring */
146 extern os_error_code_t namestring_file_id(char *namestring,struct file_id *fi);
147 /* fill FI for an existing file handle */
148 extern os_error_code_t handle_file_id (HANDLE fh, struct file_id *fi);
149 /* if the file IDs are identical, return 1, otherwise return 0 */
150 extern int file_id_eq (struct file_id *fi1, struct file_id *fi2);
151 
152 /* Delete a file
153    extern BOOL DeleteFile (LPCTSTR FileName);
154  used by pathname.d */
155 
156 /* Rename a file
157    extern BOOL MoveFile (LPCTSTR ExistingFileName, LPCTSTR NewFileName);
158  used by pathname.d */
159 
160 /* Directory search
161    extern HANDLE FindFirstFile (LPCTSTR FileName, LPWIN32_FIND_DATA FindFileData);
162    extern BOOL FindNextFile (HANDLE FindFile, LPWIN32_FIND_DATA FindFileData);
163    extern BOOL FindClose (HANDLE FindFile);
164  used by pathname.d */
165 
166 /* Create a directory
167    extern BOOL CreateDirectory (LPCTSTR PathName, SECURITY_ATTRIBUTES* SecurityAttributes);
168  used by pathname.d */
169 
170 /* Delete a directory
171    extern BOOL RemoveDirectory (LPCTSTR PathName);
172  used by pathname.d */
173 
174 /* Working with open files
175    extern HANDLE CreateFile (LPCTSTR FileName, DWORD DesiredAccess, DWORD ShareMode, SECURITY_ATTRIBUTES* SecurityAttributes, DWORD CreationDistribution, DWORD FlagsAndAttributes, HANDLE TemplateFile);
176    extern HANDLE GetStdHandle (DWORD StdHandle);
177    extern DWORD GetFileSize (HANDLE File, LPDWORD FileSizeHigh);
178    extern DWORD SetFilePointer (HANDLE File, LONG DistanceToMove, LONG* DistanceToMoveHigh, DWORD MoveMethod);
179    extern BOOL ReadFile (HANDLE File, void* Buffer, DWORD BytesToRead, DWORD* BytesRead, OVERLAPPED* Overlapped);
180    extern BOOL WriteFile (HANDLE File, const void* Buffer, DWORD BytesToWrite, DWORD* BytesWritten, OVERLAPPED* Overlapped);
181    extern BOOL GetConsoleMode (HANDLE ConsoleHandle, LPDWORD Mode);
182    extern BOOL ReadConsole (HANDLE ConsoleInput, void* Buffer, DWORD BytesToRead, DWORD* BytesRead, void* Reserved);
183    extern BOOL GetNumberOfConsoleInputEvents (HANDLE ConsoleInput, LPDWORD NumberOfEvents);
184    extern BOOL PeekConsoleInput (HANDLE ConsoleInput, PINPUT_RECORD Buffer, DWORD Length, LPDWORD NumberOfEventsRead);
185    extern BOOL ReadConsoleInput (HANDLE ConsoleInput, PINPUT_RECORD Buffer, DWORD Length, LPDWORD NumberOfEventsRead);
186    extern BOOL WriteConsoleInput (HANDLE ConsoleInput, CONST INPUT_RECORD * Buffer, DWORD Length, LPDWORD NumberOfEventsWritten);
187    extern BOOL WriteConsole (HANDLE ConsoleOutput, const void* Buffer, DWORD BytesToWrite, DWORD* BytesWritten, void* Reserved);
188    extern HANDLE CreateEvent (SECURITY_ATTRIBUTES* EventAttributes, BOOL ManualReset, BOOL InitialState, LPCTSTR Name);
189    extern BOOL ResetEvent (HANDLE Event);
190    extern BOOL GetOverlappedResult (HANDLE File, OVERLAPPED* Overlapped, DWORD* NumberOfBytesTransferred, BOOL Wait);
191    extern BOOL CloseHandle (HANDLE Object);
192    //extern BOOL DuplicateHandle (HANDLE SourceProcessHandle, HANDLE SourceHandle, HANDLE TargetProcessHandle, HANDLE* TargetHandle, DWORD DesiredAccess, BOOL InheritHandle, DWORD Options);
193    //extern BOOL FlushFileBuffers (HANDLE File);
194    extern BOOL PeekNamedPipe (HANDLE NamedPipe, void* Buffer, DWORD BufferSize, DWORD* BytesRead, DWORD* TotalBytesAvail, DWORD* BytesLeftThisMessage);
195    extern BOOL PurgeComm (HANDLE File, DWORD Flags);
196    extern BOOL FlushConsoleInputBuffer (HANDLE ConsoleInput); */
197 #define uAsciiChar uChar.AsciiChar
198 /* used by spvw.d, stream.d, pathname.d, win32aux.d
199    My private error code when Ctrl-C has been pressed. */
200 #define ERROR_SIGINT ERROR_SUCCESS
201 /* Like ReadConsoleInput with Length==1, but is interruptible by Ctrl-C. */
202 extern BOOL ReadConsoleInput1 (HANDLE ConsoleInput, PINPUT_RECORD Buffer, LPDWORD NumberOfEventsRead);
203 /* The following functions deal with all kinds of file/pipe/console handles */
204 extern int fd_read_wont_hang_p (HANDLE fd);
205 #ifdef MICROSOFT
206 typedef long ssize_t;
207 #endif
208 extern ssize_t fd_read (HANDLE fd, void* buf, size_t nbyte, perseverance_t persev);
209 extern ssize_t fd_write (HANDLE fd, const void* buf, size_t nbyte, perseverance_t persev);
210 #define safe_read(fd,buf,nbyte)  fd_read(fd,buf,nbyte,persev_partial)
211 #define full_read(fd,buf,nbyte)  fd_read(fd,buf,nbyte,persev_full)
212 #define safe_write(fd,buf,nbyte)  fd_write(fd,buf,nbyte,persev_partial)
213 #define full_write(fd,buf,nbyte)  fd_write(fd,buf,nbyte,persev_full)
214 /* Changing the position within a file. */
215 /* _off_t is sint32, but the Win32 APIs support 64-bit file offsets. */
216 #define off_t  sint64
217 #undef SIZEOF_OFF_T  /* on mingw, it was defined in config.h */
218 #define SIZEOF_OFF_T  8
219 #ifdef __MINGW32__
220   #include <io.h>
221   #undef lseek
222   #define lseek clisp_lseek /* avoid collision with prototype in <mingw/io.h> */
223 #endif
224 extern off_t lseek (HANDLE fd, off_t offset, DWORD mode);
225 #undef SEEK_SET
226 #undef SEEK_CUR
227 #undef SEEK_END
228 #define SEEK_SET  FILE_BEGIN
229 #define SEEK_CUR  FILE_CURRENT
230 #define SEEK_END  FILE_END
231 /* used by spvw.d, stream.d */
232 
233 /* Socket connections */
234 #ifdef __MINGW32__
235 /* this kills a warning in </usr/include/w32api/winsock.h>
236  and </usr/include/w32api/winsock2.h>:
237  "fd_set and associated macros have been defined in sys/types.
238   This may cause runtime problems with W32 sockets"
239  Bruno said:
240  I think this warning means that read(), write() don't work on sockets
241  in mingw32.  Like on BeOS.  CLISP already handles this.
242  See the #ifs around stream.d:low_write_unbuffered_socket() etc. */
243 #define USE_SYS_TYPES_FD_SET
244 #endif
245 
246 #include <winsock2.h>
247 #include <ws2tcpip.h>
248 
249 #ifdef __MINGW32__
250 #undef USE_SYS_TYPES_FD_SET
251 #endif
252 /* extern int WSAStartup (WORD VersionRequested, WSADATA* WSAData);
253    extern int WSAGetLastError (void);
254    extern void WSASetLastError (int Error);
255    extern int WSACancelBlockingCall (void); */
256 #ifndef socklen_t
257 #define socklen_t  int
258 #endif
259 
260 /* Reading and writing from a socket */
261 extern int sock_read (SOCKET fd, void* buf, size_t nbyte, perseverance_t persev);
262 extern int sock_write (SOCKET fd, const void* buf, size_t nbyte, perseverance_t persev);
263 /* Interruptible wait for something on socket */
264 typedef enum { socket_wait_read, socket_wait_write, socket_wait_except } socket_wait_event;
265 extern int interruptible_socket_wait (SOCKET socket_handle, socket_wait_event waitwhat, struct timeval * timeout_ptr);
266 /* Wrapping and unwrapping of a socket in a Lisp object */
267 #define allocate_socket(fd)  allocate_handle((Handle)(fd))
268 #define TheSocket(obj)  (SOCKET)TheHandle(obj)
269 /* Autoconfiguration macros */
270 #define HAVE_GETHOSTNAME
271 #ifndef MAXHOSTNAMELEN
272   #define MAXHOSTNAMELEN 64
273 #endif
274 #define HAVE_GETHOSTBYNAME
275 #define HAVE_IPV4  1
276 #define HAVE_IPV6  1
277 #undef HAVE_NETINET_TCP_H
278 #define SETSOCKOPT_CONST const
279 #define SETSOCKOPT_ARG_T char*
280 #define SETSOCKOPT_OPTLEN_T int
281 #define HAVE_SHUTDOWN
282 /* Do not define HAVE_SELECT because select() works on sockets only.
283  used by error.d, misc.d, socket.d, stream.d
284  requires linking with wsock32.lib */
285 
286 /* Hacking the terminal */
287 #ifdef __MINGW32__
288   /* #include <io.h> */
289   #define isatty clisp_isatty /* avoid collision with prototype in <mingw/io.h> */
290 #endif
291 extern int isatty (HANDLE handle); /* see win32aux.d */
292 /* used by stream.d */
293 
294 /* Date and time
295    Don't use GetSystemTime(), because it's unreliable. (See comment in
296    MSVC4.0 crt/src/time.c.) Better use GetLocalTime().
297    //extern void GetLocalTime (SYSTEMTIME* SystemTime);
298    But GetLocalTime() ignores the TZ environment variable, so use _ftime(). */
299 #include <sys/timeb.h>
300 #ifdef MICROSOFT
301   #define timeb _timeb
302   #define ftime _ftime
303 #endif
304 /* extern void ftime (struct timeb *); */
305 #include <time.h>
306 /* extern struct tm * localtime (time_t*);
307    extern struct tm * gmtime (time_t*);
308    extern BOOL FileTimeToLocalFileTime (const FILETIME* FileTime, FILETIME* LocalFileTime);
309    extern BOOL FileTimeToSystemTime (const FILETIME* LocalFileTime, SYSTEMTIME* LocalSystemTime);
310  used by time.d */
311 
312 /* Pausing
313    extern void Sleep (DWORD Milliseconds);
314  used by win32aux.d
315    Sleep a certain time.
316    Return true after normal termination, false if interrupted by Ctrl-C. */
317 extern BOOL msleep (DWORD milliseconds);
318 extern unsigned int sleep (unsigned int seconds);
319 /* used by time.d, socket.d */
320 
321 /* Calling programs
322   extern BOOL CreateProcess (LPCTSTR ApplicationName, LPTSTR CommandLine,
323       LPSECURITY_ATTRIBUTES ProcessAttributes,
324       LPSECURITY_ATTRIBUTES ThreadAttributes,
325       BOOL InheritHandles, DWORD CreationFlags, LPVOID Environment,
326       LPCTSTR CurrentDirectory, LPSTARTUPINFO StartupInfo,
327       LPPROCESS_INFORMATION ProcessInformation);
328   extern BOOL GetExitCodeProcess (HANDLE Process, LPDWORD ExitCode);
329   extern BOOL CreatePipe (PHANDLE ReadPipe, PHANDLE WritePipe,
330       LPSECURITY_ATTRIBUTES PipeAttributes, DWORD Size);
331   extern BOOL DuplicateHandle (HANDLE SourceProcessHandle, HANDLE SourceHandle,
332       HANDLE TargetProcessHandle, LPHANDLE TargetHandle,
333       DWORD DesiredAccess, BOOL InheritHandle, DWORD Options);
334   used by win32aux.d, pathname.d, stream.d */
335 extern BOOL MyCreateProcess (LPTSTR CommandLine, HANDLE StdInput,
336                              HANDLE StdOutput, HANDLE StdError,
337                              LPPROCESS_INFORMATION ProcessInformation);
338 /* used by pathname.d, stream.d */
339 
340 /* Getting more information about the machine.
341    extern LONG RegOpenKeyEx (HKEY Key, LPCTSTR SubKey, DWORD Options, REGSAM Desired, PHKEY Result);
342    extern LONG RegQueryValueEx (HKEY Key, LPTSTR ValueName, LPDWORD Reserved, LPDWORD Type, LPBYTE Data, LPDWORD cbData);
343    extern LONG RegCloseKey (HKEY Key);
344  used by misc.d
345  requires linking with advapi32.lib */
346 
347 /* Examining the memory map.
348    extern DWORD VirtualQuery (LPCVOID Address, PMEMORY_BASIC_INFORMATION Buffer, DWORD Length); */
349 extern void DumpProcessMemoryMap (FILE* out); /* see win32aux.d */
350 /* used by spvw.d */
351 
352 /* Getting virtual memory
353    //extern void GetSystemInfo (LPSYSTEM_INFO SystemInfo);
354    extern LPVOID VirtualAlloc (LPVOID Address, DWORD Size, DWORD AllocationType, DWORD Protect);
355    extern BOOL VirtualFree (LPVOID Address, DWORD Size, DWORD FreeType);
356    extern BOOL VirtualProtect (LPVOID Address, DWORD Size, DWORD NewProtect, PDWORD OldProtect);
357    //extern HANDLE CreateFileMapping (HANDLE File, LPSECURITY_ATTRIBUTES FileMappingAttributes, DWORD Protect, DWORD MaximumSizeHigh, DWORD MaximumSizeLow, LPCTSTR Name);
358    //extern LPVOID MapViewOfFileEx (HANDLE FileMappingObject, DWORD DesiredAccess, DWORD FileOffsetHigh, DWORD FileOffsetLow, DWORD NumberOfBytesToMap, LPVOID BaseAddress);
359    //extern BOOL UnmapViewOfFile (LPCVOID BaseAddress); */
360 #define HAVE_WIN32_VM
361 /* So you can write munmap() and mprotect() write by your own. mmap() is
362    emulated, because MapViewOfFileEx() has too many disadvantages.
363    See spvw.d. */
364 /* #define HAVE_MMAP */
365 #define HAVE_MUNMAP
366 #define HAVE_WORKING_MPROTECT
367 #if defined(HAVE_MPROTECT) /* mprotect from libgcc uses Unix constants */
368   #define PROT_NONE  0
369   #define PROT_READ  1
370   #define PROT_READ_WRITE 3
371 #else
372   #define PROT_NONE  PAGE_NOACCESS
373   #define PROT_READ  PAGE_READONLY
374   #define PROT_READ_WRITE PAGE_READWRITE
375 #endif
376 /* PROT_WRITE, PROT_EXEC not used
377  used by spvw.d */
378 
379 #ifdef FIONBIO                  /*  */
380   /* for socket.d: non-blocking I/O a la BSD 4.2 */
381   #define NO_BLOCK_DECL()  \
382     int non_blocking_io = 1
383   #define START_NO_BLOCK(handle, on_fail)                         \
384     if (ioctl(handle,FIONBIO,&non_blocking_io)) { on_fail; }
385   #define END_NO_BLOCK(handle, on_fail)            do {           \
386       non_blocking_io = 0;                                        \
387       if (ioctl(handle,FIONBIO,&non_blocking_io)) { on_fail; }    \
388     } while (0)
389 #endif
390