]>
Commit | Line | Data |
---|---|---|
c7de829c WD |
1 | /**************************************************************************** |
2 | * | |
3 | * SciTech OS Portability Manager Library | |
4 | * | |
5 | * ======================================================================== | |
6 | * | |
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 | |
11 | * | |
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. | |
16 | * | |
17 | * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. | |
18 | * | |
19 | * The Initial Developer of the Original Code is SciTech Software, Inc. | |
20 | * All Rights Reserved. | |
21 | * | |
22 | * ======================================================================== | |
23 | * | |
24 | * Language: ANSI C | |
25 | * Environment: Win32 | |
26 | * | |
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. | |
32 | * | |
33 | ****************************************************************************/ | |
34 | ||
35 | #define WIN32_LEAN_AND_MEAN | |
36 | #define STRICT | |
37 | #include <windows.h> | |
38 | #include <mmsystem.h> | |
39 | #include <stdio.h> | |
40 | #include <stdlib.h> | |
41 | #include <string.h> | |
42 | #include <direct.h> | |
43 | #include "pmapi.h" | |
44 | #include "drvlib/os/os.h" | |
45 | #include "pm_help.h" | |
46 | ||
47 | /*--------------------------- Global variables ----------------------------*/ | |
48 | ||
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; | |
57 | ||
58 | static char *szMachineNameKey = "System\\CurrentControlSet\\control\\ComputerName\\ComputerName"; | |
59 | static char *szMachineNameKeyNT = "System\\CurrentControlSet\\control\\ComputerName\\ActiveComputerName"; | |
60 | static char *szMachineName = "ComputerName"; | |
61 | ||
62 | /*----------------------------- Implementation ----------------------------*/ | |
63 | ||
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. | |
67 | */ | |
68 | ||
69 | #define CHECK_FOR_PMHELP() \ | |
70 | { \ | |
71 | if (_PM_hDevice == INVALID_HANDLE_VALUE) \ | |
8bde7f77 WD |
72 | if (_PM_haveWinNT) \ |
73 | PM_fatalError("Unable to connect to PMHELP.SYS or SDDHELP.SYS!"); \ | |
74 | else \ | |
75 | PM_fatalError("Unable to connect to PMHELP.VXD or SDDHELP.VXD!"); \ | |
c7de829c WD |
76 | } |
77 | ||
78 | /**************************************************************************** | |
79 | REMARKS: | |
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) | |
86 | { | |
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]; | |
91 | char *env; | |
92 | ||
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. | |
96 | */ | |
97 | if (!inited) { | |
8bde7f77 WD |
98 | /* Determine if we are running under Windows NT or not and |
99 | * set the global OS type variable. | |
100 | */ | |
101 | _PM_haveWinNT = false; | |
102 | if ((GetVersion() & 0x80000000UL) == 0) | |
103 | _PM_haveWinNT = true; | |
104 | ___drv_os_type = (_PM_haveWinNT) ? _OS_WINNT : _OS_WIN95; | |
105 | ||
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; | |
114 | } | |
115 | } | |
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. | |
119 | */ | |
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. | |
125 | */ | |
126 | _PM_hDevice = CreateFile(PMHELP_VXD_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0); | |
127 | } | |
128 | } | |
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) { | |
133 | if (_PM_haveWinNT) | |
134 | PM_fatalError("Older version of PMHELP.SYS found!"); | |
135 | else | |
136 | PM_fatalError("Older version of PMHELP.VXD found!"); | |
137 | } | |
138 | ||
139 | /* Now set the current path inside the VxD so it knows what the | |
140 | * current directory is for loading Nucleus drivers. | |
141 | */ | |
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!"); | |
145 | ||
146 | /* Now pass down the NUCLEUS_PATH environment variable to the device | |
147 | * driver so it can use this value if it is found. | |
148 | */ | |
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!"); | |
153 | } | |
154 | ||
155 | /* Enable IOPL for ring-3 code by default if driver is present */ | |
156 | if (_PM_haveWinNT) | |
157 | PM_setIOPL(3); | |
158 | } | |
159 | ||
160 | /* Indicate that we have been initialised */ | |
161 | inited = true; | |
162 | } | |
c7de829c WD |
163 | } |
164 | ||
165 | /**************************************************************************** | |
166 | REMARKS: | |
167 | We do have BIOS access under Windows 9x, but not under Windows NT. | |
168 | ****************************************************************************/ | |
169 | int PMAPI PM_setIOPL( | |
170 | int iopl) | |
171 | { | |
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; | |
177 | ||
178 | /* Enable I/O by adjusting the I/O permissions map on Windows NT */ | |
179 | if (_PM_haveWinNT) { | |
8bde7f77 WD |
180 | CHECK_FOR_PMHELP(); |
181 | if (iopl == 3) | |
182 | DeviceIoControl(_PM_hDevice, PMHELP_ENABLERING3IOPL, inBuf, sizeof(inBuf),outBuf, sizeof(outBuf), &count, NULL); | |
183 | else | |
184 | DeviceIoControl(_PM_hDevice, PMHELP_DISABLERING3IOPL, inBuf, sizeof(inBuf),outBuf, sizeof(outBuf), &count, NULL); | |
185 | cntIOPL = iopl; | |
186 | return oldIOPL; | |
187 | } | |
c7de829c WD |
188 | |
189 | /* We always have IOPL on Windows 9x */ | |
190 | return 3; | |
191 | } | |
192 | ||
193 | /**************************************************************************** | |
194 | REMARKS: | |
195 | We do have BIOS access under Windows 9x, but not under Windows NT. | |
196 | ****************************************************************************/ | |
197 | ibool PMAPI PM_haveBIOSAccess(void) | |
198 | { | |
199 | if (PM_getOSType() == _OS_WINNT) | |
8bde7f77 | 200 | return false; |
c7de829c | 201 | else |
8bde7f77 | 202 | return _PM_hDevice != INVALID_HANDLE_VALUE; |
c7de829c WD |
203 | } |
204 | ||
205 | /**************************************************************************** | |
206 | REMARKS: | |
207 | Return the operating system type identifier. | |
208 | ****************************************************************************/ | |
209 | long PMAPI PM_getOSType(void) | |
210 | { | |
211 | if ((GetVersion() & 0x80000000UL) == 0) | |
8bde7f77 | 212 | return ___drv_os_type = _OS_WINNT; |
c7de829c | 213 | else |
8bde7f77 | 214 | return ___drv_os_type = _OS_WIN95; |
c7de829c WD |
215 | } |
216 | ||
217 | /**************************************************************************** | |
218 | REMARKS: | |
219 | Return the runtime type identifier. | |
220 | ****************************************************************************/ | |
221 | int PMAPI PM_getModeType(void) | |
222 | { | |
223 | return PM_386; | |
224 | } | |
225 | ||
226 | /**************************************************************************** | |
227 | REMARKS: | |
228 | Add a file directory separator to the end of the filename. | |
229 | ****************************************************************************/ | |
230 | void PMAPI PM_backslash( | |
231 | char *s) | |
232 | { | |
233 | uint pos = strlen(s); | |
234 | if (s[pos-1] != '\\') { | |
8bde7f77 WD |
235 | s[pos] = '\\'; |
236 | s[pos+1] = '\0'; | |
237 | } | |
c7de829c WD |
238 | } |
239 | ||
240 | /**************************************************************************** | |
241 | REMARKS: | |
242 | Add a user defined PM_fatalError cleanup function. | |
243 | ****************************************************************************/ | |
244 | void PMAPI PM_setFatalErrorCleanup( | |
245 | void (PMAPIP cleanup)(void)) | |
246 | { | |
247 | fatalErrorCleanup = cleanup; | |
248 | } | |
249 | ||
250 | /**************************************************************************** | |
251 | REMARKS: | |
252 | Report a fatal error condition and halt the program. | |
253 | ****************************************************************************/ | |
254 | void PMAPI PM_fatalError( | |
255 | const char *msg) | |
256 | { | |
257 | if (fatalErrorCleanup) | |
8bde7f77 | 258 | fatalErrorCleanup(); |
c7de829c WD |
259 | MessageBox(NULL,msg,"Fatal Error!", MB_ICONEXCLAMATION); |
260 | exit(1); | |
261 | } | |
262 | ||
263 | /**************************************************************************** | |
264 | REMARKS: | |
265 | Allocate the real mode VESA transfer buffer for communicating with the BIOS. | |
266 | ****************************************************************************/ | |
267 | void * PMAPI PM_getVESABuf( | |
268 | uint *len, | |
269 | uint *rseg, | |
270 | uint *roff) | |
271 | { | |
272 | DWORD outBuf[4]; /* Buffer to receive data from VxD */ | |
273 | DWORD count; /* Count of bytes returned from VxD */ | |
274 | ||
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). | |
280 | */ | |
281 | if (!inited) | |
8bde7f77 | 282 | PM_init(); |
c7de829c | 283 | if (!VESABuf_ptr) { |
8bde7f77 WD |
284 | CHECK_FOR_PMHELP(); |
285 | if (DeviceIoControl(_PM_hDevice, PMHELP_GETVESABUF32, NULL, 0, | |
286 | outBuf, sizeof(outBuf), &count, NULL)) { | |
287 | if (!outBuf[0]) | |
288 | return NULL; | |
289 | VESABuf_ptr = (void*)outBuf[0]; | |
290 | VESABuf_len = outBuf[1]; | |
291 | VESABuf_rseg = outBuf[2]; | |
292 | VESABuf_roff = outBuf[3]; | |
293 | } | |
294 | } | |
c7de829c WD |
295 | *len = VESABuf_len; |
296 | *rseg = VESABuf_rseg; | |
297 | *roff = VESABuf_roff; | |
298 | return VESABuf_ptr; | |
299 | } | |
300 | ||
301 | /**************************************************************************** | |
302 | REMARKS: | |
303 | Check if a key has been pressed. | |
304 | ****************************************************************************/ | |
305 | int PMAPI PM_kbhit(void) | |
306 | { | |
307 | /* Not used in Windows */ | |
308 | return true; | |
309 | } | |
310 | ||
311 | /**************************************************************************** | |
312 | REMARKS: | |
313 | Wait for and return the next keypress. | |
314 | ****************************************************************************/ | |
315 | int PMAPI PM_getch(void) | |
316 | { | |
317 | /* Not used in Windows */ | |
318 | return 0xD; | |
319 | } | |
320 | ||
321 | /**************************************************************************** | |
322 | REMARKS: | |
323 | Set the location of the OS console cursor. | |
324 | ****************************************************************************/ | |
325 | void PM_setOSCursorLocation( | |
326 | int x, | |
327 | int y) | |
328 | { | |
329 | /* Nothing to do for Windows */ | |
330 | (void)x; | |
331 | (void)y; | |
332 | } | |
333 | ||
334 | /**************************************************************************** | |
335 | REMARKS: | |
336 | Set the width of the OS console. | |
337 | ****************************************************************************/ | |
338 | void PM_setOSScreenWidth( | |
339 | int width, | |
340 | int height) | |
341 | { | |
342 | /* Nothing to do for Windows */ | |
343 | (void)width; | |
344 | (void)height; | |
345 | } | |
346 | ||
347 | /**************************************************************************** | |
348 | REMARKS: | |
349 | Set the real time clock handler (used for software stereo modes). | |
350 | ****************************************************************************/ | |
351 | ibool PMAPI PM_setRealTimeClockHandler( | |
352 | PM_intHandler ih, | |
353 | int frequency) | |
354 | { | |
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 | |
357 | * the VxD level. | |
358 | */ | |
359 | (void)ih; | |
360 | (void)frequency; | |
361 | return false; | |
362 | } | |
363 | ||
364 | /**************************************************************************** | |
365 | REMARKS: | |
366 | Set the real time clock frequency (for stereo modes). | |
367 | ****************************************************************************/ | |
368 | void PMAPI PM_setRealTimeClockFrequency( | |
369 | int frequency) | |
370 | { | |
371 | /* Not supported under Win32 */ | |
372 | (void)frequency; | |
373 | } | |
374 | ||
375 | /**************************************************************************** | |
376 | REMARKS: | |
377 | Restore the original real time clock handler. | |
378 | ****************************************************************************/ | |
379 | void PMAPI PM_restoreRealTimeClockHandler(void) | |
380 | { | |
381 | /* Not supported under Win32 */ | |
382 | } | |
383 | ||
384 | /**************************************************************************** | |
385 | REMARKS: | |
386 | Return the current operating system path or working directory. | |
387 | ****************************************************************************/ | |
388 | char * PMAPI PM_getCurrentPath( | |
389 | char *path, | |
390 | int maxLen) | |
391 | { | |
392 | return getcwd(path,maxLen); | |
393 | } | |
394 | ||
395 | /**************************************************************************** | |
396 | REMARKS: | |
397 | Query a string from the registry (extended version). | |
398 | ****************************************************************************/ | |
399 | static ibool REG_queryStringEx( | |
400 | HKEY hKey, | |
401 | const char *szValue, | |
402 | char *value, | |
403 | ulong size) | |
404 | { | |
405 | DWORD type; | |
406 | ||
407 | if (RegQueryValueEx(hKey,(PCHAR)szValue,(PDWORD)NULL,(PDWORD)&type,(LPBYTE)value,(PDWORD)&size) == ERROR_SUCCESS) | |
8bde7f77 | 408 | return true; |
c7de829c WD |
409 | return false; |
410 | } | |
411 | ||
412 | /**************************************************************************** | |
413 | REMARKS: | |
414 | Query a string from the registry. | |
415 | ****************************************************************************/ | |
416 | static ibool REG_queryString( | |
417 | const char *szKey, | |
418 | const char *szValue, | |
419 | char *value, | |
420 | DWORD size) | |
421 | { | |
422 | HKEY hKey; | |
423 | ibool status = false; | |
424 | ||
425 | memset(value,0,sizeof(value)); | |
426 | if (RegOpenKey(HKEY_LOCAL_MACHINE,szKey,&hKey) == ERROR_SUCCESS) { | |
8bde7f77 WD |
427 | status = REG_queryStringEx(hKey,szValue,value,size); |
428 | RegCloseKey(hKey); | |
429 | } | |
c7de829c WD |
430 | return status; |
431 | } | |
432 | ||
433 | /**************************************************************************** | |
434 | REMARKS: | |
435 | Return the drive letter for the boot drive. | |
436 | ****************************************************************************/ | |
437 | char PMAPI PM_getBootDrive(void) | |
438 | { | |
439 | static char path[256]; | |
440 | GetSystemDirectory(path,sizeof(path)); | |
441 | return path[0]; | |
442 | } | |
443 | ||
444 | /**************************************************************************** | |
445 | REMARKS: | |
446 | Return the path to the VBE/AF driver files. | |
447 | ****************************************************************************/ | |
448 | const char * PMAPI PM_getVBEAFPath(void) | |
449 | { | |
450 | return "c:\\"; | |
451 | } | |
452 | ||
453 | /**************************************************************************** | |
454 | REMARKS: | |
455 | Return the path to the Nucleus driver files. | |
456 | ****************************************************************************/ | |
457 | const char * PMAPI PM_getNucleusPath(void) | |
458 | { | |
459 | static char path[256]; | |
460 | char *env; | |
461 | ||
462 | if ((env = getenv("NUCLEUS_PATH")) != NULL) | |
8bde7f77 | 463 | return env; |
c7de829c WD |
464 | GetSystemDirectory(path,sizeof(path)); |
465 | strcat(path,"\\nucleus"); | |
466 | return path; | |
467 | } | |
468 | ||
469 | /**************************************************************************** | |
470 | REMARKS: | |
471 | Return the path to the Nucleus configuration files. | |
472 | ****************************************************************************/ | |
473 | const char * PMAPI PM_getNucleusConfigPath(void) | |
474 | { | |
475 | static char path[256]; | |
476 | strcpy(path,PM_getNucleusPath()); | |
477 | PM_backslash(path); | |
478 | strcat(path,"config"); | |
479 | return path; | |
480 | } | |
481 | ||
482 | /**************************************************************************** | |
483 | REMARKS: | |
484 | Return a unique identifier for the machine if possible. | |
485 | ****************************************************************************/ | |
486 | const char * PMAPI PM_getUniqueID(void) | |
487 | { | |
488 | return PM_getMachineName(); | |
489 | } | |
490 | ||
491 | /**************************************************************************** | |
492 | REMARKS: | |
493 | Get the name of the machine on the network. | |
494 | ****************************************************************************/ | |
495 | const char * PMAPI PM_getMachineName(void) | |
496 | { | |
497 | static char name[256]; | |
498 | ||
499 | if (REG_queryString(szMachineNameKey,szMachineName,name,sizeof(name))) | |
8bde7f77 | 500 | return name; |
c7de829c | 501 | if (REG_queryString(szMachineNameKeyNT,szMachineName,name,sizeof(name))) |
8bde7f77 | 502 | return name; |
c7de829c WD |
503 | return "Unknown"; |
504 | } | |
505 | ||
506 | /**************************************************************************** | |
507 | REMARKS: | |
508 | Return a pointer to the real mode BIOS data area. | |
509 | ****************************************************************************/ | |
510 | void * PMAPI PM_getBIOSPointer(void) | |
511 | { | |
512 | if (_PM_haveWinNT) { | |
8bde7f77 | 513 | /* On Windows NT we have to map it physically directly */ |
c7de829c | 514 | return PM_mapPhysicalAddr(0x400, 0x1000, true); |
8bde7f77 | 515 | } |
c7de829c | 516 | else { |
8bde7f77 WD |
517 | /* For Windows 9x we can access this memory directly */ |
518 | return (void*)0x400; | |
519 | } | |
c7de829c WD |
520 | } |
521 | ||
522 | /**************************************************************************** | |
523 | REMARKS: | |
524 | Return a pointer to 0xA0000 physical VGA graphics framebuffer. | |
525 | ****************************************************************************/ | |
526 | void * PMAPI PM_getA0000Pointer(void) | |
527 | { | |
528 | if (_PM_haveWinNT) { | |
8bde7f77 | 529 | /* On Windows NT we have to map it physically directly */ |
c7de829c | 530 | return PM_mapPhysicalAddr(0xA0000, 0x0FFFF, false); |
8bde7f77 | 531 | } |
c7de829c | 532 | else { |
8bde7f77 WD |
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 | |
535 | * bank switching. | |
536 | */ | |
537 | return (void*)0xA0000; | |
538 | } | |
c7de829c WD |
539 | } |
540 | ||
541 | /**************************************************************************** | |
542 | REMARKS: | |
543 | Map a physical address to a linear address in the callers process. | |
544 | ****************************************************************************/ | |
545 | void * PMAPI PM_mapPhysicalAddr( | |
546 | ulong base, | |
547 | ulong limit, | |
548 | ibool isCached) | |
549 | { | |
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 */ | |
553 | ||
554 | if (!inited) | |
8bde7f77 | 555 | PM_init(); |
c7de829c WD |
556 | inBuf[0] = base; |
557 | inBuf[1] = limit; | |
558 | inBuf[2] = isCached; | |
559 | CHECK_FOR_PMHELP(); | |
560 | if (DeviceIoControl(_PM_hDevice, PMHELP_MAPPHYS32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
561 | outBuf, sizeof(outBuf), &count, NULL)) |
562 | return (void*)outBuf[0]; | |
c7de829c WD |
563 | return NULL; |
564 | } | |
565 | ||
566 | /**************************************************************************** | |
567 | REMARKS: | |
568 | Free a physical address mapping allocated by PM_mapPhysicalAddr. | |
569 | ****************************************************************************/ | |
570 | void PMAPI PM_freePhysicalAddr( | |
571 | void *ptr, | |
572 | ulong limit) | |
573 | { | |
574 | /* We never free the mappings under Win32 (the VxD tracks them and | |
575 | * reissues the same mappings until the system is rebooted). | |
576 | */ | |
577 | (void)ptr; | |
578 | (void)limit; | |
579 | } | |
580 | ||
581 | /**************************************************************************** | |
582 | REMARKS: | |
583 | Find the physical address of a linear memory address in current process. | |
584 | ****************************************************************************/ | |
585 | ulong PMAPI PM_getPhysicalAddr( | |
586 | void *p) | |
587 | { | |
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 */ | |
591 | ||
592 | if (!inited) | |
8bde7f77 | 593 | PM_init(); |
c7de829c WD |
594 | inBuf[0] = (ulong)p; |
595 | CHECK_FOR_PMHELP(); | |
596 | if (DeviceIoControl(_PM_hDevice, PMHELP_GETPHYSICALADDR32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
597 | outBuf, sizeof(outBuf), &count, NULL)) |
598 | return outBuf[0]; | |
c7de829c WD |
599 | return 0xFFFFFFFFUL; |
600 | } | |
601 | ||
602 | /**************************************************************************** | |
603 | REMARKS: | |
604 | Find the physical address of a linear memory address in current process. | |
605 | ****************************************************************************/ | |
606 | ibool PMAPI PM_getPhysicalAddrRange( | |
607 | void *p, | |
608 | ulong length, | |
609 | ulong *physAddress) | |
610 | { | |
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 */ | |
614 | ||
615 | if (!inited) | |
8bde7f77 | 616 | PM_init(); |
c7de829c WD |
617 | inBuf[0] = (ulong)p; |
618 | inBuf[1] = (ulong)length; | |
619 | inBuf[2] = (ulong)physAddress; | |
620 | CHECK_FOR_PMHELP(); | |
621 | if (DeviceIoControl(_PM_hDevice, PMHELP_GETPHYSICALADDRRANGE32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
622 | outBuf, sizeof(outBuf), &count, NULL)) |
623 | return outBuf[0]; | |
c7de829c WD |
624 | return false; |
625 | } | |
626 | ||
627 | /**************************************************************************** | |
628 | REMARKS: | |
629 | Sleep for the specified number of milliseconds. | |
630 | ****************************************************************************/ | |
631 | void PMAPI PM_sleep( | |
632 | ulong milliseconds) | |
633 | { | |
634 | Sleep(milliseconds); | |
635 | } | |
636 | ||
637 | /**************************************************************************** | |
638 | REMARKS: | |
639 | Return the base I/O port for the specified COM port. | |
640 | ****************************************************************************/ | |
641 | int PMAPI PM_getCOMPort(int port) | |
642 | { | |
8bde7f77 WD |
643 | /* TODO: Re-code this to determine real values using the Plug and Play */ |
644 | /* manager for the OS. */ | |
c7de829c | 645 | switch (port) { |
8bde7f77 WD |
646 | case 0: return 0x3F8; |
647 | case 1: return 0x2F8; | |
648 | case 2: return 0x3E8; | |
649 | case 3: return 0x2E8; | |
650 | } | |
c7de829c WD |
651 | return 0; |
652 | } | |
653 | ||
654 | /**************************************************************************** | |
655 | REMARKS: | |
656 | Return the base I/O port for the specified LPT port. | |
657 | ****************************************************************************/ | |
658 | int PMAPI PM_getLPTPort(int port) | |
659 | { | |
8bde7f77 WD |
660 | /* TODO: Re-code this to determine real values using the Plug and Play */ |
661 | /* manager for the OS. */ | |
c7de829c | 662 | switch (port) { |
8bde7f77 WD |
663 | case 0: return 0x3BC; |
664 | case 1: return 0x378; | |
665 | case 2: return 0x278; | |
666 | } | |
c7de829c WD |
667 | return 0; |
668 | } | |
669 | ||
670 | /**************************************************************************** | |
671 | REMARKS: | |
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 | |
676 | 0 interrupt context. | |
677 | ****************************************************************************/ | |
678 | void * PMAPI PM_mallocShared( | |
679 | long size) | |
680 | { | |
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 */ | |
684 | ||
685 | inBuf[0] = size; | |
686 | CHECK_FOR_PMHELP(); | |
687 | if (DeviceIoControl(_PM_hDevice, PMHELP_MALLOCSHARED32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
688 | outBuf, sizeof(outBuf), &count, NULL)) |
689 | return (void*)outBuf[0]; | |
c7de829c WD |
690 | return NULL; |
691 | } | |
692 | ||
693 | /**************************************************************************** | |
694 | REMARKS: | |
695 | Free a block of shared memory. | |
696 | ****************************************************************************/ | |
697 | void PMAPI PM_freeShared( | |
698 | void *ptr) | |
699 | { | |
700 | DWORD inBuf[1]; /* Buffer to send data to VxD */ | |
701 | ||
702 | inBuf[0] = (ulong)ptr; | |
703 | CHECK_FOR_PMHELP(); | |
704 | DeviceIoControl(_PM_hDevice, PMHELP_FREESHARED32, inBuf, sizeof(inBuf), NULL, 0, NULL, NULL); | |
705 | } | |
706 | ||
707 | /**************************************************************************** | |
708 | REMARKS: | |
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( | |
714 | void *base, | |
715 | ulong limit) | |
716 | { | |
717 | (void)base; | |
718 | (void)limit; | |
719 | return base; | |
720 | } | |
721 | ||
722 | /**************************************************************************** | |
723 | REMARKS: | |
724 | Map a real mode pointer to a protected mode pointer. | |
725 | ****************************************************************************/ | |
726 | void * PMAPI PM_mapRealPointer( | |
727 | uint r_seg, | |
728 | uint r_off) | |
729 | { | |
730 | return (void*)(MK_PHYS(r_seg,r_off)); | |
731 | } | |
732 | ||
733 | /**************************************************************************** | |
734 | REMARKS: | |
735 | Allocate a block of real mode memory | |
736 | ****************************************************************************/ | |
737 | void * PMAPI PM_allocRealSeg( | |
738 | uint size, | |
739 | uint *r_seg, | |
740 | uint *r_off) | |
741 | { | |
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). | |
745 | */ | |
746 | (void)size; | |
747 | (void)r_seg; | |
748 | (void)r_off; | |
749 | return NULL; | |
750 | } | |
751 | ||
752 | /**************************************************************************** | |
753 | REMARKS: | |
754 | Free a block of real mode memory. | |
755 | ****************************************************************************/ | |
756 | void PMAPI PM_freeRealSeg( | |
757 | void *mem) | |
758 | { | |
759 | /* Not supported in Windows */ | |
760 | (void)mem; | |
761 | } | |
762 | ||
763 | /**************************************************************************** | |
764 | REMARKS: | |
765 | Issue a real mode interrupt (parameters in DPMI compatible structure) | |
766 | ****************************************************************************/ | |
767 | void PMAPI DPMI_int86( | |
768 | int intno, | |
769 | DPMI_regs *regs) | |
770 | { | |
771 | DWORD inBuf[2]; /* Buffer to send data to VxD */ | |
772 | DWORD count; /* Count of bytes returned from VxD */ | |
773 | ||
774 | if (!inited) | |
8bde7f77 | 775 | PM_init(); |
c7de829c WD |
776 | inBuf[0] = intno; |
777 | inBuf[1] = (ulong)regs; | |
778 | CHECK_FOR_PMHELP(); | |
779 | DeviceIoControl(_PM_hDevice, PMHELP_DPMIINT8632, inBuf, sizeof(inBuf), | |
8bde7f77 | 780 | NULL, 0, &count, NULL); |
c7de829c WD |
781 | } |
782 | ||
783 | /**************************************************************************** | |
784 | REMARKS: | |
785 | Issue a real mode interrupt. | |
786 | ****************************************************************************/ | |
787 | int PMAPI PM_int86( | |
788 | int intno, | |
789 | RMREGS *in, | |
790 | RMREGS *out) | |
791 | { | |
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 */ | |
795 | ||
796 | if (!inited) | |
8bde7f77 | 797 | PM_init(); |
c7de829c WD |
798 | inBuf[0] = intno; |
799 | inBuf[1] = (ulong)in; | |
800 | inBuf[2] = (ulong)out; | |
801 | CHECK_FOR_PMHELP(); | |
802 | if (DeviceIoControl(_PM_hDevice, PMHELP_INT8632, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
803 | outBuf, sizeof(outBuf), &count, NULL)) |
804 | return outBuf[0]; | |
c7de829c WD |
805 | return 0; |
806 | } | |
807 | ||
808 | /**************************************************************************** | |
809 | REMARKS: | |
810 | Issue a real mode interrupt. | |
811 | ****************************************************************************/ | |
812 | int PMAPI PM_int86x( | |
813 | int intno, | |
814 | RMREGS *in, | |
815 | RMREGS *out, | |
816 | RMSREGS *sregs) | |
817 | { | |
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 */ | |
821 | ||
822 | if (!inited) | |
8bde7f77 | 823 | PM_init(); |
c7de829c WD |
824 | inBuf[0] = intno; |
825 | inBuf[1] = (ulong)in; | |
826 | inBuf[2] = (ulong)out; | |
827 | inBuf[3] = (ulong)sregs; | |
828 | CHECK_FOR_PMHELP(); | |
829 | if (DeviceIoControl(_PM_hDevice, PMHELP_INT86X32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
830 | outBuf, sizeof(outBuf), &count, NULL)) |
831 | return outBuf[0]; | |
c7de829c WD |
832 | return 0; |
833 | } | |
834 | ||
835 | /**************************************************************************** | |
836 | REMARKS: | |
837 | Call a real mode far function. | |
838 | ****************************************************************************/ | |
839 | void PMAPI PM_callRealMode( | |
840 | uint seg, | |
841 | uint off, | |
842 | RMREGS *in, | |
843 | RMSREGS *sregs) | |
844 | { | |
845 | DWORD inBuf[4]; /* Buffer to send data to VxD */ | |
846 | DWORD count; /* Count of bytes returned from VxD */ | |
847 | ||
848 | if (!inited) | |
8bde7f77 | 849 | PM_init(); |
c7de829c WD |
850 | inBuf[0] = seg; |
851 | inBuf[1] = off; | |
852 | inBuf[2] = (ulong)in; | |
853 | inBuf[3] = (ulong)sregs; | |
854 | CHECK_FOR_PMHELP(); | |
855 | DeviceIoControl(_PM_hDevice, PMHELP_CALLREALMODE32, inBuf, sizeof(inBuf), | |
8bde7f77 | 856 | NULL, 0, &count, NULL); |
c7de829c WD |
857 | } |
858 | ||
859 | /**************************************************************************** | |
860 | REMARKS: | |
861 | Return the amount of available memory. | |
862 | ****************************************************************************/ | |
863 | void PMAPI PM_availableMemory( | |
864 | ulong *physical, | |
865 | ulong *total) | |
866 | { | |
867 | /* We don't support this under Win32 at the moment */ | |
868 | *physical = *total = 0; | |
869 | } | |
870 | ||
871 | /**************************************************************************** | |
872 | REMARKS: | |
873 | Allocate a block of locked, physical memory for DMA operations. | |
874 | ****************************************************************************/ | |
875 | void * PMAPI PM_allocLockedMem( | |
876 | uint size, | |
877 | ulong *physAddr, | |
878 | ibool contiguous, | |
879 | ibool below16M) | |
880 | { | |
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 */ | |
884 | ||
885 | if (!inited) | |
8bde7f77 | 886 | PM_init(); |
c7de829c WD |
887 | inBuf[0] = size; |
888 | inBuf[1] = (ulong)physAddr; | |
889 | inBuf[2] = (ulong)contiguous; | |
890 | inBuf[3] = (ulong)below16M; | |
891 | CHECK_FOR_PMHELP(); | |
892 | if (DeviceIoControl(_PM_hDevice, PMHELP_ALLOCLOCKED32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
893 | outBuf, sizeof(outBuf), &count, NULL)) |
894 | return (void*)outBuf[0]; | |
c7de829c WD |
895 | return NULL; |
896 | } | |
897 | ||
898 | /**************************************************************************** | |
899 | REMARKS: | |
900 | Free a block of locked physical memory. | |
901 | ****************************************************************************/ | |
902 | void PMAPI PM_freeLockedMem( | |
903 | void *p, | |
904 | uint size, | |
905 | ibool contiguous) | |
906 | { | |
907 | DWORD inBuf[3]; /* Buffer to send data to VxD */ | |
908 | DWORD count; /* Count of bytes returned from VxD */ | |
909 | ||
910 | if (!inited) | |
8bde7f77 | 911 | PM_init(); |
c7de829c WD |
912 | inBuf[0] = (ulong)p; |
913 | inBuf[1] = size; | |
914 | inBuf[2] = contiguous; | |
915 | CHECK_FOR_PMHELP(); | |
916 | DeviceIoControl(_PM_hDevice, PMHELP_FREELOCKED32, inBuf, sizeof(inBuf), | |
8bde7f77 | 917 | NULL, 0, &count, NULL); |
c7de829c WD |
918 | } |
919 | ||
920 | /**************************************************************************** | |
921 | REMARKS: | |
922 | Allocates a page aligned and page sized block of memory | |
923 | ****************************************************************************/ | |
924 | void * PMAPI PM_allocPage( | |
925 | ibool locked) | |
926 | { | |
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 */ | |
930 | ||
931 | if (!inited) | |
8bde7f77 | 932 | PM_init(); |
c7de829c WD |
933 | inBuf[0] = locked; |
934 | CHECK_FOR_PMHELP(); | |
935 | if (DeviceIoControl(_PM_hDevice, PMHELP_ALLOCPAGE32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
936 | outBuf, sizeof(outBuf), &count, NULL)) |
937 | return (void*)outBuf[0]; | |
c7de829c WD |
938 | return NULL; |
939 | } | |
940 | ||
941 | /**************************************************************************** | |
942 | REMARKS: | |
943 | Free a page aligned and page sized block of memory | |
944 | ****************************************************************************/ | |
945 | void PMAPI PM_freePage( | |
946 | void *p) | |
947 | { | |
948 | DWORD inBuf[1]; /* Buffer to send data to VxD */ | |
949 | DWORD count; /* Count of bytes returned from VxD */ | |
950 | ||
951 | if (!inited) | |
8bde7f77 | 952 | PM_init(); |
c7de829c WD |
953 | inBuf[0] = (ulong)p; |
954 | CHECK_FOR_PMHELP(); | |
955 | DeviceIoControl(_PM_hDevice, PMHELP_FREEPAGE32, inBuf, sizeof(inBuf), | |
8bde7f77 | 956 | NULL, 0, &count, NULL); |
c7de829c WD |
957 | } |
958 | ||
959 | /**************************************************************************** | |
960 | REMARKS: | |
961 | Lock linear memory so it won't be paged. | |
962 | ****************************************************************************/ | |
963 | int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh) | |
964 | { | |
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 */ | |
968 | ||
969 | inBuf[0] = (ulong)p; | |
970 | inBuf[1] = len; | |
971 | inBuf[2] = (ulong)lh; | |
972 | CHECK_FOR_PMHELP(); | |
973 | if (DeviceIoControl(_PM_hDevice, PMHELP_LOCKDATAPAGES32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
974 | outBuf, sizeof(outBuf), &count, NULL)) |
975 | return outBuf[0]; | |
c7de829c WD |
976 | return 0; |
977 | } | |
978 | ||
979 | /**************************************************************************** | |
980 | REMARKS: | |
981 | Unlock linear memory so it won't be paged. | |
982 | ****************************************************************************/ | |
983 | int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh) | |
984 | { | |
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 */ | |
988 | ||
989 | inBuf[0] = (ulong)p; | |
990 | inBuf[1] = len; | |
991 | inBuf[2] = (ulong)lh; | |
992 | CHECK_FOR_PMHELP(); | |
993 | if (DeviceIoControl(_PM_hDevice, PMHELP_UNLOCKDATAPAGES32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
994 | outBuf, sizeof(outBuf), &count, NULL)) |
995 | return outBuf[0]; | |
c7de829c WD |
996 | return 0; |
997 | } | |
998 | ||
999 | /**************************************************************************** | |
1000 | REMARKS: | |
1001 | Lock linear memory so it won't be paged. | |
1002 | ****************************************************************************/ | |
1003 | int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh) | |
1004 | { | |
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 */ | |
1008 | ||
1009 | inBuf[0] = (ulong)p; | |
1010 | inBuf[1] = len; | |
1011 | inBuf[2] = (ulong)lh; | |
1012 | CHECK_FOR_PMHELP(); | |
1013 | if (DeviceIoControl(_PM_hDevice, PMHELP_LOCKCODEPAGES32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
1014 | outBuf, sizeof(outBuf), &count, NULL)) |
1015 | return outBuf[0]; | |
c7de829c WD |
1016 | return 0; |
1017 | } | |
1018 | ||
1019 | /**************************************************************************** | |
1020 | REMARKS: | |
1021 | Unlock linear memory so it won't be paged. | |
1022 | ****************************************************************************/ | |
1023 | int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh) | |
1024 | { | |
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 */ | |
1028 | ||
1029 | inBuf[0] = (ulong)p; | |
1030 | inBuf[1] = len; | |
1031 | inBuf[2] = (ulong)lh; | |
1032 | CHECK_FOR_PMHELP(); | |
1033 | if (DeviceIoControl(_PM_hDevice, PMHELP_UNLOCKCODEPAGES32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
1034 | outBuf, sizeof(outBuf), &count, NULL)) |
1035 | return outBuf[0]; | |
c7de829c WD |
1036 | return 0; |
1037 | } | |
1038 | ||
1039 | /**************************************************************************** | |
1040 | REMARKS: | |
1041 | Call the VBE/Core software interrupt to change display banks. | |
1042 | ****************************************************************************/ | |
1043 | void PMAPI PM_setBankA( | |
1044 | int bank) | |
1045 | { | |
1046 | RMREGS regs; | |
1047 | regs.x.ax = 0x4F05; | |
1048 | regs.x.bx = 0x0000; | |
1049 | regs.x.dx = bank; | |
1050 | PM_int86(0x10,®s,®s); | |
1051 | } | |
1052 | ||
1053 | /**************************************************************************** | |
1054 | REMARKS: | |
1055 | Call the VBE/Core software interrupt to change display banks. | |
1056 | ****************************************************************************/ | |
1057 | void PMAPI PM_setBankAB( | |
1058 | int bank) | |
1059 | { | |
1060 | RMREGS regs; | |
1061 | regs.x.ax = 0x4F05; | |
1062 | regs.x.bx = 0x0000; | |
1063 | regs.x.dx = bank; | |
1064 | PM_int86(0x10,®s,®s); | |
1065 | regs.x.ax = 0x4F05; | |
1066 | regs.x.bx = 0x0001; | |
1067 | regs.x.dx = bank; | |
1068 | PM_int86(0x10,®s,®s); | |
1069 | } | |
1070 | ||
1071 | /**************************************************************************** | |
1072 | REMARKS: | |
1073 | Call the VBE/Core software interrupt to change display start address. | |
1074 | ****************************************************************************/ | |
1075 | void PMAPI PM_setCRTStart( | |
1076 | int x, | |
1077 | int y, | |
1078 | int waitVRT) | |
1079 | { | |
1080 | RMREGS regs; | |
1081 | regs.x.ax = 0x4F07; | |
1082 | regs.x.bx = waitVRT; | |
1083 | regs.x.cx = x; | |
1084 | regs.x.dx = y; | |
1085 | PM_int86(0x10,®s,®s); | |
1086 | } | |
1087 | ||
1088 | /**************************************************************************** | |
1089 | REMARKS: | |
1090 | Enable write combining for the memory region. | |
1091 | ****************************************************************************/ | |
1092 | ibool PMAPI PM_enableWriteCombine( | |
1093 | ulong base, | |
1094 | ulong length, | |
1095 | uint type) | |
1096 | { | |
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 */ | |
1100 | ||
1101 | if (!inited) | |
8bde7f77 | 1102 | PM_init(); |
c7de829c WD |
1103 | inBuf[0] = base; |
1104 | inBuf[1] = length; | |
1105 | inBuf[2] = type; | |
1106 | CHECK_FOR_PMHELP(); | |
1107 | if (DeviceIoControl(_PM_hDevice, PMHELP_ENABLELFBCOMB32, inBuf, sizeof(inBuf), | |
8bde7f77 WD |
1108 | outBuf, sizeof(outBuf), &count, NULL)) |
1109 | return outBuf[0]; | |
c7de829c WD |
1110 | return false; |
1111 | } | |
1112 | ||
1113 | /**************************************************************************** | |
1114 | REMARKS: | |
1115 | Get the page directory base register value | |
1116 | ****************************************************************************/ | |
1117 | ulong PMAPI _PM_getPDB(void) | |
1118 | { | |
1119 | DWORD outBuf[1]; /* Buffer to receive data from VxD */ | |
1120 | DWORD count; /* Count of bytes returned from VxD */ | |
1121 | ||
1122 | CHECK_FOR_PMHELP(); | |
1123 | if (DeviceIoControl(_PM_hDevice, PMHELP_GETPDB32, NULL, 0, | |
8bde7f77 WD |
1124 | outBuf, sizeof(outBuf), &count, NULL)) |
1125 | return outBuf[0]; | |
c7de829c WD |
1126 | return 0; |
1127 | } | |
1128 | ||
1129 | /**************************************************************************** | |
1130 | REMARKS: | |
1131 | Flush the translation lookaside buffer. | |
1132 | ****************************************************************************/ | |
1133 | void PMAPI PM_flushTLB(void) | |
1134 | { | |
1135 | CHECK_FOR_PMHELP(); | |
1136 | DeviceIoControl(_PM_hDevice, PMHELP_FLUSHTLB32, NULL, 0, NULL, 0, NULL, NULL); | |
1137 | } | |
1138 | ||
1139 | /**************************************************************************** | |
1140 | REMARKS: | |
1141 | Execute the POST on the secondary BIOS for a controller. | |
1142 | ****************************************************************************/ | |
1143 | ibool PMAPI PM_doBIOSPOST( | |
1144 | ushort axVal, | |
1145 | ulong BIOSPhysAddr, | |
1146 | void *mappedBIOS, | |
1147 | ulong BIOSLen) | |
1148 | { | |
1149 | /* This is never done by Win32 programs, but rather done by the VxD | |
1150 | * when the system boots. | |
1151 | */ | |
1152 | (void)axVal; | |
1153 | (void)BIOSPhysAddr; | |
1154 | (void)mappedBIOS; | |
1155 | (void)BIOSLen; | |
1156 | return false; | |
1157 | } | |
1158 | ||
1159 | /**************************************************************************** | |
1160 | REMARKS: | |
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) | |
1166 | { | |
1167 | return (PM_MODULE)LoadLibrary(szDLLName); | |
1168 | } | |
1169 | ||
1170 | /**************************************************************************** | |
1171 | REMARKS: | |
1172 | Get the address of a named procedure from a shared library. | |
1173 | ****************************************************************************/ | |
1174 | void * PMAPI PM_getProcAddress( | |
1175 | PM_MODULE hModule, | |
1176 | const char *szProcName) | |
1177 | { | |
1178 | return (void*)GetProcAddress((HINSTANCE)hModule,szProcName); | |
1179 | } | |
1180 | ||
1181 | /**************************************************************************** | |
1182 | REMARKS: | |
1183 | Unload a shared library. | |
1184 | ****************************************************************************/ | |
1185 | void PMAPI PM_freeLibrary( | |
1186 | PM_MODULE hModule) | |
1187 | { | |
1188 | FreeLibrary((HINSTANCE)hModule); | |
1189 | } | |
1190 | ||
1191 | /**************************************************************************** | |
1192 | REMARKS: | |
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) | |
1198 | { | |
1199 | ulong dwSize = findData->dwSize; | |
1200 | ||
1201 | memset(findData,0,findData->dwSize); | |
1202 | findData->dwSize = dwSize; | |
1203 | if (blk->dwFileAttributes & FILE_ATTRIBUTE_READONLY) | |
8bde7f77 | 1204 | findData->attrib |= PM_FILE_READONLY; |
c7de829c | 1205 | if (blk->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
8bde7f77 | 1206 | findData->attrib |= PM_FILE_DIRECTORY; |
c7de829c | 1207 | if (blk->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) |
8bde7f77 | 1208 | findData->attrib |= PM_FILE_ARCHIVE; |
c7de829c | 1209 | if (blk->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) |
8bde7f77 | 1210 | findData->attrib |= PM_FILE_HIDDEN; |
c7de829c | 1211 | if (blk->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) |
8bde7f77 | 1212 | findData->attrib |= PM_FILE_SYSTEM; |
c7de829c WD |
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; | |
1217 | } | |
1218 | ||
1219 | /**************************************************************************** | |
1220 | REMARKS: | |
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) | |
1226 | { | |
1227 | WIN32_FIND_DATA blk; | |
1228 | HANDLE hfile; | |
1229 | ||
1230 | if ((hfile = FindFirstFile(filename,&blk)) != INVALID_HANDLE_VALUE) { | |
8bde7f77 WD |
1231 | convertFindData(findData,&blk); |
1232 | return (void*)hfile; | |
1233 | } | |
c7de829c WD |
1234 | return PM_FILE_INVALID; |
1235 | } | |
1236 | ||
1237 | /**************************************************************************** | |
1238 | REMARKS: | |
1239 | Function to find the next file matching a search criteria in a directory. | |
1240 | ****************************************************************************/ | |
1241 | ibool PMAPI PM_findNextFile( | |
1242 | void *handle, | |
1243 | PM_findData *findData) | |
1244 | { | |
1245 | WIN32_FIND_DATA blk; | |
1246 | ||
1247 | if (FindNextFile((HANDLE)handle,&blk)) { | |
8bde7f77 WD |
1248 | convertFindData(findData,&blk); |
1249 | return true; | |
1250 | } | |
c7de829c WD |
1251 | return false; |
1252 | } | |
1253 | ||
1254 | /**************************************************************************** | |
1255 | REMARKS: | |
1256 | Function to close the find process | |
1257 | ****************************************************************************/ | |
1258 | void PMAPI PM_findClose( | |
1259 | void *handle) | |
1260 | { | |
1261 | FindClose((HANDLE)handle); | |
1262 | } | |
1263 | ||
1264 | /**************************************************************************** | |
1265 | REMARKS: | |
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 | |
1269 | numbering is: | |
1270 | ||
1271 | 1 - Drive A: | |
1272 | 2 - Drive B: | |
1273 | 3 - Drive C: | |
1274 | etc | |
1275 | ||
1276 | ****************************************************************************/ | |
1277 | ibool PMAPI PM_driveValid( | |
1278 | char drive) | |
1279 | { | |
1280 | char buf[5]; | |
1281 | int type; | |
1282 | ||
1283 | sprintf(buf,"%c:\\", drive); | |
1284 | return ((type = GetDriveType(buf)) != 0 && type != 1); | |
1285 | } | |
1286 | ||
1287 | /**************************************************************************** | |
1288 | REMARKS: | |
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( | |
1294 | int drive, | |
1295 | char *dir, | |
1296 | int len) | |
1297 | { | |
8bde7f77 WD |
1298 | /* NT stores the current directory for drive N in the magic environment */ |
1299 | /* variable =N: so we simply look for that environment variable. */ | |
c7de829c WD |
1300 | char envname[4]; |
1301 | ||
1302 | envname[0] = '='; | |
1303 | envname[1] = drive - 1 + 'A'; | |
1304 | envname[2] = ':'; | |
1305 | envname[3] = '\0'; | |
1306 | if (GetEnvironmentVariable(envname,dir,len) == 0) { | |
8bde7f77 WD |
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]; | |
1310 | dir[1] = ':'; | |
1311 | dir[2] = '\\'; | |
1312 | dir[3] = '\0'; | |
1313 | SetEnvironmentVariable(envname,dir); | |
1314 | } | |
c7de829c WD |
1315 | } |
1316 | ||
1317 | /**************************************************************************** | |
1318 | REMARKS: | |
1319 | Function to change the file attributes for a specific file. | |
1320 | ****************************************************************************/ | |
1321 | void PMAPI PM_setFileAttr( | |
1322 | const char *filename, | |
1323 | uint attrib) | |
1324 | { | |
1325 | DWORD attr = 0; | |
1326 | ||
1327 | if (attrib & PM_FILE_READONLY) | |
8bde7f77 | 1328 | attr |= FILE_ATTRIBUTE_READONLY; |
c7de829c | 1329 | if (attrib & PM_FILE_ARCHIVE) |
8bde7f77 | 1330 | attr |= FILE_ATTRIBUTE_ARCHIVE; |
c7de829c | 1331 | if (attrib & PM_FILE_HIDDEN) |
8bde7f77 | 1332 | attr |= FILE_ATTRIBUTE_HIDDEN; |
c7de829c | 1333 | if (attrib & PM_FILE_SYSTEM) |
8bde7f77 | 1334 | attr |= FILE_ATTRIBUTE_SYSTEM; |
c7de829c WD |
1335 | SetFileAttributes((LPSTR)filename, attr); |
1336 | } | |
1337 | ||
1338 | /**************************************************************************** | |
1339 | REMARKS: | |
1340 | Function to get the file attributes for a specific file. | |
1341 | ****************************************************************************/ | |
1342 | uint PMAPI PM_getFileAttr( | |
1343 | const char *filename) | |
1344 | { | |
1345 | DWORD attr = GetFileAttributes(filename); | |
1346 | uint attrib = 0; | |
1347 | ||
1348 | if (attr & FILE_ATTRIBUTE_READONLY) | |
8bde7f77 | 1349 | attrib |= PM_FILE_READONLY; |
c7de829c | 1350 | if (attr & FILE_ATTRIBUTE_ARCHIVE) |
8bde7f77 | 1351 | attrib |= PM_FILE_ARCHIVE; |
c7de829c | 1352 | if (attr & FILE_ATTRIBUTE_HIDDEN) |
8bde7f77 | 1353 | attrib |= PM_FILE_HIDDEN; |
c7de829c | 1354 | if (attr & FILE_ATTRIBUTE_SYSTEM) |
8bde7f77 | 1355 | attrib |= PM_FILE_SYSTEM; |
c7de829c WD |
1356 | return attrib; |
1357 | } | |
1358 | ||
1359 | /**************************************************************************** | |
1360 | REMARKS: | |
1361 | Function to create a directory. | |
1362 | ****************************************************************************/ | |
1363 | ibool PMAPI PM_mkdir( | |
1364 | const char *filename) | |
1365 | { | |
1366 | return CreateDirectory(filename,NULL); | |
1367 | } | |
1368 | ||
1369 | /**************************************************************************** | |
1370 | REMARKS: | |
1371 | Function to remove a directory. | |
1372 | ****************************************************************************/ | |
1373 | ibool PMAPI PM_rmdir( | |
1374 | const char *filename) | |
1375 | { | |
1376 | return RemoveDirectory(filename); | |
1377 | } | |
1378 | ||
1379 | /**************************************************************************** | |
1380 | REMARKS: | |
1381 | Function to get the file time and date for a specific file. | |
1382 | ****************************************************************************/ | |
1383 | ibool PMAPI PM_getFileTime( | |
1384 | const char *filename, | |
1385 | ibool gmTime, | |
1386 | PM_time *time) | |
1387 | { | |
1388 | HFILE f; | |
1389 | OFSTRUCT of; | |
1390 | FILETIME utcTime,localTime; | |
1391 | SYSTEMTIME sysTime; | |
1392 | ibool status = false; | |
1393 | ||
1394 | of.cBytes = sizeof(of); | |
1395 | if ((f = OpenFile(filename,&of,OF_READ)) == HFILE_ERROR) | |
8bde7f77 | 1396 | return false; |
c7de829c | 1397 | if (!GetFileTime((HANDLE)f,NULL,NULL,&utcTime)) |
8bde7f77 | 1398 | goto Exit; |
c7de829c | 1399 | if (!gmTime) { |
8bde7f77 WD |
1400 | if (!FileTimeToLocalFileTime(&utcTime,&localTime)) |
1401 | goto Exit; | |
1402 | } | |
c7de829c | 1403 | else |
8bde7f77 | 1404 | localTime = utcTime; |
c7de829c | 1405 | if (!FileTimeToSystemTime(&localTime,&sysTime)) |
8bde7f77 | 1406 | goto Exit; |
c7de829c WD |
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; | |
1413 | status = true; | |
1414 | ||
1415 | Exit: | |
1416 | CloseHandle((HANDLE)f); | |
1417 | return status; | |
1418 | } | |
1419 | ||
1420 | /**************************************************************************** | |
1421 | REMARKS: | |
1422 | Function to set the file time and date for a specific file. | |
1423 | ****************************************************************************/ | |
1424 | ibool PMAPI PM_setFileTime( | |
1425 | const char *filename, | |
1426 | ibool gmTime, | |
1427 | PM_time *time) | |
1428 | { | |
1429 | HFILE f; | |
1430 | OFSTRUCT of; | |
1431 | FILETIME utcTime,localTime; | |
1432 | SYSTEMTIME sysTime; | |
1433 | ibool status = false; | |
1434 | ||
1435 | of.cBytes = sizeof(of); | |
1436 | if ((f = OpenFile(filename,&of,OF_WRITE)) == HFILE_ERROR) | |
8bde7f77 | 1437 | return false; |
c7de829c WD |
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)) | |
8bde7f77 | 1445 | goto Exit; |
c7de829c | 1446 | if (!gmTime) { |
8bde7f77 WD |
1447 | if (!LocalFileTimeToFileTime(&localTime,&utcTime)) |
1448 | goto Exit; | |
1449 | } | |
c7de829c | 1450 | else |
8bde7f77 | 1451 | utcTime = localTime; |
c7de829c | 1452 | if (!SetFileTime((HANDLE)f,NULL,NULL,&utcTime)) |
8bde7f77 | 1453 | goto Exit; |
c7de829c WD |
1454 | status = true; |
1455 | ||
1456 | Exit: | |
1457 | CloseHandle((HANDLE)f); | |
1458 | return status; | |
1459 | } |