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

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

volume api updates (LVM)

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