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

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

Use aspi interface in os2cdrom.dmd for SCSI ioctls

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