]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/bios_emulator/scitech/src/pm/ntdrv/pm.c
* Patch by Thomas Frieden, 13 Nov 2002:
[karo-tx-uboot.git] / board / MAI / bios_emulator / scitech / src / pm / ntdrv / pm.c
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:  32-bit Windows NT device drivers.
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 #include "pmapi.h"
36 #include "drvlib/os/os.h"
37 #include "sdd/sddhelp.h"
38 #include "mtrr.h"
39 #include "oshdr.h"
40
41 /*--------------------------- Global variables ----------------------------*/
42
43 char                _PM_cntPath[PM_MAX_PATH] = "";
44 char                _PM_nucleusPath[PM_MAX_PATH] = "";
45 static void (PMAPIP fatalErrorCleanup)(void) = NULL;
46
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";
52
53 /*----------------------------- Implementation ----------------------------*/
54
55 /****************************************************************************
56 REMARKS:
57 Initialise the PM library.
58 ****************************************************************************/
59 void PMAPI PM_init(void)
60 {
61     /* Initialiase the MTRR module */
62     MTRR_init();
63 }
64
65 /****************************************************************************
66 REMARKS:
67 Return the operating system type identifier.
68 ****************************************************************************/
69 long PMAPI PM_getOSType(void)
70 {
71     return _OS_WINNTDRV;
72 }
73
74 /****************************************************************************
75 REMARKS:
76 Return the runtime type identifier.
77 ****************************************************************************/
78 int PMAPI PM_getModeType(void)
79 {
80     return PM_386;
81 }
82
83 /****************************************************************************
84 REMARKS:
85 Add a file directory separator to the end of the filename.
86 ****************************************************************************/
87 void PMAPI PM_backslash(char *s)
88 {
89     uint pos = strlen(s);
90     if (s[pos-1] != '\\') {
91         s[pos] = '\\';
92         s[pos+1] = '\0';
93         }
94 }
95
96 /****************************************************************************
97 REMARKS:
98 Add a user defined PM_fatalError cleanup function.
99 ****************************************************************************/
100 void PMAPI PM_setFatalErrorCleanup(
101     void (PMAPIP cleanup)(void))
102 {
103     fatalErrorCleanup = cleanup;
104 }
105
106 /****************************************************************************
107 REMARKS:
108 Handle fatal errors internally in the driver.
109 ****************************************************************************/
110 void PMAPI PM_fatalError(
111     const char *msg)
112 {
113     ULONG   BugCheckCode = 0;
114     ULONG   MoreBugCheckData[4] = {0};
115     char    *p;
116     ULONG   len;
117
118     if (fatalErrorCleanup)
119         fatalErrorCleanup();
120
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);  
124         return ;
125 #endif
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.
130     //
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)
135             break;
136
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];
143
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];
149
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];
155
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];
161
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];
167
168     // Halt the system!
169     KeBugCheckEx(BugCheckCode, MoreBugCheckData[0], MoreBugCheckData[1], MoreBugCheckData[2], MoreBugCheckData[3]);
170 }
171
172 /****************************************************************************
173 REMARKS:
174 Return the current operating system path or working directory.
175 ****************************************************************************/
176 char * PMAPI PM_getCurrentPath(
177     char *path,
178     int maxLen)
179 {
180     strncpy(path,_PM_cntPath,maxLen);
181     path[maxLen-1] = 0;
182     return path;
183 }
184
185 /****************************************************************************
186 PARAMETERS:
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
191
192 RETURNS:
193 true if the key was found, false if not.
194 ****************************************************************************/
195 static ibool REG_queryString(
196     char *szKey,
197     const char *szValue,
198     char *value,
199     DWORD size)
200 {
201     ibool                           status;
202     NTSTATUS                        rval;
203     ULONG                           length;
204     HANDLE                          Handle;
205     OBJECT_ATTRIBUTES               keyAttributes;
206     UNICODE_STRING                  *uniKey = NULL;
207     UNICODE_STRING                  *uniValue = NULL;
208     PKEY_VALUE_FULL_INFORMATION         fullInfo = NULL;
209     STRING                          stringdata;
210     UNICODE_STRING                  unidata;
211
212     // Convert strings to UniCode
213     status = false;
214     if ((uniKey = _PM_CStringToUnicodeString(szKey)) == NULL)
215         goto Exit;
216     if ((uniValue = _PM_CStringToUnicodeString(szValue)) == NULL)
217         goto Exit;
218
219     // Open the key
220     InitializeObjectAttributes( &keyAttributes,
221                                 uniKey,
222                                 OBJ_CASE_INSENSITIVE,
223                                 NULL,
224                                 NULL );
225     rval = ZwOpenKey( &Handle,
226                       KEY_ALL_ACCESS,
227                       &keyAttributes );
228     if (!NT_SUCCESS(rval))
229         goto Exit;
230
231     // Query the value
232     length = sizeof (KEY_VALUE_FULL_INFORMATION)
233            + size * sizeof(WCHAR);
234     if ((fullInfo = ExAllocatePool (PagedPool, length)) == NULL)
235         goto Exit;
236     RtlZeroMemory(fullInfo, length);
237     rval = ZwQueryValueKey (Handle,
238                             uniValue,
239                             KeyValueFullInformation,
240                             fullInfo,
241                             length,
242                             &length);
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);
248
249         // Convert unicode univalue to ansi string.
250         rval = RtlUnicodeStringToAnsiString(&stringdata, &unidata, TRUE);
251         if (NT_SUCCESS(rval)) {
252             strcpy(value,stringdata.Buffer);
253             status = true;
254             }
255         }
256
257 Exit:
258     if (fullInfo) ExFreePool(fullInfo);
259     if (uniKey) _PM_FreeUnicodeString(uniKey);
260     if (uniValue) _PM_FreeUnicodeString(uniValue);
261     return status;
262 }
263
264 /****************************************************************************
265 REMARKS:
266 Return the drive letter for the boot drive.
267 ****************************************************************************/
268 char PMAPI PM_getBootDrive(void)
269 {
270     char path[256];
271     if (REG_queryString(szNTWindowsKey,szNTSystemRoot,path,sizeof(path)))
272         return 'c';
273     return path[0];
274 }
275
276 /****************************************************************************
277 REMARKS:
278 Return the path to the VBE/AF driver files.
279 ****************************************************************************/
280 const char * PMAPI PM_getVBEAFPath(void)
281 {
282     return "c:\\";
283 }
284
285 /****************************************************************************
286 REMARKS:
287 Return the path to the Nucleus driver files.
288 ****************************************************************************/
289 const char * PMAPI PM_getNucleusPath(void)
290 {
291     static char path[256];
292
293     if (strlen(_PM_nucleusPath) > 0) {
294         strcpy(path,_PM_nucleusPath);
295         PM_backslash(path);
296         return path;
297         }
298     if (!REG_queryString(szNTWindowsKey,szNTSystemRoot,path,sizeof(path)))
299         strcpy(path,"c:\\winnt");
300     PM_backslash(path);
301     strcat(path,"system32\\nucleus");
302     return path;
303 }
304
305 /****************************************************************************
306 REMARKS:
307 Return the path to the Nucleus configuration files.
308 ****************************************************************************/
309 const char * PMAPI PM_getNucleusConfigPath(void)
310 {
311     static char path[256];
312     strcpy(path,PM_getNucleusPath());
313     PM_backslash(path);
314     strcat(path,"config");
315     return path;
316 }
317
318 /****************************************************************************
319 REMARKS:
320 Return a unique identifier for the machine if possible.
321 ****************************************************************************/
322 const char * PMAPI PM_getUniqueID(void)
323 {
324     return PM_getMachineName();
325 }
326
327 /****************************************************************************
328 REMARKS:
329 Get the name of the machine on the network.
330 ****************************************************************************/
331 const char * PMAPI PM_getMachineName(void)
332 {
333     static char name[256];
334
335     if (REG_queryString(szMachineNameKey,szMachineName,name,sizeof(name)))
336         return name;
337     if (REG_queryString(szMachineNameKeyNT,szMachineName,name,sizeof(name)))
338         return name;
339     return "Unknown";
340 }
341
342 /****************************************************************************
343 REMARKS:
344 Check if a key has been pressed.
345 ****************************************************************************/
346 int PMAPI PM_kbhit(void)
347 {
348     // Not used in NT drivers
349     return true;
350 }
351
352 /****************************************************************************
353 REMARKS:
354 Wait for and return the next keypress.
355 ****************************************************************************/
356 int PMAPI PM_getch(void)
357 {
358     // Not used in NT drivers
359     return 0xD;
360 }
361
362 /****************************************************************************
363 REMARKS:
364 Open a console for output to the screen, creating the main event handling
365 window if necessary.
366 ****************************************************************************/
367 PM_HWND PMAPI PM_openConsole(
368     PM_HWND hwndUser,
369     int device,
370     int xRes,
371     int yRes,
372     int bpp,
373     ibool fullScreen)
374 {
375     // Not used in NT drivers
376     (void)hwndUser;
377     (void)device;
378     (void)xRes;
379     (void)yRes;
380     (void)bpp;
381     (void)fullScreen;
382     return NULL;
383 }
384
385 /****************************************************************************
386 REMARKS:
387 Find the size of the console state buffer.
388 ****************************************************************************/
389 int PMAPI PM_getConsoleStateSize(void)
390 {
391     // Not used in NT drivers
392     return 1;
393 }
394
395 /****************************************************************************
396 REMARKS:
397 Save the state of the console.
398 ****************************************************************************/
399 void PMAPI PM_saveConsoleState(
400     void *stateBuf,
401     PM_HWND hwndConsole)
402 {
403     // Not used in NT drivers
404     (void)stateBuf;
405     (void)hwndConsole;
406 }
407
408 /****************************************************************************
409 REMARKS:
410 Set the suspend application callback for the fullscreen console.
411 ****************************************************************************/
412 void PMAPI PM_setSuspendAppCallback(
413     PM_saveState_cb saveState)
414 {
415     // Not used in NT drivers
416     (void)saveState;
417 }
418
419 /****************************************************************************
420 REMARKS:
421 Restore the console state.
422 ****************************************************************************/
423 void PMAPI PM_restoreConsoleState(
424     const void *stateBuf,
425     PM_HWND hwndConsole)
426 {
427     // Not used in NT drivers
428     (void)stateBuf;
429     (void)hwndConsole;
430 }
431
432 /****************************************************************************
433 REMARKS:
434 Close the fullscreen console.
435 ****************************************************************************/
436 void PMAPI PM_closeConsole(
437     PM_HWND hwndConsole)
438 {
439     // Not used in NT drivers
440     (void)hwndConsole;
441 }
442
443 /****************************************************************************
444 REMARKS:
445 Set the location of the OS console cursor.
446 ****************************************************************************/
447 void PMAPI PM_setOSCursorLocation(
448     int x,
449     int y)
450 {
451     /* Nothing to do for Windows */
452     (void)x;
453     (void)y;
454 }
455
456 /****************************************************************************
457 REMARKS:
458 Set the width of the OS console.
459 ****************************************************************************/
460 void PMAPI PM_setOSScreenWidth(
461     int width,
462     int height)
463 {
464     /* Nothing to do for Windows */
465     (void)width;
466     (void)height;
467 }
468
469 /****************************************************************************
470 REMARKS:
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(
475     void *base,
476     ulong limit)
477 {
478     // Not used anymore
479     (void)base;
480     (void)limit;
481     return NULL;
482 }
483
484 /****************************************************************************
485 REMARKS:
486 Execute the POST on the secondary BIOS for a controller.
487 ****************************************************************************/
488 ibool PMAPI PM_doBIOSPOST(
489     ushort axVal,
490     ulong BIOSPhysAddr,
491     void *mappedBIOS,
492     ulong BIOSLen)
493 {
494     // This may not be possible in NT and should be done by the OS anyway
495     (void)axVal;
496     (void)BIOSPhysAddr;
497     (void)mappedBIOS;
498     (void)BIOSLen;
499     return false;
500 }
501
502 /****************************************************************************
503 REMARKS:
504 Return a pointer to the real mode BIOS data area.
505 ****************************************************************************/
506 void * PMAPI PM_getBIOSPointer(void)
507 {
508     // Note that on NT this probably does not do what we expect!
509     return PM_mapPhysicalAddr(0x400, 0x1000, true);
510 }
511
512 /****************************************************************************
513 REMARKS:
514 Return a pointer to 0xA0000 physical VGA graphics framebuffer.
515 ****************************************************************************/
516 void * PMAPI PM_getA0000Pointer(void)
517 {
518     return PM_mapPhysicalAddr(0xA0000,0xFFFF,false);
519 }
520
521 /****************************************************************************
522 REMARKS:
523 Sleep for the specified number of milliseconds.
524 ****************************************************************************/
525 void PMAPI PM_sleep(
526     ulong milliseconds)
527 {
528     // We never use this in NT drivers
529     (void)milliseconds;
530 }
531
532 /****************************************************************************
533 REMARKS:
534 Return the base I/O port for the specified COM port.
535 ****************************************************************************/
536 int PMAPI PM_getCOMPort(int port)
537 {
538     // TODO: Re-code this to determine real values using the Plug and Play
539     //       manager for the OS.
540     switch (port) {
541         case 0: return 0x3F8;
542         case 1: return 0x2F8;
543         case 2: return 0x3E8;
544         case 3: return 0x2E8;
545         }
546     return 0;
547 }
548
549 /****************************************************************************
550 REMARKS:
551 Return the base I/O port for the specified LPT port.
552 ****************************************************************************/
553 int PMAPI PM_getLPTPort(int port)
554 {
555     // TODO: Re-code this to determine real values using the Plug and Play
556     //       manager for the OS.
557     switch (port) {
558         case 0: return 0x3BC;
559         case 1: return 0x378;
560         case 2: return 0x278;
561         }
562     return 0;
563 }
564
565 /****************************************************************************
566 REMARKS:
567 Returns available memory. Not possible under Windows.
568 ****************************************************************************/
569 void PMAPI PM_availableMemory(
570     ulong *physical,
571     ulong *total)
572 {
573     *physical = *total = 0;
574 }
575
576 /****************************************************************************
577 REMARKS:
578 OS specific shared libraries not supported inside a VxD
579 ****************************************************************************/
580 PM_MODULE PMAPI PM_loadLibrary(
581     const char *szDLLName)
582 {
583     // Not used in NT drivers
584     (void)szDLLName;
585     return NULL;
586 }
587
588 /****************************************************************************
589 REMARKS:
590 OS specific shared libraries not supported inside a VxD
591 ****************************************************************************/
592 void * PMAPI PM_getProcAddress(
593     PM_MODULE hModule,
594     const char *szProcName)
595 {
596     // Not used in NT drivers
597     (void)hModule;
598     (void)szProcName;
599     return NULL;
600 }
601
602 /****************************************************************************
603 REMARKS:
604 OS specific shared libraries not supported inside a VxD
605 ****************************************************************************/
606 void PMAPI PM_freeLibrary(
607     PM_MODULE hModule)
608 {
609     // Not used in NT drivers
610     (void)hModule;
611 }
612
613 /****************************************************************************
614 REMARKS:
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)
620 {
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.
624     (void)filename;
625     (void)findData;
626     return PM_FILE_INVALID;
627 }
628
629 /****************************************************************************
630 REMARKS:
631 Function to find the next file matching a search criteria in a directory.
632 ****************************************************************************/
633 ibool PMAPI PM_findNextFile(
634     void *handle,
635     PM_findData *findData)
636 {
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.
641     (void)handle;
642     (void)findData;
643     return false;
644 }
645
646 /****************************************************************************
647 REMARKS:
648 Function to close the find process
649 ****************************************************************************/
650 void PMAPI PM_findClose(
651     void *handle)
652 {
653     // TODO: This function should close the find process. This may do
654     //       nothing for some OS'es.
655     (void)handle;
656 }
657
658 /****************************************************************************
659 REMARKS:
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
663 numbering is:
664
665     1   - Drive A:
666     2   - Drive B:
667     3   - Drive C:
668     etc
669
670 ****************************************************************************/
671 ibool PMAPI PM_driveValid(
672     char drive)
673 {
674     // Not supported in NT drivers
675     (void)drive;
676     return false;
677 }
678
679 /****************************************************************************
680 REMARKS:
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(
686     int drive,
687     char *dir,
688     int len)
689 {
690     // Not supported in NT drivers
691     (void)drive;
692     (void)dir;
693     (void)len;
694 }
695
696 /****************************************************************************
697 PARAMETERS:
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
701
702 RETURNS:
703 Error code describing the result.
704
705 REMARKS:
706 Function to enable write combining for the specified region of memory.
707 ****************************************************************************/
708 int PMAPI PM_enableWriteCombine(
709     ulong base,
710     ulong size,
711     uint type)
712 {
713     return MTRR_enableWriteCombine(base,size,type);
714 }
715
716 /****************************************************************************
717 REMARKS:
718 Function to change the file attributes for a specific file.
719 ****************************************************************************/
720 void PMAPI PM_setFileAttr(
721     const char *filename,
722     uint attrib)
723 {
724     NTSTATUS                status;
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;
735
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;
745
746     // Add prefix for addressing the file system. "\??\" is short for "\DosDevices\"
747     strcpy(kernelFilename, "\\??\\");
748     strcat(kernelFilename, filename);
749
750     // Convert filename string to ansi string
751     if ((uniFile = _PM_CStringToUnicodeString(kernelFilename)) == NULL)
752         goto Exit;
753
754     // Must open a file to query it's attributes
755     InitializeObjectAttributes (&ObjectAttributes,
756                                 uniFile,
757                                 OBJ_CASE_INSENSITIVE,
758                                 NULL,
759                                 NULL );
760     status = ZwCreateFile( &FileHandle,
761                             DesiredAccess | SYNCHRONIZE,
762                             &ObjectAttributes,
763                             &IoStatusBlock,
764                             NULL,                  //AllocationSize  OPTIONAL,
765                             FILE_ATTRIBUTE_NORMAL,
766                             ShareAccess,
767                             CreateDisposition,
768                             FILE_RANDOM_ACCESS,        //CreateOptions,
769                             NULL,                  //EaBuffer  OPTIONAL,
770                             0                      //EaLength (required if EaBuffer)
771                             );
772     if (!NT_SUCCESS (status))
773         goto Exit;
774
775     // Query timestamps
776     status = ZwQueryInformationFile(FileHandle,
777                                     &IoStatusBlock,
778                                     &FileBasic,
779                                     sizeof(FILE_BASIC_INFORMATION),
780                                     FileBasicInformation
781                                     );
782     if (!NT_SUCCESS (status))
783         goto Exit;
784
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;
789
790     // Set timestamps
791     ZwSetInformationFile(   FileHandle,
792                             &IoStatusBlock,
793                             &FileBasic,
794                             sizeof(FILE_BASIC_INFORMATION),
795                             FileBasicInformation
796                             );
797
798 Exit:
799     if (FileHandle) ZwClose(FileHandle);
800     if (uniFile) _PM_FreeUnicodeString(uniFile);
801     return;
802 }
803
804 /****************************************************************************
805 REMARKS:
806 Function to get the file attributes for a specific file.
807 ****************************************************************************/
808 uint PMAPI PM_getFileAttr(
809     const char *filename)
810 {
811     NTSTATUS                status;
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;
822     uint                    retval = 0;
823
824     // Add prefix for addressing the file system. "\??\" is short for "\DosDevices\"
825     strcpy(kernelFilename, "\\??\\");
826     strcat(kernelFilename, filename);
827
828     // Convert filename string to ansi string
829     if ((uniFile = _PM_CStringToUnicodeString(kernelFilename)) == NULL)
830         goto Exit;
831
832     // Must open a file to query it's attributes
833     InitializeObjectAttributes (&ObjectAttributes,
834                                 uniFile,
835                                 OBJ_CASE_INSENSITIVE,
836                                 NULL,
837                                 NULL );
838     status = ZwCreateFile( &FileHandle,
839                            DesiredAccess | SYNCHRONIZE,
840                            &ObjectAttributes,
841                            &IoStatusBlock,
842                            NULL,                  //AllocationSize  OPTIONAL,
843                            FILE_ATTRIBUTE_NORMAL,
844                            ShareAccess,
845                            CreateDisposition,
846                            FILE_RANDOM_ACCESS,        //CreateOptions,
847                            NULL,                  //EaBuffer  OPTIONAL,
848                            0                      //EaLength (required if EaBuffer)
849                            );
850     if (!NT_SUCCESS (status))
851         goto Exit;
852
853     // Query timestamps
854     status = ZwQueryInformationFile(FileHandle,
855                                     &IoStatusBlock,
856                                     &FileBasic,
857                                     sizeof(FILE_BASIC_INFORMATION),
858                                     FileBasicInformation
859                                     );
860     if (!NT_SUCCESS (status))
861         goto Exit;
862
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;
872
873 Exit:
874     if (FileHandle) ZwClose(FileHandle);
875     if (uniFile) _PM_FreeUnicodeString(uniFile);
876     return retval;
877 }
878
879 /****************************************************************************
880 REMARKS:
881 Function to create a directory.
882 ****************************************************************************/
883 ibool PMAPI PM_mkdir(
884     const char *filename)
885 {
886     // Not supported in NT drivers
887     (void)filename;
888     return false;
889 }
890
891 /****************************************************************************
892 REMARKS:
893 Function to remove a directory.
894 ****************************************************************************/
895 ibool PMAPI PM_rmdir(
896     const char *filename)
897 {
898     // Not supported in NT drivers
899     (void)filename;
900     return false;
901 }
902
903 /****************************************************************************
904 REMARKS:
905 Function to get the file time and date for a specific file.
906 ****************************************************************************/
907 ibool PMAPI PM_getFileTime(
908     const char *filename,
909     ibool gmTime,
910     PM_time *time)
911 {
912     // Not supported in NT drivers
913     (void)filename;
914     (void)gmTime;
915     (void)time;
916     return false;
917 }
918
919 /****************************************************************************
920 REMARKS:
921 Function to set the file time and date for a specific file.
922 ****************************************************************************/
923 ibool PMAPI PM_setFileTime(
924     const char *filename,
925     ibool gmTime,
926     PM_time *time)
927 {
928     // Not supported in NT drivers
929     (void)filename;
930     (void)gmTime;
931     (void)time;
932     return false;
933 }
934