source: trunk/src/kernel32/hmdisk.cpp@ 9304

Last change on this file since 9304 was 9304, checked in by sandervl, 23 years ago

FindFirst/NextVolumeA fixes for ignoring LVM volumes

File size: 77.5 KB
Line 
1/* $Id: hmdisk.cpp,v 1.56 2002-09-27 14:35:56 sandervl Exp $ */
2
3/*
4 * Win32 Disk API functions for OS/2
5 *
6 * Copyright 2000-2002 Sander van Leeuwen
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#include <os2win.h>
13#include <string.h>
14#include <stdio.h>
15#include <versionos2.h>
16
17#include <misc.h>
18#include "hmdisk.h"
19#include "mmap.h"
20#include <win\winioctl.h>
21#include <win\ntddscsi.h>
22#include <win\wnaspi32.h>
23#include "oslibdos.h"
24#include "osliblvm.h"
25#include "oslibcdio.h"
26#include "asmutil.h"
27#include <custombuild.h>
28
29#define DBG_LOCALLOG DBG_hmdisk
30#include "dbglocal.h"
31
32#define BIT_0 (1)
33#define BIT_1 (2)
34#define BIT_2 (4)
35#define BIT_11 (1<<11)
36
37//Converts BCD to decimal; doesn't check for illegal BCD nrs
38#define BCDToDec(a) ((a >> 4) * 10 + (a & 0xF))
39
40
41typedef struct
42{
43 BOOL fCDIoSupported;
44 ULONG driveLetter;
45 ULONG driveType;
46 ULONG dwVolumelabel;
47 CHAR signature[8];
48 DWORD dwAccess;
49 DWORD dwShare;
50 DWORD dwCreation;
51 DWORD dwFlags;
52 LPSECURITY_ATTRIBUTES lpSecurityAttributes;
53 HFILE hTemplate;
54 BOOL fPhysicalDisk;
55 DWORD dwPhysicalDiskNr;
56 BOOL fCDPlaying;
57 BOOL fShareViolation;
58 DWORD fLocked;
59 LARGE_INTEGER StartingOffset;
60 LARGE_INTEGER PartitionSize;
61 LARGE_INTEGER CurrentFilePointer;
62 CHAR szVolumeName[256];
63} DRIVE_INFO;
64
65static BOOL fPhysicalDiskAccess = FALSE;
66
67//******************************************************************************
68//******************************************************************************
69void WIN32API EnablePhysicalDiskAccess(BOOL fEnable)
70{
71 fPhysicalDiskAccess = fEnable;
72}
73//******************************************************************************
74//******************************************************************************
75HMDeviceDiskClass::HMDeviceDiskClass(LPCSTR lpDeviceName) : HMDeviceKernelObjectClass(lpDeviceName)
76{
77 HMDeviceRegisterEx("\\\\.\\PHYSICALDRIVE", this, NULL);
78 HMDeviceRegisterEx(VOLUME_NAME_PREFIX, this, NULL);
79}
80
81/*****************************************************************************
82 * Name : HMDeviceDiskClass::FindDevice
83 * Purpose : Checks if lpDeviceName belongs to this device class
84 * Parameters: LPCSTR lpClassDevName
85 * LPCSTR lpDeviceName
86 * int namelength
87 * Variables :
88 * Result : checks if name is for a drive of physical disk
89 * Remark :
90 * Status :
91 *
92 * Author : SvL
93 *****************************************************************************/
94BOOL HMDeviceDiskClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
95{
96 // check for "x:"
97 if (namelength == 2)
98 {
99 if (lpDeviceName[1] != ':')
100 return FALSE;
101
102 if (!( ((lpDeviceName[0] >= 'A') &&
103 (lpDeviceName[0] <= 'Z')) ||
104 ((lpDeviceName[0] >= 'a') &&
105 (lpDeviceName[0] <= 'z')) ))
106 return FALSE;
107
108 return TRUE;
109 }
110
111 //\\.\x: -> length 6
112 //\\.\PHYSICALDRIVEn -> length 18
113 if(namelength != 6 && namelength != 18) {
114 if(VERSION_IS_WIN2000_OR_HIGHER()) {
115 if(!strncmp(lpDeviceName, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1)) {
116 return TRUE;
117 }
118 }
119 return FALSE;
120 }
121
122 // \\.\x: -> drive x (i.e. \\.\C:)
123 // \\.\PHYSICALDRIVEn -> drive n (n>=0)
124 if((strncmp(lpDeviceName, "\\\\.\\", 4) == 0) &&
125 namelength == 6 && lpDeviceName[5] == ':')
126 {
127 return TRUE;
128 }
129 if((strncmp(lpDeviceName, "\\\\.\\PHYSICALDRIVE", 17) == 0) && namelength == 18) {
130 return TRUE;
131 }
132 return FALSE;
133}
134//******************************************************************************
135//******************************************************************************
136DWORD HMDeviceDiskClass::CreateFile (LPCSTR lpFileName,
137 PHMHANDLEDATA pHMHandleData,
138 PVOID lpSecurityAttributes,
139 PHMHANDLEDATA pHMHandleDataTemplate)
140{
141 HFILE hFile;
142 HFILE hTemplate;
143 DWORD dwDriveType;
144 CHAR szDiskName[256];
145 CHAR szVolumeName[256] = "";
146 VOLUME_DISK_EXTENTS volext = {0};
147 BOOL fPhysicalDisk = FALSE;
148 DWORD dwPhysicalDiskNr = 0;
149
150 dprintf2(("KERNEL32: HMDeviceDiskClass::CreateFile %s(%s,%08x,%08x,%08x)\n",
151 lpHMDeviceName, lpFileName, pHMHandleData, lpSecurityAttributes, pHMHandleDataTemplate));
152
153 //TODO: check in NT if CREATE_ALWAYS is allowed!!
154 if(pHMHandleData->dwCreation != OPEN_EXISTING) {
155 dprintf(("Invalid creation flags %x!!", pHMHandleData->dwCreation));
156 return ERROR_INVALID_PARAMETER;
157 }
158
159 char szDrive[4];
160 szDrive[1] = ':';
161 szDrive[2] = '\0';
162
163 //if volume name, query
164 if(!strncmp(lpFileName, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1))
165 {
166 int length;
167
168 if(!VERSION_IS_WIN2000_OR_HIGHER() || !fPhysicalDiskAccess) {
169 return ERROR_FILE_NOT_FOUND; //not allowed
170 }
171 if(OSLibLVMStripVolumeName(lpFileName, szVolumeName, sizeof(szVolumeName)))
172 {
173 BOOL fLVMVolume;
174
175 dwDriveType = GetDriveTypeA(lpFileName);
176
177 szDrive[0] = OSLibLVMQueryDriveFromVolumeName(szVolumeName);
178 if(szDrive[0] == -1) {
179 return ERROR_FILE_NOT_FOUND; //not found
180 }
181 if((dwDriveType == DRIVE_FIXED) && OSLibLVMGetVolumeExtents(szDrive[0], szVolumeName, &volext, &fLVMVolume) == FALSE) {
182 return ERROR_FILE_NOT_FOUND; //not found
183 }
184 if(szDrive[0] == 0)
185 {
186 //volume isn't mounted
187
188 //Note: this only works on Warp 4.5 and up
189 sprintf(szDiskName, "\\\\.\\Physical_Disk%d", volext.Extents[0].DiskNumber+1);
190 fPhysicalDisk = TRUE;
191 dwPhysicalDiskNr = volext.Extents[0].DiskNumber + 1;
192
193 if(fLVMVolume && (pHMHandleData->dwAccess & GENERIC_WRITE)) {
194 //no write access allowed for LVM volumes
195 dprintf(("CreateFile: WARNING: Write access to LVM volume denied!!"));
196 pHMHandleData->dwAccess &= ~GENERIC_WRITE;
197 }
198 }
199 else {
200 //mounted drive, make sure access requested is readonly, else fail
201 if(pHMHandleData->dwAccess & GENERIC_WRITE) {
202 //no write access allowed for mounted partitions
203 dprintf(("CreateFile: WARNING: Write access to mounted partition denied!!"));
204 pHMHandleData->dwAccess &= ~GENERIC_WRITE;
205 }
206 strcpy(szDiskName, szDrive);
207 }
208 }
209 else return ERROR_FILE_NOT_FOUND;
210 }
211 else
212 if(strncmp(lpFileName, "\\\\.\\PHYSICALDRIVE", 17) == 0)
213 {
214 if(!fPhysicalDiskAccess) {
215 return ERROR_FILE_NOT_FOUND; //not allowed
216 }
217
218 //Note: this only works on Warp 4.5 and up
219 sprintf(szDiskName, "\\\\.\\Physical_Disk%c", lpFileName[17]+1);
220 fPhysicalDisk = TRUE;
221 dwPhysicalDiskNr = (DWORD)(lpFileName[17] - '0')+1;
222
223 //TODO: could be removable in theory
224 dwDriveType = DRIVE_FIXED;
225
226 if(pHMHandleData->dwAccess & GENERIC_WRITE) {
227 //no write access allowed for whole disks
228 dprintf(("CreateFile: WARNING: Write access to whole disk denied!!"));
229 pHMHandleData->dwAccess &= ~GENERIC_WRITE;
230 }
231 }
232 else {
233 strcpy(szDiskName, lpFileName);
234 szDrive[0] = *lpFileName;
235 dwDriveType = GetDriveTypeA(szDrive);
236 if(dwDriveType == DRIVE_DOESNOTEXIST) {
237 //If the drive doesn't exist, then fail right here
238 dprintf(("Drive %s does not exist; fail", szDrive));
239 return ERROR_INVALID_DRIVE; //right error??
240 }
241 }
242
243 //Disable error popus. NT allows an app to open a cdrom/dvd drive without a disk inside
244 //OS/2 fails in that case with error ERROR_NOT_READY
245 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
246 hFile = OSLibDosCreateFile(szDiskName,
247 pHMHandleData->dwAccess,
248 pHMHandleData->dwShare,
249 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
250 pHMHandleData->dwCreation,
251 pHMHandleData->dwFlags,
252 hTemplate);
253
254 //It is not allowed to open a readonly device with GENERIC_WRITE in OS/2;
255 //try with readonly again if that happened
256 //NOTE: Some applications open it with GENERIC_WRITE as Windows 2000 requires
257 // this for some aspi functions
258 if(hFile == INVALID_HANDLE_ERROR && dwDriveType == DRIVE_CDROM &&
259 (pHMHandleData->dwAccess & GENERIC_WRITE))
260 {
261 pHMHandleData->dwAccess &= ~GENERIC_WRITE;
262 hFile = OSLibDosCreateFile((LPSTR)szDiskName,
263 pHMHandleData->dwAccess,
264 pHMHandleData->dwShare,
265 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
266 pHMHandleData->dwCreation,
267 pHMHandleData->dwFlags,
268 hTemplate);
269 }
270 SetErrorMode(oldmode);
271
272 DWORD lasterror = GetLastError();
273 if(hFile != INVALID_HANDLE_ERROR || lasterror == ERROR_NOT_READY ||
274 lasterror == ERROR_SHARING_VIOLATION)
275 {
276 if(hFile == INVALID_HANDLE_ERROR) {
277 dprintf(("Drive not ready"));
278 SetLastError(NO_ERROR);
279 pHMHandleData->hHMHandle = 0; //handle lookup fails if this is set to -1
280 }
281 else pHMHandleData->hHMHandle = hFile;
282
283 DRIVE_INFO *drvInfo = (DRIVE_INFO *)malloc(sizeof(DRIVE_INFO));
284 if(drvInfo == NULL) {
285 DebugInt3();
286 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
287 return ERROR_OUTOFMEMORY;
288 }
289 pHMHandleData->dwUserData = (DWORD)drvInfo;
290
291 if(lasterror == ERROR_SHARING_VIOLATION) {
292 drvInfo->fShareViolation = TRUE;
293 }
294
295 memset(drvInfo, 0, sizeof(DRIVE_INFO));
296 drvInfo->dwAccess = pHMHandleData->dwAccess;
297 drvInfo->dwShare = pHMHandleData->dwShare;
298 drvInfo->lpSecurityAttributes = (LPSECURITY_ATTRIBUTES)lpSecurityAttributes;
299 drvInfo->dwCreation= pHMHandleData->dwCreation;
300 drvInfo->dwFlags = pHMHandleData->dwFlags;
301 drvInfo->hTemplate = hTemplate;
302 drvInfo->fLocked = FALSE;
303
304 //save volume start & length if volume must be accessed through the physical disk
305 //(no other choice for unmounted volumes)
306 drvInfo->fPhysicalDisk = fPhysicalDisk;
307 drvInfo->dwPhysicalDiskNr = dwPhysicalDiskNr;
308 drvInfo->StartingOffset = volext.Extents[0].StartingOffset;
309 drvInfo->PartitionSize = volext.Extents[0].ExtentLength;
310
311 //save volume name for later (IOCtls)
312 strncpy(drvInfo->szVolumeName, szVolumeName, sizeof(drvInfo->szVolumeName)-1);
313
314 drvInfo->driveLetter = *lpFileName; //save drive letter
315 if(drvInfo->driveLetter >= 'a') {
316 drvInfo->driveLetter = drvInfo->driveLetter - ((int)'a' - (int)'A');
317 }
318
319 drvInfo->driveType = dwDriveType;
320 if(drvInfo->driveType == DRIVE_CDROM)
321 {
322 drvInfo->fCDIoSupported = OSLibCdIoIsSupported(pHMHandleData->hHMHandle);
323
324 //get cdrom signature
325 DWORD parsize = 4;
326 DWORD datasize = 4;
327 strcpy(drvInfo->signature, "CD01");
328 OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x80, 0x61, &drvInfo->signature[0], 4, &parsize,
329 &drvInfo->signature[0], 4, &datasize);
330 }
331
332 if(hFile && drvInfo->driveType != DRIVE_FIXED) {
333 OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &drvInfo->dwVolumelabel, NULL, 0);
334 }
335
336 //for an unmounted partition we open the physical disk that contains it, so we
337 //must set the file pointer to the correct beginning
338 if(drvInfo->fPhysicalDisk && (drvInfo->StartingOffset.HighPart != 0 ||
339 drvInfo->StartingOffset.LowPart != 0))
340 {
341 SetFilePointer(pHMHandleData, 0, NULL, FILE_BEGIN);
342 }
343 //If the disk handle was valid, then we must lock it if the drive
344 //was opened without share flags
345 if(pHMHandleData->hHMHandle && drvInfo->dwShare == 0) {
346 dprintf(("Locking drive"));
347 if(OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_LOCKDRIVE,0,0,0,0,0,0))
348 {
349 dprintf(("Sharing violation while attempting to lock the drive"));
350 OSLibDosClose(pHMHandleData->hHMHandle);
351 free(drvInfo);
352 return ERROR_SHARING_VIOLATION;
353 }
354 drvInfo->fLocked = TRUE;
355 }
356 return (NO_ERROR);
357 }
358 else {
359 dprintf(("CreateFile failed; error %d", GetLastError()));
360 return(GetLastError());
361 }
362}
363//******************************************************************************
364//******************************************************************************
365DWORD HMDeviceDiskClass::OpenDisk(PVOID pDrvInfo)
366{
367 char filename[3];
368 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pDrvInfo;
369 HFILE hFile;
370
371 filename[0] = drvInfo->driveLetter;
372 filename[1] = ':';
373 filename[2] = 0;
374
375 //Disable error popus. NT allows an app to open a cdrom/dvd drive without a disk inside
376 //OS/2 fails in that case with error ERROR_NOT_READY
377 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
378 hFile = OSLibDosCreateFile(filename,
379 drvInfo->dwAccess,
380 drvInfo->dwShare,
381 drvInfo->lpSecurityAttributes,
382 drvInfo->dwCreation,
383 drvInfo->dwFlags,
384 drvInfo->hTemplate);
385 SetErrorMode(oldmode);
386
387 if (hFile != INVALID_HANDLE_ERROR || GetLastError() == ERROR_NOT_READY)
388 {
389 if(hFile == INVALID_HANDLE_ERROR) {
390 dprintf(("Drive not ready"));
391 return 0;
392 }
393 if(drvInfo->driveType == DRIVE_CDROM)
394 {
395 drvInfo->fCDIoSupported = OSLibCdIoIsSupported(hFile);
396
397 //get cdrom signature
398 DWORD parsize = 4;
399 DWORD datasize = 4;
400 strcpy(drvInfo->signature, "CD01");
401 OSLibDosDevIOCtl(hFile, 0x80, 0x61, &drvInfo->signature[0], 4, &parsize,
402 &drvInfo->signature[0], 4, &datasize);
403 }
404 OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &drvInfo->dwVolumelabel, NULL, 0);
405
406 //If the disk handle was valid, then we must lock it if the drive
407 //was opened without share flags
408 if(hFile && drvInfo->dwShare == 0) {
409 dprintf(("Locking drive"));
410 if(OSLibDosDevIOCtl(hFile,IOCTL_DISK,DSK_LOCKDRIVE,0,0,0,0,0,0))
411 {
412 dprintf(("Sharing violation while attempting to lock the drive"));
413 OSLibDosClose(hFile);
414 return 0;
415 }
416 drvInfo->fLocked = TRUE;
417 }
418 return hFile;
419 }
420 return 0;
421}
422//******************************************************************************
423//******************************************************************************
424BOOL HMDeviceDiskClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
425{
426 BOOL ret = TRUE;
427
428 if(pHMHandleData->hHMHandle) {
429 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
430 if(drvInfo && drvInfo->fLocked) {
431 dprintf(("Unlocking drive"));
432 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_UNLOCKDRIVE,0,0,0,0,0,0);
433 }
434 ret = OSLibDosClose(pHMHandleData->hHMHandle);
435 }
436 if(pHMHandleData->dwUserData) {
437 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
438 free(drvInfo);
439 }
440 return ret;
441}
442//******************************************************************************
443//******************************************************************************
444
445
446// this helper function just calls the specified
447// ioctl function for the CDROM manager with no
448// parameter packet other than the CD01 signature
449// and no data packet.
450static BOOL ioctlCDROMSimple(PHMHANDLEDATA pHMHandleData,
451 DWORD dwCategory,
452 DWORD dwFunction,
453 LPDWORD lpBytesReturned, DRIVE_INFO *pdrvInfo)
454{
455 DWORD dwParameterSize = 4;
456 DWORD dwDataSize = 0;
457 DWORD ret;
458
459 if(lpBytesReturned)
460 *lpBytesReturned = 0;
461
462 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
463 dwCategory,
464 dwFunction,
465 pdrvInfo->signature,
466 4,
467 &dwParameterSize,
468 NULL,
469 0,
470 &dwDataSize);
471 return (ret == ERROR_SUCCESS);
472}
473
474
475// this helper function just calls the specified
476// ioctl function for the DISK manager with the
477// specified function codes
478static BOOL ioctlDISKUnlockEject(PHMHANDLEDATA pHMHandleData,
479 DWORD dwCommand,
480 DWORD dwDiskHandle,
481 LPDWORD lpBytesReturned)
482{
483#pragma pack(1)
484 struct
485 {
486 BYTE ucCommand;
487 BYTE ucHandle;
488 } ParameterBlock;
489#pragma pack()
490
491 DWORD dwParameterSize = sizeof( ParameterBlock );
492 DWORD dwDataSize = 0;
493 DWORD ret;
494
495 ParameterBlock.ucCommand = dwCommand;
496 ParameterBlock.ucHandle = dwDiskHandle;
497
498 if(lpBytesReturned)
499 *lpBytesReturned = 0;
500
501 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
502 IOCTL_DISK,
503 DSK_UNLOCKEJECTMEDIA,
504 &ParameterBlock,
505 sizeof( ParameterBlock ),
506 &dwParameterSize,
507 NULL,
508 0,
509 &dwDataSize);
510 return (ret == ERROR_SUCCESS);
511}
512
513
514
515BOOL HMDeviceDiskClass::DeviceIoControl(PHMHANDLEDATA pHMHandleData, DWORD dwIoControlCode,
516 LPVOID lpInBuffer, DWORD nInBufferSize,
517 LPVOID lpOutBuffer, DWORD nOutBufferSize,
518 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
519{
520#ifdef DEBUG
521 char *msg = NULL;
522
523 switch(dwIoControlCode)
524 {
525 case FSCTL_DELETE_REPARSE_POINT:
526 msg = "FSCTL_DELETE_REPARSE_POINT";
527 break;
528 case FSCTL_DISMOUNT_VOLUME:
529 msg = "FSCTL_DISMOUNT_VOLUME";
530 break;
531 case FSCTL_GET_COMPRESSION:
532 msg = "FSCTL_GET_COMPRESSION";
533 break;
534 case FSCTL_GET_REPARSE_POINT:
535 msg = "FSCTL_GET_REPARSE_POINT";
536 break;
537 case FSCTL_LOCK_VOLUME:
538 msg = "FSCTL_LOCK_VOLUME";
539 break;
540 case FSCTL_QUERY_ALLOCATED_RANGES:
541 msg = "FSCTL_QUERY_ALLOCATED_RANGES";
542 break;
543 case FSCTL_SET_COMPRESSION:
544 msg = "FSCTL_SET_COMPRESSION";
545 break;
546 case FSCTL_SET_REPARSE_POINT:
547 msg = "FSCTL_SET_REPARSE_POINT";
548 break;
549 case FSCTL_SET_SPARSE:
550 msg = "FSCTL_SET_SPARSE";
551 break;
552 case FSCTL_SET_ZERO_DATA:
553 msg = "FSCTL_SET_ZERO_DATA";
554 break;
555 case FSCTL_UNLOCK_VOLUME:
556 msg = "FSCTL_UNLOCK_VOLUME";
557 break;
558 case IOCTL_DISK_CHECK_VERIFY:
559 msg = "IOCTL_DISK_CHECK_VERIFY";
560 break;
561 case IOCTL_DISK_EJECT_MEDIA:
562 msg = "IOCTL_DISK_EJECT_MEDIA";
563 break;
564 case IOCTL_DISK_FORMAT_TRACKS:
565 msg = "IOCTL_DISK_FORMAT_TRACKS";
566 break;
567 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
568 msg = "IOCTL_DISK_GET_DRIVE_GEOMETRY";
569 break;
570 case IOCTL_DISK_IS_WRITABLE:
571 msg = "IOCTL_DISK_IS_WRITABLE";
572 break;
573 case IOCTL_DISK_GET_DRIVE_LAYOUT:
574 msg = "IOCTL_DISK_GET_DRIVE_LAYOUT";
575 break;
576 case IOCTL_DISK_GET_MEDIA_TYPES:
577 msg = "IOCTL_DISK_GET_MEDIA_TYPES";
578 break;
579 case IOCTL_DISK_GET_PARTITION_INFO:
580 msg = "IOCTL_DISK_GET_PARTITION_INFO";
581 break;
582 case IOCTL_DISK_LOAD_MEDIA:
583 msg = "IOCTL_DISK_LOAD_MEDIA";
584 break;
585 case IOCTL_DISK_MEDIA_REMOVAL:
586 msg = "IOCTL_DISK_MEDIA_REMOVAL";
587 break;
588 case IOCTL_DISK_PERFORMANCE:
589 msg = "IOCTL_DISK_PERFORMANCE";
590 break;
591 case IOCTL_DISK_REASSIGN_BLOCKS:
592 msg = "IOCTL_DISK_REASSIGN_BLOCKS";
593 break;
594 case IOCTL_DISK_SET_DRIVE_LAYOUT:
595 msg = "IOCTL_DISK_SET_DRIVE_LAYOUT";
596 break;
597 case IOCTL_DISK_SET_PARTITION_INFO:
598 msg = "IOCTL_DISK_SET_PARTITION_INFO";
599 break;
600 case IOCTL_DISK_VERIFY:
601 msg = "IOCTL_DISK_VERIFY";
602 break;
603 case IOCTL_SERIAL_LSRMST_INSERT:
604 msg = "IOCTL_SERIAL_LSRMST_INSERT";
605 break;
606 case IOCTL_STORAGE_CHECK_VERIFY:
607 msg = "IOCTL_STORAGE_CHECK_VERIFY";
608 break;
609 case IOCTL_STORAGE_EJECT_MEDIA:
610 msg = "IOCTL_STORAGE_EJECT_MEDIA";
611 break;
612 case IOCTL_STORAGE_GET_MEDIA_TYPES:
613 msg = "IOCTL_STORAGE_GET_MEDIA_TYPES";
614 break;
615 case IOCTL_STORAGE_LOAD_MEDIA:
616 msg = "IOCTL_STORAGE_LOAD_MEDIA";
617 break;
618 case IOCTL_STORAGE_MEDIA_REMOVAL:
619 msg = "IOCTL_STORAGE_MEDIA_REMOVAL";
620 break;
621 case IOCTL_SCSI_PASS_THROUGH:
622 msg = "IOCTL_SCSI_PASS_THROUGH";
623 break;
624 case IOCTL_SCSI_MINIPORT:
625 msg = "IOCTL_SCSI_MINIPORT";
626 break;
627 case IOCTL_SCSI_GET_INQUIRY_DATA:
628 msg = "IOCTL_SCSI_GET_INQUIRY_DATA";
629 break;
630 case IOCTL_SCSI_GET_CAPABILITIES:
631 msg = "IOCTL_SCSI_GET_CAPABILITIES";
632 break;
633 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
634 msg = "IOCTL_SCSI_PASS_THROUGH_DIRECT";
635 break;
636 case IOCTL_SCSI_GET_ADDRESS:
637 msg = "IOCTL_SCSI_GET_ADDRESS";
638 break;
639 case IOCTL_SCSI_RESCAN_BUS:
640 msg = "IOCTL_SCSI_RESCAN_BUS";
641 break;
642 case IOCTL_SCSI_GET_DUMP_POINTERS:
643 msg = "IOCTL_SCSI_GET_DUMP_POINTERS";
644 break;
645 case IOCTL_SCSI_FREE_DUMP_POINTERS:
646 msg = "IOCTL_SCSI_FREE_DUMP_POINTERS";
647 break;
648 case IOCTL_IDE_PASS_THROUGH:
649 msg = "IOCTL_IDE_PASS_THROUGH";
650 break;
651 case IOCTL_CDROM_UNLOAD_DRIVER:
652 msg = "IOCTL_CDROM_UNLOAD_DRIVER";
653 break;
654 case IOCTL_CDROM_READ_TOC:
655 msg = "IOCTL_CDROM_READ_TOC";
656 break;
657 case IOCTL_CDROM_GET_CONTROL:
658 msg = "IOCTL_CDROM_GET_CONTROL";
659 break;
660 case IOCTL_CDROM_PLAY_AUDIO_MSF:
661 msg = "IOCTL_CDROM_PLAY_AUDIO_MSF";
662 break;
663 case IOCTL_CDROM_SEEK_AUDIO_MSF:
664 msg = "IOCTL_CDROM_SEEK_AUDIO_MSF";
665 break;
666 case IOCTL_CDROM_STOP_AUDIO:
667 msg = "IOCTL_CDROM_STOP_AUDIO";
668 break;
669 case IOCTL_CDROM_PAUSE_AUDIO:
670 msg = "IOCTL_CDROM_PAUSE_AUDIO";
671 break;
672 case IOCTL_CDROM_RESUME_AUDIO:
673 msg = "IOCTL_CDROM_RESUME_AUDIO";
674 break;
675 case IOCTL_CDROM_GET_VOLUME:
676 msg = "IOCTL_CDROM_GET_VOLUME";
677 break;
678 case IOCTL_CDROM_SET_VOLUME:
679 msg = "IOCTL_CDROM_SET_VOLUME";
680 break;
681 case IOCTL_CDROM_READ_Q_CHANNEL:
682 msg = "IOCTL_CDROM_READ_Q_CHANNEL";
683 break;
684 case IOCTL_CDROM_GET_LAST_SESSION:
685 msg = "IOCTL_CDROM_GET_LAST_SESSION";
686 break;
687 case IOCTL_CDROM_RAW_READ:
688 msg = "IOCTL_CDROM_RAW_READ";
689 break;
690 case IOCTL_CDROM_DISK_TYPE:
691 msg = "IOCTL_CDROM_DISK_TYPE";
692 break;
693 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
694 msg = "IOCTL_CDROM_GET_DRIVE_GEOMETRY";
695 break;
696 case IOCTL_CDROM_CHECK_VERIFY:
697 msg = "IOCTL_CDROM_CHECK_VERIFY";
698 break;
699 case IOCTL_CDROM_MEDIA_REMOVAL:
700 msg = "IOCTL_CDROM_MEDIA_REMOVAL";
701 break;
702 case IOCTL_CDROM_EJECT_MEDIA:
703 msg = "IOCTL_CDROM_EJECT_MEDIA";
704 break;
705 case IOCTL_CDROM_LOAD_MEDIA:
706 msg = "IOCTL_CDROM_LOAD_MEDIA";
707 break;
708 case IOCTL_CDROM_RESERVE:
709 msg = "IOCTL_CDROM_RESERVE";
710 break;
711 case IOCTL_CDROM_RELEASE:
712 msg = "IOCTL_CDROM_RELEASE";
713 break;
714 case IOCTL_CDROM_FIND_NEW_DEVICES:
715 msg = "IOCTL_CDROM_FIND_NEW_DEVICES";
716 break;
717 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
718 msg = "IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS";
719 break;
720 }
721 if(msg) {
722 dprintf(("HMDeviceDiskClass::DeviceIoControl %s %x %d %x %d %x %x", msg, lpInBuffer, nInBufferSize,
723 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped));
724 }
725#endif
726
727 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
728 if(drvInfo == NULL) {
729 dprintf(("ERROR: DeviceIoControl: drvInfo == NULL!!!"));
730 DebugInt3();
731 SetLastError(ERROR_INVALID_HANDLE);
732 return FALSE;
733 }
734 switch(dwIoControlCode)
735 {
736 case FSCTL_DELETE_REPARSE_POINT:
737 case FSCTL_DISMOUNT_VOLUME:
738 case FSCTL_GET_COMPRESSION:
739 case FSCTL_GET_REPARSE_POINT:
740 case FSCTL_LOCK_VOLUME:
741 case FSCTL_QUERY_ALLOCATED_RANGES:
742 case FSCTL_SET_COMPRESSION:
743 case FSCTL_SET_REPARSE_POINT:
744 case FSCTL_SET_SPARSE:
745 case FSCTL_SET_ZERO_DATA:
746 case FSCTL_UNLOCK_VOLUME:
747 break;
748
749 case IOCTL_DISK_FORMAT_TRACKS:
750 case IOCTL_DISK_GET_DRIVE_LAYOUT:
751 break;
752
753 case IOCTL_DISK_IS_WRITABLE:
754 {
755 APIRET rc;
756 DWORD ret;
757 ULONG ulBytesRead = 0; /* Number of bytes read by DosRead */
758 ULONG ulWrote = 0; /* Number of bytes written by DosWrite */
759 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
760 UCHAR uchFileData[1] = {'0'}; /* Data to write to file */
761
762 if(!pHMHandleData->hHMHandle)
763 {
764 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
765 if(!pHMHandleData->hHMHandle) {
766 dprintf(("No disk inserted; aborting"));
767 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
768 return FALSE;
769 }
770 }
771 if(drvInfo->driveType == DRIVE_CDROM) {
772 //TODO: check behaviour in NT
773 SetLastError(ERROR_WRITE_PROTECT);
774 return FALSE;
775 }
776 else
777 if(drvInfo->driveType == DRIVE_FIXED) {
778 SetLastError(ERROR_SUCCESS);
779 return TRUE;
780 }
781
782 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
783
784 /* Read the first byte of the disk */
785 rc = OSLibDosRead(pHMHandleData->hHMHandle, /* File Handle */
786 uchFileData, /* String to be read */
787 1L, /* Length of string to be read */
788 &ulBytesRead); /* Bytes actually read */
789
790 if (rc == 0)
791 {
792 dprintf(("IOCTL_DISK_IS_WRITABLE:OSLibDosRead failed with rc %08xh %x", rc,GetLastError()));
793 SetLastError(ERROR_ACCESS_DENIED);
794 goto writecheckfail;
795 }
796
797 /* Move the file pointer back */
798 rc = OSLibDosSetFilePtr (pHMHandleData->hHMHandle, /* File Handle */
799 -1,OSLIB_SETPTR_FILE_CURRENT);
800 if (rc == -1)
801 {
802 dprintf(("IOCTL_DISK_IS_WRITABLE:OSLibDosSetFilePtr failed with rc %d", rc));
803 SetLastError(ERROR_ACCESS_DENIED);
804 goto writecheckfail;
805 }
806
807 rc = OSLibDosWrite(pHMHandleData->hHMHandle, /* File handle */
808 (PVOID) uchFileData, /* String to be written */
809 1, /* Size of string to be written */
810 &ulWrote); /* Bytes actually written */
811
812 dprintf2(("IOCTL_DISK_IS_WRITABLE:OSLibDosWrite returned with rc %x %x", rc,GetLastError()));
813 if (rc == 0)
814 {
815 if (GetLastError() == ERROR_WRITE_PROTECT)
816 {
817 SetLastError(ERROR_WRITE_PROTECT);
818 goto writecheckfail;
819 }
820 }
821 SetErrorMode(oldmode);
822 SetLastError(ERROR_SUCCESS);
823 return TRUE;
824
825writecheckfail:
826 SetErrorMode(oldmode);
827 return FALSE;
828 }
829 //Basically the same as IOCTL_DISK_GET_DRIVE_GEOMETRY, but these two ioctls
830 //are supposed to work even without media in the drive
831 case IOCTL_STORAGE_GET_MEDIA_TYPES:
832 case IOCTL_DISK_GET_MEDIA_TYPES:
833 {
834 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)lpOutBuffer;
835 if(nOutBufferSize < sizeof(DISK_GEOMETRY) || !pGeom) {
836 SetLastError(ERROR_INSUFFICIENT_BUFFER);
837 return FALSE;
838 }
839 if(lpBytesReturned) {
840 *lpBytesReturned = 0;
841 }
842 if(!pHMHandleData->hHMHandle) {
843 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
844 //we don't care if there's a disk present or not
845 }
846
847 if(OSLibDosGetDiskGeometry(pHMHandleData->hHMHandle, drvInfo->driveLetter, pGeom) == FALSE) {
848 dprintf(("!ERROR!: IOCTL_DISK_GET_MEDIA_TYPES: OSLibDosGetDiskGeometry failed!!"));
849 return FALSE;
850 }
851 if(lpBytesReturned) {
852 *lpBytesReturned = sizeof(DISK_GEOMETRY);
853 }
854 SetLastError(ERROR_SUCCESS);
855 return TRUE;
856 }
857
858 //This ioctl is different from IOCTL_DISK_GET_MEDIA_TYPES; some applications
859 //use it to determine if a disk is present or whether a media change has
860 //occurred
861 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
862 {
863 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)lpOutBuffer;
864 if(nOutBufferSize < sizeof(DISK_GEOMETRY) || !pGeom) {
865 SetLastError(ERROR_INSUFFICIENT_BUFFER);
866 return FALSE;
867 }
868 if(lpBytesReturned) {
869 *lpBytesReturned = 0;
870 }
871
872 ULONG volumelabel;
873 APIRET rc;
874
875 if(!pHMHandleData->hHMHandle) {
876 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
877 if(!pHMHandleData->hHMHandle) {
878 dprintf(("No disk inserted; aborting"));
879 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
880 return FALSE;
881 }
882 }
883
884 //Applications can use this IOCTL to check if the floppy has been changed
885 //OSLibDosGetDiskGeometry won't fail when that happens so we read the
886 //volume label from the disk and return ERROR_MEDIA_CHANGED if the volume
887 //label has changed
888 //TODO: Find better way to determine if floppy was removed or switched
889 if(drvInfo->driveType != DRIVE_FIXED)
890 {
891 rc = OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &volumelabel, NULL, 0);
892 if(rc) {
893 dprintf(("IOCTL_DISK_GET_DRIVE_GEOMETRY: OSLibDosQueryVolumeSerialAndName failed with rc %d", GetLastError()));
894 if(pHMHandleData->hHMHandle) {
895 if(drvInfo->fLocked) {
896 dprintf(("Unlocking drive"));
897 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_UNLOCKDRIVE,0,0,0,0,0,0);
898 drvInfo->fLocked = FALSE;
899 }
900 OSLibDosClose(pHMHandleData->hHMHandle);
901 }
902 pHMHandleData->hHMHandle = 0;
903 SetLastError(ERROR_MEDIA_CHANGED);
904 return FALSE;
905 }
906 if(volumelabel != drvInfo->dwVolumelabel) {
907 dprintf(("IOCTL_DISK_GET_DRIVE_GEOMETRY: volume changed %x -> %x", drvInfo->dwVolumelabel, volumelabel));
908 SetLastError(ERROR_MEDIA_CHANGED);
909 return FALSE;
910 }
911 }
912
913 if(drvInfo->fPhysicalDisk) {
914 if(OSLibLVMGetDiskGeometry(drvInfo->dwPhysicalDiskNr, pGeom) == FALSE) {
915 dprintf(("!ERROR!: IOCTL_DISK_GET_DRIVE_GEOMETRY: OSLibDosGetDiskGeometry failed!!"));
916 return FALSE;
917 }
918 }
919 else {
920 if(OSLibDosGetDiskGeometry(pHMHandleData->hHMHandle, drvInfo->driveLetter, pGeom) == FALSE) {
921 dprintf(("!ERROR!: IOCTL_DISK_GET_DRIVE_GEOMETRY: OSLibDosGetDiskGeometry failed!!"));
922 return FALSE;
923 }
924 }
925 dprintf(("Cylinders %d", pGeom->Cylinders));
926 dprintf(("TracksPerCylinder %d", pGeom->TracksPerCylinder));
927 dprintf(("SectorsPerTrack %d", pGeom->SectorsPerTrack));
928 dprintf(("BytesPerSector %d", pGeom->BytesPerSector));
929 dprintf(("MediaType %d", pGeom->MediaType));
930 if(lpBytesReturned) {
931 *lpBytesReturned = sizeof(DISK_GEOMETRY);
932 }
933 SetLastError(ERROR_SUCCESS);
934 return TRUE;
935 }
936
937 case IOCTL_DISK_GET_PARTITION_INFO:
938 {
939 PPARTITION_INFORMATION pPartition = (PPARTITION_INFORMATION)lpOutBuffer;
940 if(nOutBufferSize < sizeof(PARTITION_INFORMATION) || !pPartition) {
941 SetLastError(ERROR_INSUFFICIENT_BUFFER);
942 return FALSE;
943 }
944 if(lpBytesReturned) {
945 *lpBytesReturned = sizeof(PARTITION_INFORMATION);
946 }
947 if(OSLibLVMGetPartitionInfo(drvInfo->driveLetter, drvInfo->szVolumeName, pPartition) == FALSE) {
948 SetLastError(ERROR_NOT_ENOUGH_MEMORY); //wrong error, but who cares
949 return FALSE;
950 }
951
952 SetLastError(ERROR_SUCCESS);
953 return TRUE;
954 }
955
956 case IOCTL_DISK_LOAD_MEDIA:
957 case IOCTL_DISK_MEDIA_REMOVAL:
958 case IOCTL_DISK_PERFORMANCE:
959 case IOCTL_DISK_REASSIGN_BLOCKS:
960 case IOCTL_DISK_SET_DRIVE_LAYOUT:
961 case IOCTL_DISK_SET_PARTITION_INFO:
962 case IOCTL_DISK_VERIFY:
963 case IOCTL_SERIAL_LSRMST_INSERT:
964 break;
965
966
967 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
968 {
969 PVOLUME_DISK_EXTENTS pVolExtent = (PVOLUME_DISK_EXTENTS)lpOutBuffer;
970 if(nOutBufferSize < sizeof(VOLUME_DISK_EXTENTS) || !pVolExtent) {
971 SetLastError(ERROR_INSUFFICIENT_BUFFER);
972 return FALSE;
973 }
974 if(OSLibLVMGetVolumeExtents(drvInfo->driveLetter, drvInfo->szVolumeName, pVolExtent) == FALSE) {
975 SetLastError(ERROR_NOT_ENOUGH_MEMORY); //wrong error, but who cares
976 return FALSE;
977 }
978
979 if(lpBytesReturned) {
980 *lpBytesReturned = sizeof(VOLUME_DISK_EXTENTS);
981 }
982 SetLastError(ERROR_SUCCESS);
983 return TRUE;
984 }
985
986 // -----------
987 // CDROM class
988 // -----------
989 case IOCTL_CDROM_READ_TOC:
990 {
991#pragma pack(1)
992 typedef struct
993 {
994 BYTE ucFirstTrack;
995 BYTE ucLastTrack;
996 DWORD ulLeadOutAddr;
997 } AudioDiskInfo;
998 typedef struct
999 {
1000 DWORD ulTrackAddr;
1001 BYTE ucTrackControl;
1002 } AudioTrackInfo;
1003 typedef struct
1004 {
1005 BYTE signature[4];
1006 BYTE ucTrack;
1007 } ParameterBlock;
1008#pragma pack()
1009 PCDROM_TOC pTOC = (PCDROM_TOC)lpOutBuffer;
1010 DWORD rc, numtracks;
1011 DWORD parsize = 4;
1012 DWORD datasize;
1013 AudioDiskInfo diskinfo;
1014 AudioTrackInfo trackinfo;
1015 ParameterBlock parm;
1016
1017 if(lpBytesReturned)
1018 *lpBytesReturned = 0;
1019
1020 if(!pTOC) {
1021 SetLastError(ERROR_INVALID_PARAMETER);
1022 return FALSE;
1023 }
1024 if(nOutBufferSize < sizeof(CDROM_TOC)) {
1025 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1026 return FALSE;
1027 }
1028 memset(pTOC, 0, nOutBufferSize);
1029 //IOCTL_CDROMAUDIO (0x81), CDROMAUDIO_GETAUDIODISK (0x61)
1030 datasize = sizeof(diskinfo);
1031 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x61, &drvInfo->signature[0], 4, &parsize,
1032 &diskinfo, sizeof(diskinfo), &datasize);
1033 if(rc != NO_ERROR) {
1034 dprintf(("OSLibDosDevIOCtl failed with rc %d", rc));
1035 return FALSE;
1036 }
1037 pTOC->FirstTrack = diskinfo.ucFirstTrack;
1038 pTOC->LastTrack = diskinfo.ucLastTrack;
1039 numtracks = pTOC->LastTrack - pTOC->FirstTrack + 1;
1040 dprintf(("first %d, last %d, num %d", pTOC->FirstTrack, pTOC->LastTrack, numtracks));
1041
1042 //numtracks+1, because we have to add a track at the end
1043 int length = 4 + (numtracks+1)*sizeof(TRACK_DATA);
1044 //big endian format
1045 pTOC->Length[0] = HIBYTE((length-2)); //minus length itself;
1046 pTOC->Length[1] = LOBYTE((length-2)); //minus length itself;
1047
1048 if(nOutBufferSize < length) {
1049 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1050 return FALSE;
1051 }
1052
1053 for(int i=0;i<numtracks;i++)
1054 {
1055 parsize = sizeof(parm);
1056 memcpy(parm.signature, drvInfo->signature, 4);
1057 parm.ucTrack = pTOC->FirstTrack+i;
1058
1059 datasize = sizeof(trackinfo);
1060
1061 //IOCTL_CDROMAUDIO (0x81), CDROMAUDIO_GETAUDIOTRACK (0x62)
1062 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x62, &parm, sizeof(parm), &parsize,
1063 &trackinfo, sizeof(trackinfo), &datasize);
1064 if(rc != NO_ERROR) {
1065 dprintf(("OSLibDosDevIOCtl failed with rc %d", rc));
1066 return FALSE;
1067 }
1068 pTOC->TrackData[i].TrackNumber = pTOC->FirstTrack + i;
1069 pTOC->TrackData[i].Reserved = 0;
1070 pTOC->TrackData[i].Control = trackinfo.ucTrackControl >> 4;
1071 pTOC->TrackData[i].Adr = trackinfo.ucTrackControl & 0xF;
1072 pTOC->TrackData[i].Reserved1 = 0;
1073 //big endian format
1074 pTOC->TrackData[i].Address[0] = HIBYTE(HIWORD(trackinfo.ulTrackAddr));
1075 pTOC->TrackData[i].Address[1] = LOBYTE(HIWORD(trackinfo.ulTrackAddr));
1076 pTOC->TrackData[i].Address[2] = HIBYTE(LOWORD(trackinfo.ulTrackAddr));
1077 pTOC->TrackData[i].Address[3] = LOBYTE(LOWORD(trackinfo.ulTrackAddr));
1078 dprintf(("IOCTL_CDROM_READ_TOC track %d Control %d Adr %d address %x", pTOC->FirstTrack+i, pTOC->TrackData[i].Control, pTOC->TrackData[i].Adr, trackinfo.ulTrackAddr));
1079 }
1080
1081 //Add a track at the end (presumably so the app can determine the size of the 1st track)
1082 //That is what NT4, SP6 does anyway
1083 pTOC->TrackData[numtracks].TrackNumber = 0xAA;
1084 pTOC->TrackData[numtracks].Reserved = 0;
1085 pTOC->TrackData[numtracks].Control = pTOC->TrackData[numtracks-1].Control;
1086 pTOC->TrackData[numtracks].Adr = pTOC->TrackData[numtracks-1].Adr;
1087 pTOC->TrackData[numtracks].Reserved1 = 0;
1088 //big endian format
1089 //Address of pseudo track is the address of the lead-out track
1090 pTOC->TrackData[numtracks].Address[0] = HIBYTE(HIWORD(diskinfo.ulLeadOutAddr));
1091 pTOC->TrackData[numtracks].Address[1] = LOBYTE(HIWORD(diskinfo.ulLeadOutAddr));
1092 pTOC->TrackData[numtracks].Address[2] = HIBYTE(LOWORD(diskinfo.ulLeadOutAddr));
1093 pTOC->TrackData[numtracks].Address[3] = LOBYTE(LOWORD(diskinfo.ulLeadOutAddr));
1094
1095 if(lpBytesReturned)
1096 *lpBytesReturned = length;
1097
1098 SetLastError(ERROR_SUCCESS);
1099 return TRUE;
1100 }
1101
1102 case IOCTL_CDROM_UNLOAD_DRIVER:
1103 case IOCTL_CDROM_GET_CONTROL:
1104 break;
1105
1106 case IOCTL_CDROM_PLAY_AUDIO_MSF:
1107 {
1108#pragma pack(1)
1109 struct
1110 {
1111 DWORD ucSignature;
1112 BYTE ucAddressingMode;
1113 DWORD ulStartingMSF;
1114 DWORD ulEndingMSF;
1115 } ParameterBlock;
1116#pragma pack()
1117 PCDROM_PLAY_AUDIO_MSF pPlay = (PCDROM_PLAY_AUDIO_MSF)lpInBuffer;
1118
1119 if(nInBufferSize < sizeof(CDROM_SEEK_AUDIO_MSF)) {
1120 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1121 return FALSE;
1122 }
1123 if(lpBytesReturned)
1124 *lpBytesReturned = 0;
1125
1126 dprintf(("Play CDROM audio playback %d:%d (%d) - %d:%d (%d)", pPlay->StartingM, pPlay->StartingS, pPlay->StartingF, pPlay->EndingM, pPlay->EndingS, pPlay->EndingF));
1127
1128 // setup the parameter block
1129 memcpy(&ParameterBlock.ucSignature, drvInfo->signature, 4);
1130 ParameterBlock.ucAddressingMode = 1; // MSF format
1131
1132 ParameterBlock.ulStartingMSF = pPlay->StartingM << 16 |
1133 pPlay->StartingS << 8 |
1134 pPlay->StartingF;
1135 ParameterBlock.ulEndingMSF = pPlay->EndingM << 16 |
1136 pPlay->EndingS << 8 |
1137 pPlay->EndingF;
1138
1139 DWORD dwParameterSize = sizeof( ParameterBlock );
1140 DWORD dwDataSize = 0;
1141 DWORD ret;
1142
1143 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
1144 0x81, // IOCTL_CDROMAUDIO
1145 0x50, // CDROMAUDIO_PLAYAUDIO
1146 &ParameterBlock,
1147 sizeof( ParameterBlock ),
1148 &dwParameterSize,
1149 NULL,
1150 0,
1151 &dwDataSize);
1152 if(ret != ERROR_SUCCESS) {
1153 dprintf(("IOCTL_CDROMAUDIO, CDROMAUDIO_PLAYAUDIO failed!!"));
1154 }
1155 drvInfo->fCDPlaying = TRUE;
1156 return (ret == ERROR_SUCCESS);
1157 }
1158
1159 case IOCTL_CDROM_SEEK_AUDIO_MSF:
1160 {
1161#pragma pack(1)
1162 struct
1163 {
1164 DWORD ucSignature;
1165 BYTE ucAddressingMode;
1166 DWORD ulStartingMSF;
1167 } ParameterBlock;
1168#pragma pack()
1169 CDROM_SEEK_AUDIO_MSF *pSeek = (CDROM_SEEK_AUDIO_MSF *)lpInBuffer;
1170
1171 if(nInBufferSize < sizeof(CDROM_SEEK_AUDIO_MSF)) {
1172 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1173 return FALSE;
1174 }
1175 if(lpBytesReturned)
1176 *lpBytesReturned = 0;
1177
1178 dprintf(("IOCTL_CDROMDISK, CDROMDISK_SEEK %d:%d (%d)", pSeek->M, pSeek->S, pSeek->F));
1179
1180 // setup the parameter block
1181 memcpy(&ParameterBlock.ucSignature, drvInfo->signature, 4);
1182 ParameterBlock.ucAddressingMode = 1; // MSF format
1183
1184 ParameterBlock.ulStartingMSF = pSeek->M << 16 |
1185 pSeek->S << 8 |
1186 pSeek->F;
1187
1188 DWORD dwParameterSize = sizeof( ParameterBlock );
1189 DWORD dwDataSize = 0;
1190 DWORD ret;
1191
1192 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
1193 0x80, // IOCTL_CDROMDISK
1194 0x50, // CDROMDISK_SEEK
1195 &ParameterBlock,
1196 sizeof( ParameterBlock ),
1197 &dwParameterSize,
1198 NULL,
1199 0,
1200 &dwDataSize);
1201 if(ret != ERROR_SUCCESS) {
1202 dprintf(("IOCTL_CDROMDISK, CDROMDISK_SEEK %x failed!!", ParameterBlock.ulStartingMSF));
1203 }
1204 return (ret == ERROR_SUCCESS);
1205 }
1206
1207 case IOCTL_CDROM_PAUSE_AUDIO:
1208 // NO BREAK CASE
1209 // Note: for OS/2, pause and stop seems to be the same!
1210
1211 case IOCTL_CDROM_STOP_AUDIO:
1212 {
1213 dprintf(("Stop / pause CDROM audio playback"));
1214 drvInfo->fCDPlaying = FALSE;
1215 return ioctlCDROMSimple(pHMHandleData,
1216 0x81, // IOCTL_CDROMAUDIO
1217 0x51, // CDROMAUDIO_STOPAUDIO
1218 lpBytesReturned, drvInfo);
1219 }
1220
1221 case IOCTL_CDROM_RESUME_AUDIO:
1222 {
1223 dprintf(("Resume CDROM audio playback"));
1224 drvInfo->fCDPlaying = TRUE;
1225 return ioctlCDROMSimple(pHMHandleData,
1226 0x81, // IOCTL_CDROMAUDIO
1227 0x52, // CDROMAUDIO_RESUMEAUDIO
1228 lpBytesReturned, drvInfo);
1229 }
1230
1231 case IOCTL_CDROM_GET_VOLUME:
1232 {
1233 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpOutBuffer;
1234 char volbuf[8];
1235 DWORD parsize, datasize, ret;
1236
1237 if(nOutBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
1238 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1239 return FALSE;
1240 }
1241 if(lpBytesReturned) {
1242 *lpBytesReturned = 0;
1243 }
1244 parsize = 4;
1245 datasize = 8;
1246 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x60, drvInfo->signature, 4, &parsize,
1247 volbuf, 8, &datasize);
1248
1249 if(ret)
1250 return FALSE;
1251
1252 if(lpBytesReturned) {
1253 *lpBytesReturned = sizeof(VOLUME_CONTROL);
1254 }
1255 pVol->PortVolume[0] = volbuf[1];
1256 pVol->PortVolume[1] = volbuf[3];
1257 pVol->PortVolume[2] = volbuf[5];
1258 pVol->PortVolume[3] = volbuf[7];
1259 SetLastError(ERROR_SUCCESS);
1260 return TRUE;
1261 }
1262
1263 case IOCTL_CDROM_SET_VOLUME:
1264 {
1265 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpInBuffer;
1266 char volbuf[8];
1267 DWORD parsize, datasize, ret;
1268
1269 if(nInBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
1270 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1271 return FALSE;
1272 }
1273 if(lpBytesReturned) {
1274 *lpBytesReturned = 0;
1275 }
1276 parsize = 4;
1277 datasize = 8;
1278 volbuf[0] = 0;
1279 volbuf[1] = pVol->PortVolume[0];
1280 volbuf[2] = 1;
1281 volbuf[3] = pVol->PortVolume[1];
1282 volbuf[4] = 2;
1283 volbuf[5] = pVol->PortVolume[2];
1284 volbuf[6] = 3;
1285 volbuf[7] = pVol->PortVolume[3];
1286 dprintf(("Set CD volume (%d,%d)(%d,%d)", pVol->PortVolume[0], pVol->PortVolume[1], pVol->PortVolume[2], pVol->PortVolume[3]));
1287 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x40, drvInfo->signature, 4, &parsize,
1288 volbuf, 8, &datasize);
1289
1290 if(ret)
1291 return FALSE;
1292
1293 SetLastError(ERROR_SUCCESS);
1294 return TRUE;
1295 }
1296 case IOCTL_CDROM_READ_Q_CHANNEL:
1297 {
1298#pragma pack(1)
1299 struct
1300 {
1301 BYTE ucControlAddr;
1302 BYTE ucTrackNr;
1303 BYTE ucIndex;
1304 BYTE ucRuntimeTrackMin;
1305 BYTE ucRuntimeTrackSec;
1306 BYTE ucRuntimeTrackFrame;
1307 BYTE ucReserved;
1308 BYTE ucRuntimeDiscMin;
1309 BYTE ucRuntimeDiscSec;
1310 BYTE ucRuntimeDiscFrame;
1311 } DataBlock;
1312 struct {
1313 WORD usAudioStatus;
1314 DWORD ulStartLoc;
1315 DWORD ulEndLoc;
1316 } DataBlockStatus;
1317#pragma pack()
1318 CDROM_SUB_Q_DATA_FORMAT *pFormat = (CDROM_SUB_Q_DATA_FORMAT*)lpInBuffer;
1319 SUB_Q_CHANNEL_DATA *pChannelData = (SUB_Q_CHANNEL_DATA *)lpOutBuffer;
1320 char signature[8];
1321
1322 if(nInBufferSize < sizeof(CDROM_SUB_Q_DATA_FORMAT) || !pFormat) {
1323 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1324 return FALSE;
1325 }
1326 if(nOutBufferSize < sizeof(SUB_Q_CHANNEL_DATA) || !pChannelData) {
1327 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1328 return FALSE;
1329 }
1330 if(lpBytesReturned) {
1331 *lpBytesReturned = 0;
1332 }
1333
1334 DWORD dwParameterSize = 4;
1335 DWORD dwDataSize = sizeof(DataBlock);
1336 DWORD ret;
1337
1338 memcpy(signature, drvInfo->signature, dwParameterSize);
1339
1340 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
1341 0x81, // IOCTL_CDROMAUDIO
1342 0x63, // CDROMAUDIO_GETSUBCHANNELQ
1343 signature,
1344 dwParameterSize,
1345 &dwParameterSize,
1346 &DataBlock,
1347 sizeof(DataBlock),
1348 &dwDataSize);
1349 if(ret != ERROR_SUCCESS) {
1350 dprintf(("IOCTL_CDROMAUDIO, CDROMAUDIO_GETSUBCHANNELQ failed!!"));
1351 return FALSE;
1352 }
1353
1354 dwDataSize = sizeof(DataBlockStatus);
1355 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
1356 0x81, // IOCTL_CDROMAUDIO
1357 0x65, // CDROMAUDIO_GETAUDIOSTATUS
1358 signature,
1359 dwParameterSize,
1360 &dwParameterSize,
1361 &DataBlockStatus,
1362 sizeof(DataBlockStatus),
1363 &dwDataSize);
1364 if(ret != ERROR_SUCCESS) {
1365 dprintf(("IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIOSTATUS failed!!"));
1366 return FALSE;
1367 }
1368 dprintf(("CDROMAUDIO_GETAUDIOSTATUS returned %d %x %x", DataBlockStatus.usAudioStatus, DataBlockStatus.ulStartLoc, DataBlockStatus.ulEndLoc));
1369
1370 pChannelData->CurrentPosition.Header.Reserved = 0;
1371 if(DataBlockStatus.usAudioStatus & 1) {
1372 pChannelData->CurrentPosition.Header.AudioStatus = AUDIO_STATUS_PAUSED;
1373 }
1374 else {
1375 if(DataBlockStatus.ulStartLoc == 0) {//no play command has been issued before
1376 pChannelData->CurrentPosition.Header.AudioStatus = AUDIO_STATUS_NO_STATUS;
1377 }
1378 else {//assume in progress, but could alse be finished playing
1379 pChannelData->CurrentPosition.Header.AudioStatus = (drvInfo->fCDPlaying) ? AUDIO_STATUS_IN_PROGRESS : AUDIO_STATUS_PLAY_COMPLETE;
1380 }
1381 }
1382
1383 switch(pFormat->Format) {
1384 case IOCTL_CDROM_SUB_Q_CHANNEL:
1385 dprintf(("IOCTL_CDROM_SUB_Q_CHANNEL not supported"));
1386 return FALSE;
1387 case IOCTL_CDROM_CURRENT_POSITION:
1388 pChannelData->CurrentPosition.Header.DataLength[0] = sizeof(pChannelData->CurrentPosition);
1389 pChannelData->CurrentPosition.Header.DataLength[1] = 0;
1390 pChannelData->CurrentPosition.Control = DataBlock.ucControlAddr >> 4;
1391 pChannelData->CurrentPosition.ADR = DataBlock.ucControlAddr & 0xF;
1392 pChannelData->CurrentPosition.IndexNumber = BCDToDec(DataBlock.ucIndex);
1393 pChannelData->CurrentPosition.TrackNumber = BCDToDec(DataBlock.ucTrackNr);
1394 pChannelData->CurrentPosition.TrackRelativeAddress[1] = DataBlock.ucRuntimeTrackMin;
1395 pChannelData->CurrentPosition.TrackRelativeAddress[2] = DataBlock.ucRuntimeTrackSec;
1396 pChannelData->CurrentPosition.TrackRelativeAddress[3] = DataBlock.ucRuntimeTrackFrame;
1397 pChannelData->CurrentPosition.AbsoluteAddress[1] = DataBlock.ucRuntimeDiscMin;
1398 pChannelData->CurrentPosition.AbsoluteAddress[2] = DataBlock.ucRuntimeDiscSec;
1399 pChannelData->CurrentPosition.AbsoluteAddress[3] = DataBlock.ucRuntimeDiscFrame;
1400 pChannelData->CurrentPosition.FormatCode = IOCTL_CDROM_CURRENT_POSITION;
1401 dprintf(("IOCTL_CDROM_CURRENT_POSITION: Control %x ADR %x Index %d Track %d Track Rel %d:%d (%d) Absolute %d:%d (%d)", pChannelData->CurrentPosition.Control, pChannelData->CurrentPosition.ADR, pChannelData->CurrentPosition.IndexNumber, pChannelData->CurrentPosition.TrackNumber, pChannelData->CurrentPosition.TrackRelativeAddress[1], pChannelData->CurrentPosition.TrackRelativeAddress[2], pChannelData->CurrentPosition.TrackRelativeAddress[3], pChannelData->CurrentPosition.AbsoluteAddress[1], pChannelData->CurrentPosition.AbsoluteAddress[2], pChannelData->CurrentPosition.AbsoluteAddress[3]));
1402 if(lpBytesReturned) {
1403 *lpBytesReturned = sizeof(*pChannelData);
1404 }
1405 break;
1406 case IOCTL_CDROM_MEDIA_CATALOG:
1407 dprintf(("IOCTL_CDROM_MEDIA_CATALOG not supported"));
1408 return FALSE;
1409 case IOCTL_CDROM_TRACK_ISRC:
1410 dprintf(("IOCTL_CDROM_TRACK_ISRC not supported"));
1411 return FALSE;
1412 }
1413 return (ret == ERROR_SUCCESS);
1414 }
1415
1416 case IOCTL_CDROM_GET_LAST_SESSION:
1417 case IOCTL_CDROM_RAW_READ:
1418 case IOCTL_CDROM_DISK_TYPE:
1419 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
1420 case IOCTL_CDROM_MEDIA_REMOVAL:
1421 break;
1422
1423 case IOCTL_CDROM_EJECT_MEDIA:
1424 {
1425 dprintf(("Eject CDROM media"));
1426 return ioctlCDROMSimple(pHMHandleData,
1427 0x80, // IOCTL_CDROM
1428 0x44, // CDROMDISK_EJECTDISK
1429 lpBytesReturned, drvInfo);
1430 }
1431
1432 case IOCTL_CDROM_LOAD_MEDIA:
1433 {
1434 dprintf(("Loading CDROM media"));
1435 return ioctlCDROMSimple(pHMHandleData,
1436 0x80, // IOCTL_CDROM
1437 0x45, // CDROMDISK_CLOSETRAY
1438 lpBytesReturned, drvInfo);
1439 }
1440
1441 case IOCTL_CDROM_RESERVE:
1442 case IOCTL_CDROM_RELEASE:
1443 case IOCTL_CDROM_FIND_NEW_DEVICES:
1444 break;
1445
1446
1447 // -------------
1448 // STORAGE class
1449 // -------------
1450
1451 case IOCTL_CDROM_CHECK_VERIFY:
1452 if(drvInfo->driveType != DRIVE_CDROM) {
1453 SetLastError(ERROR_GEN_FAILURE); //TODO: right error?
1454 return FALSE;
1455 }
1456 //no break;
1457 case IOCTL_DISK_CHECK_VERIFY:
1458 case IOCTL_STORAGE_CHECK_VERIFY:
1459 {
1460#pragma pack(1)
1461 typedef struct
1462 {
1463 BYTE ucCommandInfo;
1464 WORD usDriveUnit;
1465 } ParameterBlock;
1466#pragma pack()
1467
1468 dprintf(("IOCTL_CDROM(DISK/STORAGE)CHECK_VERIFY %s", drvInfo->signature));
1469 if(lpBytesReturned) {
1470 *lpBytesReturned = 0;
1471 }
1472
1473 if(!pHMHandleData->hHMHandle) {
1474 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1475 if(!pHMHandleData->hHMHandle) {
1476 dprintf(("No disk inserted; aborting"));
1477 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
1478 return FALSE;
1479 }
1480 }
1481
1482 DWORD parsize = sizeof(ParameterBlock);
1483 DWORD datasize = 2;
1484 WORD status = 0;
1485 DWORD rc;
1486 ParameterBlock parm;
1487
1488 parm.ucCommandInfo = 0;
1489 parm.usDriveUnit = drvInfo->driveLetter - 'A';
1490// rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x08, 0x66, &parm, sizeof(parm), &parsize,
1491 //TODO: this doesn't work for floppies for some reason...
1492 rc = OSLibDosDevIOCtl(-1, IOCTL_DISK, DSK_GETLOCKSTATUS, &parm, sizeof(parm), &parsize,
1493 &status, sizeof(status), &datasize);
1494 if(rc != NO_ERROR) {
1495 dprintf(("OSLibDosDevIOCtl failed with rc %d datasize %d", rc, datasize));
1496 return FALSE;
1497 }
1498 dprintf(("Disk status 0x%x", status));
1499 //if no disk present, return FALSE
1500 if(!(status & (BIT_2))) {
1501 SetLastError(ERROR_NOT_READY); //NT4, SP6 returns this
1502 return FALSE;
1503 }
1504 SetLastError(NO_ERROR);
1505 return TRUE;
1506 }
1507
1508 case IOCTL_DISK_EJECT_MEDIA:
1509 case IOCTL_STORAGE_EJECT_MEDIA:
1510 {
1511 dprintf(("Ejecting storage media"));
1512 return ioctlDISKUnlockEject(pHMHandleData,
1513 0x02, // EJECT media
1514 -1,
1515 lpBytesReturned);
1516 }
1517
1518 case IOCTL_STORAGE_LOAD_MEDIA:
1519 // case IOCTL_STORAGE_LOAD_MEDIA2:
1520 {
1521 dprintf(("Loading storage media"));
1522 return ioctlDISKUnlockEject(pHMHandleData,
1523 0x03, // LOAD media
1524 -1,
1525 lpBytesReturned);
1526 }
1527
1528 // case IOCTL_STORAGE_EJECTION_CONTROL:
1529 case IOCTL_STORAGE_MEDIA_REMOVAL:
1530 break;
1531
1532
1533 // -------------------
1534 // SCSI passthru class
1535 // -------------------
1536
1537 case IOCTL_SCSI_MINIPORT:
1538 case IOCTL_SCSI_GET_INQUIRY_DATA:
1539 break;
1540
1541 case IOCTL_SCSI_GET_CAPABILITIES:
1542 break;
1543
1544 case IOCTL_SCSI_PASS_THROUGH:
1545 //no break; same as IOCTL_SCSI_PASS_THROUGH_DIRECT
1546 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
1547 {
1548 PSCSI_PASS_THROUGH_DIRECT pPacket = (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer;
1549 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1550 CDIO_CMD_BUFFER cdiocmd;
1551
1552 if(nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT) ||
1553 !pPacket || pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
1554 {
1555 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1556 return FALSE;
1557 }
1558
1559 if(!drvInfo || drvInfo->fCDIoSupported == FALSE) {
1560 dprintf(("os2cdrom.dmd CD interface not supported!!"));
1561 SetLastError(ERROR_ACCESS_DENIED);
1562 return FALSE;
1563 }
1564 if(lpBytesReturned) {
1565 *lpBytesReturned = 0;
1566 }
1567
1568 if(pPacket->CdbLength > sizeof(cdiocmd.arCDB)) {
1569 dprintf(("CDB buffer too big (%d)!!", pPacket->CdbLength));
1570 SetLastError(ERROR_INVALID_PARAMETER);
1571 return FALSE;
1572 }
1573
1574 memset(&cdiocmd, 0, sizeof(cdiocmd));
1575
1576 switch(pPacket->DataIn) {
1577 case SCSI_IOCTL_DATA_OUT:
1578 cdiocmd.flDirection = CMDDIR_OUTPUT;
1579 break;
1580 case SCSI_IOCTL_DATA_IN:
1581 cdiocmd.flDirection = CMDDIR_INPUT;
1582 break;
1583 case SCSI_IOCTL_DATA_UNSPECIFIED:
1584 cdiocmd.flDirection = CMDDIR_OUTPUT|CMDDIR_INPUT;;
1585 break;
1586 default:
1587 dprintf(("Invalid DataIn (%d)!!", pPacket->DataIn));
1588 SetLastError(ERROR_INVALID_PARAMETER);
1589 return FALSE;
1590 }
1591
1592 cdiocmd.cbCDB = pPacket->CdbLength;
1593 memcpy(cdiocmd.arCDB, pPacket->Cdb, pPacket->CdbLength);
1594
1595 dprintf(("IOCTL_SCSI_PASS_THROUGH_DIRECT %x len %x, %x%02x%02x%02x %x%02x", pPacket->Cdb[0], pPacket->DataTransferLength, pPacket->Cdb[2], pPacket->Cdb[3], pPacket->Cdb[4], pPacket->Cdb[5], pPacket->Cdb[7], pPacket->Cdb[8]));
1596
1597 if(OSLibCdIoSendCommand(pHMHandleData->hHMHandle, &cdiocmd, pPacket->DataBuffer, pPacket->DataTransferLength) == FALSE) {
1598 dprintf(("OSLibCdIoSendCommand failed!!"));
1599 pPacket->ScsiStatus = SS_ERR;
1600 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
1601 return FALSE;
1602 }
1603
1604 if(pPacket->SenseInfoLength) {
1605 if(OSLibCdIoRequestSense(pHMHandleData->hHMHandle, (char *)pPacket + pPacket->SenseInfoOffset, pPacket->SenseInfoLength) == FALSE) {
1606 dprintf(("OSLibCdIoRequestSense failed!!"));
1607 pPacket->ScsiStatus = SS_ERR;
1608 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
1609 return FALSE;
1610 }
1611 }
1612 pPacket->ScsiStatus = SS_COMP;
1613 SetLastError(ERROR_SUCCESS);
1614 return TRUE;
1615 }
1616 case IOCTL_SCSI_GET_ADDRESS:
1617 {
1618 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1619
1620 if(!drvInfo || drvInfo->fCDIoSupported == FALSE) {
1621 dprintf(("os2cdrom.dmd CD interface not supported!!"));
1622 SetLastError(ERROR_ACCESS_DENIED);
1623 return FALSE;
1624 }
1625
1626 if(!lpOutBuffer || nOutBufferSize < 8) {
1627 SetLastError(ERROR_INSUFFICIENT_BUFFER); //todo: right error?
1628 return(FALSE);
1629 }
1630 SCSI_ADDRESS *addr = (SCSI_ADDRESS *)lpOutBuffer;
1631 addr->Length = sizeof(SCSI_ADDRESS);
1632 addr->PortNumber = 0;
1633 addr->PathId = 0;
1634 //irrelevant, since os2cdrom.dmd doesn't need them
1635 addr->TargetId = 1;
1636 addr->Lun = 0;
1637 SetLastError(ERROR_SUCCESS);
1638 return TRUE;
1639 }
1640
1641 case IOCTL_SCSI_RESCAN_BUS:
1642 case IOCTL_SCSI_GET_DUMP_POINTERS:
1643 case IOCTL_SCSI_FREE_DUMP_POINTERS:
1644 case IOCTL_IDE_PASS_THROUGH:
1645 break;
1646
1647 }
1648 dprintf(("HMDeviceDiskClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
1649 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1650 return FALSE;
1651}
1652/*****************************************************************************
1653 * Name : BOOL HMDeviceDiskClass::ReadFile
1654 * Purpose : read data from handle / device
1655 * Parameters: PHMHANDLEDATA pHMHandleData,
1656 * LPCVOID lpBuffer,
1657 * DWORD nNumberOfBytesToRead,
1658 * LPDWORD lpNumberOfBytesRead,
1659 * LPOVERLAPPED lpOverlapped
1660 * Variables :
1661 * Result : Boolean
1662 * Remark :
1663 * Status :
1664 *
1665 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1666 *****************************************************************************/
1667
1668BOOL HMDeviceDiskClass::ReadFile(PHMHANDLEDATA pHMHandleData,
1669 LPCVOID lpBuffer,
1670 DWORD nNumberOfBytesToRead,
1671 LPDWORD lpNumberOfBytesRead,
1672 LPOVERLAPPED lpOverlapped,
1673 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1674{
1675 LPVOID lpRealBuf;
1676 Win32MemMap *map;
1677 DWORD offset, bytesread;
1678 BOOL bRC;
1679 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1680
1681 dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
1682 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped));
1683
1684 //It's legal for this pointer to be NULL
1685 if(lpNumberOfBytesRead)
1686 *lpNumberOfBytesRead = 0;
1687 else
1688 lpNumberOfBytesRead = &bytesread;
1689
1690 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1691 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1692 SetLastError(ERROR_INVALID_PARAMETER);
1693 return FALSE;
1694 }
1695
1696 if(lpCompletionRoutine) {
1697 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
1698 }
1699
1700 //If we didn't get an OS/2 handle for the disk before, get one now
1701 if(!pHMHandleData->hHMHandle) {
1702 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1703 if(!pHMHandleData->hHMHandle) {
1704 dprintf(("No disk inserted; aborting"));
1705 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
1706 return FALSE;
1707 }
1708 }
1709
1710 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1711 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1712 }
1713
1714 //SvL: DosRead doesn't like writing to memory addresses returned by
1715 // DosAliasMem -> search for original memory mapped pointer and use
1716 // that one + commit pages if not already present
1717 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
1718 if(map) {
1719 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1720 DWORD nrpages = nNumberOfBytesToRead/4096;
1721 if(offset & 0xfff)
1722 nrpages++;
1723 if(nNumberOfBytesToRead & 0xfff)
1724 nrpages++;
1725
1726 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1727 }
1728 else lpRealBuf = (LPVOID)lpBuffer;
1729
1730 //if unmounted volume, check upper boundary as we're accessing the entire physical drive
1731 //instead of just the volume
1732 if(drvInfo->fPhysicalDisk && (drvInfo->StartingOffset.HighPart != 0 ||
1733 drvInfo->StartingOffset.LowPart != 0))
1734 {
1735 LARGE_INTEGER distance, result, endpos;
1736
1737 //calculate end position in partition
1738 Add64(&drvInfo->StartingOffset, &drvInfo->PartitionSize, &endpos);
1739
1740 distance.HighPart = 0;
1741 distance.LowPart = nNumberOfBytesToRead;
1742 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
1743
1744 //check upper boundary
1745 if(result.HighPart > endpos.HighPart ||
1746 (result.HighPart == endpos.HighPart && result.LowPart > endpos.LowPart) )
1747 {
1748 Sub64(&endpos, &drvInfo->CurrentFilePointer, &result);
1749 nNumberOfBytesToRead = result.LowPart;
1750 dprintf(("Read past end of volume; nNumberOfBytesToRead reduced to %d", nNumberOfBytesToRead));
1751 DebugInt3();
1752 }
1753 }
1754
1755 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1756 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1757 }
1758 // else {
1759 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
1760 (PVOID)lpRealBuf,
1761 nNumberOfBytesToRead,
1762 lpNumberOfBytesRead);
1763// }
1764
1765 if(bRC == 0) {
1766 dprintf(("KERNEL32: HMDeviceDiskClass::ReadFile returned %08xh %x", bRC, GetLastError()));
1767 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
1768 }
1769 else dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile read %x bytes pos %x", *lpNumberOfBytesRead, SetFilePointer(pHMHandleData, 0, NULL, FILE_CURRENT)));
1770
1771 //if unmounted volume, add starting offset to position as we're accessing the entire physical drive
1772 //instead of just the volume
1773 if(drvInfo->fPhysicalDisk && (drvInfo->StartingOffset.HighPart != 0 ||
1774 drvInfo->StartingOffset.LowPart != 0) && bRC == TRUE)
1775 {
1776 LARGE_INTEGER distance, result;
1777
1778 distance.HighPart = 0;
1779 distance.LowPart = *lpNumberOfBytesRead;
1780 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
1781 drvInfo->CurrentFilePointer = result;
1782
1783 dprintf(("New unmounted volume current file pointer %08x%08x", drvInfo->CurrentFilePointer.HighPart, drvInfo->CurrentFilePointer.LowPart));
1784 }
1785
1786 return bRC;
1787}
1788/*****************************************************************************
1789 * Name : DWORD HMDeviceDiskClass::SetFilePointer
1790 * Purpose : set file pointer
1791 * Parameters: PHMHANDLEDATA pHMHandleData
1792 * LONG lDistanceToMove
1793 * PLONG lpDistanceToMoveHigh
1794 * DWORD dwMoveMethod
1795 * Variables :
1796 * Result : API returncode
1797 * Remark :
1798 * Status :
1799 *
1800 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1801 *****************************************************************************/
1802DWORD HMDeviceDiskClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
1803 LONG lDistanceToMove,
1804 PLONG lpDistanceToMoveHigh,
1805 DWORD dwMoveMethod)
1806{
1807 DWORD ret;
1808
1809 if(lpDistanceToMoveHigh) {
1810 dprintf(("KERNEL32: HMDeviceDiskClass::SetFilePointer %s %08x%08x %d",
1811 lpHMDeviceName, *lpDistanceToMoveHigh, lDistanceToMove, dwMoveMethod));
1812 }
1813
1814 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1815 if(drvInfo == NULL) {
1816 dprintf(("ERROR: SetFilePointer: drvInfo == NULL!!!"));
1817 DebugInt3();
1818 SetLastError(ERROR_INVALID_HANDLE);
1819 return FALSE;
1820 }
1821
1822 if(!pHMHandleData->hHMHandle) {
1823 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1824 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1825 if(!pHMHandleData->hHMHandle) {
1826 dprintf(("No disk inserted; aborting"));
1827 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
1828 return -1;
1829 }
1830 }
1831
1832 //if unmounted volume, add starting offset to position as we're accessing the entire physical drive
1833 //instead of just the volume
1834 if(drvInfo->fPhysicalDisk && (drvInfo->StartingOffset.HighPart != 0 ||
1835 drvInfo->StartingOffset.LowPart != 0))
1836 {
1837 LARGE_INTEGER distance, result, endpos;
1838 LARGE_INTEGER position;
1839
1840 if(lpDistanceToMoveHigh) {
1841 distance.HighPart = *lpDistanceToMoveHigh;
1842 }
1843 else {
1844 if(lDistanceToMove < 0) {
1845 distance.HighPart = -1;
1846 }
1847 else distance.HighPart = 0;
1848 }
1849 distance.LowPart = lDistanceToMove;
1850
1851 //calculate end position in partition
1852 Add64(&drvInfo->StartingOffset, &drvInfo->PartitionSize, &endpos);
1853 result.HighPart = 0;
1854 result.LowPart = 1;
1855 Sub64(&endpos, &result, &endpos);
1856
1857 switch(dwMoveMethod) {
1858 case FILE_BEGIN:
1859 Add64(&distance, &drvInfo->StartingOffset, &result);
1860 break;
1861 case FILE_CURRENT:
1862 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
1863 break;
1864 case FILE_END:
1865 Add64(&distance, &endpos, &result);
1866 break;
1867 }
1868 //check upper boundary
1869 if(result.HighPart > endpos.HighPart ||
1870 (result.HighPart == endpos.HighPart && result.LowPart > endpos.LowPart) )
1871 {
1872 SetLastError(ERROR_INVALID_PARAMETER);
1873 return -1;
1874 }
1875 //check lower boundary
1876 if(result.HighPart < drvInfo->StartingOffset.HighPart ||
1877 (result.HighPart == drvInfo->StartingOffset.HighPart && result.LowPart < drvInfo->StartingOffset.LowPart))
1878 {
1879 SetLastError(ERROR_NEGATIVE_SEEK);
1880 return -1;
1881 }
1882
1883 dprintf(("SetFilePointer (unmounted partition) %08x%08x -> %08x%08x", distance.HighPart, distance.LowPart, result.HighPart, result.LowPart));
1884 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
1885 result.LowPart,
1886 (DWORD *)&result.HighPart,
1887 FILE_BEGIN);
1888
1889 Sub64(&result, &drvInfo->StartingOffset, &drvInfo->CurrentFilePointer);
1890 ret = drvInfo->CurrentFilePointer.LowPart;
1891 if(lpDistanceToMoveHigh) {
1892 *lpDistanceToMoveHigh = drvInfo->CurrentFilePointer.HighPart;
1893 }
1894 }
1895 else {
1896 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
1897 lDistanceToMove,
1898 (DWORD *)lpDistanceToMoveHigh,
1899 dwMoveMethod);
1900 }
1901
1902 if(ret == -1) {
1903 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
1904 }
1905 return ret;
1906}
1907
1908/*****************************************************************************
1909 * Name : BOOL HMDeviceDiskClass::WriteFile
1910 * Purpose : write data to handle / device
1911 * Parameters: PHMHANDLEDATA pHMHandleData,
1912 * LPCVOID lpBuffer,
1913 * DWORD nNumberOfBytesToWrite,
1914 * LPDWORD lpNumberOfBytesWritten,
1915 * LPOVERLAPPED lpOverlapped
1916 * Variables :
1917 * Result : Boolean
1918 * Remark :
1919 * Status :
1920 *
1921 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1922 *****************************************************************************/
1923
1924BOOL HMDeviceDiskClass::WriteFile(PHMHANDLEDATA pHMHandleData,
1925 LPCVOID lpBuffer,
1926 DWORD nNumberOfBytesToWrite,
1927 LPDWORD lpNumberOfBytesWritten,
1928 LPOVERLAPPED lpOverlapped,
1929 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1930{
1931 LPVOID lpRealBuf;
1932 Win32MemMap *map;
1933 DWORD offset, byteswritten;
1934 BOOL bRC;
1935
1936 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
1937 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
1938 lpOverlapped));
1939
1940 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1941 if(drvInfo == NULL) {
1942 dprintf(("ERROR: WriteFile: drvInfo == NULL!!!"));
1943 DebugInt3();
1944 SetLastError(ERROR_INVALID_HANDLE);
1945 return FALSE;
1946 }
1947 if(!(drvInfo->dwAccess & GENERIC_WRITE)) {
1948 dprintf(("ERROR: WriteFile: write access denied!"));
1949 SetLastError(ERROR_ACCESS_DENIED);
1950 return FALSE;
1951 }
1952 //It's legal for this pointer to be NULL
1953 if(lpNumberOfBytesWritten)
1954 *lpNumberOfBytesWritten = 0;
1955 else
1956 lpNumberOfBytesWritten = &byteswritten;
1957
1958 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1959 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1960 SetLastError(ERROR_INVALID_PARAMETER);
1961 return FALSE;
1962 }
1963 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1964 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1965 }
1966 if(lpCompletionRoutine) {
1967 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
1968 }
1969
1970 //If we didn't get an OS/2 handle for the disk before, get one now
1971 if(!pHMHandleData->hHMHandle) {
1972 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1973 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1974 if(!pHMHandleData->hHMHandle) {
1975 dprintf(("No disk inserted; aborting"));
1976 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
1977 return FALSE;
1978 }
1979 }
1980
1981 //SvL: DosWrite doesn't like reading from memory addresses returned by
1982 // DosAliasMem -> search for original memory mapped pointer and use
1983 // that one + commit pages if not already present
1984 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_READ);
1985 if(map) {
1986 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1987 DWORD nrpages = nNumberOfBytesToWrite/4096;
1988 if(offset & 0xfff)
1989 nrpages++;
1990 if(nNumberOfBytesToWrite & 0xfff)
1991 nrpages++;
1992
1993 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1994 }
1995 else lpRealBuf = (LPVOID)lpBuffer;
1996
1997 //if unmounted volume, check upper boundary as we're accessing the entire physical drive
1998 //instead of just the volume
1999 if(drvInfo->fPhysicalDisk && (drvInfo->StartingOffset.HighPart != 0 ||
2000 drvInfo->StartingOffset.LowPart != 0))
2001 {
2002 LARGE_INTEGER distance, result, endpos;
2003
2004 //calculate end position in partition
2005 Add64(&drvInfo->StartingOffset, &drvInfo->PartitionSize, &endpos);
2006
2007 distance.HighPart = 0;
2008 distance.LowPart = nNumberOfBytesToWrite;
2009 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
2010
2011 //check upper boundary
2012 if(result.HighPart > endpos.HighPart ||
2013 (result.HighPart == endpos.HighPart && result.LowPart > endpos.LowPart) )
2014 {
2015 Sub64(&endpos, &drvInfo->CurrentFilePointer, &result);
2016 nNumberOfBytesToWrite = result.LowPart;
2017 dprintf(("Write past end of volume; nNumberOfBytesToWrite reduced to %d", nNumberOfBytesToWrite));
2018 DebugInt3();
2019 }
2020 }
2021
2022 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
2023 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
2024 }
2025// else {
2026 bRC = OSLibDosWrite(pHMHandleData->hHMHandle,
2027 (PVOID)lpRealBuf,
2028 nNumberOfBytesToWrite,
2029 lpNumberOfBytesWritten);
2030// }
2031
2032 //if unmounted volume, add starting offset to position as we're accessing the entire physical drive
2033 //instead of just the volume
2034 if(drvInfo->fPhysicalDisk && (drvInfo->StartingOffset.HighPart != 0 ||
2035 drvInfo->StartingOffset.LowPart != 0) && bRC == TRUE)
2036 {
2037 LARGE_INTEGER distance, result;
2038
2039 distance.HighPart = 0;
2040 distance.LowPart = *lpNumberOfBytesWritten;
2041 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
2042 drvInfo->CurrentFilePointer = result;
2043
2044 dprintf(("New unmounted volume current file pointer %08x%08x", drvInfo->CurrentFilePointer.HighPart, drvInfo->CurrentFilePointer.LowPart));
2045 }
2046
2047 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile returned %08xh\n",
2048 bRC));
2049
2050 return bRC;
2051}
2052
2053/*****************************************************************************
2054 * Name : DWORD HMDeviceDiskClass::GetFileSize
2055 * Purpose : set file time
2056 * Parameters: PHMHANDLEDATA pHMHandleData
2057 * PDWORD pSize
2058 * Variables :
2059 * Result : API returncode
2060 * Remark :
2061 * Status :
2062 *
2063 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
2064 *****************************************************************************/
2065
2066DWORD HMDeviceDiskClass::GetFileSize(PHMHANDLEDATA pHMHandleData,
2067 PDWORD lpdwFileSizeHigh)
2068{
2069#if 1
2070 //Verified in NT4
2071 dprintf(("WARNING: GetFileSize doesn't work for drive objects; returning error (same as Windows)"));
2072 SetLastError(ERROR_INVALID_PARAMETER);
2073 return -1; //INVALID_SET_FILE_POINTER
2074#else
2075 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
2076 if(drvInfo == NULL) {
2077 dprintf(("ERROR: GetFileSize: drvInfo == NULL!!!"));
2078 DebugInt3();
2079 SetLastError(ERROR_INVALID_HANDLE);
2080 return -1; //INVALID_SET_FILE_POINTER
2081 }
2082
2083 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileSize %s(%08xh,%08xh)\n",
2084 lpHMDeviceName, pHMHandleData, lpdwFileSizeHigh));
2085
2086 //If we didn't get an OS/2 handle for the disk before, get one now
2087 if(!pHMHandleData->hHMHandle) {
2088 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
2089 if(!pHMHandleData->hHMHandle) {
2090 dprintf(("No disk inserted; aborting"));
2091 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
2092 return -1; //INVALID_SET_FILE_POINTER
2093 }
2094 }
2095
2096 if(drvInfo->PartitionSize.HighPart || drvInfo->PartitionSize.LowPart) {
2097 if(lpdwFileSizeHigh)
2098 *lpdwFileSizeHigh = drvInfo->PartitionSize.HighPart;
2099
2100 return drvInfo->PartitionSize.LowPart;
2101 }
2102 else {
2103 LARGE_INTEGER position, size;
2104
2105 //get current position
2106 position.HighPart = 0;
2107 position.LowPart = SetFilePointer(pHMHandleData, 0, (PLONG)&position.HighPart, FILE_CURRENT);
2108 SetFilePointer(pHMHandleData, 0, NULL, FILE_BEGIN);
2109 size.HighPart = 0;
2110 size.LowPart = SetFilePointer(pHMHandleData, 0, (PLONG)&size.HighPart, FILE_END);
2111
2112 //restore old position
2113 SetFilePointer(pHMHandleData, position.LowPart, (PLONG)&position.HighPart, FILE_BEGIN);
2114
2115 if(lpdwFileSizeHigh)
2116 *lpdwFileSizeHigh = size.HighPart;
2117
2118 return size.LowPart;
2119 }
2120#endif
2121}
2122
2123/*****************************************************************************
2124 * Name : DWORD HMDeviceDiskClass::GetFileType
2125 * Purpose : determine the handle type
2126 * Parameters: PHMHANDLEDATA pHMHandleData
2127 * Variables :
2128 * Result : API returncode
2129 * Remark :
2130 * Status :
2131 *
2132 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
2133 *****************************************************************************/
2134
2135DWORD HMDeviceDiskClass::GetFileType(PHMHANDLEDATA pHMHandleData)
2136{
2137 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileType %s(%08x)\n",
2138 lpHMDeviceName, pHMHandleData));
2139
2140 return FILE_TYPE_DISK;
2141}
2142//******************************************************************************
2143//******************************************************************************
Note: See TracBrowser for help on using the repository browser.