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 * ========================================================================
25 * Environment: 32-bit Windows NT device drivers.
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 ****************************************************************************/
36 #include "drvlib/os/os.h"
37 #include "sdd/sddhelp.h"
41 /*--------------------------- Global variables ----------------------------*/
43 char _PM_cntPath[PM_MAX_PATH] = "";
44 char _PM_nucleusPath[PM_MAX_PATH] = "";
45 static void (PMAPIP fatalErrorCleanup)(void) = NULL;
47 static char *szNTWindowsKey = "\\REGISTRY\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion";
48 static char *szNTSystemRoot = "SystemRoot";
49 static char *szMachineNameKey = "\\REGISTRY\\Machine\\System\\CurrentControlSet\\control\\ComputerName\\ComputerName";
50 static char *szMachineNameKeyNT = "\\REGISTRY\\Machine\\System\\CurrentControlSet\\control\\ComputerName\\ActiveComputerName";
51 static char *szMachineName = "ComputerName";
53 /*----------------------------- Implementation ----------------------------*/
55 /****************************************************************************
57 Initialise the PM library.
58 ****************************************************************************/
59 void PMAPI PM_init(void)
61 /* Initialiase the MTRR module */
65 /****************************************************************************
67 Return the operating system type identifier.
68 ****************************************************************************/
69 long PMAPI PM_getOSType(void)
74 /****************************************************************************
76 Return the runtime type identifier.
77 ****************************************************************************/
78 int PMAPI PM_getModeType(void)
83 /****************************************************************************
85 Add a file directory separator to the end of the filename.
86 ****************************************************************************/
87 void PMAPI PM_backslash(char *s)
90 if (s[pos-1] != '\\') {
96 /****************************************************************************
98 Add a user defined PM_fatalError cleanup function.
99 ****************************************************************************/
100 void PMAPI PM_setFatalErrorCleanup(
101 void (PMAPIP cleanup)(void))
103 fatalErrorCleanup = cleanup;
106 /****************************************************************************
108 Handle fatal errors internally in the driver.
109 ****************************************************************************/
110 void PMAPI PM_fatalError(
113 ULONG BugCheckCode = 0;
114 ULONG MoreBugCheckData[4] = {0};
118 if (fatalErrorCleanup)
121 #ifdef DBG // Send output to debugger, just return so as not to force a reboot
122 #pragma message("INFO: building for debug, PM_fatalError() re-routed")
123 DBGMSG2("SDDHELP> PM_fatalError(): ERROR: %s\n", msg);
126 // KeBugCheckEx brings down the system in a controlled
127 // manner when the caller discovers an unrecoverable
128 // inconsistency that would corrupt the system if
129 // the caller continued to run.
131 // hack - dump the first 20 chars in hex using the variables
132 // provided - Each ULONG is equal to four characters...
133 for(len = 0; len < 20; len++)
134 if (msg[len] == (char)0)
137 // This looks bad but it's quick and reliable...
138 p = (char *)&BugCheckCode;
139 if(len > 0) p[3] = msg[0];
140 if(len > 1) p[2] = msg[1];
141 if(len > 2) p[1] = msg[2];
142 if(len > 3) p[0] = msg[3];
144 p = (char *)&MoreBugCheckData[0];
145 if(len > 4) p[3] = msg[4];
146 if(len > 5) p[2] = msg[5];
147 if(len > 6) p[1] = msg[6];
148 if(len > 7) p[0] = msg[7];
150 p = (char *)&MoreBugCheckData[1];
151 if(len > 8) p[3] = msg[8];
152 if(len > 9) p[2] = msg[9];
153 if(len > 10) p[1] = msg[10];
154 if(len > 11) p[0] = msg[11];
156 p = (char *)&MoreBugCheckData[2];
157 if(len > 12) p[3] = msg[12];
158 if(len > 13) p[2] = msg[13];
159 if(len > 14) p[1] = msg[14];
160 if(len > 15) p[0] = msg[15];
162 p = (char *)&MoreBugCheckData[3];
163 if(len > 16) p[3] = msg[16];
164 if(len > 17) p[2] = msg[17];
165 if(len > 18) p[1] = msg[18];
166 if(len > 19) p[0] = msg[19];
169 KeBugCheckEx(BugCheckCode, MoreBugCheckData[0], MoreBugCheckData[1], MoreBugCheckData[2], MoreBugCheckData[3]);
172 /****************************************************************************
174 Return the current operating system path or working directory.
175 ****************************************************************************/
176 char * PMAPI PM_getCurrentPath(
180 strncpy(path,_PM_cntPath,maxLen);
185 /****************************************************************************
187 szKey - Key to query (can contain version number formatting)
188 szValue - Value to get information for
189 value - Place to store the registry key data read
190 size - Size of the string buffer to read into
193 true if the key was found, false if not.
194 ****************************************************************************/
195 static ibool REG_queryString(
205 OBJECT_ATTRIBUTES keyAttributes;
206 UNICODE_STRING *uniKey = NULL;
207 UNICODE_STRING *uniValue = NULL;
208 PKEY_VALUE_FULL_INFORMATION fullInfo = NULL;
210 UNICODE_STRING unidata;
212 // Convert strings to UniCode
214 if ((uniKey = _PM_CStringToUnicodeString(szKey)) == NULL)
216 if ((uniValue = _PM_CStringToUnicodeString(szValue)) == NULL)
220 InitializeObjectAttributes( &keyAttributes,
222 OBJ_CASE_INSENSITIVE,
225 rval = ZwOpenKey( &Handle,
228 if (!NT_SUCCESS(rval))
232 length = sizeof (KEY_VALUE_FULL_INFORMATION)
233 + size * sizeof(WCHAR);
234 if ((fullInfo = ExAllocatePool (PagedPool, length)) == NULL)
236 RtlZeroMemory(fullInfo, length);
237 rval = ZwQueryValueKey (Handle,
239 KeyValueFullInformation,
243 if (NT_SUCCESS (rval)) {
244 // Create the UniCode string so we can convert it
245 unidata.Buffer = (PWCHAR)(((PCHAR)fullInfo) + fullInfo->DataOffset);
246 unidata.Length = (USHORT)fullInfo->DataLength;
247 unidata.MaximumLength = (USHORT)fullInfo->DataLength + sizeof(WCHAR);
249 // Convert unicode univalue to ansi string.
250 rval = RtlUnicodeStringToAnsiString(&stringdata, &unidata, TRUE);
251 if (NT_SUCCESS(rval)) {
252 strcpy(value,stringdata.Buffer);
258 if (fullInfo) ExFreePool(fullInfo);
259 if (uniKey) _PM_FreeUnicodeString(uniKey);
260 if (uniValue) _PM_FreeUnicodeString(uniValue);
264 /****************************************************************************
266 Return the drive letter for the boot drive.
267 ****************************************************************************/
268 char PMAPI PM_getBootDrive(void)
271 if (REG_queryString(szNTWindowsKey,szNTSystemRoot,path,sizeof(path)))
276 /****************************************************************************
278 Return the path to the VBE/AF driver files.
279 ****************************************************************************/
280 const char * PMAPI PM_getVBEAFPath(void)
285 /****************************************************************************
287 Return the path to the Nucleus driver files.
288 ****************************************************************************/
289 const char * PMAPI PM_getNucleusPath(void)
291 static char path[256];
293 if (strlen(_PM_nucleusPath) > 0) {
294 strcpy(path,_PM_nucleusPath);
298 if (!REG_queryString(szNTWindowsKey,szNTSystemRoot,path,sizeof(path)))
299 strcpy(path,"c:\\winnt");
301 strcat(path,"system32\\nucleus");
305 /****************************************************************************
307 Return the path to the Nucleus configuration files.
308 ****************************************************************************/
309 const char * PMAPI PM_getNucleusConfigPath(void)
311 static char path[256];
312 strcpy(path,PM_getNucleusPath());
314 strcat(path,"config");
318 /****************************************************************************
320 Return a unique identifier for the machine if possible.
321 ****************************************************************************/
322 const char * PMAPI PM_getUniqueID(void)
324 return PM_getMachineName();
327 /****************************************************************************
329 Get the name of the machine on the network.
330 ****************************************************************************/
331 const char * PMAPI PM_getMachineName(void)
333 static char name[256];
335 if (REG_queryString(szMachineNameKey,szMachineName,name,sizeof(name)))
337 if (REG_queryString(szMachineNameKeyNT,szMachineName,name,sizeof(name)))
342 /****************************************************************************
344 Check if a key has been pressed.
345 ****************************************************************************/
346 int PMAPI PM_kbhit(void)
348 // Not used in NT drivers
352 /****************************************************************************
354 Wait for and return the next keypress.
355 ****************************************************************************/
356 int PMAPI PM_getch(void)
358 // Not used in NT drivers
362 /****************************************************************************
364 Open a console for output to the screen, creating the main event handling
366 ****************************************************************************/
367 PM_HWND PMAPI PM_openConsole(
375 // Not used in NT drivers
385 /****************************************************************************
387 Find the size of the console state buffer.
388 ****************************************************************************/
389 int PMAPI PM_getConsoleStateSize(void)
391 // Not used in NT drivers
395 /****************************************************************************
397 Save the state of the console.
398 ****************************************************************************/
399 void PMAPI PM_saveConsoleState(
403 // Not used in NT drivers
408 /****************************************************************************
410 Set the suspend application callback for the fullscreen console.
411 ****************************************************************************/
412 void PMAPI PM_setSuspendAppCallback(
413 PM_saveState_cb saveState)
415 // Not used in NT drivers
419 /****************************************************************************
421 Restore the console state.
422 ****************************************************************************/
423 void PMAPI PM_restoreConsoleState(
424 const void *stateBuf,
427 // Not used in NT drivers
432 /****************************************************************************
434 Close the fullscreen console.
435 ****************************************************************************/
436 void PMAPI PM_closeConsole(
439 // Not used in NT drivers
443 /****************************************************************************
445 Set the location of the OS console cursor.
446 ****************************************************************************/
447 void PMAPI PM_setOSCursorLocation(
451 /* Nothing to do for Windows */
456 /****************************************************************************
458 Set the width of the OS console.
459 ****************************************************************************/
460 void PMAPI PM_setOSScreenWidth(
464 /* Nothing to do for Windows */
469 /****************************************************************************
471 Maps a shared memory block into process address space. Does nothing since
472 the memory blocks are already globally mapped into all processes.
473 ****************************************************************************/
474 void * PMAPI PM_mapToProcess(
484 /****************************************************************************
486 Execute the POST on the secondary BIOS for a controller.
487 ****************************************************************************/
488 ibool PMAPI PM_doBIOSPOST(
494 // This may not be possible in NT and should be done by the OS anyway
502 /****************************************************************************
504 Return a pointer to the real mode BIOS data area.
505 ****************************************************************************/
506 void * PMAPI PM_getBIOSPointer(void)
508 // Note that on NT this probably does not do what we expect!
509 return PM_mapPhysicalAddr(0x400, 0x1000, true);
512 /****************************************************************************
514 Return a pointer to 0xA0000 physical VGA graphics framebuffer.
515 ****************************************************************************/
516 void * PMAPI PM_getA0000Pointer(void)
518 return PM_mapPhysicalAddr(0xA0000,0xFFFF,false);
521 /****************************************************************************
523 Sleep for the specified number of milliseconds.
524 ****************************************************************************/
528 // We never use this in NT drivers
532 /****************************************************************************
534 Return the base I/O port for the specified COM port.
535 ****************************************************************************/
536 int PMAPI PM_getCOMPort(int port)
538 // TODO: Re-code this to determine real values using the Plug and Play
539 // manager for the OS.
541 case 0: return 0x3F8;
542 case 1: return 0x2F8;
543 case 2: return 0x3E8;
544 case 3: return 0x2E8;
549 /****************************************************************************
551 Return the base I/O port for the specified LPT port.
552 ****************************************************************************/
553 int PMAPI PM_getLPTPort(int port)
555 // TODO: Re-code this to determine real values using the Plug and Play
556 // manager for the OS.
558 case 0: return 0x3BC;
559 case 1: return 0x378;
560 case 2: return 0x278;
565 /****************************************************************************
567 Returns available memory. Not possible under Windows.
568 ****************************************************************************/
569 void PMAPI PM_availableMemory(
573 *physical = *total = 0;
576 /****************************************************************************
578 OS specific shared libraries not supported inside a VxD
579 ****************************************************************************/
580 PM_MODULE PMAPI PM_loadLibrary(
581 const char *szDLLName)
583 // Not used in NT drivers
588 /****************************************************************************
590 OS specific shared libraries not supported inside a VxD
591 ****************************************************************************/
592 void * PMAPI PM_getProcAddress(
594 const char *szProcName)
596 // Not used in NT drivers
602 /****************************************************************************
604 OS specific shared libraries not supported inside a VxD
605 ****************************************************************************/
606 void PMAPI PM_freeLibrary(
609 // Not used in NT drivers
613 /****************************************************************************
615 Function to find the first file matching a search criteria in a directory.
616 ****************************************************************************/
617 void *PMAPI PM_findFirstFile(
618 const char *filename,
619 PM_findData *findData)
621 // TODO: This function should start a directory enumeration search
622 // given the filename (with wildcards). The data should be
623 // converted and returned in the findData standard form.
626 return PM_FILE_INVALID;
629 /****************************************************************************
631 Function to find the next file matching a search criteria in a directory.
632 ****************************************************************************/
633 ibool PMAPI PM_findNextFile(
635 PM_findData *findData)
637 // TODO: This function should find the next file in directory enumeration
638 // search given the search criteria defined in the call to
639 // PM_findFirstFile. The data should be converted and returned
640 // in the findData standard form.
646 /****************************************************************************
648 Function to close the find process
649 ****************************************************************************/
650 void PMAPI PM_findClose(
653 // TODO: This function should close the find process. This may do
654 // nothing for some OS'es.
658 /****************************************************************************
660 Function to determine if a drive is a valid drive or not. Under Unix this
661 function will return false for anything except a value of 3 (considered
662 the root drive, and equivalent to C: for non-Unix systems). The drive
670 ****************************************************************************/
671 ibool PMAPI PM_driveValid(
674 // Not supported in NT drivers
679 /****************************************************************************
681 Function to get the current working directory for the specififed drive.
682 Under Unix this will always return the current working directory regardless
683 of what the value of 'drive' is.
684 ****************************************************************************/
685 void PMAPI PM_getdcwd(
690 // Not supported in NT drivers
696 /****************************************************************************
698 base - The starting physical base address of the region
699 size - The size in bytes of the region
700 type - Type to place into the MTRR register
703 Error code describing the result.
706 Function to enable write combining for the specified region of memory.
707 ****************************************************************************/
708 int PMAPI PM_enableWriteCombine(
713 return MTRR_enableWriteCombine(base,size,type);
716 /****************************************************************************
718 Function to change the file attributes for a specific file.
719 ****************************************************************************/
720 void PMAPI PM_setFileAttr(
721 const char *filename,
725 ACCESS_MASK DesiredAccess = GENERIC_READ | GENERIC_WRITE;
726 OBJECT_ATTRIBUTES ObjectAttributes;
727 ULONG ShareAccess = FILE_SHARE_READ;
728 ULONG CreateDisposition = FILE_OPEN;
729 HANDLE FileHandle = NULL;
730 UNICODE_STRING *uniFile = NULL;
731 IO_STATUS_BLOCK IoStatusBlock;
732 FILE_BASIC_INFORMATION FileBasic;
733 char kernelFilename[PM_MAX_PATH+5];
734 ULONG FileAttributes = 0;
736 // Convert file attribute flags
737 if (attrib & PM_FILE_READONLY)
738 FileAttributes |= FILE_ATTRIBUTE_READONLY;
739 if (attrib & PM_FILE_ARCHIVE)
740 FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
741 if (attrib & PM_FILE_HIDDEN)
742 FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
743 if (attrib & PM_FILE_SYSTEM)
744 FileAttributes |= FILE_ATTRIBUTE_SYSTEM;
746 // Add prefix for addressing the file system. "\??\" is short for "\DosDevices\"
747 strcpy(kernelFilename, "\\??\\");
748 strcat(kernelFilename, filename);
750 // Convert filename string to ansi string
751 if ((uniFile = _PM_CStringToUnicodeString(kernelFilename)) == NULL)
754 // Must open a file to query it's attributes
755 InitializeObjectAttributes (&ObjectAttributes,
757 OBJ_CASE_INSENSITIVE,
760 status = ZwCreateFile( &FileHandle,
761 DesiredAccess | SYNCHRONIZE,
764 NULL, //AllocationSize OPTIONAL,
765 FILE_ATTRIBUTE_NORMAL,
768 FILE_RANDOM_ACCESS, //CreateOptions,
769 NULL, //EaBuffer OPTIONAL,
770 0 //EaLength (required if EaBuffer)
772 if (!NT_SUCCESS (status))
776 status = ZwQueryInformationFile(FileHandle,
779 sizeof(FILE_BASIC_INFORMATION),
782 if (!NT_SUCCESS (status))
785 // Change the four bits we change
786 FileBasic.FileAttributes &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_ARCHIVE
787 | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
788 FileBasic.FileAttributes |= FileAttributes;
791 ZwSetInformationFile( FileHandle,
794 sizeof(FILE_BASIC_INFORMATION),
799 if (FileHandle) ZwClose(FileHandle);
800 if (uniFile) _PM_FreeUnicodeString(uniFile);
804 /****************************************************************************
806 Function to get the file attributes for a specific file.
807 ****************************************************************************/
808 uint PMAPI PM_getFileAttr(
809 const char *filename)
812 ACCESS_MASK DesiredAccess = GENERIC_READ | GENERIC_WRITE;
813 OBJECT_ATTRIBUTES ObjectAttributes;
814 ULONG ShareAccess = FILE_SHARE_READ;
815 ULONG CreateDisposition = FILE_OPEN;
816 HANDLE FileHandle = NULL;
817 UNICODE_STRING *uniFile = NULL;
818 IO_STATUS_BLOCK IoStatusBlock;
819 FILE_BASIC_INFORMATION FileBasic;
820 char kernelFilename[PM_MAX_PATH+5];
821 ULONG FileAttributes = 0;
824 // Add prefix for addressing the file system. "\??\" is short for "\DosDevices\"
825 strcpy(kernelFilename, "\\??\\");
826 strcat(kernelFilename, filename);
828 // Convert filename string to ansi string
829 if ((uniFile = _PM_CStringToUnicodeString(kernelFilename)) == NULL)
832 // Must open a file to query it's attributes
833 InitializeObjectAttributes (&ObjectAttributes,
835 OBJ_CASE_INSENSITIVE,
838 status = ZwCreateFile( &FileHandle,
839 DesiredAccess | SYNCHRONIZE,
842 NULL, //AllocationSize OPTIONAL,
843 FILE_ATTRIBUTE_NORMAL,
846 FILE_RANDOM_ACCESS, //CreateOptions,
847 NULL, //EaBuffer OPTIONAL,
848 0 //EaLength (required if EaBuffer)
850 if (!NT_SUCCESS (status))
854 status = ZwQueryInformationFile(FileHandle,
857 sizeof(FILE_BASIC_INFORMATION),
860 if (!NT_SUCCESS (status))
863 // Translate the file attributes
864 if (FileBasic.FileAttributes & FILE_ATTRIBUTE_READONLY)
865 retval |= PM_FILE_READONLY;
866 if (FileBasic.FileAttributes & FILE_ATTRIBUTE_ARCHIVE)
867 retval |= PM_FILE_ARCHIVE;
868 if (FileBasic.FileAttributes & FILE_ATTRIBUTE_HIDDEN)
869 retval |= PM_FILE_HIDDEN;
870 if (FileBasic.FileAttributes & FILE_ATTRIBUTE_SYSTEM)
871 retval |= PM_FILE_SYSTEM;
874 if (FileHandle) ZwClose(FileHandle);
875 if (uniFile) _PM_FreeUnicodeString(uniFile);
879 /****************************************************************************
881 Function to create a directory.
882 ****************************************************************************/
883 ibool PMAPI PM_mkdir(
884 const char *filename)
886 // Not supported in NT drivers
891 /****************************************************************************
893 Function to remove a directory.
894 ****************************************************************************/
895 ibool PMAPI PM_rmdir(
896 const char *filename)
898 // Not supported in NT drivers
903 /****************************************************************************
905 Function to get the file time and date for a specific file.
906 ****************************************************************************/
907 ibool PMAPI PM_getFileTime(
908 const char *filename,
912 // Not supported in NT drivers
919 /****************************************************************************
921 Function to set the file time and date for a specific file.
922 ****************************************************************************/
923 ibool PMAPI PM_setFileTime(
924 const char *filename,
928 // Not supported in NT drivers