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

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

PF: Implemented IOCTL_CDROM_RAW_READ

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