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

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

CDROM ioctls added + fixed read toc

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