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

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

IOCTL_DISK_GET_DRIVE_GEOMETRY must fail if no disk is inserted; IOCTL_STORAGE_GET_MEDIA_TYPES/IOCTL_DISK_GET_MEDIA_TYPES shouldn't

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