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

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

CreateFile now fails earlier if used for non-existing drive letter

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