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

Last change on this file since 22018 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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