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

Last change on this file since 7699 was 7699, checked in by sandervl, 24 years ago

corrected some return values in hmdiskhmdisk.cpp

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