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

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

Lock drive when sharing is disabled (CreateFile for drives); unlock when closed

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