1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 
7 #ifndef UDF_FORMAT_MEDIA
8 ULONG   LockMode       = 0;
9 BOOLEAN opt_invalidate_volume = FALSE;
10 #endif //UDF_FORMAT_MEDIA
11 
12 #ifndef CDRW_W32
13 #ifndef UDF_FORMAT_MEDIA
14 BOOLEAN open_as_device = FALSE;
15 #endif //UDF_FORMAT_MEDIA
16 #ifdef USE_SKIN_MODEL
17 
18 PSKIN_API SkinAPI = NULL;
19 
20 PSKIN_API
21 SkinLoad(
22     PWCHAR path,
23     HINSTANCE hInstance,      // handle to current instance
24     HINSTANCE hPrevInstance,  // handle to previous instance
25     int nCmdShow              // show state
26     )
27 {
28     HMODULE hm;
29     PSKIN_API Skin;
30     PSKIN_API (__stdcall *SkinInit) (VOID);
31 
32     hm = LoadLibraryW(path);
33     if(!hm)
34         return NULL;
35     SkinInit = (PSKIN_API(__stdcall *)(void))GetProcAddress(hm, "SkinInit");
36     if(!SkinInit)
37         return NULL;
38     Skin = SkinInit();
39     if(!Skin)
40         return NULL;
41     Skin->Init(hInstance, hPrevInstance, nCmdShow);
42     return Skin;
43 }
44 
45 
46 #endif //USE_SKIN_MODEL
47 
48 #ifdef _BROWSE_UDF_
49 #ifndef LIBUDF
50 
51 extern PVCB Vcb;
52 
53 #endif // LIBUDF
54 #endif //_BROWSE_UDF_
55 
56 #ifdef LIBUDF
57 #define _lphUdf  ((PUDF_VOL_HANDLE_I)(DeviceObject->lpContext))
58 #endif //LIBUDF
59 #ifdef LIBUDFFMT
60 #define _lphUdf  (DeviceObject->cbio)
61 #endif //LIBUDFFMT
62 
63 #ifndef CDRW_W32
64 
65 NTSTATUS
66 UDFPhSendIOCTL(
67     IN ULONG IoControlCode,
68     IN PDEVICE_OBJECT DeviceObject,
69     IN PVOID InputBuffer ,
70     IN ULONG InputBufferLength,
71     OUT PVOID OutputBuffer ,
72     IN ULONG OutputBufferLength,
73     IN BOOLEAN OverrideVerify,
74     OUT PVOID Iosb OPTIONAL
75     )
76 {
77     ULONG real_read;
78 #if !defined(LIBUDF) && !defined(LIBUDFFMT)
79     ULONG ret;
80 
81     ULONG RC = DeviceIoControl(DeviceObject->h,IoControlCode,
82                                 InputBuffer,InputBufferLength,
83                                 OutputBuffer,OutputBufferLength,
84                                 &real_read,NULL);
85 
86     if (!RC) {
87         ret = GetLastError();
88     }
89     return RC ? 1 : -1;
90 
91 #else // LIBUDF
92 
93     ULONG RC = _lphUdf->lpIOCtlFunc(_lphUdf->lpParameter,IoControlCode,
94                                 InputBuffer,InputBufferLength,
95                                 OutputBuffer,OutputBufferLength,
96                                 &real_read);
97 
98     return RC;
99 
100 #endif // LIBUDF
101 
102 } // end UDFPhSendIOCTL()
103 
104 
105 NTSTATUS
106 UDFPhReadSynchronous(
107     PDEVICE_OBJECT DeviceObject,  // the physical device object
108     PVOID          Buffer,
109     ULONG          Length,
110     LONGLONG       Offset,
111     PULONG         ReadBytes,
112     ULONG          Flags
113     )
114 {
115 
116 #if !defined(LIBUDF) && !defined(LIBUDFFMT)
117 
118     NTSTATUS    RC;
119 //    UDFPrint(("UDFPhRead: Length: %x Lba: %lx\n",Length>>0xb,Offset>>0xb));
120     LONG HiOffs = (ULONG)(Offset >> 32);
121 
122     RC = SetFilePointer(DeviceObject->h,(ULONG)Offset,&HiOffs,FILE_BEGIN);
123     if(RC == INVALID_SET_FILE_POINTER) {
124         if(GetLastError() != NO_ERROR) {
125             UDFPrint(("UDFPhReadSynchronous: error %x\n", GetLastError()));
126             return STATUS_END_OF_FILE;
127         }
128     }
129     RC = ReadFile(DeviceObject->h,Buffer,Length,ReadBytes,NULL);
130     if(NT_SUCCESS(RC) &&
131         (!(*ReadBytes))) {
132         RC = GetLastError();
133         return STATUS_END_OF_FILE;
134     }
135     return STATUS_SUCCESS;
136 
137 #else // LIBUDF
138 
139     return _lphUdf->lpReadFunc(_lphUdf->lpParameter,
140                               Buffer,
141                               Length,
142                               Offset,
143                               ReadBytes);
144 
145 #endif //defined LIBUDF || defined LIBUDFFMT
146 
147 } // end UDFPhReadSynchronous()
148 
149 
150 NTSTATUS
151 UDFPhWriteSynchronous(
152     PDEVICE_OBJECT     DeviceObject,  // the physical device object
153     PVOID          Buffer,
154     ULONG          Length,
155     LONGLONG       Offset,
156     PULONG         WrittenBytes,
157     ULONG          Flags
158     )
159 {
160 #if !defined(LIBUDF) && !defined(LIBUDFFMT)
161 
162     NTSTATUS    RC = STATUS_SUCCESS;
163     LONG HiOffs = (ULONG)(Offset >> 32);
164     PVOID Buffer2 = NULL;
165     PVOID Buffer3 = NULL;
166 
167     RC = SetFilePointer(DeviceObject->h,(ULONG)Offset,&HiOffs,FILE_BEGIN);
168     if(RC == INVALID_SET_FILE_POINTER) {
169         if(GetLastError() != NO_ERROR) {
170             UDFPrint(("UDFPhWriteSynchronous: error %x\n", GetLastError()));
171             return STATUS_END_OF_FILE;
172         }
173     }
174 
175     Buffer2 = ExAllocatePool(NonPagedPool, Length+0x10000);
176     Buffer3 = (PVOID)( ((ULONG)Buffer2 + 0xffff) & ~0xffff);
177     RtlCopyMemory(Buffer3, Buffer, Length);
178 
179     RC = WriteFile(DeviceObject->h,Buffer3,Length,WrittenBytes,NULL);
180     if(!RC ||
181         !(*WrittenBytes)) {
182         RC = GetLastError();
183         UDFPrint(("UDFPhWriteSynchronous: EOF, error %x\n", RC));
184         RC = STATUS_END_OF_FILE;
185     } else {
186         RC = STATUS_SUCCESS;
187     }
188 
189     if(Buffer2) ExFreePool(Buffer2);
190 
191     return RC;
192 
193 #else // LIBUDF
194 
195     return _lphUdf->lpWriteFunc(_lphUdf->lpParameter,
196                               Buffer,
197                               Length,
198                               Offset,
199                               WrittenBytes);
200 
201 #endif // LIBUDF
202 
203 } // end UDFPhWriteSynchronous()
204 
205 #if 0
206 NTSTATUS
207 UDFPhWriteVerifySynchronous(
208     PDEVICE_OBJECT  DeviceObject,   // the physical device object
209     PVOID           Buffer,
210     ULONG           Length,
211     LONGLONG        Offset,
212     PULONG          WrittenBytes,
213     ULONG           Flags
214     )
215 {
216     NTSTATUS RC;
217     PUCHAR v_buff = NULL;
218     ULONG ReadBytes;
219 
220     RC = UDFPhWriteSynchronous(DeviceObject, Buffer, Length, Offset, WrittenBytes, 0);
221     if(!Verify)
222         return RC;
223     v_buff = (PUCHAR)DbgAllocatePool(NonPagedPool, Length);
224     if(!v_buff)
225         return RC;
226 
227     RC = UDFPhSendIOCTL( IOCTL_CDRW_SYNC_CACHE, DeviceObject,
228                     NULL,0, NULL,0, FALSE, NULL);
229 
230     RC = UDFPhReadSynchronous(DeviceObject, v_buff, Length, Offset, &ReadBytes, 0);
231     if(!NT_SUCCESS(RC)) {
232         BrutePoint();
233         DbgFreePool(v_buff);
234         return RC;
235     }
236     if(RtlCompareMemory(v_buff, Buffer, ReadBytes) == Length) {
237         DbgFreePool(v_buff);
238         return RC;
239     }
240     BrutePoint();
241     DbgFreePool(v_buff);
242     return STATUS_LOST_WRITEBEHIND_DATA;
243 } // end UDFPhWriteVerifySynchronous()
244 #endif
245 
246 VOID
247 set_image_size(
248     HANDLE h,
249 //    ULONG LBA)
250     int64  len)
251 {
252     LONG offh = (ULONG)(len >> 32);
253                         //( (LONGLONG)LBA >> (32-Vcb->BlockSizeBits) );
254 
255     SetFilePointer((HANDLE)h, (ULONG)(len /*(LBA << Vcb->BlockSizeBits)*/ ), &offh, FILE_BEGIN);
256     SetEndOfFile(h);
257     offh = 0;
258     SetFilePointer((HANDLE)h, 0, &offh, FILE_BEGIN);
259 } // end set_image_size()
260 
261 int64
262 get_file_size(
263     HANDLE h
264     )
265 {
266     LONG hsz = 0;
267     LONG lsz;
268 
269     lsz = SetFilePointer(h, 0, &hsz, FILE_END);
270     return (((int64)hsz) << 32) | lsz;
271 } // end get_file_size()
272 
273 int64
274 set_file_pointer(
275     HANDLE h,
276     int64 sz
277     )
278 {
279     ULONG hsz = (ULONG)(sz >> 32);
280     ULONG lsz = (ULONG)sz;
281 
282     lsz = SetFilePointer(h, lsz, (PLONG)&hsz, FILE_BEGIN);
283     return (((int64)hsz) << 32) | lsz;
284 } // end set_file_pointer()
285 
286 #endif //CDRW_W32
287 
288 #ifndef LIBUDF
289 
290 #ifndef UDF_FORMAT_MEDIA
291 
292 ULONG
293 write(
294     PVCB Vcb,
295     HANDLE h,
296     PCHAR buff,
297     ULONG len)
298 {
299     ULONG written;
300     LONG offh = 0;
301     ULONG offl = SetFilePointer((HANDLE)h, 0, &offh, FILE_CURRENT);
302 //    ULONG Lba = (ULONG)((((LONGLONG)offh << 32) + offl) >> Vcb->BlockSizeBits);
303 
304     UDFWriteData(Vcb, FALSE, (((LONGLONG)offh)<<32)+offl, len, FALSE, buff, &written);
305 
306     SetFilePointer((HANDLE)h, offl, &offh, FILE_BEGIN);
307     offh = 0;
308     SetFilePointer((HANDLE)h, written, &offh, FILE_CURRENT);
309 
310     return written;
311 } // end write()
312 #endif //UDF_FORMAT_MEDIA
313 
314 #endif // LIBUDF
315 
316 #endif //CDRW_W32
317 
318 #ifdef NT_NATIVE_MODE
319 
320 BOOL
321 Privilege(
322     LPTSTR pszPrivilege,
323     BOOL bEnable
324     )
325 {
326 #ifndef NT_NATIVE_MODE
327     HANDLE           hToken;
328     TOKEN_PRIVILEGES tp;
329 
330     // obtain the token, first check the thread and then the process
331     if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TRUE, &hToken)) {
332         if (GetLastError() == ERROR_NO_TOKEN) {
333             if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
334                 return FALSE;
335             }
336         } else {
337             return FALSE;
338         }
339     }
340 
341     // get the luid for the privilege
342     if (!LookupPrivilegeValue(NULL, pszPrivilege, &tp.Privileges[0].Luid)) {
343         CloseHandle(hToken);
344         return FALSE;
345     }
346 
347     tp.PrivilegeCount = 1;
348 
349     if (bEnable)
350         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
351     else
352         tp.Privileges[0].Attributes = 0;
353 
354     // enable or disable the privilege
355     if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0)) {
356         CloseHandle(hToken);
357         return FALSE;
358     }
359 
360     if (!CloseHandle(hToken))
361         return FALSE;
362 
363 #endif //NT_NATIVE_MODE
364 
365     return TRUE;
366 
367 } // end Privilege()
368 #endif //NT_NATIVE_MODE
369 
370 #ifndef LIBUDF
371 
372 extern "C"
373 ULONG
374 MyLockVolume(
375     HANDLE h,
376     ULONG* pLockMode // OUT
377     )
378 {
379     ULONG RC;
380     ULONG returned;
381 
382     (*pLockMode) = -1;
383 #ifndef CDRW_W32
384     RC = DeviceIoControl(h,IOCTL_UDF_LOCK_VOLUME_BY_PID,NULL,0,NULL,0,&returned,NULL);
385     if(RC) {
386         (*pLockMode) = IOCTL_UDF_LOCK_VOLUME_BY_PID;
387         return STATUS_SUCCESS;
388     }
389 #endif //CDRW_W32
390 
391     RC = DeviceIoControl(h,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&returned,NULL);
392     if(RC) {
393         (*pLockMode) = FSCTL_LOCK_VOLUME;
394         return STATUS_SUCCESS;
395     }
396     return STATUS_UNSUCCESSFUL;
397 } // MyLockVolume()
398 
399 extern "C"
400 ULONG
401 MyUnlockVolume(
402     HANDLE h,
403     ULONG* pLockMode // IN
404     )
405 {
406     ULONG returned;
407 
408 #ifndef CDRW_W32
409     if((*pLockMode) == IOCTL_UDF_LOCK_VOLUME_BY_PID) {
410         return DeviceIoControl(h,IOCTL_UDF_UNLOCK_VOLUME_BY_PID,NULL,0,NULL,0,&returned,NULL);
411     }
412 #endif //CDRW_W32
413 
414     return DeviceIoControl(h,FSCTL_UNLOCK_VOLUME,NULL,0,NULL,0,&returned,NULL);
415 
416 } // MyUnlockVolume()
417 
418 void
419 my_retrieve_vol_type(
420 #ifndef CDRW_W32
421     PVCB Vcb,
422 #endif
423     PWCHAR fn
424     )
425 {
426 #ifndef CDRW_W32
427     if(wcslen(fn) == 2 && fn[1] == ':') {
428         ULONG DevType = GetDriveTypeW(fn);
429         UDFPrint(("  DevType %x\n", DevType));
430         switch(DevType) {
431         case DRIVE_CDROM:
432             Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;
433             break;
434         default:
435             Vcb->PhDeviceType = FILE_DEVICE_DISK;
436             break;
437         }
438     }
439     if(wcslen(fn) == 2 && fn[1] == ';') {
440         UserPrint(("Warrning: File name is similar to drive letter.\n"
441                    "  Don't you type semicolon ';' instead of colon ':' ?\n"));
442     }
443 #endif //CDRW_W32
444 } // end my_retrieve_vol_type()
445 
446 
447 #ifdef NT_NATIVE_MODE
448 #define GetLastError()    ((ULONG)(-1))
449 #endif //NT_NATIVE_MODE
450 
451 #define MAX_INVALIDATE_VOLUME_RETRY 8
452 
453 extern "C"
454 HANDLE
455 my_open(
456 #ifndef CDRW_W32
457     PVCB Vcb,
458 #endif
459     PWCHAR fn
460     )
461 {
462     HANDLE h/*, h2*/;
463     WCHAR deviceNameBuffer[0x200];
464     WCHAR FSNameBuffer[0x200];
465 //    CCHAR RealDeviceName[0x200];
466 //    WCHAR DeviceName[MAX_PATH+1];
467     ULONG RC;
468     ULONG retry;
469     ULONG i;
470     BOOLEAN CantLock = FALSE;
471     PULONG pLockMode;
472 #ifdef NT_NATIVE_MODE
473     IO_STATUS_BLOCK ioStatus;
474     OBJECT_ATTRIBUTES ObjectAttributes;
475     UNICODE_STRING uniFilename;
476 #endif //NT_NATIVE_MODE
477     ULONG returned;
478 
479 #ifndef CDRW_W32
480 #ifdef UDF_FORMAT_MEDIA
481     PUDFFmtState fms = Vcb->fms;
482     fms->
483 #endif
484         open_as_device = TRUE;
485 #endif //CDRW_W32
486 
487     pLockMode = &
488 #ifdef UDF_FORMAT_MEDIA
489         fms->
490 #endif
491         LockMode;
492 
493     // make several retries to workaround smart applications,
494     // those attempts to work with volume immediately after arrival
495     retry = 1 +
496 #ifdef UDF_FORMAT_MEDIA
497         fms->
498 #endif
499             opt_invalidate_volume ? 0 : MAX_INVALIDATE_VOLUME_RETRY;
500 
501 #ifndef NT_NATIVE_MODE
502     swprintf(deviceNameBuffer, L"%ws\\", fn);
503     UDFPrint(("my_open: %S\n", fn));
504     i = sizeof(FSNameBuffer)/sizeof(FSNameBuffer[0]);
505     if(GetVolumeInformationW(deviceNameBuffer, NULL, 0,
506         &returned, &returned, &returned, FSNameBuffer, i)) {
507         UDFPrint(("my_open: FS: %S\n", FSNameBuffer));
508         if(!wcscmp(FSNameBuffer, L"Unknown")) {
509             retry++;
510         }
511     } else {
512         UDFPrint(("my_open: FS: ???\n"));
513     }
514     UDFPrint(("my_open: retry %d times\n", retry));
515 
516 #endif //NT_NATIVE_MODE
517 
518     do {
519     // open as device
520 #ifndef NT_NATIVE_MODE
521     swprintf(deviceNameBuffer, L"\\\\.\\%ws", fn);
522     if(wcslen(fn) == 2 && fn[1] == ';') {
523         UserPrint(("Warrning: File name is similar to drive letter.\n"
524                    "  Don't you type semicolon ';' instead of colon ':' ?\n"));
525     }
526     h = (HANDLE)(-1);
527     for(i=0; i<4; i++) {
528         if(h == ((HANDLE)-1)) {
529             h = CreateFileW(deviceNameBuffer, GENERIC_READ | GENERIC_WRITE,
530                            ((i & 1) ? 0 : FILE_SHARE_READ) | ((i & 2) ? 0 : FILE_SHARE_WRITE),
531                            NULL,
532                            OPEN_EXISTING,
533                            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING,  NULL);
534             if(h != ((HANDLE)-1)) {
535                 UDFPrint(("  opened i=%x\n", i));
536             }
537         }
538     }
539 #else //NT_NATIVE_MODE
540     uniFilename.Length = swprintf(deviceNameBuffer, L"\\??\\%ws", fn);
541     uniFilename.Buffer = deviceNameBuffer;
542     uniFilename.Length *= sizeof(WCHAR);
543     uniFilename.MaximumLength = uniFilename.Length + sizeof(WCHAR);
544 
545     h = (HANDLE)(-1);
546     for(i=0; i<4; i++) {
547         InitializeObjectAttributes(&ObjectAttributes, &uniFilename, OBJ_CASE_INSENSITIVE, NULL, NULL);
548         if(h == ((HANDLE)-1)) {
549             RC = NtCreateFile(&h,
550                                      GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
551                                      &ObjectAttributes,
552                                      &ioStatus,
553                                      NULL,
554                                      FILE_ATTRIBUTE_NORMAL,
555                                      ((i & 1) ? 0 : FILE_SHARE_READ) | ((i & 2) ? 0 : FILE_SHARE_WRITE),
556                                      FILE_OPEN,
557                                      FILE_SYNCHRONOUS_IO_NONALERT | FILE_COMPLETE_IF_OPLOCKED | FILE_WRITE_THROUGH | FILE_NO_INTERMEDIATE_BUFFERING,
558                                      NULL,
559                                      0);
560             if(!NT_SUCCESS(RC)) {
561                 UDFPrint(("  opened i2=%x\n", i));
562                 h = ((HANDLE)-1);
563             }
564         }
565     }
566 #endif //NT_NATIVE_MODE
567     if(h != ((HANDLE)-1)) {
568 #ifndef CDRW_W32
569 #ifdef UDF_FORMAT_MEDIA
570         if(fms->opt_flush || fms->opt_probe) {
571             return h;
572         }
573 #endif //UDF_FORMAT_MEDIA
574         my_retrieve_vol_type(Vcb, fn);
575 #else
576         my_retrieve_vol_type(fn);
577 #endif //CDRW_W32
578         if(!NT_SUCCESS(MyLockVolume(h,pLockMode))) {
579 #ifndef CDRW_W32
580             if(retry < MAX_INVALIDATE_VOLUME_RETRY) {
581                 retry++;
582                 if(!Privilege(SE_TCB_NAME, TRUE)) {
583                     UDFPrint(("SE_TCB privilege not held\n"));
584                 } else
585                 if(DeviceIoControl(h,FSCTL_INVALIDATE_VOLUMES,&h,sizeof(h),NULL,0,&returned,NULL) ) {
586                     UDFPrint(("  FSCTL_INVALIDATE_VOLUMES ok, status %x\n", GetLastError()));
587                     CloseHandle(h);
588                     continue;
589                 } else {
590 //#ifndef CDRW_W32
591                     UDFPrint(("  FSCTL_INVALIDATE_VOLUMES failed, error %x\n", GetLastError()));
592                     RC = GetLastError();
593                     if(DeviceIoControl(h,IOCTL_UDF_INVALIDATE_VOLUMES,&h,sizeof(h),NULL,0,&returned,NULL) ) {
594                         UDFPrint(("  IOCTL_UDF_INVALIDATE_VOLUMES ok, status %x\n", GetLastError()));
595                         CloseHandle(h);
596                         continue;
597                     }
598                     UDFPrint(("  IOCTL_UDF_INVALIDATE_VOLUMES, error %x\n", GetLastError()));
599 //#endif //CDRW_W32
600                 }
601                 UserPrint(("can't lock volume, retry\n"));
602                 CloseHandle(h);
603                 continue;
604             }
605 #endif //CDRW_W32
606             UserPrint(("can't lock volume\n"));
607 #ifndef NT_NATIVE_MODE
608             // In native mode the volume can be not mounted yet !!!
609             CantLock = TRUE;
610             CloseHandle(h);
611             h = NULL;
612             goto try_as_file;
613 #endif //NT_NATIVE_MODE
614         }
615 //#ifndef CDRW_W32
616         if(!DeviceIoControl(h,FSCTL_ALLOW_EXTENDED_DASD_IO,NULL,0,NULL,0,&returned,NULL)) {
617             UDFPrint(("Warning: can't allow extended DASD i/o\n"));
618         }
619 //#endif //CDRW_W32
620 
621         UDFPrint(("  opened, h=%x\n", h));
622         return h;
623     }
624     RC = GetLastError();
625 
626 #ifndef NT_NATIVE_MODE
627     h = CreateFileW(deviceNameBuffer, GENERIC_READ,
628                    FILE_SHARE_READ,
629                    NULL,
630                    OPEN_EXISTING,
631                    FILE_ATTRIBUTE_NORMAL,  NULL);
632 #else //NT_NATIVE_MODE
633     RC = NtCreateFile(&h,
634                              GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
635                              &ObjectAttributes,
636                              &ioStatus,
637                              NULL,
638                              FILE_ATTRIBUTE_NORMAL,
639                              FILE_SHARE_READ,
640                              FILE_OPEN,
641                              FILE_SYNCHRONOUS_IO_NONALERT | FILE_COMPLETE_IF_OPLOCKED | FILE_WRITE_THROUGH,
642                              NULL,
643                              0);
644     if(!NT_SUCCESS(RC)) {
645         h = ((HANDLE)-1);
646     }
647 #endif //NT_NATIVE_MODE
648     if(h != ((HANDLE)-1)) {
649 
650         UDFPrint(("  opened R/O, h=%x\n", h));
651 #ifndef CDRW_W32
652         my_retrieve_vol_type(Vcb, fn);
653 #else
654         my_retrieve_vol_type(fn);
655 #endif
656 
657         UserPrint(("read-only open\n"));
658         if(!NT_SUCCESS(MyLockVolume(h,pLockMode))) {
659 #ifndef CDRW_W32
660             if(retry < MAX_INVALIDATE_VOLUME_RETRY) {
661                 retry++;
662                 if(!Privilege(SE_TCB_NAME, TRUE)) {
663                     UDFPrint(("SE_TCB privilege not held\n"));
664                 } else
665                 if(DeviceIoControl(h,FSCTL_INVALIDATE_VOLUMES,&h,sizeof(h),NULL,0,&returned,NULL) ) {
666                     CloseHandle(h);
667                     continue;
668                 }
669                 UserPrint(("can't lock read-only volumem retry"));
670                 CloseHandle(h);
671                 continue;
672             }
673 #endif //CDRW_W32
674             UserPrint(("can't lock read-only volume"));
675 #ifndef NT_NATIVE_MODE
676             CantLock = TRUE;
677             CloseHandle(h);
678             h = NULL;
679             goto try_as_file;
680 #endif //NT_NATIVE_MODE
681         }
682 //        write_cdfs = TRUE;
683 //        DeviceIoControl(h,FSCTL_DISMOUNT_VOLUME,NULL,0,NULL,0,&returned,NULL);
684         return h;
685     }
686 #ifndef NT_NATIVE_MODE
687 try_as_file:
688 #endif //NT_NATIVE_MODE
689 
690 #ifndef CDRW_W32
691 #ifdef UDF_FORMAT_MEDIA
692     fms->
693 #endif
694     open_as_device = FALSE;
695     // open as plain file
696     Vcb->PhDeviceType = FILE_DEVICE_DISK;
697 #endif //CDRW_W32
698 
699     UserPrint(("try image file\n"));
700 #ifndef NT_NATIVE_MODE
701     h = CreateFileW(fn, GENERIC_READ | GENERIC_WRITE,
702                    FILE_SHARE_READ,
703                    NULL,
704                    CREATE_ALWAYS,
705                    FILE_ATTRIBUTE_NORMAL,  NULL);
706 #else //NT_NATIVE_MODE
707     RC = NtCreateFile(&h,
708                              GENERIC_READ | SYNCHRONIZE,
709                              &ObjectAttributes,
710                              &ioStatus,
711                              NULL,
712                              FILE_ATTRIBUTE_NORMAL,
713                              FILE_SHARE_READ,
714                              FILE_OPEN,
715                              FILE_SYNCHRONOUS_IO_NONALERT | FILE_COMPLETE_IF_OPLOCKED | FILE_WRITE_THROUGH,
716                              NULL,
717                              0);
718     if(!NT_SUCCESS(RC)) {
719         h = ((HANDLE)-1);
720     }
721 #endif //NT_NATIVE_MODE
722     if(h == ((HANDLE)-1)) {
723 
724         RC = GetLastError();
725         if(CantLock) {
726 #ifndef CDRW_W32
727             my_exit(
728 #ifdef UDF_FORMAT_MEDIA
729                 fms,
730 #endif
731                 MKUDF_CANT_LOCK_VOL);
732 #else
733             return NULL;
734 #endif //CDRW_W32
735         }
736 #ifndef CDRW_W32
737         UserPrint(("error opening device or image file"));
738         my_exit(
739 #ifdef UDF_FORMAT_MEDIA
740                 fms,
741 #endif
742             MKUDF_CANT_OPEN_FILE);
743 #else
744         return NULL;
745 #endif //CDRW_W32
746     }
747     UDFPrint(("  opened as file, h=%x\n", h));
748     break;
749 
750     } while(TRUE);
751     return h;
752 } // end my_open()
753 
754 #endif //LIBUDF
755 
756 #ifndef CDRW_W32
757 
758 uint64
759 udf_lseek64(
760     HANDLE fd,
761     uint64 offset,
762     int whence)
763 {
764     LONG offh = (ULONG)(offset>>32);
765     LONG offl;
766     offl = SetFilePointer(fd, (ULONG)offset, &offh, whence);
767     if(offl == -1 && offh == -1) {
768         return -1;
769     }
770     return (((uint64)offh) << 32) | (uint64)offl;
771 } // end udf_lseek64()
772 
773 #ifdef LIBUDFFMT
774 BOOLEAN
775 udf_get_sizes(
776     IN PDEVICE_OBJECT DeviceObject,
777     IN ULONG* blocks
778     )
779 {
780     ULONG bs;
781     int64 sz;
782     ULONG RC;
783 
784     RC = _lphUdf->lpGetSizeFunc(_lphUdf->lpParameter, &sz, &bs);
785 
786     (*blocks) = (ULONG)(sz/bs);
787 
788     return(OS_SUCCESS(RC));
789 }
790 #endif //LIBUDFFMT
791 
792 #include "string_lib.cpp"
793 
794 #ifdef _BROWSE_UDF_
795 #ifndef LIBUDF
796 
797 ULONG
798 UDFGetDevType(
799     PDEVICE_OBJECT DeviceObject
800     )
801 {
802     if(DeviceObject && DeviceObject == Vcb->TargetDeviceObject) {
803         return Vcb->PhDeviceType;
804     }
805     return FILE_DEVICE_DISK;
806 } // end UDFGetDevType()
807 
808 #else  // LIBUDF
809 
810 ULONG
811 UDFGetDevType(
812     PDEVICE_OBJECT DeviceObject
813     )
814 {
815 #define lphUdf  ((PUDF_VOL_HANDLE_I)(DeviceObject->lpContext))
816     return lphUdf->bHddDevice ? FILE_DEVICE_DISK : FILE_DEVICE_CD_ROM;
817 #undef lphUdf
818 } // end UDFGetDevType()
819 
820 #endif // LIBUDF
821 
822 #endif //_BROWSE_UDF_
823 
824 #endif //CDRW_W32
825 
826 #ifndef NT_NATIVE_MODE
827 
828 #ifdef PRINT_DBG_CONSOLE
829 CHAR dbg_print_tmp_buff[2048];
830 
831 BOOLEAN was_enter = TRUE;
832 
833 extern "C"
834 VOID
835 PrintDbgConsole(
836     PCHAR DebugMessage,
837     ...
838     )
839 {
840     int len;
841     va_list ap;
842     va_start(ap, DebugMessage);
843 
844     if(was_enter) {
845         strcpy(&dbg_print_tmp_buff[0], JS_DBG_PREFIX);
846         len = _vsnprintf(&dbg_print_tmp_buff[sizeof(JS_DBG_PREFIX)-1], 2047-sizeof(JS_DBG_PREFIX), DebugMessage, ap);
847     } else {
848         len = _vsnprintf(&dbg_print_tmp_buff[0], 2047, DebugMessage, ap);
849     }
850     dbg_print_tmp_buff[2047] = 0;
851     if(len > 0 &&
852        (dbg_print_tmp_buff[len-1] == '\n' ||
853         dbg_print_tmp_buff[len-1] == '\r') ) {
854         was_enter = TRUE;
855     } else {
856         was_enter = FALSE;
857     }
858 
859     OutputDebugString(&dbg_print_tmp_buff[0]);
860 
861     va_end(ap);
862 
863 } // end PrintDbgConsole()
864 #else // PRINT_DBG_CONSOLE
865 VOID
866 PrintDbgConsole(
867     PCHAR DebugMessage,
868     ...
869     )
870 {
871 } // end ClassDebugPrint()
872 #endif //PRINT_DBG_CONSOLE
873 
874 BOOLEAN
875 RtlTimeFieldsToTime(
876     IN PTIME_FIELDS TimeFields,
877     IN PLARGE_INTEGER Time
878     )
879 {
880     SYSTEMTIME st;
881 
882     st.wYear         = TimeFields->Year;
883     st.wMonth        = TimeFields->Month;
884     st.wDayOfWeek    = 0;
885     st.wDay          = TimeFields->Day;
886     st.wHour         = TimeFields->Hour;
887     st.wMinute       = TimeFields->Minute;
888     st.wSecond       = TimeFields->Second;
889     st.wMilliseconds = TimeFields->Milliseconds;
890 
891     return SystemTimeToFileTime(&st, (PFILETIME)Time);
892 } // end RtlTimeFieldsToTime()
893 
894 BOOLEAN
895 RtlTimeToTimeFields(
896     IN PLARGE_INTEGER Time,
897     IN PTIME_FIELDS TimeFields
898     )
899 {
900     SYSTEMTIME st;
901     BOOLEAN retval;
902 
903     retval = FileTimeToSystemTime((PFILETIME)Time, &st);
904 
905     TimeFields->Year         = st.wYear;
906     TimeFields->Month        = st.wMonth;
907     TimeFields->Weekday      = st.wDayOfWeek;
908     TimeFields->Day          = st.wDay;
909     TimeFields->Hour         = st.wHour;
910     TimeFields->Minute       = st.wMinute;
911     TimeFields->Second       = st.wSecond;
912     TimeFields->Milliseconds = st.wMilliseconds;
913 
914     return retval;
915 } // end ()
916 
917 #endif //NT_NATIVE_MODE
918 
919 #ifdef USE_THREAD_HEAPS
920 
921 HANDLE MemLock = NULL;
922 
923 VOID
924 ExInitThreadPools()
925 {
926     MemLock = CreateMutex(NULL, 0, NULL);
927 }
928 
929 VOID
930 ExDeInitThreadPools()
931 {
932     if(MemLock)
933         CloseHandle(MemLock);
934 }
935 
936 #define MAX_THREADS_WITH_OWN_POOL   128
937 
938 typedef struct _THREAD_POOL_LIST_ITEM {
939     HANDLE HeapHandle;
940     ULONG  ThreadId;
941 } THREAD_POOL_LIST_ITEM, *PTHREAD_POOL_LIST_ITEM;
942 
943 ULONG LastThreadPool = -1;
944 THREAD_POOL_LIST_ITEM ThreadPoolList[MAX_THREADS_WITH_OWN_POOL];
945 
946 extern "C"
947 PVOID
948 #ifdef KERNEL_MODE_MM_BEHAVIOR
949 _ExAllocatePool_(
950 #else
951 ExAllocatePool(
952 #endif
953     ULONG MemoryType,
954     ULONG Size
955     )
956 {
957     ULONG i;
958     ULONG ThreadId = GetCurrentThreadId();
959     BOOLEAN found = FALSE;
960 
961     WaitForSingleObject(MemLock,-1);
962 
963     for(i=0; i<(LastThreadPool+1); i++) {
964         if(ThreadPoolList[i].ThreadId == ThreadId) {
965             found = TRUE;
966             break;
967         }
968     }
969     if(found) {
970         ReleaseMutex(MemLock);
971         return HeapAlloc(ThreadPoolList[i].HeapHandle, HEAP_NO_SERIALIZE, Size);
972     }
973     for(i=0; i<(LastThreadPool+1); i++) {
974         if(ThreadPoolList[i].ThreadId == -1) {
975             break;
976         }
977     }
978     if(i>=MAX_THREADS_WITH_OWN_POOL) {
979         ReleaseMutex(MemLock);
980         return NULL;
981     }
982     ThreadPoolList[i].ThreadId   = ThreadId;
983     ThreadPoolList[i].HeapHandle = HeapCreate(HEAP_NO_SERIALIZE, 128*PAGE_SIZE, 0);
984     if(!ThreadPoolList[i].HeapHandle) {
985         ThreadPoolList[i].ThreadId = -1;
986         ReleaseMutex(MemLock);
987         return NULL;
988     }
989 
990     if(i+1 > LastThreadPool+1)
991         LastThreadPool = i;
992 
993     ReleaseMutex(MemLock);
994 
995     return HeapAlloc(ThreadPoolList[i].HeapHandle, HEAP_NO_SERIALIZE, Size);
996 
997 } // end ExAllocatePool()
998 
999 extern "C"
1000 VOID
1001 #ifdef KERNEL_MODE_MM_BEHAVIOR
1002 _ExFreePool_(
1003 #else
1004 ExFreePool(
1005 #endif
1006     PVOID Addr
1007     )
1008 {
1009     ULONG ThreadId = GetCurrentThreadId();
1010     ULONG i;
1011 
1012     WaitForSingleObject(MemLock,-1);
1013     for(i=0; i<(LastThreadPool+1); i++) {
1014         if(ThreadPoolList[i].ThreadId == ThreadId) {
1015             break;
1016         }
1017     }
1018     if(i+1 > LastThreadPool+1) {
1019         // Not found
1020         BrutePoint();
1021         //__asm int 3;
1022         return;
1023     }
1024     HeapFree(ThreadPoolList[i].HeapHandle, HEAP_NO_SERIALIZE, Addr);
1025 
1026     ReleaseMutex(MemLock);
1027 
1028 } // end ExFreePool()
1029 
1030 extern "C"
1031 VOID
1032 ExFreeThreadPool()
1033 {
1034     ULONG ThreadId = GetCurrentThreadId();
1035     ULONG i;
1036 
1037     WaitForSingleObject(MemLock,-1);
1038     for(i=0; i<(LastThreadPool+1); i++) {
1039         if(ThreadPoolList[i].ThreadId == ThreadId) {
1040             break;
1041         }
1042     }
1043     if(i+1 > LastThreadPool+1) {
1044         // Not found
1045         BrutePoint();
1046         //__asm int 3;
1047         return;
1048     }
1049     HeapDestroy(ThreadPoolList[i].HeapHandle);
1050     ThreadPoolList[i].HeapHandle = INVALID_HANDLE_VALUE;
1051     ThreadPoolList[i].ThreadId   = -1;
1052 
1053     ReleaseMutex(MemLock);
1054 }
1055 
1056 #endif //USE_THREAD_HEAPS
1057 
1058 #if defined(KERNEL_MODE_MM_BEHAVIOR)
1059 extern "C"
1060 PVOID
1061 ExAllocatePool(
1062     ULONG MemoryType,
1063     ULONG Size
1064     )
1065 {
1066     PVOID Addr;
1067     PVOID uAddr;
1068     if(Size < PAGE_SIZE) {
1069 #ifdef USE_THREAD_HEAPS
1070         Addr = _ExAllocatePool_(MemoryType, Size+8);
1071 #else
1072         Addr = GlobalAlloc(GMEM_DISCARDABLE, Size+8);
1073 #endif
1074         if(!Addr)
1075             return NULL;
1076         uAddr = ((PCHAR)Addr)+8;
1077     } else {
1078 #ifdef USE_THREAD_HEAPS
1079         Addr = _ExAllocatePool_(MemoryType, Size+PAGE_SIZE*2);
1080 #else
1081         Addr = GlobalAlloc(GMEM_DISCARDABLE, Size+PAGE_SIZE*2);
1082 #endif
1083         if(!Addr)
1084             return NULL;
1085         uAddr = (PVOID)(((ULONG)(((PCHAR)Addr)+PAGE_SIZE)) & ~(PAGE_SIZE-1));
1086     }
1087     *(((PULONG)uAddr)-2) = (ULONG)Addr;
1088     *(((PULONG)uAddr)-1) = 0xFEDCBA98;
1089     return uAddr;
1090 } // end ExAllocatePool()
1091 
1092 extern "C"
1093 VOID
1094 ExFreePool(
1095     PVOID uAddr
1096     )
1097 {
1098     PVOID Addr;
1099 
1100     if(*(((PULONG)uAddr)-1) == 0xFEDCBA98) {
1101         Addr = (PVOID)(*(((PULONG)uAddr)-2));
1102 #ifdef USE_THREAD_HEAPS
1103         _ExFreePool_(Addr);
1104 #else
1105         GlobalFree(Addr);
1106 #endif
1107         return;
1108     }
1109     BrutePoint();
1110 } // end ExFreePool()
1111 #endif //defined(KERNEL_MODE_MM_BEHAVIOR) || defined(NT_NATIVE_MODE)
1112 
1113 #ifdef _lphUdf
1114 #undef _lphUdf
1115 #endif //_lphUdf
1116 
1117 extern "C"
1118 BOOLEAN
1119 ProbeMemory(
1120     PVOID   MemPtr,
1121     ULONG   Length,
1122     BOOLEAN ForWrite
1123     )
1124 {
1125     ULONG i;
1126     UCHAR a;
1127     if(!MemPtr && !Length)
1128         return TRUE;
1129     if(!MemPtr || !Length)
1130         return FALSE;
1131     _SEH2_TRY {
1132         a = ((PCHAR)MemPtr)[Length-1];
1133         if(ForWrite) {
1134             ((PCHAR)MemPtr)[Length-1] = a;
1135         }
1136         for(i=0; i<Length; i+=PAGE_SIZE) {
1137             a = ((PCHAR)MemPtr)[i];
1138             if(ForWrite) {
1139                 ((PCHAR)MemPtr)[i] = a;
1140             }
1141         }
1142     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1143         return FALSE;
1144     } _SEH2_END;
1145     return TRUE;
1146 } // end ProbeMemory()
1147 
1148 #ifdef NT_NATIVE_MODE
1149 #include "env_spec_nt.cpp"
1150 #endif //NT_NATIVE_MODE
1151