1 /****************************************************************************
3 * SciTech OS Portability Manager Library
5 * ========================================================================
7 * The contents of this file are subject to the SciTech MGL Public
8 * License Version 1.0 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.scitechsoft.com/mgl-license.txt
12 * Software distributed under the License is distributed on an
13 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
17 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
19 * The Initial Developer of the Original Code is SciTech Software, Inc.
20 * All Rights Reserved.
22 * ========================================================================
27 * Description: Implementation for the OS Portability Manager Library, which
28 * contains functions to implement OS specific services in a
29 * generic, cross platform API. Porting the OS Portability
30 * Manager library is the first step to porting any SciTech
31 * products to a new platform.
33 ****************************************************************************/
35 #define WIN32_LEAN_AND_MEAN
44 #include "drvlib/os/os.h"
47 /*--------------------------- Global variables ----------------------------*/
49 ibool _PM_haveWinNT; /* True if we are running on NT */
50 static uint VESABuf_len = 1024; /* Length of the VESABuf buffer */
51 static void *VESABuf_ptr = NULL;/* Near pointer to VESABuf */
52 static uint VESABuf_rseg; /* Real mode segment of VESABuf */
53 static uint VESABuf_roff; /* Real mode offset of VESABuf */
54 HANDLE _PM_hDevice = NULL; /* Handle to Win32 VxD */
55 static ibool inited = false; /* Flags if we are initialised */
56 static void (PMAPIP fatalErrorCleanup)(void) = NULL;
58 static char *szMachineNameKey = "System\\CurrentControlSet\\control\\ComputerName\\ComputerName";
59 static char *szMachineNameKeyNT = "System\\CurrentControlSet\\control\\ComputerName\\ActiveComputerName";
60 static char *szMachineName = "ComputerName";
62 /*----------------------------- Implementation ----------------------------*/
64 /* Macro to check for a valid, loaded version of PMHELP. We check this
65 * on demand when we need these services rather than when PM_init() is
66 * called because if we are running on DirectDraw we don't need PMHELP.VXD.
69 #define CHECK_FOR_PMHELP() \
71 if (_PM_hDevice == INVALID_HANDLE_VALUE) \
73 PM_fatalError("Unable to connect to PMHELP.SYS or SDDHELP.SYS!"); \
75 PM_fatalError("Unable to connect to PMHELP.VXD or SDDHELP.VXD!"); \
78 /****************************************************************************
80 Initialise the PM library and connect to our helper device driver. If we
81 cannot connect to our helper device driver, we bail out with an error
82 message. Our Windows 9x VxD is dynamically loadable, so it can be loaded
83 after the system has started.
84 ****************************************************************************/
85 void PMAPI PM_init(void)
87 DWORD inBuf[1]; /* Buffer to receive data from VxD */
88 DWORD outBuf[1]; /* Buffer to receive data from VxD */
89 DWORD count; /* Count of bytes returned from VxD */
90 char cntPath[PM_MAX_PATH];
93 /* Create a file handle for the static VxD if possible, otherwise
94 * dynamically load the PMHELP helper VxD. Note that if an old version
95 * of SDD is loaded, we use the PMHELP VxD instead.
98 /* Determine if we are running under Windows NT or not and
99 * set the global OS type variable.
101 _PM_haveWinNT = false;
102 if ((GetVersion() & 0x80000000UL) == 0)
103 _PM_haveWinNT = true;
104 ___drv_os_type = (_PM_haveWinNT) ? _OS_WINNT : _OS_WIN95;
106 /* Now try to connect to SDDHELP.VXD or SDDHELP.SYS */
107 _PM_hDevice = CreateFile(SDDHELP_MODULE_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);
108 if (_PM_hDevice != INVALID_HANDLE_VALUE) {
109 if (!DeviceIoControl(_PM_hDevice, PMHELP_GETVER32, NULL, 0,
110 outBuf, sizeof(outBuf), &count, NULL) || outBuf[0] < PMHELP_VERSION) {
111 /* Old version of SDDHELP loaded, so use PMHELP instead */
112 CloseHandle(_PM_hDevice);
113 _PM_hDevice = INVALID_HANDLE_VALUE;
116 if (_PM_hDevice == INVALID_HANDLE_VALUE) {
117 /* First try to see if there is a currently loaded PMHELP driver.
118 * This is usually the case when we are running under Windows NT/2K.
120 _PM_hDevice = CreateFile(PMHELP_MODULE_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);
121 if (_PM_hDevice == INVALID_HANDLE_VALUE) {
122 /* The driver was not staticly loaded, so try creating a file handle
123 * to a dynamic version of the VxD if possible. Note that on WinNT/2K we
124 * cannot support dynamically loading the drivers.
126 _PM_hDevice = CreateFile(PMHELP_VXD_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);
129 if (_PM_hDevice != INVALID_HANDLE_VALUE) {
130 /* Call the driver to determine the version number */
131 if (!DeviceIoControl(_PM_hDevice, PMHELP_GETVER32, inBuf, sizeof(inBuf),
132 outBuf, sizeof(outBuf), &count, NULL) || outBuf[0] < PMHELP_VERSION) {
134 PM_fatalError("Older version of PMHELP.SYS found!");
136 PM_fatalError("Older version of PMHELP.VXD found!");
139 /* Now set the current path inside the VxD so it knows what the
140 * current directory is for loading Nucleus drivers.
142 inBuf[0] = (ulong)PM_getCurrentPath(cntPath,sizeof(cntPath));
143 if (!DeviceIoControl(_PM_hDevice, PMHELP_SETCNTPATH32, inBuf, sizeof(inBuf), outBuf, sizeof(outBuf), &count, NULL))
144 PM_fatalError("Unable to set VxD current path!");
146 /* Now pass down the NUCLEUS_PATH environment variable to the device
147 * driver so it can use this value if it is found.
149 if ((env = getenv("NUCLEUS_PATH")) != NULL) {
150 inBuf[0] = (ulong)env;
151 if (!DeviceIoControl(_PM_hDevice, PMHELP_SETNUCLEUSPATH32, inBuf, sizeof(inBuf), outBuf, sizeof(outBuf), &count, NULL))
152 PM_fatalError("Unable to set VxD Nucleus path!");
155 /* Enable IOPL for ring-3 code by default if driver is present */
160 /* Indicate that we have been initialised */
165 /****************************************************************************
167 We do have BIOS access under Windows 9x, but not under Windows NT.
168 ****************************************************************************/
169 int PMAPI PM_setIOPL(
172 DWORD inBuf[1]; /* Buffer to receive data from VxD */
173 DWORD outBuf[1]; /* Buffer to receive data from VxD */
174 DWORD count; /* Count of bytes returned from VxD */
175 static int cntIOPL = 0;
176 int oldIOPL = cntIOPL;
178 /* Enable I/O by adjusting the I/O permissions map on Windows NT */
182 DeviceIoControl(_PM_hDevice, PMHELP_ENABLERING3IOPL, inBuf, sizeof(inBuf),outBuf, sizeof(outBuf), &count, NULL);
184 DeviceIoControl(_PM_hDevice, PMHELP_DISABLERING3IOPL, inBuf, sizeof(inBuf),outBuf, sizeof(outBuf), &count, NULL);
189 /* We always have IOPL on Windows 9x */
193 /****************************************************************************
195 We do have BIOS access under Windows 9x, but not under Windows NT.
196 ****************************************************************************/
197 ibool PMAPI PM_haveBIOSAccess(void)
199 if (PM_getOSType() == _OS_WINNT)
202 return _PM_hDevice != INVALID_HANDLE_VALUE;
205 /****************************************************************************
207 Return the operating system type identifier.
208 ****************************************************************************/
209 long PMAPI PM_getOSType(void)
211 if ((GetVersion() & 0x80000000UL) == 0)
212 return ___drv_os_type = _OS_WINNT;
214 return ___drv_os_type = _OS_WIN95;
217 /****************************************************************************
219 Return the runtime type identifier.
220 ****************************************************************************/
221 int PMAPI PM_getModeType(void)
226 /****************************************************************************
228 Add a file directory separator to the end of the filename.
229 ****************************************************************************/
230 void PMAPI PM_backslash(
233 uint pos = strlen(s);
234 if (s[pos-1] != '\\') {
240 /****************************************************************************
242 Add a user defined PM_fatalError cleanup function.
243 ****************************************************************************/
244 void PMAPI PM_setFatalErrorCleanup(
245 void (PMAPIP cleanup)(void))
247 fatalErrorCleanup = cleanup;
250 /****************************************************************************
252 Report a fatal error condition and halt the program.
253 ****************************************************************************/
254 void PMAPI PM_fatalError(
257 if (fatalErrorCleanup)
259 MessageBox(NULL,msg,"Fatal Error!", MB_ICONEXCLAMATION);
263 /****************************************************************************
265 Allocate the real mode VESA transfer buffer for communicating with the BIOS.
266 ****************************************************************************/
267 void * PMAPI PM_getVESABuf(
272 DWORD outBuf[4]; /* Buffer to receive data from VxD */
273 DWORD count; /* Count of bytes returned from VxD */
275 /* We require the helper VxD to be loaded staticly in order to support
276 * the VESA transfer buffer. We do not support dynamically allocating
277 * real mode memory buffers from Win32 programs (we need a 16-bit DLL
278 * for this, and Windows 9x becomes very unstable if you free the
279 * memory blocks out of order).
285 if (DeviceIoControl(_PM_hDevice, PMHELP_GETVESABUF32, NULL, 0,
286 outBuf, sizeof(outBuf), &count, NULL)) {
289 VESABuf_ptr = (void*)outBuf[0];
290 VESABuf_len = outBuf[1];
291 VESABuf_rseg = outBuf[2];
292 VESABuf_roff = outBuf[3];
296 *rseg = VESABuf_rseg;
297 *roff = VESABuf_roff;
301 /****************************************************************************
303 Check if a key has been pressed.
304 ****************************************************************************/
305 int PMAPI PM_kbhit(void)
307 /* Not used in Windows */
311 /****************************************************************************
313 Wait for and return the next keypress.
314 ****************************************************************************/
315 int PMAPI PM_getch(void)
317 /* Not used in Windows */
321 /****************************************************************************
323 Set the location of the OS console cursor.
324 ****************************************************************************/
325 void PM_setOSCursorLocation(
329 /* Nothing to do for Windows */
334 /****************************************************************************
336 Set the width of the OS console.
337 ****************************************************************************/
338 void PM_setOSScreenWidth(
342 /* Nothing to do for Windows */
347 /****************************************************************************
349 Set the real time clock handler (used for software stereo modes).
350 ****************************************************************************/
351 ibool PMAPI PM_setRealTimeClockHandler(
355 /* We do not support this from Win32 programs. Rather the VxD handles
356 * this stuff it will take care of hooking the stereo flip functions at
364 /****************************************************************************
366 Set the real time clock frequency (for stereo modes).
367 ****************************************************************************/
368 void PMAPI PM_setRealTimeClockFrequency(
371 /* Not supported under Win32 */
375 /****************************************************************************
377 Restore the original real time clock handler.
378 ****************************************************************************/
379 void PMAPI PM_restoreRealTimeClockHandler(void)
381 /* Not supported under Win32 */
384 /****************************************************************************
386 Return the current operating system path or working directory.
387 ****************************************************************************/
388 char * PMAPI PM_getCurrentPath(
392 return getcwd(path,maxLen);
395 /****************************************************************************
397 Query a string from the registry (extended version).
398 ****************************************************************************/
399 static ibool REG_queryStringEx(
407 if (RegQueryValueEx(hKey,(PCHAR)szValue,(PDWORD)NULL,(PDWORD)&type,(LPBYTE)value,(PDWORD)&size) == ERROR_SUCCESS)
412 /****************************************************************************
414 Query a string from the registry.
415 ****************************************************************************/
416 static ibool REG_queryString(
423 ibool status = false;
425 memset(value,0,sizeof(value));
426 if (RegOpenKey(HKEY_LOCAL_MACHINE,szKey,&hKey) == ERROR_SUCCESS) {
427 status = REG_queryStringEx(hKey,szValue,value,size);
433 /****************************************************************************
435 Return the drive letter for the boot drive.
436 ****************************************************************************/
437 char PMAPI PM_getBootDrive(void)
439 static char path[256];
440 GetSystemDirectory(path,sizeof(path));
444 /****************************************************************************
446 Return the path to the VBE/AF driver files.
447 ****************************************************************************/
448 const char * PMAPI PM_getVBEAFPath(void)
453 /****************************************************************************
455 Return the path to the Nucleus driver files.
456 ****************************************************************************/
457 const char * PMAPI PM_getNucleusPath(void)
459 static char path[256];
462 if ((env = getenv("NUCLEUS_PATH")) != NULL)
464 GetSystemDirectory(path,sizeof(path));
465 strcat(path,"\\nucleus");
469 /****************************************************************************
471 Return the path to the Nucleus configuration files.
472 ****************************************************************************/
473 const char * PMAPI PM_getNucleusConfigPath(void)
475 static char path[256];
476 strcpy(path,PM_getNucleusPath());
478 strcat(path,"config");
482 /****************************************************************************
484 Return a unique identifier for the machine if possible.
485 ****************************************************************************/
486 const char * PMAPI PM_getUniqueID(void)
488 return PM_getMachineName();
491 /****************************************************************************
493 Get the name of the machine on the network.
494 ****************************************************************************/
495 const char * PMAPI PM_getMachineName(void)
497 static char name[256];
499 if (REG_queryString(szMachineNameKey,szMachineName,name,sizeof(name)))
501 if (REG_queryString(szMachineNameKeyNT,szMachineName,name,sizeof(name)))
506 /****************************************************************************
508 Return a pointer to the real mode BIOS data area.
509 ****************************************************************************/
510 void * PMAPI PM_getBIOSPointer(void)
513 /* On Windows NT we have to map it physically directly */
514 return PM_mapPhysicalAddr(0x400, 0x1000, true);
517 /* For Windows 9x we can access this memory directly */
522 /****************************************************************************
524 Return a pointer to 0xA0000 physical VGA graphics framebuffer.
525 ****************************************************************************/
526 void * PMAPI PM_getA0000Pointer(void)
529 /* On Windows NT we have to map it physically directly */
530 return PM_mapPhysicalAddr(0xA0000, 0x0FFFF, false);
533 /* Always use the 0xA0000 linear address so that we will use
534 * whatever page table mappings are set up for us (ie: for virtual
537 return (void*)0xA0000;
541 /****************************************************************************
543 Map a physical address to a linear address in the callers process.
544 ****************************************************************************/
545 void * PMAPI PM_mapPhysicalAddr(
550 DWORD inBuf[3]; /* Buffer to send data to VxD */
551 DWORD outBuf[1]; /* Buffer to receive data from VxD */
552 DWORD count; /* Count of bytes returned from VxD */
560 if (DeviceIoControl(_PM_hDevice, PMHELP_MAPPHYS32, inBuf, sizeof(inBuf),
561 outBuf, sizeof(outBuf), &count, NULL))
562 return (void*)outBuf[0];
566 /****************************************************************************
568 Free a physical address mapping allocated by PM_mapPhysicalAddr.
569 ****************************************************************************/
570 void PMAPI PM_freePhysicalAddr(
574 /* We never free the mappings under Win32 (the VxD tracks them and
575 * reissues the same mappings until the system is rebooted).
581 /****************************************************************************
583 Find the physical address of a linear memory address in current process.
584 ****************************************************************************/
585 ulong PMAPI PM_getPhysicalAddr(
588 DWORD inBuf[1]; /* Buffer to send data to VxD */
589 DWORD outBuf[1]; /* Buffer to receive data from VxD */
590 DWORD count; /* Count of bytes returned from VxD */
596 if (DeviceIoControl(_PM_hDevice, PMHELP_GETPHYSICALADDR32, inBuf, sizeof(inBuf),
597 outBuf, sizeof(outBuf), &count, NULL))
602 /****************************************************************************
604 Find the physical address of a linear memory address in current process.
605 ****************************************************************************/
606 ibool PMAPI PM_getPhysicalAddrRange(
611 DWORD inBuf[3]; /* Buffer to send data to VxD */
612 DWORD outBuf[1]; /* Buffer to receive data from VxD */
613 DWORD count; /* Count of bytes returned from VxD */
618 inBuf[1] = (ulong)length;
619 inBuf[2] = (ulong)physAddress;
621 if (DeviceIoControl(_PM_hDevice, PMHELP_GETPHYSICALADDRRANGE32, inBuf, sizeof(inBuf),
622 outBuf, sizeof(outBuf), &count, NULL))
627 /****************************************************************************
629 Sleep for the specified number of milliseconds.
630 ****************************************************************************/
637 /****************************************************************************
639 Return the base I/O port for the specified COM port.
640 ****************************************************************************/
641 int PMAPI PM_getCOMPort(int port)
643 /* TODO: Re-code this to determine real values using the Plug and Play */
644 /* manager for the OS. */
646 case 0: return 0x3F8;
647 case 1: return 0x2F8;
648 case 2: return 0x3E8;
649 case 3: return 0x2E8;
654 /****************************************************************************
656 Return the base I/O port for the specified LPT port.
657 ****************************************************************************/
658 int PMAPI PM_getLPTPort(int port)
660 /* TODO: Re-code this to determine real values using the Plug and Play */
661 /* manager for the OS. */
663 case 0: return 0x3BC;
664 case 1: return 0x378;
665 case 2: return 0x278;
670 /****************************************************************************
672 Allocate a block of shared memory. For Win9x we allocate shared memory
673 as locked, global memory that is accessible from any memory context
674 (including interrupt time context), which allows us to load our important
675 data structure and code such that we can access it directly from a ring
677 ****************************************************************************/
678 void * PMAPI PM_mallocShared(
681 DWORD inBuf[1]; /* Buffer to send data to VxD */
682 DWORD outBuf[1]; /* Buffer to receive data from VxD */
683 DWORD count; /* Count of bytes returned from VxD */
687 if (DeviceIoControl(_PM_hDevice, PMHELP_MALLOCSHARED32, inBuf, sizeof(inBuf),
688 outBuf, sizeof(outBuf), &count, NULL))
689 return (void*)outBuf[0];
693 /****************************************************************************
695 Free a block of shared memory.
696 ****************************************************************************/
697 void PMAPI PM_freeShared(
700 DWORD inBuf[1]; /* Buffer to send data to VxD */
702 inBuf[0] = (ulong)ptr;
704 DeviceIoControl(_PM_hDevice, PMHELP_FREESHARED32, inBuf, sizeof(inBuf), NULL, 0, NULL, NULL);
707 /****************************************************************************
709 Map a linear memory address to the calling process address space. The
710 address will have been allocated in another process using the
711 PM_mapPhysicalAddr function.
712 ****************************************************************************/
713 void * PMAPI PM_mapToProcess(
722 /****************************************************************************
724 Map a real mode pointer to a protected mode pointer.
725 ****************************************************************************/
726 void * PMAPI PM_mapRealPointer(
730 return (void*)(MK_PHYS(r_seg,r_off));
733 /****************************************************************************
735 Allocate a block of real mode memory
736 ****************************************************************************/
737 void * PMAPI PM_allocRealSeg(
742 /* We do not support dynamically allocating real mode memory buffers
743 * from Win32 programs (we need a 16-bit DLL for this, and Windows
744 * 9x becomes very unstable if you free the memory blocks out of order).
752 /****************************************************************************
754 Free a block of real mode memory.
755 ****************************************************************************/
756 void PMAPI PM_freeRealSeg(
759 /* Not supported in Windows */
763 /****************************************************************************
765 Issue a real mode interrupt (parameters in DPMI compatible structure)
766 ****************************************************************************/
767 void PMAPI DPMI_int86(
771 DWORD inBuf[2]; /* Buffer to send data to VxD */
772 DWORD count; /* Count of bytes returned from VxD */
777 inBuf[1] = (ulong)regs;
779 DeviceIoControl(_PM_hDevice, PMHELP_DPMIINT8632, inBuf, sizeof(inBuf),
780 NULL, 0, &count, NULL);
783 /****************************************************************************
785 Issue a real mode interrupt.
786 ****************************************************************************/
792 DWORD inBuf[3]; /* Buffer to send data to VxD */
793 DWORD outBuf[1]; /* Buffer to receive data from VxD */
794 DWORD count; /* Count of bytes returned from VxD */
799 inBuf[1] = (ulong)in;
800 inBuf[2] = (ulong)out;
802 if (DeviceIoControl(_PM_hDevice, PMHELP_INT8632, inBuf, sizeof(inBuf),
803 outBuf, sizeof(outBuf), &count, NULL))
808 /****************************************************************************
810 Issue a real mode interrupt.
811 ****************************************************************************/
818 DWORD inBuf[4]; /* Buffer to send data to VxD */
819 DWORD outBuf[1]; /* Buffer to receive data from VxD */
820 DWORD count; /* Count of bytes returned from VxD */
825 inBuf[1] = (ulong)in;
826 inBuf[2] = (ulong)out;
827 inBuf[3] = (ulong)sregs;
829 if (DeviceIoControl(_PM_hDevice, PMHELP_INT86X32, inBuf, sizeof(inBuf),
830 outBuf, sizeof(outBuf), &count, NULL))
835 /****************************************************************************
837 Call a real mode far function.
838 ****************************************************************************/
839 void PMAPI PM_callRealMode(
845 DWORD inBuf[4]; /* Buffer to send data to VxD */
846 DWORD count; /* Count of bytes returned from VxD */
852 inBuf[2] = (ulong)in;
853 inBuf[3] = (ulong)sregs;
855 DeviceIoControl(_PM_hDevice, PMHELP_CALLREALMODE32, inBuf, sizeof(inBuf),
856 NULL, 0, &count, NULL);
859 /****************************************************************************
861 Return the amount of available memory.
862 ****************************************************************************/
863 void PMAPI PM_availableMemory(
867 /* We don't support this under Win32 at the moment */
868 *physical = *total = 0;
871 /****************************************************************************
873 Allocate a block of locked, physical memory for DMA operations.
874 ****************************************************************************/
875 void * PMAPI PM_allocLockedMem(
881 DWORD inBuf[4]; /* Buffer to send data to VxD */
882 DWORD outBuf[1]; /* Buffer to receive data from VxD */
883 DWORD count; /* Count of bytes returned from VxD */
888 inBuf[1] = (ulong)physAddr;
889 inBuf[2] = (ulong)contiguous;
890 inBuf[3] = (ulong)below16M;
892 if (DeviceIoControl(_PM_hDevice, PMHELP_ALLOCLOCKED32, inBuf, sizeof(inBuf),
893 outBuf, sizeof(outBuf), &count, NULL))
894 return (void*)outBuf[0];
898 /****************************************************************************
900 Free a block of locked physical memory.
901 ****************************************************************************/
902 void PMAPI PM_freeLockedMem(
907 DWORD inBuf[3]; /* Buffer to send data to VxD */
908 DWORD count; /* Count of bytes returned from VxD */
914 inBuf[2] = contiguous;
916 DeviceIoControl(_PM_hDevice, PMHELP_FREELOCKED32, inBuf, sizeof(inBuf),
917 NULL, 0, &count, NULL);
920 /****************************************************************************
922 Allocates a page aligned and page sized block of memory
923 ****************************************************************************/
924 void * PMAPI PM_allocPage(
927 DWORD inBuf[2]; /* Buffer to send data to VxD */
928 DWORD outBuf[1]; /* Buffer to receive data from VxD */
929 DWORD count; /* Count of bytes returned from VxD */
935 if (DeviceIoControl(_PM_hDevice, PMHELP_ALLOCPAGE32, inBuf, sizeof(inBuf),
936 outBuf, sizeof(outBuf), &count, NULL))
937 return (void*)outBuf[0];
941 /****************************************************************************
943 Free a page aligned and page sized block of memory
944 ****************************************************************************/
945 void PMAPI PM_freePage(
948 DWORD inBuf[1]; /* Buffer to send data to VxD */
949 DWORD count; /* Count of bytes returned from VxD */
955 DeviceIoControl(_PM_hDevice, PMHELP_FREEPAGE32, inBuf, sizeof(inBuf),
956 NULL, 0, &count, NULL);
959 /****************************************************************************
961 Lock linear memory so it won't be paged.
962 ****************************************************************************/
963 int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
965 DWORD inBuf[2]; /* Buffer to send data to VxD */
966 DWORD outBuf[1]; /* Buffer to receive data from VxD */
967 DWORD count; /* Count of bytes returned from VxD */
971 inBuf[2] = (ulong)lh;
973 if (DeviceIoControl(_PM_hDevice, PMHELP_LOCKDATAPAGES32, inBuf, sizeof(inBuf),
974 outBuf, sizeof(outBuf), &count, NULL))
979 /****************************************************************************
981 Unlock linear memory so it won't be paged.
982 ****************************************************************************/
983 int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
985 DWORD inBuf[2]; /* Buffer to send data to VxD */
986 DWORD outBuf[1]; /* Buffer to receive data from VxD */
987 DWORD count; /* Count of bytes returned from VxD */
991 inBuf[2] = (ulong)lh;
993 if (DeviceIoControl(_PM_hDevice, PMHELP_UNLOCKDATAPAGES32, inBuf, sizeof(inBuf),
994 outBuf, sizeof(outBuf), &count, NULL))
999 /****************************************************************************
1001 Lock linear memory so it won't be paged.
1002 ****************************************************************************/
1003 int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
1005 DWORD inBuf[2]; /* Buffer to send data to VxD */
1006 DWORD outBuf[1]; /* Buffer to receive data from VxD */
1007 DWORD count; /* Count of bytes returned from VxD */
1009 inBuf[0] = (ulong)p;
1011 inBuf[2] = (ulong)lh;
1013 if (DeviceIoControl(_PM_hDevice, PMHELP_LOCKCODEPAGES32, inBuf, sizeof(inBuf),
1014 outBuf, sizeof(outBuf), &count, NULL))
1019 /****************************************************************************
1021 Unlock linear memory so it won't be paged.
1022 ****************************************************************************/
1023 int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
1025 DWORD inBuf[2]; /* Buffer to send data to VxD */
1026 DWORD outBuf[1]; /* Buffer to receive data from VxD */
1027 DWORD count; /* Count of bytes returned from VxD */
1029 inBuf[0] = (ulong)p;
1031 inBuf[2] = (ulong)lh;
1033 if (DeviceIoControl(_PM_hDevice, PMHELP_UNLOCKCODEPAGES32, inBuf, sizeof(inBuf),
1034 outBuf, sizeof(outBuf), &count, NULL))
1039 /****************************************************************************
1041 Call the VBE/Core software interrupt to change display banks.
1042 ****************************************************************************/
1043 void PMAPI PM_setBankA(
1050 PM_int86(0x10,®s,®s);
1053 /****************************************************************************
1055 Call the VBE/Core software interrupt to change display banks.
1056 ****************************************************************************/
1057 void PMAPI PM_setBankAB(
1064 PM_int86(0x10,®s,®s);
1068 PM_int86(0x10,®s,®s);
1071 /****************************************************************************
1073 Call the VBE/Core software interrupt to change display start address.
1074 ****************************************************************************/
1075 void PMAPI PM_setCRTStart(
1082 regs.x.bx = waitVRT;
1085 PM_int86(0x10,®s,®s);
1088 /****************************************************************************
1090 Enable write combining for the memory region.
1091 ****************************************************************************/
1092 ibool PMAPI PM_enableWriteCombine(
1097 DWORD inBuf[3]; /* Buffer to send data to VxD */
1098 DWORD outBuf[1]; /* Buffer to receive data from VxD */
1099 DWORD count; /* Count of bytes returned from VxD */
1107 if (DeviceIoControl(_PM_hDevice, PMHELP_ENABLELFBCOMB32, inBuf, sizeof(inBuf),
1108 outBuf, sizeof(outBuf), &count, NULL))
1113 /****************************************************************************
1115 Get the page directory base register value
1116 ****************************************************************************/
1117 ulong PMAPI _PM_getPDB(void)
1119 DWORD outBuf[1]; /* Buffer to receive data from VxD */
1120 DWORD count; /* Count of bytes returned from VxD */
1123 if (DeviceIoControl(_PM_hDevice, PMHELP_GETPDB32, NULL, 0,
1124 outBuf, sizeof(outBuf), &count, NULL))
1129 /****************************************************************************
1131 Flush the translation lookaside buffer.
1132 ****************************************************************************/
1133 void PMAPI PM_flushTLB(void)
1136 DeviceIoControl(_PM_hDevice, PMHELP_FLUSHTLB32, NULL, 0, NULL, 0, NULL, NULL);
1139 /****************************************************************************
1141 Execute the POST on the secondary BIOS for a controller.
1142 ****************************************************************************/
1143 ibool PMAPI PM_doBIOSPOST(
1149 /* This is never done by Win32 programs, but rather done by the VxD
1150 * when the system boots.
1159 /****************************************************************************
1161 Load an OS specific shared library or DLL. If the OS does not support
1162 shared libraries, simply return NULL.
1163 ****************************************************************************/
1164 PM_MODULE PMAPI PM_loadLibrary(
1165 const char *szDLLName)
1167 return (PM_MODULE)LoadLibrary(szDLLName);
1170 /****************************************************************************
1172 Get the address of a named procedure from a shared library.
1173 ****************************************************************************/
1174 void * PMAPI PM_getProcAddress(
1176 const char *szProcName)
1178 return (void*)GetProcAddress((HINSTANCE)hModule,szProcName);
1181 /****************************************************************************
1183 Unload a shared library.
1184 ****************************************************************************/
1185 void PMAPI PM_freeLibrary(
1188 FreeLibrary((HINSTANCE)hModule);
1191 /****************************************************************************
1193 Internal function to convert the find data to the generic interface.
1194 ****************************************************************************/
1195 static void convertFindData(
1196 PM_findData *findData,
1197 WIN32_FIND_DATA *blk)
1199 ulong dwSize = findData->dwSize;
1201 memset(findData,0,findData->dwSize);
1202 findData->dwSize = dwSize;
1203 if (blk->dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1204 findData->attrib |= PM_FILE_READONLY;
1205 if (blk->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1206 findData->attrib |= PM_FILE_DIRECTORY;
1207 if (blk->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
1208 findData->attrib |= PM_FILE_ARCHIVE;
1209 if (blk->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
1210 findData->attrib |= PM_FILE_HIDDEN;
1211 if (blk->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
1212 findData->attrib |= PM_FILE_SYSTEM;
1213 findData->sizeLo = blk->nFileSizeLow;
1214 findData->sizeHi = blk->nFileSizeHigh;
1215 strncpy(findData->name,blk->cFileName,PM_MAX_PATH);
1216 findData->name[PM_MAX_PATH-1] = 0;
1219 /****************************************************************************
1221 Function to find the first file matching a search criteria in a directory.
1222 ****************************************************************************/
1223 void *PMAPI PM_findFirstFile(
1224 const char *filename,
1225 PM_findData *findData)
1227 WIN32_FIND_DATA blk;
1230 if ((hfile = FindFirstFile(filename,&blk)) != INVALID_HANDLE_VALUE) {
1231 convertFindData(findData,&blk);
1232 return (void*)hfile;
1234 return PM_FILE_INVALID;
1237 /****************************************************************************
1239 Function to find the next file matching a search criteria in a directory.
1240 ****************************************************************************/
1241 ibool PMAPI PM_findNextFile(
1243 PM_findData *findData)
1245 WIN32_FIND_DATA blk;
1247 if (FindNextFile((HANDLE)handle,&blk)) {
1248 convertFindData(findData,&blk);
1254 /****************************************************************************
1256 Function to close the find process
1257 ****************************************************************************/
1258 void PMAPI PM_findClose(
1261 FindClose((HANDLE)handle);
1264 /****************************************************************************
1266 Function to determine if a drive is a valid drive or not. Under Unix this
1267 function will return false for anything except a value of 3 (considered
1268 the root drive, and equivalent to C: for non-Unix systems). The drive
1276 ****************************************************************************/
1277 ibool PMAPI PM_driveValid(
1283 sprintf(buf,"%c:\\", drive);
1284 return ((type = GetDriveType(buf)) != 0 && type != 1);
1287 /****************************************************************************
1289 Function to get the current working directory for the specififed drive.
1290 Under Unix this will always return the current working directory regardless
1291 of what the value of 'drive' is.
1292 ****************************************************************************/
1293 void PMAPI PM_getdcwd(
1298 /* NT stores the current directory for drive N in the magic environment */
1299 /* variable =N: so we simply look for that environment variable. */
1303 envname[1] = drive - 1 + 'A';
1306 if (GetEnvironmentVariable(envname,dir,len) == 0) {
1307 /* The current directory or the drive has not been set yet, so */
1308 /* simply set it to the root. */
1309 dir[0] = envname[1];
1313 SetEnvironmentVariable(envname,dir);
1317 /****************************************************************************
1319 Function to change the file attributes for a specific file.
1320 ****************************************************************************/
1321 void PMAPI PM_setFileAttr(
1322 const char *filename,
1327 if (attrib & PM_FILE_READONLY)
1328 attr |= FILE_ATTRIBUTE_READONLY;
1329 if (attrib & PM_FILE_ARCHIVE)
1330 attr |= FILE_ATTRIBUTE_ARCHIVE;
1331 if (attrib & PM_FILE_HIDDEN)
1332 attr |= FILE_ATTRIBUTE_HIDDEN;
1333 if (attrib & PM_FILE_SYSTEM)
1334 attr |= FILE_ATTRIBUTE_SYSTEM;
1335 SetFileAttributes((LPSTR)filename, attr);
1338 /****************************************************************************
1340 Function to get the file attributes for a specific file.
1341 ****************************************************************************/
1342 uint PMAPI PM_getFileAttr(
1343 const char *filename)
1345 DWORD attr = GetFileAttributes(filename);
1348 if (attr & FILE_ATTRIBUTE_READONLY)
1349 attrib |= PM_FILE_READONLY;
1350 if (attr & FILE_ATTRIBUTE_ARCHIVE)
1351 attrib |= PM_FILE_ARCHIVE;
1352 if (attr & FILE_ATTRIBUTE_HIDDEN)
1353 attrib |= PM_FILE_HIDDEN;
1354 if (attr & FILE_ATTRIBUTE_SYSTEM)
1355 attrib |= PM_FILE_SYSTEM;
1359 /****************************************************************************
1361 Function to create a directory.
1362 ****************************************************************************/
1363 ibool PMAPI PM_mkdir(
1364 const char *filename)
1366 return CreateDirectory(filename,NULL);
1369 /****************************************************************************
1371 Function to remove a directory.
1372 ****************************************************************************/
1373 ibool PMAPI PM_rmdir(
1374 const char *filename)
1376 return RemoveDirectory(filename);
1379 /****************************************************************************
1381 Function to get the file time and date for a specific file.
1382 ****************************************************************************/
1383 ibool PMAPI PM_getFileTime(
1384 const char *filename,
1390 FILETIME utcTime,localTime;
1392 ibool status = false;
1394 of.cBytes = sizeof(of);
1395 if ((f = OpenFile(filename,&of,OF_READ)) == HFILE_ERROR)
1397 if (!GetFileTime((HANDLE)f,NULL,NULL,&utcTime))
1400 if (!FileTimeToLocalFileTime(&utcTime,&localTime))
1404 localTime = utcTime;
1405 if (!FileTimeToSystemTime(&localTime,&sysTime))
1407 time->year = sysTime.wYear;
1408 time->mon = sysTime.wMonth-1;
1409 time->day = sysTime.wYear;
1410 time->hour = sysTime.wHour;
1411 time->min = sysTime.wMinute;
1412 time->sec = sysTime.wSecond;
1416 CloseHandle((HANDLE)f);
1420 /****************************************************************************
1422 Function to set the file time and date for a specific file.
1423 ****************************************************************************/
1424 ibool PMAPI PM_setFileTime(
1425 const char *filename,
1431 FILETIME utcTime,localTime;
1433 ibool status = false;
1435 of.cBytes = sizeof(of);
1436 if ((f = OpenFile(filename,&of,OF_WRITE)) == HFILE_ERROR)
1438 sysTime.wYear = time->year;
1439 sysTime.wMonth = time->mon+1;
1440 sysTime.wYear = time->day;
1441 sysTime.wHour = time->hour;
1442 sysTime.wMinute = time->min;
1443 sysTime.wSecond = time->sec;
1444 if (!SystemTimeToFileTime(&sysTime,&localTime))
1447 if (!LocalFileTimeToFileTime(&localTime,&utcTime))
1451 utcTime = localTime;
1452 if (!SetFileTime((HANDLE)f,NULL,NULL,&utcTime))
1457 CloseHandle((HANDLE)f);