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

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

Cleaned up memory map code

File size: 81.5 KB
Line 
1/* $Id: hmdisk.cpp,v 1.61 2003-02-18 18:48:54 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 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/4096;
1842 if(offset & 0xfff)
1843 nrpages++;
1844 if(nNumberOfBytesToRead & 0xfff)
1845 nrpages++;
1846
1847 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1848 map->Release();
1849 }
1850 else lpRealBuf = (LPVOID)lpBuffer;
1851
1852 //if unmounted volume, check upper boundary as we're accessing the entire physical drive
1853 //instead of just the volume
1854 if(UNMOUNTED_VOLUME(drvInfo))
1855 {
1856 LARGE_INTEGER distance, result, endpos;
1857
1858 //calculate end position in partition
1859 Add64(&drvInfo->StartingOffset, &drvInfo->PartitionSize, &endpos);
1860
1861 distance.HighPart = 0;
1862 distance.LowPart = nNumberOfBytesToRead;
1863 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
1864
1865 //check upper boundary
1866 if(result.HighPart > endpos.HighPart ||
1867 (result.HighPart == endpos.HighPart && result.LowPart > endpos.LowPart) )
1868 {
1869 Sub64(&endpos, &drvInfo->CurrentFilePointer, &result);
1870 nNumberOfBytesToRead = result.LowPart;
1871 dprintf(("Read past end of volume; nNumberOfBytesToRead reduced to %d", nNumberOfBytesToRead));
1872 DebugInt3();
1873 }
1874 }
1875
1876 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1877 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1878 }
1879 // else {
1880 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
1881 (PVOID)lpRealBuf,
1882 nNumberOfBytesToRead,
1883 lpNumberOfBytesRead);
1884// }
1885
1886 if(bRC == 0) {
1887 dprintf(("KERNEL32: HMDeviceDiskClass::ReadFile returned %08xh %x", bRC, GetLastError()));
1888 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
1889 }
1890 else dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile read %x bytes pos %x", *lpNumberOfBytesRead, SetFilePointer(pHMHandleData, 0, NULL, FILE_CURRENT)));
1891
1892 //if unmounted volume, add starting offset to position as we're accessing the entire physical drive
1893 //instead of just the volume
1894 if(UNMOUNTED_VOLUME(drvInfo) && bRC == TRUE)
1895 {
1896 LARGE_INTEGER distance, result;
1897
1898 distance.HighPart = 0;
1899 distance.LowPart = *lpNumberOfBytesRead;
1900 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
1901 drvInfo->CurrentFilePointer = result;
1902
1903 dprintf(("New unmounted volume current file pointer %08x%08x", drvInfo->CurrentFilePointer.HighPart, drvInfo->CurrentFilePointer.LowPart));
1904 }
1905
1906 return bRC;
1907}
1908/*****************************************************************************
1909 * Name : DWORD HMDeviceDiskClass::SetFilePointer
1910 * Purpose : set file pointer
1911 * Parameters: PHMHANDLEDATA pHMHandleData
1912 * LONG lDistanceToMove
1913 * PLONG lpDistanceToMoveHigh
1914 * DWORD dwMoveMethod
1915 * Variables :
1916 * Result : API returncode
1917 * Remark :
1918 * Status :
1919 *
1920 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1921 *****************************************************************************/
1922DWORD HMDeviceDiskClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
1923 LONG lDistanceToMove,
1924 PLONG lpDistanceToMoveHigh,
1925 DWORD dwMoveMethod)
1926{
1927 DWORD ret;
1928
1929 if(lpDistanceToMoveHigh) {
1930 dprintf(("KERNEL32: HMDeviceDiskClass::SetFilePointer %s %08x%08x %d",
1931 lpHMDeviceName, *lpDistanceToMoveHigh, lDistanceToMove, dwMoveMethod));
1932 }
1933
1934 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1935 if(drvInfo == NULL) {
1936 dprintf(("ERROR: SetFilePointer: drvInfo == NULL!!!"));
1937 DebugInt3();
1938 SetLastError(ERROR_INVALID_HANDLE);
1939 return FALSE;
1940 }
1941
1942 if(!pHMHandleData->hHMHandle) {
1943 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1944 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1945 if(!pHMHandleData->hHMHandle) {
1946 dprintf(("No disk inserted; aborting"));
1947 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
1948 return -1;
1949 }
1950 }
1951
1952 //if unmounted volume, add starting offset to position as we're accessing the entire physical drive
1953 //instead of just the volume
1954 if(UNMOUNTED_VOLUME(drvInfo))
1955 {
1956 LARGE_INTEGER distance, result, endpos;
1957 LARGE_INTEGER position;
1958
1959 if(lpDistanceToMoveHigh) {
1960 distance.HighPart = *lpDistanceToMoveHigh;
1961 }
1962 else {
1963 if(lDistanceToMove < 0) {
1964 distance.HighPart = -1;
1965 }
1966 else distance.HighPart = 0;
1967 }
1968 distance.LowPart = lDistanceToMove;
1969
1970 //calculate end position in partition
1971 Add64(&drvInfo->StartingOffset, &drvInfo->PartitionSize, &endpos);
1972
1973 switch(dwMoveMethod) {
1974 case FILE_BEGIN:
1975 Add64(&distance, &drvInfo->StartingOffset, &result);
1976 break;
1977 case FILE_CURRENT:
1978 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
1979 break;
1980 case FILE_END:
1981 Add64(&distance, &endpos, &result);
1982 break;
1983 }
1984 //check upper boundary
1985 if(result.HighPart > endpos.HighPart ||
1986 (result.HighPart == endpos.HighPart && result.LowPart > endpos.LowPart) )
1987 {
1988 SetLastError(ERROR_INVALID_PARAMETER);
1989 return -1;
1990 }
1991 //check lower boundary
1992 if(result.HighPart < drvInfo->StartingOffset.HighPart ||
1993 (result.HighPart == drvInfo->StartingOffset.HighPart && result.LowPart < drvInfo->StartingOffset.LowPart))
1994 {
1995 SetLastError(ERROR_NEGATIVE_SEEK);
1996 return -1;
1997 }
1998
1999 dprintf(("SetFilePointer (unmounted partition) %08x%08x -> %08x%08x", distance.HighPart, distance.LowPart, result.HighPart, result.LowPart));
2000 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
2001 result.LowPart,
2002 (DWORD *)&result.HighPart,
2003 FILE_BEGIN);
2004 //save new file pointer
2005 drvInfo->CurrentFilePointer.HighPart = result.HighPart;
2006 drvInfo->CurrentFilePointer.LowPart = ret;
2007
2008 //subtract volume start to get relative offset
2009 Sub64(&drvInfo->CurrentFilePointer, &drvInfo->StartingOffset, &result);
2010 ret = result.LowPart;
2011 if(lpDistanceToMoveHigh) {
2012 *lpDistanceToMoveHigh = result.HighPart;
2013 }
2014 }
2015 else {
2016 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
2017 lDistanceToMove,
2018 (DWORD *)lpDistanceToMoveHigh,
2019 dwMoveMethod);
2020 }
2021
2022 if(ret == -1) {
2023 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
2024 }
2025 return ret;
2026}
2027
2028/*****************************************************************************
2029 * Name : BOOL HMDeviceDiskClass::WriteFile
2030 * Purpose : write data to handle / device
2031 * Parameters: PHMHANDLEDATA pHMHandleData,
2032 * LPCVOID lpBuffer,
2033 * DWORD nNumberOfBytesToWrite,
2034 * LPDWORD lpNumberOfBytesWritten,
2035 * LPOVERLAPPED lpOverlapped
2036 * Variables :
2037 * Result : Boolean
2038 * Remark :
2039 * Status :
2040 *
2041 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
2042 *****************************************************************************/
2043
2044BOOL HMDeviceDiskClass::WriteFile(PHMHANDLEDATA pHMHandleData,
2045 LPCVOID lpBuffer,
2046 DWORD nNumberOfBytesToWrite,
2047 LPDWORD lpNumberOfBytesWritten,
2048 LPOVERLAPPED lpOverlapped,
2049 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
2050{
2051 LPVOID lpRealBuf;
2052 Win32MemMap *map;
2053 DWORD offset, byteswritten;
2054 BOOL bRC;
2055
2056 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
2057 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
2058 lpOverlapped));
2059
2060 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
2061 if(drvInfo == NULL) {
2062 dprintf(("ERROR: WriteFile: drvInfo == NULL!!!"));
2063 DebugInt3();
2064 SetLastError(ERROR_INVALID_HANDLE);
2065 return FALSE;
2066 }
2067 if(!(drvInfo->dwAccess & GENERIC_WRITE)) {
2068 dprintf(("ERROR: WriteFile: write access denied!"));
2069 SetLastError(ERROR_ACCESS_DENIED);
2070 return FALSE;
2071 }
2072 //It's legal for this pointer to be NULL
2073 if(lpNumberOfBytesWritten)
2074 *lpNumberOfBytesWritten = 0;
2075 else
2076 lpNumberOfBytesWritten = &byteswritten;
2077
2078 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
2079 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
2080 SetLastError(ERROR_INVALID_PARAMETER);
2081 return FALSE;
2082 }
2083 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
2084 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
2085 }
2086 if(lpCompletionRoutine) {
2087 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
2088 }
2089
2090 //If we didn't get an OS/2 handle for the disk before, get one now
2091 if(!pHMHandleData->hHMHandle) {
2092 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
2093 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
2094 if(!pHMHandleData->hHMHandle) {
2095 dprintf(("No disk inserted; aborting"));
2096 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
2097 return FALSE;
2098 }
2099 }
2100
2101 //SvL: DosWrite doesn't like reading from memory addresses returned by
2102 // DosAliasMem -> search for original memory mapped pointer and use
2103 // that one + commit pages if not already present
2104 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_READ);
2105 if(map) {
2106 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
2107 DWORD nrpages = nNumberOfBytesToWrite/4096;
2108 if(offset & 0xfff)
2109 nrpages++;
2110 if(nNumberOfBytesToWrite & 0xfff)
2111 nrpages++;
2112
2113 map->commitPage(offset & ~0xfff, TRUE, nrpages);
2114 map->Release();
2115 }
2116 else lpRealBuf = (LPVOID)lpBuffer;
2117
2118 //if unmounted volume, check upper boundary as we're accessing the entire physical drive
2119 //instead of just the volume
2120 if(UNMOUNTED_VOLUME(drvInfo))
2121 {
2122 LARGE_INTEGER distance, result, endpos;
2123
2124 //calculate end position in partition
2125 Add64(&drvInfo->StartingOffset, &drvInfo->PartitionSize, &endpos);
2126
2127 distance.HighPart = 0;
2128 distance.LowPart = nNumberOfBytesToWrite;
2129 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
2130
2131 //check upper boundary
2132 if(result.HighPart > endpos.HighPart ||
2133 (result.HighPart == endpos.HighPart && result.LowPart > endpos.LowPart) )
2134 {
2135 Sub64(&endpos, &drvInfo->CurrentFilePointer, &result);
2136 nNumberOfBytesToWrite = result.LowPart;
2137 dprintf(("Write past end of volume; nNumberOfBytesToWrite reduced to %d", nNumberOfBytesToWrite));
2138 DebugInt3();
2139 }
2140 }
2141
2142 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
2143 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
2144 }
2145// else {
2146#if 0
2147 bRC = TRUE;
2148 *lpNumberOfBytesWritten = nNumberOfBytesToWrite;
2149#else
2150 bRC = OSLibDosWrite(pHMHandleData->hHMHandle,
2151 (PVOID)lpRealBuf,
2152 nNumberOfBytesToWrite,
2153 lpNumberOfBytesWritten);
2154#endif
2155// }
2156
2157 //if unmounted volume, add starting offset to position as we're accessing the entire physical drive
2158 //instead of just the volume
2159 if(UNMOUNTED_VOLUME(drvInfo) && bRC == TRUE)
2160 {
2161 LARGE_INTEGER distance, result;
2162
2163 distance.HighPart = 0;
2164 distance.LowPart = *lpNumberOfBytesWritten;
2165 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
2166 drvInfo->CurrentFilePointer = result;
2167
2168 dprintf(("New unmounted volume current file pointer %08x%08x", drvInfo->CurrentFilePointer.HighPart, drvInfo->CurrentFilePointer.LowPart));
2169 }
2170
2171 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile returned %08xh\n",
2172 bRC));
2173
2174 return bRC;
2175}
2176
2177/*****************************************************************************
2178 * Name : DWORD HMDeviceDiskClass::GetFileSize
2179 * Purpose : set file time
2180 * Parameters: PHMHANDLEDATA pHMHandleData
2181 * PDWORD pSize
2182 * Variables :
2183 * Result : API returncode
2184 * Remark :
2185 * Status :
2186 *
2187 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
2188 *****************************************************************************/
2189
2190DWORD HMDeviceDiskClass::GetFileSize(PHMHANDLEDATA pHMHandleData,
2191 PDWORD lpdwFileSizeHigh)
2192{
2193#if 1
2194 //Verified in NT4
2195 dprintf(("WARNING: GetFileSize doesn't work for drive objects; returning error (same as Windows)"));
2196 SetLastError(ERROR_INVALID_PARAMETER);
2197 return -1; //INVALID_SET_FILE_POINTER
2198#else
2199 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
2200 if(drvInfo == NULL) {
2201 dprintf(("ERROR: GetFileSize: drvInfo == NULL!!!"));
2202 DebugInt3();
2203 SetLastError(ERROR_INVALID_HANDLE);
2204 return -1; //INVALID_SET_FILE_POINTER
2205 }
2206
2207 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileSize %s(%08xh,%08xh)\n",
2208 lpHMDeviceName, pHMHandleData, lpdwFileSizeHigh));
2209
2210 //If we didn't get an OS/2 handle for the disk before, get one now
2211 if(!pHMHandleData->hHMHandle) {
2212 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
2213 if(!pHMHandleData->hHMHandle) {
2214 dprintf(("No disk inserted; aborting"));
2215 SetLastError((drvInfo->fShareViolation) ? ERROR_SHARING_VIOLATION : ERROR_NOT_READY);
2216 return -1; //INVALID_SET_FILE_POINTER
2217 }
2218 }
2219
2220 if(drvInfo->PartitionSize.HighPart || drvInfo->PartitionSize.LowPart) {
2221 if(lpdwFileSizeHigh)
2222 *lpdwFileSizeHigh = drvInfo->PartitionSize.HighPart;
2223
2224 return drvInfo->PartitionSize.LowPart;
2225 }
2226 else {
2227 LARGE_INTEGER position, size;
2228
2229 //get current position
2230 position.HighPart = 0;
2231 position.LowPart = SetFilePointer(pHMHandleData, 0, (PLONG)&position.HighPart, FILE_CURRENT);
2232 SetFilePointer(pHMHandleData, 0, NULL, FILE_BEGIN);
2233 size.HighPart = 0;
2234 size.LowPart = SetFilePointer(pHMHandleData, 0, (PLONG)&size.HighPart, FILE_END);
2235
2236 //restore old position
2237 SetFilePointer(pHMHandleData, position.LowPart, (PLONG)&position.HighPart, FILE_BEGIN);
2238
2239 if(lpdwFileSizeHigh)
2240 *lpdwFileSizeHigh = size.HighPart;
2241
2242 return size.LowPart;
2243 }
2244#endif
2245}
2246
2247/*****************************************************************************
2248 * Name : DWORD HMDeviceDiskClass::GetFileType
2249 * Purpose : determine the handle type
2250 * Parameters: PHMHANDLEDATA pHMHandleData
2251 * Variables :
2252 * Result : API returncode
2253 * Remark :
2254 * Status :
2255 *
2256 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
2257 *****************************************************************************/
2258
2259DWORD HMDeviceDiskClass::GetFileType(PHMHANDLEDATA pHMHandleData)
2260{
2261 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileType %s(%08x)\n",
2262 lpHMDeviceName, pHMHandleData));
2263
2264 return FILE_TYPE_DISK;
2265}
2266//******************************************************************************
2267//******************************************************************************
Note: See TracBrowser for help on using the repository browser.