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

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

fixed CreateFile for disks

File size: 69.2 KB
Line 
1/* $Id: hmdisk.cpp,v 1.48 2002-06-26 11:08:32 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 if(!pHMHandleData->hHMHandle) {
787 dprintf(("No disk inserted; aborting"));
788 SetLastError(ERROR_NOT_READY);
789 return FALSE;
790 }
791 }
792
793 //Applications can use this IOCTL to check if the floppy has been changed
794 //OSLibDosGetDiskGeometry won't fail when that happens so we read the
795 //volume label from the disk and return ERROR_MEDIA_CHANGED if the volume
796 //label has changed
797 //TODO: Find better way to determine if floppy was removed or switched
798 if(drvInfo->driveType != DRIVE_FIXED)
799 {
800 rc = OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &volumelabel, NULL, 0);
801 if(rc) {
802 dprintf(("IOCTL_DISK_GET_DRIVE_GEOMETRY: OSLibDosQueryVolumeSerialAndName failed with rc %d", GetLastError()));
803 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
804 pHMHandleData->hHMHandle = 0;
805 SetLastError(ERROR_MEDIA_CHANGED);
806 return FALSE;
807 }
808 if(volumelabel != drvInfo->dwVolumelabel) {
809 dprintf(("IOCTL_DISK_GET_DRIVE_GEOMETRY: volume changed %x -> %x", drvInfo->dwVolumelabel, volumelabel));
810 SetLastError(ERROR_MEDIA_CHANGED);
811 return FALSE;
812 }
813 }
814
815 if(OSLibDosGetDiskGeometry(pHMHandleData->hHMHandle, drvInfo->driveLetter, pGeom) == FALSE) {
816 return FALSE;
817 }
818 if(lpBytesReturned) {
819 *lpBytesReturned = sizeof(DISK_GEOMETRY);
820 }
821 SetLastError(ERROR_SUCCESS);
822 return TRUE;
823 }
824
825 case IOCTL_DISK_GET_PARTITION_INFO:
826 {
827 PPARTITION_INFORMATION pPartition = (PPARTITION_INFORMATION)lpOutBuffer;
828 if(nOutBufferSize < sizeof(PARTITION_INFORMATION) || !pPartition) {
829 SetLastError(ERROR_INSUFFICIENT_BUFFER);
830 return FALSE;
831 }
832 if(lpBytesReturned) {
833 *lpBytesReturned = sizeof(PARTITION_INFORMATION);
834 }
835 if(OSLibLVMGetPartitionInfo(drvInfo->driveLetter, drvInfo->szVolumeName, pPartition) == FALSE) {
836 SetLastError(ERROR_NOT_ENOUGH_MEMORY); //wrong error, but who cares
837 return FALSE;
838 }
839
840 SetLastError(ERROR_SUCCESS);
841 return TRUE;
842 }
843
844 case IOCTL_DISK_LOAD_MEDIA:
845 case IOCTL_DISK_MEDIA_REMOVAL:
846 case IOCTL_DISK_PERFORMANCE:
847 case IOCTL_DISK_REASSIGN_BLOCKS:
848 case IOCTL_DISK_SET_DRIVE_LAYOUT:
849 case IOCTL_DISK_SET_PARTITION_INFO:
850 case IOCTL_DISK_VERIFY:
851 case IOCTL_SERIAL_LSRMST_INSERT:
852 break;
853
854
855 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
856 {
857 PVOLUME_DISK_EXTENTS pVolExtent = (PVOLUME_DISK_EXTENTS)lpOutBuffer;
858 if(nOutBufferSize < sizeof(VOLUME_DISK_EXTENTS) || !pVolExtent) {
859 SetLastError(ERROR_INSUFFICIENT_BUFFER);
860 return FALSE;
861 }
862 if(OSLibLVMGetVolumeExtents(drvInfo->driveLetter, drvInfo->szVolumeName, pVolExtent) == FALSE) {
863 SetLastError(ERROR_NOT_ENOUGH_MEMORY); //wrong error, but who cares
864 return FALSE;
865 }
866
867 if(lpBytesReturned) {
868 *lpBytesReturned = sizeof(VOLUME_DISK_EXTENTS);
869 }
870 SetLastError(ERROR_SUCCESS);
871 return TRUE;
872 }
873
874 // -----------
875 // CDROM class
876 // -----------
877 case IOCTL_CDROM_READ_TOC:
878 {
879#pragma pack(1)
880 typedef struct
881 {
882 BYTE ucFirstTrack;
883 BYTE ucLastTrack;
884 DWORD ulLeadOutAddr;
885 } AudioDiskInfo;
886 typedef struct
887 {
888 DWORD ulTrackAddr;
889 BYTE ucTrackControl;
890 } AudioTrackInfo;
891 typedef struct
892 {
893 BYTE signature[4];
894 BYTE ucTrack;
895 } ParameterBlock;
896#pragma pack()
897 PCDROM_TOC pTOC = (PCDROM_TOC)lpOutBuffer;
898 DWORD rc, numtracks;
899 DWORD parsize = 4;
900 DWORD datasize;
901 AudioDiskInfo diskinfo;
902 AudioTrackInfo trackinfo;
903 ParameterBlock parm;
904
905 if(lpBytesReturned)
906 *lpBytesReturned = 0;
907
908 if(!pTOC) {
909 SetLastError(ERROR_INVALID_PARAMETER);
910 return FALSE;
911 }
912 if(nOutBufferSize < sizeof(CDROM_TOC)) {
913 SetLastError(ERROR_INSUFFICIENT_BUFFER);
914 return FALSE;
915 }
916 memset(pTOC, 0, nOutBufferSize);
917 //IOCTL_CDROMAUDIO (0x81), CDROMAUDIO_GETAUDIODISK (0x61)
918 datasize = sizeof(diskinfo);
919 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x61, &drvInfo->signature[0], 4, &parsize,
920 &diskinfo, sizeof(diskinfo), &datasize);
921 if(rc != NO_ERROR) {
922 dprintf(("OSLibDosDevIOCtl failed with rc %d", rc));
923 return FALSE;
924 }
925 pTOC->FirstTrack = diskinfo.ucFirstTrack;
926 pTOC->LastTrack = diskinfo.ucLastTrack;
927 numtracks = pTOC->LastTrack - pTOC->FirstTrack + 1;
928 dprintf(("first %d, last %d, num %d", pTOC->FirstTrack, pTOC->LastTrack, numtracks));
929
930 //numtracks+1, because we have to add a track at the end
931 int length = 4 + (numtracks+1)*sizeof(TRACK_DATA);
932 //big endian format
933 pTOC->Length[0] = HIBYTE((length-2)); //minus length itself;
934 pTOC->Length[1] = LOBYTE((length-2)); //minus length itself;
935
936 if(nOutBufferSize < length) {
937 SetLastError(ERROR_INSUFFICIENT_BUFFER);
938 return FALSE;
939 }
940
941 for(int i=0;i<numtracks;i++)
942 {
943 parsize = sizeof(parm);
944 memcpy(parm.signature, drvInfo->signature, 4);
945 parm.ucTrack = pTOC->FirstTrack+i;
946
947 datasize = sizeof(trackinfo);
948
949 //IOCTL_CDROMAUDIO (0x81), CDROMAUDIO_GETAUDIOTRACK (0x62)
950 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x62, &parm, sizeof(parm), &parsize,
951 &trackinfo, sizeof(trackinfo), &datasize);
952 if(rc != NO_ERROR) {
953 dprintf(("OSLibDosDevIOCtl failed with rc %d", rc));
954 return FALSE;
955 }
956 pTOC->TrackData[i].TrackNumber = pTOC->FirstTrack + i;
957 pTOC->TrackData[i].Reserved = 0;
958 pTOC->TrackData[i].Control = trackinfo.ucTrackControl >> 4;
959 pTOC->TrackData[i].Adr = trackinfo.ucTrackControl & 0xF;
960 pTOC->TrackData[i].Reserved1 = 0;
961 //big endian format
962 pTOC->TrackData[i].Address[0] = HIBYTE(HIWORD(trackinfo.ulTrackAddr));
963 pTOC->TrackData[i].Address[1] = LOBYTE(HIWORD(trackinfo.ulTrackAddr));
964 pTOC->TrackData[i].Address[2] = HIBYTE(LOWORD(trackinfo.ulTrackAddr));
965 pTOC->TrackData[i].Address[3] = LOBYTE(LOWORD(trackinfo.ulTrackAddr));
966 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));
967 }
968
969 //Add a track at the end (presumably so the app can determine the size of the 1st track)
970 //That is what NT4, SP6 does anyway
971 pTOC->TrackData[numtracks].TrackNumber = 0xAA;
972 pTOC->TrackData[numtracks].Reserved = 0;
973 pTOC->TrackData[numtracks].Control = pTOC->TrackData[numtracks-1].Control;
974 pTOC->TrackData[numtracks].Adr = pTOC->TrackData[numtracks-1].Adr;
975 pTOC->TrackData[numtracks].Reserved1 = 0;
976 //big endian format
977 //Address of pseudo track is the address of the lead-out track
978 pTOC->TrackData[numtracks].Address[0] = HIBYTE(HIWORD(diskinfo.ulLeadOutAddr));
979 pTOC->TrackData[numtracks].Address[1] = LOBYTE(HIWORD(diskinfo.ulLeadOutAddr));
980 pTOC->TrackData[numtracks].Address[2] = HIBYTE(LOWORD(diskinfo.ulLeadOutAddr));
981 pTOC->TrackData[numtracks].Address[3] = LOBYTE(LOWORD(diskinfo.ulLeadOutAddr));
982
983 if(lpBytesReturned)
984 *lpBytesReturned = length;
985
986 SetLastError(ERROR_SUCCESS);
987 return TRUE;
988 }
989
990 case IOCTL_CDROM_UNLOAD_DRIVER:
991 case IOCTL_CDROM_GET_CONTROL:
992 break;
993
994 case IOCTL_CDROM_PLAY_AUDIO_MSF:
995 {
996#pragma pack(1)
997 struct
998 {
999 DWORD ucSignature;
1000 BYTE ucAddressingMode;
1001 DWORD ulStartingMSF;
1002 DWORD ulEndingMSF;
1003 } ParameterBlock;
1004#pragma pack()
1005 PCDROM_PLAY_AUDIO_MSF pPlay = (PCDROM_PLAY_AUDIO_MSF)lpInBuffer;
1006
1007 if(nInBufferSize < sizeof(CDROM_SEEK_AUDIO_MSF)) {
1008 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1009 return FALSE;
1010 }
1011 if(lpBytesReturned)
1012 *lpBytesReturned = 0;
1013
1014 dprintf(("Play CDROM audio playback %d:%d (%d) - %d:%d (%d)", pPlay->StartingM, pPlay->StartingS, pPlay->StartingF, pPlay->EndingM, pPlay->EndingS, pPlay->EndingF));
1015
1016 // setup the parameter block
1017 memcpy(&ParameterBlock.ucSignature, drvInfo->signature, 4);
1018 ParameterBlock.ucAddressingMode = 1; // MSF format
1019
1020 ParameterBlock.ulStartingMSF = pPlay->StartingM << 16 |
1021 pPlay->StartingS << 8 |
1022 pPlay->StartingF;
1023 ParameterBlock.ulEndingMSF = pPlay->EndingM << 16 |
1024 pPlay->EndingS << 8 |
1025 pPlay->EndingF;
1026
1027 DWORD dwParameterSize = sizeof( ParameterBlock );
1028 DWORD dwDataSize = 0;
1029 DWORD ret;
1030
1031 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
1032 0x81, // IOCTL_CDROMAUDIO
1033 0x50, // CDROMAUDIO_PLAYAUDIO
1034 &ParameterBlock,
1035 sizeof( ParameterBlock ),
1036 &dwParameterSize,
1037 NULL,
1038 0,
1039 &dwDataSize);
1040 if(ret != ERROR_SUCCESS) {
1041 dprintf(("IOCTL_CDROMAUDIO, CDROMAUDIO_PLAYAUDIO failed!!"));
1042 }
1043 drvInfo->fCDPlaying = TRUE;
1044 return (ret == ERROR_SUCCESS);
1045 }
1046
1047 case IOCTL_CDROM_SEEK_AUDIO_MSF:
1048 {
1049#pragma pack(1)
1050 struct
1051 {
1052 DWORD ucSignature;
1053 BYTE ucAddressingMode;
1054 DWORD ulStartingMSF;
1055 } ParameterBlock;
1056#pragma pack()
1057 CDROM_SEEK_AUDIO_MSF *pSeek = (CDROM_SEEK_AUDIO_MSF *)lpInBuffer;
1058
1059 if(nInBufferSize < sizeof(CDROM_SEEK_AUDIO_MSF)) {
1060 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1061 return FALSE;
1062 }
1063 if(lpBytesReturned)
1064 *lpBytesReturned = 0;
1065
1066 dprintf(("IOCTL_CDROMDISK, CDROMDISK_SEEK %d:%d (%d)", pSeek->M, pSeek->S, pSeek->F));
1067
1068 // setup the parameter block
1069 memcpy(&ParameterBlock.ucSignature, drvInfo->signature, 4);
1070 ParameterBlock.ucAddressingMode = 1; // MSF format
1071
1072 ParameterBlock.ulStartingMSF = pSeek->M << 16 |
1073 pSeek->S << 8 |
1074 pSeek->F;
1075
1076 DWORD dwParameterSize = sizeof( ParameterBlock );
1077 DWORD dwDataSize = 0;
1078 DWORD ret;
1079
1080 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
1081 0x80, // IOCTL_CDROMDISK
1082 0x50, // CDROMDISK_SEEK
1083 &ParameterBlock,
1084 sizeof( ParameterBlock ),
1085 &dwParameterSize,
1086 NULL,
1087 0,
1088 &dwDataSize);
1089 if(ret != ERROR_SUCCESS) {
1090 dprintf(("IOCTL_CDROMDISK, CDROMDISK_SEEK %x failed!!", ParameterBlock.ulStartingMSF));
1091 }
1092 return (ret == ERROR_SUCCESS);
1093 }
1094
1095 case IOCTL_CDROM_PAUSE_AUDIO:
1096 // NO BREAK CASE
1097 // Note: for OS/2, pause and stop seems to be the same!
1098
1099 case IOCTL_CDROM_STOP_AUDIO:
1100 {
1101 dprintf(("Stop / pause CDROM audio playback"));
1102 drvInfo->fCDPlaying = FALSE;
1103 return ioctlCDROMSimple(pHMHandleData,
1104 0x81, // IOCTL_CDROMAUDIO
1105 0x51, // CDROMAUDIO_STOPAUDIO
1106 lpBytesReturned, drvInfo);
1107 }
1108
1109 case IOCTL_CDROM_RESUME_AUDIO:
1110 {
1111 dprintf(("Resume CDROM audio playback"));
1112 drvInfo->fCDPlaying = TRUE;
1113 return ioctlCDROMSimple(pHMHandleData,
1114 0x81, // IOCTL_CDROMAUDIO
1115 0x52, // CDROMAUDIO_RESUMEAUDIO
1116 lpBytesReturned, drvInfo);
1117 }
1118
1119 case IOCTL_CDROM_GET_VOLUME:
1120 {
1121 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpOutBuffer;
1122 char volbuf[8];
1123 DWORD parsize, datasize, ret;
1124
1125 if(nOutBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
1126 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1127 return FALSE;
1128 }
1129 if(lpBytesReturned) {
1130 *lpBytesReturned = 0;
1131 }
1132 parsize = 4;
1133 datasize = 8;
1134 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x60, drvInfo->signature, 4, &parsize,
1135 volbuf, 8, &datasize);
1136
1137 if(ret)
1138 return FALSE;
1139
1140 if(lpBytesReturned) {
1141 *lpBytesReturned = sizeof(VOLUME_CONTROL);
1142 }
1143 pVol->PortVolume[0] = volbuf[1];
1144 pVol->PortVolume[1] = volbuf[3];
1145 pVol->PortVolume[2] = volbuf[5];
1146 pVol->PortVolume[3] = volbuf[7];
1147 SetLastError(ERROR_SUCCESS);
1148 return TRUE;
1149 }
1150
1151 case IOCTL_CDROM_SET_VOLUME:
1152 {
1153 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpInBuffer;
1154 char volbuf[8];
1155 DWORD parsize, datasize, ret;
1156
1157 if(nInBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
1158 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1159 return FALSE;
1160 }
1161 if(lpBytesReturned) {
1162 *lpBytesReturned = 0;
1163 }
1164 parsize = 4;
1165 datasize = 8;
1166 volbuf[0] = 0;
1167 volbuf[1] = pVol->PortVolume[0];
1168 volbuf[2] = 1;
1169 volbuf[3] = pVol->PortVolume[1];
1170 volbuf[4] = 2;
1171 volbuf[5] = pVol->PortVolume[2];
1172 volbuf[6] = 3;
1173 volbuf[7] = pVol->PortVolume[3];
1174 dprintf(("Set CD volume (%d,%d)(%d,%d)", pVol->PortVolume[0], pVol->PortVolume[1], pVol->PortVolume[2], pVol->PortVolume[3]));
1175 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x40, drvInfo->signature, 4, &parsize,
1176 volbuf, 8, &datasize);
1177
1178 if(ret)
1179 return FALSE;
1180
1181 SetLastError(ERROR_SUCCESS);
1182 return TRUE;
1183 }
1184 case IOCTL_CDROM_READ_Q_CHANNEL:
1185 {
1186#pragma pack(1)
1187 struct
1188 {
1189 BYTE ucControlAddr;
1190 BYTE ucTrackNr;
1191 BYTE ucIndex;
1192 BYTE ucRuntimeTrackMin;
1193 BYTE ucRuntimeTrackSec;
1194 BYTE ucRuntimeTrackFrame;
1195 BYTE ucReserved;
1196 BYTE ucRuntimeDiscMin;
1197 BYTE ucRuntimeDiscSec;
1198 BYTE ucRuntimeDiscFrame;
1199 } DataBlock;
1200 struct {
1201 WORD usAudioStatus;
1202 DWORD ulStartLoc;
1203 DWORD ulEndLoc;
1204 } DataBlockStatus;
1205#pragma pack()
1206 CDROM_SUB_Q_DATA_FORMAT *pFormat = (CDROM_SUB_Q_DATA_FORMAT*)lpInBuffer;
1207 SUB_Q_CHANNEL_DATA *pChannelData = (SUB_Q_CHANNEL_DATA *)lpOutBuffer;
1208 char signature[8];
1209
1210 if(nInBufferSize < sizeof(CDROM_SUB_Q_DATA_FORMAT) || !pFormat) {
1211 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1212 return FALSE;
1213 }
1214 if(nOutBufferSize < sizeof(SUB_Q_CHANNEL_DATA) || !pChannelData) {
1215 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1216 return FALSE;
1217 }
1218 if(lpBytesReturned) {
1219 *lpBytesReturned = 0;
1220 }
1221
1222 DWORD dwParameterSize = 4;
1223 DWORD dwDataSize = sizeof(DataBlock);
1224 DWORD ret;
1225
1226 memcpy(signature, drvInfo->signature, dwParameterSize);
1227
1228 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
1229 0x81, // IOCTL_CDROMAUDIO
1230 0x63, // CDROMAUDIO_GETSUBCHANNELQ
1231 signature,
1232 dwParameterSize,
1233 &dwParameterSize,
1234 &DataBlock,
1235 sizeof(DataBlock),
1236 &dwDataSize);
1237 if(ret != ERROR_SUCCESS) {
1238 dprintf(("IOCTL_CDROMAUDIO, CDROMAUDIO_GETSUBCHANNELQ failed!!"));
1239 return FALSE;
1240 }
1241
1242 dwDataSize = sizeof(DataBlockStatus);
1243 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
1244 0x81, // IOCTL_CDROMAUDIO
1245 0x65, // CDROMAUDIO_GETAUDIOSTATUS
1246 signature,
1247 dwParameterSize,
1248 &dwParameterSize,
1249 &DataBlockStatus,
1250 sizeof(DataBlockStatus),
1251 &dwDataSize);
1252 if(ret != ERROR_SUCCESS) {
1253 dprintf(("IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIOSTATUS failed!!"));
1254 return FALSE;
1255 }
1256 dprintf(("CDROMAUDIO_GETAUDIOSTATUS returned %d %x %x", DataBlockStatus.usAudioStatus, DataBlockStatus.ulStartLoc, DataBlockStatus.ulEndLoc));
1257
1258 pChannelData->CurrentPosition.Header.Reserved = 0;
1259 if(DataBlockStatus.usAudioStatus & 1) {
1260 pChannelData->CurrentPosition.Header.AudioStatus = AUDIO_STATUS_PAUSED;
1261 }
1262 else {
1263 if(DataBlockStatus.ulStartLoc == 0) {//no play command has been issued before
1264 pChannelData->CurrentPosition.Header.AudioStatus = AUDIO_STATUS_NO_STATUS;
1265 }
1266 else {//assume in progress, but could alse be finished playing
1267 pChannelData->CurrentPosition.Header.AudioStatus = (drvInfo->fCDPlaying) ? AUDIO_STATUS_IN_PROGRESS : AUDIO_STATUS_PLAY_COMPLETE;
1268 }
1269 }
1270
1271 switch(pFormat->Format) {
1272 case IOCTL_CDROM_SUB_Q_CHANNEL:
1273 dprintf(("IOCTL_CDROM_SUB_Q_CHANNEL not supported"));
1274 return FALSE;
1275 case IOCTL_CDROM_CURRENT_POSITION:
1276 pChannelData->CurrentPosition.Header.DataLength[0] = sizeof(pChannelData->CurrentPosition);
1277 pChannelData->CurrentPosition.Header.DataLength[1] = 0;
1278 pChannelData->CurrentPosition.Control = DataBlock.ucControlAddr >> 4;
1279 pChannelData->CurrentPosition.ADR = DataBlock.ucControlAddr & 0xF;
1280 pChannelData->CurrentPosition.IndexNumber = BCDToDec(DataBlock.ucIndex);
1281 pChannelData->CurrentPosition.TrackNumber = BCDToDec(DataBlock.ucTrackNr);
1282 pChannelData->CurrentPosition.TrackRelativeAddress[1] = DataBlock.ucRuntimeTrackMin;
1283 pChannelData->CurrentPosition.TrackRelativeAddress[2] = DataBlock.ucRuntimeTrackSec;
1284 pChannelData->CurrentPosition.TrackRelativeAddress[3] = DataBlock.ucRuntimeTrackFrame;
1285 pChannelData->CurrentPosition.AbsoluteAddress[1] = DataBlock.ucRuntimeDiscMin;
1286 pChannelData->CurrentPosition.AbsoluteAddress[2] = DataBlock.ucRuntimeDiscSec;
1287 pChannelData->CurrentPosition.AbsoluteAddress[3] = DataBlock.ucRuntimeDiscFrame;
1288 pChannelData->CurrentPosition.FormatCode = IOCTL_CDROM_CURRENT_POSITION;
1289 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]));
1290 if(lpBytesReturned) {
1291 *lpBytesReturned = sizeof(*pChannelData);
1292 }
1293 break;
1294 case IOCTL_CDROM_MEDIA_CATALOG:
1295 dprintf(("IOCTL_CDROM_MEDIA_CATALOG not supported"));
1296 return FALSE;
1297 case IOCTL_CDROM_TRACK_ISRC:
1298 dprintf(("IOCTL_CDROM_TRACK_ISRC not supported"));
1299 return FALSE;
1300 }
1301 return (ret == ERROR_SUCCESS);
1302 }
1303
1304 case IOCTL_CDROM_GET_LAST_SESSION:
1305 case IOCTL_CDROM_RAW_READ:
1306 case IOCTL_CDROM_DISK_TYPE:
1307 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
1308 case IOCTL_CDROM_MEDIA_REMOVAL:
1309 break;
1310
1311 case IOCTL_CDROM_EJECT_MEDIA:
1312 {
1313 dprintf(("Eject CDROM media"));
1314 return ioctlCDROMSimple(pHMHandleData,
1315 0x80, // IOCTL_CDROM
1316 0x44, // CDROMDISK_EJECTDISK
1317 lpBytesReturned, drvInfo);
1318 }
1319
1320 case IOCTL_CDROM_LOAD_MEDIA:
1321 {
1322 dprintf(("Loading CDROM media"));
1323 return ioctlCDROMSimple(pHMHandleData,
1324 0x80, // IOCTL_CDROM
1325 0x45, // CDROMDISK_CLOSETRAY
1326 lpBytesReturned, drvInfo);
1327 }
1328
1329 case IOCTL_CDROM_RESERVE:
1330 case IOCTL_CDROM_RELEASE:
1331 case IOCTL_CDROM_FIND_NEW_DEVICES:
1332 break;
1333
1334
1335 // -------------
1336 // STORAGE class
1337 // -------------
1338
1339 case IOCTL_CDROM_CHECK_VERIFY:
1340 if(drvInfo->driveType != DRIVE_CDROM) {
1341 SetLastError(ERROR_GEN_FAILURE); //TODO: right error?
1342 return FALSE;
1343 }
1344 //no break;
1345 case IOCTL_DISK_CHECK_VERIFY:
1346 case IOCTL_STORAGE_CHECK_VERIFY:
1347 {
1348#pragma pack(1)
1349 typedef struct
1350 {
1351 BYTE ucCommandInfo;
1352 WORD usDriveUnit;
1353 } ParameterBlock;
1354#pragma pack()
1355
1356 dprintf(("IOCTL_CDROM(DISK/STORAGE)CHECK_VERIFY %s", drvInfo->signature));
1357 if(lpBytesReturned) {
1358 *lpBytesReturned = 0;
1359 }
1360
1361 if(!pHMHandleData->hHMHandle) {
1362 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1363 if(!pHMHandleData->hHMHandle) {
1364 dprintf(("No disk inserted; aborting"));
1365 SetLastError(ERROR_NOT_READY);
1366 return FALSE;
1367 }
1368 }
1369
1370 DWORD parsize = sizeof(ParameterBlock);
1371 DWORD datasize = 2;
1372 WORD status = 0;
1373 DWORD rc;
1374 ParameterBlock parm;
1375
1376 parm.ucCommandInfo = 0;
1377 parm.usDriveUnit = drvInfo->driveLetter - 'A';
1378// rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x08, 0x66, &parm, sizeof(parm), &parsize,
1379 //TODO: this doesn't work for floppies for some reason...
1380 rc = OSLibDosDevIOCtl(-1, IOCTL_DISK, DSK_GETLOCKSTATUS, &parm, sizeof(parm), &parsize,
1381 &status, sizeof(status), &datasize);
1382 if(rc != NO_ERROR) {
1383 dprintf(("OSLibDosDevIOCtl failed with rc %d datasize %d", rc, datasize));
1384 return FALSE;
1385 }
1386 dprintf(("Disk status 0x%x", status));
1387 //if no disk present, return FALSE
1388 if(!(status & (BIT_2))) {
1389 SetLastError(ERROR_NOT_READY); //NT4, SP6 returns this
1390 return FALSE;
1391 }
1392 SetLastError(NO_ERROR);
1393 return TRUE;
1394 }
1395
1396 case IOCTL_DISK_EJECT_MEDIA:
1397 case IOCTL_STORAGE_EJECT_MEDIA:
1398 {
1399 dprintf(("Ejecting storage media"));
1400 return ioctlDISKUnlockEject(pHMHandleData,
1401 0x02, // EJECT media
1402 -1,
1403 lpBytesReturned);
1404 }
1405
1406 case IOCTL_STORAGE_LOAD_MEDIA:
1407 // case IOCTL_STORAGE_LOAD_MEDIA2:
1408 {
1409 dprintf(("Loading storage media"));
1410 return ioctlDISKUnlockEject(pHMHandleData,
1411 0x03, // LOAD media
1412 -1,
1413 lpBytesReturned);
1414 }
1415
1416 // case IOCTL_STORAGE_EJECTION_CONTROL:
1417 case IOCTL_STORAGE_MEDIA_REMOVAL:
1418 break;
1419
1420
1421 // -------------------
1422 // SCSI passthru class
1423 // -------------------
1424
1425 case IOCTL_SCSI_MINIPORT:
1426 case IOCTL_SCSI_GET_INQUIRY_DATA:
1427 break;
1428
1429 case IOCTL_SCSI_GET_CAPABILITIES:
1430 break;
1431
1432 case IOCTL_SCSI_PASS_THROUGH:
1433 //no break; same as IOCTL_SCSI_PASS_THROUGH_DIRECT
1434 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
1435 {
1436 PSCSI_PASS_THROUGH_DIRECT pPacket = (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer;
1437 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1438 CDIO_CMD_BUFFER cdiocmd;
1439
1440 if(nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT) ||
1441 !pPacket || pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
1442 {
1443 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1444 return FALSE;
1445 }
1446
1447 if(!drvInfo || drvInfo->fCDIoSupported == FALSE) {
1448 dprintf(("os2cdrom.dmd CD interface not supported!!"));
1449 SetLastError(ERROR_ACCESS_DENIED);
1450 return FALSE;
1451 }
1452 if(lpBytesReturned) {
1453 *lpBytesReturned = 0;
1454 }
1455
1456 if(pPacket->CdbLength > sizeof(cdiocmd.arCDB)) {
1457 dprintf(("CDB buffer too big (%d)!!", pPacket->CdbLength));
1458 SetLastError(ERROR_INVALID_PARAMETER);
1459 return FALSE;
1460 }
1461
1462 memset(&cdiocmd, 0, sizeof(cdiocmd));
1463
1464 switch(pPacket->DataIn) {
1465 case SCSI_IOCTL_DATA_OUT:
1466 cdiocmd.flDirection = CMDDIR_OUTPUT;
1467 break;
1468 case SCSI_IOCTL_DATA_IN:
1469 cdiocmd.flDirection = CMDDIR_INPUT;
1470 break;
1471 case SCSI_IOCTL_DATA_UNSPECIFIED:
1472 cdiocmd.flDirection = CMDDIR_OUTPUT|CMDDIR_INPUT;;
1473 break;
1474 default:
1475 dprintf(("Invalid DataIn (%d)!!", pPacket->DataIn));
1476 SetLastError(ERROR_INVALID_PARAMETER);
1477 return FALSE;
1478 }
1479
1480 cdiocmd.cbCDB = pPacket->CdbLength;
1481 memcpy(cdiocmd.arCDB, pPacket->Cdb, pPacket->CdbLength);
1482
1483 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]));
1484
1485 if(OSLibCdIoSendCommand(pHMHandleData->hHMHandle, &cdiocmd, pPacket->DataBuffer, pPacket->DataTransferLength) == FALSE) {
1486 dprintf(("OSLibCdIoSendCommand failed!!"));
1487 pPacket->ScsiStatus = SS_ERR;
1488 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
1489 return FALSE;
1490 }
1491
1492 if(pPacket->SenseInfoLength) {
1493 if(OSLibCdIoRequestSense(pHMHandleData->hHMHandle, (char *)pPacket + pPacket->SenseInfoOffset, pPacket->SenseInfoLength) == FALSE) {
1494 dprintf(("OSLibCdIoRequestSense failed!!"));
1495 pPacket->ScsiStatus = SS_ERR;
1496 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
1497 return FALSE;
1498 }
1499 }
1500 pPacket->ScsiStatus = SS_COMP;
1501 SetLastError(ERROR_SUCCESS);
1502 return TRUE;
1503 }
1504 case IOCTL_SCSI_GET_ADDRESS:
1505 {
1506 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1507
1508 if(!drvInfo || drvInfo->fCDIoSupported == FALSE) {
1509 dprintf(("os2cdrom.dmd CD interface not supported!!"));
1510 SetLastError(ERROR_ACCESS_DENIED);
1511 return FALSE;
1512 }
1513
1514 if(!lpOutBuffer || nOutBufferSize < 8) {
1515 SetLastError(ERROR_INSUFFICIENT_BUFFER); //todo: right error?
1516 return(FALSE);
1517 }
1518 SCSI_ADDRESS *addr = (SCSI_ADDRESS *)lpOutBuffer;
1519 addr->Length = sizeof(SCSI_ADDRESS);
1520 addr->PortNumber = 0;
1521 addr->PathId = 0;
1522 //irrelevant, since os2cdrom.dmd doesn't need them
1523 addr->TargetId = 1;
1524 addr->Lun = 0;
1525 SetLastError(ERROR_SUCCESS);
1526 return TRUE;
1527 }
1528
1529 case IOCTL_SCSI_RESCAN_BUS:
1530 case IOCTL_SCSI_GET_DUMP_POINTERS:
1531 case IOCTL_SCSI_FREE_DUMP_POINTERS:
1532 case IOCTL_IDE_PASS_THROUGH:
1533 break;
1534
1535 }
1536 dprintf(("HMDeviceDiskClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
1537 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1538 return FALSE;
1539}
1540/*****************************************************************************
1541 * Name : BOOL HMDeviceDiskClass::ReadFile
1542 * Purpose : read data from handle / device
1543 * Parameters: PHMHANDLEDATA pHMHandleData,
1544 * LPCVOID lpBuffer,
1545 * DWORD nNumberOfBytesToRead,
1546 * LPDWORD lpNumberOfBytesRead,
1547 * LPOVERLAPPED lpOverlapped
1548 * Variables :
1549 * Result : Boolean
1550 * Remark :
1551 * Status :
1552 *
1553 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1554 *****************************************************************************/
1555
1556BOOL HMDeviceDiskClass::ReadFile(PHMHANDLEDATA pHMHandleData,
1557 LPCVOID lpBuffer,
1558 DWORD nNumberOfBytesToRead,
1559 LPDWORD lpNumberOfBytesRead,
1560 LPOVERLAPPED lpOverlapped,
1561 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1562{
1563 LPVOID lpRealBuf;
1564 Win32MemMap *map;
1565 DWORD offset, bytesread;
1566 BOOL bRC;
1567
1568 dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
1569 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped));
1570
1571 //It's legal for this pointer to be NULL
1572 if(lpNumberOfBytesRead)
1573 *lpNumberOfBytesRead = 0;
1574 else
1575 lpNumberOfBytesRead = &bytesread;
1576
1577 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1578 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1579 SetLastError(ERROR_INVALID_PARAMETER);
1580 return FALSE;
1581 }
1582
1583 if(lpCompletionRoutine) {
1584 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
1585 }
1586
1587 //If we didn't get an OS/2 handle for the disk before, get one now
1588 if(!pHMHandleData->hHMHandle) {
1589 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1590 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1591 if(!pHMHandleData->hHMHandle) {
1592 dprintf(("No disk inserted; aborting"));
1593 SetLastError(ERROR_NOT_READY);
1594 return FALSE;
1595 }
1596 }
1597
1598 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1599 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1600 }
1601
1602 //SvL: DosRead doesn't like writing to memory addresses returned by
1603 // DosAliasMem -> search for original memory mapped pointer and use
1604 // that one + commit pages if not already present
1605 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
1606 if(map) {
1607 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1608 DWORD nrpages = nNumberOfBytesToRead/4096;
1609 if(offset & 0xfff)
1610 nrpages++;
1611 if(nNumberOfBytesToRead & 0xfff)
1612 nrpages++;
1613
1614 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1615 }
1616 else lpRealBuf = (LPVOID)lpBuffer;
1617
1618 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1619 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1620 }
1621 // else {
1622 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
1623 (PVOID)lpRealBuf,
1624 nNumberOfBytesToRead,
1625 lpNumberOfBytesRead);
1626// }
1627
1628 if(bRC == 0) {
1629 dprintf(("KERNEL32: HMDeviceDiskClass::ReadFile returned %08xh %x", bRC, GetLastError()));
1630 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
1631 }
1632 else dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile read %x bytes pos %x", *lpNumberOfBytesRead, SetFilePointer(pHMHandleData, 0, NULL, FILE_CURRENT)));
1633
1634 return bRC;
1635}
1636/*****************************************************************************
1637 * Name : DWORD HMDeviceDiskClass::SetFilePointer
1638 * Purpose : set file pointer
1639 * Parameters: PHMHANDLEDATA pHMHandleData
1640 * LONG lDistanceToMove
1641 * PLONG lpDistanceToMoveHigh
1642 * DWORD dwMoveMethod
1643 * Variables :
1644 * Result : API returncode
1645 * Remark :
1646 * Status :
1647 *
1648 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1649 *****************************************************************************/
1650DWORD HMDeviceDiskClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
1651 LONG lDistanceToMove,
1652 PLONG lpDistanceToMoveHigh,
1653 DWORD dwMoveMethod)
1654{
1655 DWORD ret;
1656
1657 if(lpDistanceToMoveHigh) {
1658 dprintf(("KERNEL32: HMDeviceDiskClass::SetFilePointer %s %08x%08x %d",
1659 lpHMDeviceName, *lpDistanceToMoveHigh, lDistanceToMove, dwMoveMethod));
1660 }
1661
1662 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1663 if(drvInfo == NULL) {
1664 dprintf(("ERROR: SetFilePointer: drvInfo == NULL!!!"));
1665 DebugInt3();
1666 SetLastError(ERROR_INVALID_HANDLE);
1667 return FALSE;
1668 }
1669
1670 if(!pHMHandleData->hHMHandle) {
1671 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1672 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1673 if(!pHMHandleData->hHMHandle) {
1674 dprintf(("No disk inserted; aborting"));
1675 SetLastError(ERROR_NOT_READY);
1676 return -1;
1677 }
1678 }
1679
1680 //if unmounted volume, add starting offset to position as we're accessing the entire physical drive
1681 //instead of just the volume
1682 if(drvInfo->fPhysicalDisk && (drvInfo->StartingOffset.HighPart != 0 ||
1683 drvInfo->StartingOffset.LowPart != 0))
1684 {
1685 LARGE_INTEGER distance, result, endpos;
1686 LARGE_INTEGER position;
1687
1688 if(lpDistanceToMoveHigh) {
1689 distance.HighPart = *lpDistanceToMoveHigh;
1690 }
1691 else {
1692 if(lDistanceToMove < 0) {
1693 distance.HighPart = -1;
1694 }
1695 else distance.HighPart = 0;
1696 }
1697 distance.LowPart = lDistanceToMove;
1698
1699 //calculate end position in partition
1700 Add64(&drvInfo->StartingOffset, &drvInfo->PartitionSize, &endpos);
1701 result.HighPart = 0;
1702 result.LowPart = 1;
1703 Sub64(&endpos, &result, &endpos);
1704
1705 switch(dwMoveMethod) {
1706 case FILE_BEGIN:
1707 Add64(&distance, &drvInfo->StartingOffset, &result);
1708 break;
1709 case FILE_CURRENT:
1710 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
1711 break;
1712 case FILE_END:
1713 Add64(&distance, &endpos, &result);
1714 break;
1715 }
1716 //check upper boundary
1717 if(result.HighPart > endpos.HighPart ||
1718 (result.HighPart == endpos.HighPart && result.LowPart > endpos.LowPart) )
1719 {
1720 SetLastError(ERROR_INVALID_PARAMETER);
1721 return -1;
1722 }
1723 //check lower boundary
1724 if(result.HighPart < drvInfo->StartingOffset.HighPart ||
1725 (result.HighPart == drvInfo->StartingOffset.HighPart && result.LowPart < drvInfo->StartingOffset.LowPart))
1726 {
1727 SetLastError(ERROR_NEGATIVE_SEEK);
1728 return -1;
1729 }
1730
1731 dprintf(("SetFilePointer (unmounted partition) %08x%08x -> %08x%08x", distance.HighPart, distance.LowPart, result.HighPart, result.LowPart));
1732 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
1733 result.LowPart,
1734 (DWORD *)&result.HighPart,
1735 FILE_BEGIN);
1736
1737 Sub64(&result, &drvInfo->StartingOffset, &drvInfo->CurrentFilePointer);
1738 ret = drvInfo->CurrentFilePointer.LowPart;
1739 if(lpDistanceToMoveHigh) {
1740 *lpDistanceToMoveHigh = drvInfo->CurrentFilePointer.HighPart;
1741 }
1742 }
1743 else {
1744 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
1745 lDistanceToMove,
1746 (DWORD *)lpDistanceToMoveHigh,
1747 dwMoveMethod);
1748 }
1749
1750 if(ret == -1) {
1751 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
1752 }
1753 return ret;
1754}
1755
1756/*****************************************************************************
1757 * Name : BOOL HMDeviceDiskClass::WriteFile
1758 * Purpose : write data to handle / device
1759 * Parameters: PHMHANDLEDATA pHMHandleData,
1760 * LPCVOID lpBuffer,
1761 * DWORD nNumberOfBytesToWrite,
1762 * LPDWORD lpNumberOfBytesWritten,
1763 * LPOVERLAPPED lpOverlapped
1764 * Variables :
1765 * Result : Boolean
1766 * Remark :
1767 * Status :
1768 *
1769 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1770 *****************************************************************************/
1771
1772BOOL HMDeviceDiskClass::WriteFile(PHMHANDLEDATA pHMHandleData,
1773 LPCVOID lpBuffer,
1774 DWORD nNumberOfBytesToWrite,
1775 LPDWORD lpNumberOfBytesWritten,
1776 LPOVERLAPPED lpOverlapped,
1777 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1778{
1779 LPVOID lpRealBuf;
1780 Win32MemMap *map;
1781 DWORD offset, byteswritten;
1782 BOOL bRC;
1783
1784 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
1785 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
1786 lpOverlapped));
1787
1788 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1789 if(drvInfo == NULL) {
1790 dprintf(("ERROR: WriteFile: drvInfo == NULL!!!"));
1791 DebugInt3();
1792 SetLastError(ERROR_INVALID_HANDLE);
1793 return FALSE;
1794 }
1795 if(!(drvInfo->dwAccess & GENERIC_WRITE)) {
1796 dprintf(("ERROR: WriteFile: write access denied!"));
1797 SetLastError(ERROR_ACCESS_DENIED);
1798 return FALSE;
1799 }
1800 //It's legal for this pointer to be NULL
1801 if(lpNumberOfBytesWritten)
1802 *lpNumberOfBytesWritten = 0;
1803 else
1804 lpNumberOfBytesWritten = &byteswritten;
1805
1806 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1807 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1808 SetLastError(ERROR_INVALID_PARAMETER);
1809 return FALSE;
1810 }
1811 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1812 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1813 }
1814 if(lpCompletionRoutine) {
1815 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
1816 }
1817
1818 //If we didn't get an OS/2 handle for the disk before, get one now
1819 if(!pHMHandleData->hHMHandle) {
1820 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1821 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1822 if(!pHMHandleData->hHMHandle) {
1823 dprintf(("No disk inserted; aborting"));
1824 SetLastError(ERROR_NOT_READY);
1825 return FALSE;
1826 }
1827 }
1828
1829 //SvL: DosWrite doesn't like reading from memory addresses returned by
1830 // DosAliasMem -> search for original memory mapped pointer and use
1831 // that one + commit pages if not already present
1832 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_READ);
1833 if(map) {
1834 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1835 DWORD nrpages = nNumberOfBytesToWrite/4096;
1836 if(offset & 0xfff)
1837 nrpages++;
1838 if(nNumberOfBytesToWrite & 0xfff)
1839 nrpages++;
1840
1841 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1842 }
1843 else lpRealBuf = (LPVOID)lpBuffer;
1844
1845 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_LOCKDRIVE,0,0,0,0,0,0);
1846
1847 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1848 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1849 }
1850// else {
1851 bRC = OSLibDosWrite(pHMHandleData->hHMHandle,
1852 (PVOID)lpRealBuf,
1853 nNumberOfBytesToWrite,
1854 lpNumberOfBytesWritten);
1855// }
1856
1857 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_UNLOCKDRIVE,0,0,0,0,0,0);
1858 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile returned %08xh\n",
1859 bRC));
1860
1861 return bRC;
1862}
1863
1864/*****************************************************************************
1865 * Name : DWORD HMDeviceDiskClass::GetFileSize
1866 * Purpose : set file time
1867 * Parameters: PHMHANDLEDATA pHMHandleData
1868 * PDWORD pSize
1869 * Variables :
1870 * Result : API returncode
1871 * Remark :
1872 * Status :
1873 *
1874 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1875 *****************************************************************************/
1876
1877DWORD HMDeviceDiskClass::GetFileSize(PHMHANDLEDATA pHMHandleData,
1878 PDWORD lpdwFileSizeHigh)
1879{
1880 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1881 if(drvInfo == NULL) {
1882 dprintf(("ERROR: GetFileSize: drvInfo == NULL!!!"));
1883 DebugInt3();
1884 SetLastError(ERROR_INVALID_HANDLE);
1885 return -1; //INVALID_SET_FILE_POINTER
1886 }
1887
1888 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileSize %s(%08xh,%08xh)\n",
1889 lpHMDeviceName, pHMHandleData, lpdwFileSizeHigh));
1890
1891 //If we didn't get an OS/2 handle for the disk before, get one now
1892 if(!pHMHandleData->hHMHandle) {
1893 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1894 if(!pHMHandleData->hHMHandle) {
1895 dprintf(("No disk inserted; aborting"));
1896 SetLastError(ERROR_NOT_READY);
1897 return -1; //INVALID_SET_FILE_POINTER
1898 }
1899 }
1900
1901 if(drvInfo->PartitionSize.HighPart || drvInfo->PartitionSize.LowPart) {
1902 if(lpdwFileSizeHigh)
1903 *lpdwFileSizeHigh = drvInfo->PartitionSize.HighPart;
1904
1905 return drvInfo->PartitionSize.LowPart;
1906 }
1907 else {
1908 LARGE_INTEGER position, size;
1909
1910 //get current position
1911 position.HighPart = 0;
1912 position.LowPart = SetFilePointer(pHMHandleData, 0, (PLONG)&position.HighPart, FILE_CURRENT);
1913 SetFilePointer(pHMHandleData, 0, NULL, FILE_BEGIN);
1914 size.HighPart = 0;
1915 size.LowPart = SetFilePointer(pHMHandleData, 0, (PLONG)&size.HighPart, FILE_END);
1916
1917 //restore old position
1918 SetFilePointer(pHMHandleData, position.LowPart, (PLONG)&position.HighPart, FILE_BEGIN);
1919
1920 if(lpdwFileSizeHigh)
1921 *lpdwFileSizeHigh = size.HighPart;
1922
1923 return size.LowPart;
1924 }
1925}
1926
1927/*****************************************************************************
1928 * Name : DWORD HMDeviceDiskClass::GetFileType
1929 * Purpose : determine the handle type
1930 * Parameters: PHMHANDLEDATA pHMHandleData
1931 * Variables :
1932 * Result : API returncode
1933 * Remark :
1934 * Status :
1935 *
1936 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1937 *****************************************************************************/
1938
1939DWORD HMDeviceDiskClass::GetFileType(PHMHANDLEDATA pHMHandleData)
1940{
1941 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileType %s(%08x)\n",
1942 lpHMDeviceName, pHMHandleData));
1943
1944 return FILE_TYPE_DISK;
1945}
1946//******************************************************************************
1947//******************************************************************************
Note: See TracBrowser for help on using the repository browser.