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

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

Do not test for write capability with CDROM drives (IOCTL_DISK_IS_WRITABLE)

File size: 52.2 KB
Line 
1/* $Id: hmdisk.cpp,v 1.41 2002-04-06 14:58:35 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] = 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 IOCTL_DISK,
334 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_IS_WRITABLE:
402 msg = "IOCTL_DISK_IS_WRITABLE";
403 break;
404 case IOCTL_DISK_GET_DRIVE_LAYOUT:
405 msg = "IOCTL_DISK_GET_DRIVE_LAYOUT";
406 break;
407 case IOCTL_DISK_GET_MEDIA_TYPES:
408 msg = "IOCTL_DISK_GET_MEDIA_TYPES";
409 break;
410 case IOCTL_DISK_GET_PARTITION_INFO:
411 msg = "IOCTL_DISK_GET_PARTITION_INFO";
412 break;
413 case IOCTL_DISK_LOAD_MEDIA:
414 msg = "IOCTL_DISK_LOAD_MEDIA";
415 break;
416 case IOCTL_DISK_MEDIA_REMOVAL:
417 msg = "IOCTL_DISK_MEDIA_REMOVAL";
418 break;
419 case IOCTL_DISK_PERFORMANCE:
420 msg = "IOCTL_DISK_PERFORMANCE";
421 break;
422 case IOCTL_DISK_REASSIGN_BLOCKS:
423 msg = "IOCTL_DISK_REASSIGN_BLOCKS";
424 break;
425 case IOCTL_DISK_SET_DRIVE_LAYOUT:
426 msg = "IOCTL_DISK_SET_DRIVE_LAYOUT";
427 break;
428 case IOCTL_DISK_SET_PARTITION_INFO:
429 msg = "IOCTL_DISK_SET_PARTITION_INFO";
430 break;
431 case IOCTL_DISK_VERIFY:
432 msg = "IOCTL_DISK_VERIFY";
433 break;
434 case IOCTL_SERIAL_LSRMST_INSERT:
435 msg = "IOCTL_SERIAL_LSRMST_INSERT";
436 break;
437 case IOCTL_STORAGE_CHECK_VERIFY:
438 msg = "IOCTL_STORAGE_CHECK_VERIFY";
439 break;
440 case IOCTL_STORAGE_EJECT_MEDIA:
441 msg = "IOCTL_STORAGE_EJECT_MEDIA";
442 break;
443 case IOCTL_STORAGE_GET_MEDIA_TYPES:
444 msg = "IOCTL_STORAGE_GET_MEDIA_TYPES";
445 break;
446 case IOCTL_STORAGE_LOAD_MEDIA:
447 msg = "IOCTL_STORAGE_LOAD_MEDIA";
448 break;
449 case IOCTL_STORAGE_MEDIA_REMOVAL:
450 msg = "IOCTL_STORAGE_MEDIA_REMOVAL";
451 break;
452 case IOCTL_SCSI_PASS_THROUGH:
453 msg = "IOCTL_SCSI_PASS_THROUGH";
454 break;
455 case IOCTL_SCSI_MINIPORT:
456 msg = "IOCTL_SCSI_MINIPORT";
457 break;
458 case IOCTL_SCSI_GET_INQUIRY_DATA:
459 msg = "IOCTL_SCSI_GET_INQUIRY_DATA";
460 break;
461 case IOCTL_SCSI_GET_CAPABILITIES:
462 msg = "IOCTL_SCSI_GET_CAPABILITIES";
463 break;
464 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
465 msg = "IOCTL_SCSI_PASS_THROUGH_DIRECT";
466 break;
467 case IOCTL_SCSI_GET_ADDRESS:
468 msg = "IOCTL_SCSI_GET_ADDRESS";
469 break;
470 case IOCTL_SCSI_RESCAN_BUS:
471 msg = "IOCTL_SCSI_RESCAN_BUS";
472 break;
473 case IOCTL_SCSI_GET_DUMP_POINTERS:
474 msg = "IOCTL_SCSI_GET_DUMP_POINTERS";
475 break;
476 case IOCTL_SCSI_FREE_DUMP_POINTERS:
477 msg = "IOCTL_SCSI_FREE_DUMP_POINTERS";
478 break;
479 case IOCTL_IDE_PASS_THROUGH:
480 msg = "IOCTL_IDE_PASS_THROUGH";
481 break;
482 case IOCTL_CDROM_UNLOAD_DRIVER:
483 msg = "IOCTL_CDROM_UNLOAD_DRIVER";
484 break;
485 case IOCTL_CDROM_READ_TOC:
486 msg = "IOCTL_CDROM_READ_TOC";
487 break;
488 case IOCTL_CDROM_GET_CONTROL:
489 msg = "IOCTL_CDROM_GET_CONTROL";
490 break;
491 case IOCTL_CDROM_PLAY_AUDIO_MSF:
492 msg = "IOCTL_CDROM_PLAY_AUDIO_MSF";
493 break;
494 case IOCTL_CDROM_SEEK_AUDIO_MSF:
495 msg = "IOCTL_CDROM_SEEK_AUDIO_MSF";
496 break;
497 case IOCTL_CDROM_STOP_AUDIO:
498 msg = "IOCTL_CDROM_STOP_AUDIO";
499 break;
500 case IOCTL_CDROM_PAUSE_AUDIO:
501 msg = "IOCTL_CDROM_PAUSE_AUDIO";
502 break;
503 case IOCTL_CDROM_RESUME_AUDIO:
504 msg = "IOCTL_CDROM_RESUME_AUDIO";
505 break;
506 case IOCTL_CDROM_GET_VOLUME:
507 msg = "IOCTL_CDROM_GET_VOLUME";
508 break;
509 case IOCTL_CDROM_SET_VOLUME:
510 msg = "IOCTL_CDROM_SET_VOLUME";
511 break;
512 case IOCTL_CDROM_READ_Q_CHANNEL:
513 msg = "IOCTL_CDROM_READ_Q_CHANNEL";
514 break;
515 case IOCTL_CDROM_GET_LAST_SESSION:
516 msg = "IOCTL_CDROM_GET_LAST_SESSION";
517 break;
518 case IOCTL_CDROM_RAW_READ:
519 msg = "IOCTL_CDROM_RAW_READ";
520 break;
521 case IOCTL_CDROM_DISK_TYPE:
522 msg = "IOCTL_CDROM_DISK_TYPE";
523 break;
524 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
525 msg = "IOCTL_CDROM_GET_DRIVE_GEOMETRY";
526 break;
527 case IOCTL_CDROM_CHECK_VERIFY:
528 msg = "IOCTL_CDROM_CHECK_VERIFY";
529 break;
530 case IOCTL_CDROM_MEDIA_REMOVAL:
531 msg = "IOCTL_CDROM_MEDIA_REMOVAL";
532 break;
533 case IOCTL_CDROM_EJECT_MEDIA:
534 msg = "IOCTL_CDROM_EJECT_MEDIA";
535 break;
536 case IOCTL_CDROM_LOAD_MEDIA:
537 msg = "IOCTL_CDROM_LOAD_MEDIA";
538 break;
539 case IOCTL_CDROM_RESERVE:
540 msg = "IOCTL_CDROM_RESERVE";
541 break;
542 case IOCTL_CDROM_RELEASE:
543 msg = "IOCTL_CDROM_RELEASE";
544 break;
545 case IOCTL_CDROM_FIND_NEW_DEVICES:
546 msg = "IOCTL_CDROM_FIND_NEW_DEVICES";
547 break;
548 }
549 if(msg) {
550 dprintf(("HMDeviceDiskClass::DeviceIoControl %s %x %d %x %d %x %x", msg, lpInBuffer, nInBufferSize,
551 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped));
552 }
553#endif
554
555 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
556 if(drvInfo == NULL) {
557 dprintf(("ERROR: DeviceIoControl: drvInfo == NULL!!!"));
558 DebugInt3();
559 SetLastError(ERROR_INVALID_HANDLE);
560 return FALSE;
561 }
562 switch(dwIoControlCode)
563 {
564 case FSCTL_DELETE_REPARSE_POINT:
565 case FSCTL_DISMOUNT_VOLUME:
566 case FSCTL_GET_COMPRESSION:
567 case FSCTL_GET_REPARSE_POINT:
568 case FSCTL_LOCK_VOLUME:
569 case FSCTL_QUERY_ALLOCATED_RANGES:
570 case FSCTL_SET_COMPRESSION:
571 case FSCTL_SET_REPARSE_POINT:
572 case FSCTL_SET_SPARSE:
573 case FSCTL_SET_ZERO_DATA:
574 case FSCTL_UNLOCK_VOLUME:
575 break;
576
577 case IOCTL_DISK_FORMAT_TRACKS:
578 case IOCTL_DISK_GET_DRIVE_LAYOUT:
579 break;
580
581 case IOCTL_DISK_IS_WRITABLE:
582 {
583 APIRET rc;
584 DWORD ret;
585 ULONG ulBytesRead = 0; /* Number of bytes read by DosRead */
586 ULONG ulWrote = 0; /* Number of bytes written by DosWrite */
587 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
588 UCHAR uchFileData[1] = {'0'}; /* Data to write to file */
589
590 if(!pHMHandleData->hHMHandle)
591 {
592 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
593 if(!pHMHandleData->hHMHandle) {
594 dprintf(("No disk inserted; aborting"));
595 SetLastError(ERROR_NOT_READY);
596 return FALSE;
597 }
598 }
599 if(drvInfo->driveType == DRIVE_CDROM) {
600 //TODO: check behaviour in NT
601 SetLastError(ERROR_WRITE_PROTECT);
602 return FALSE;
603 }
604
605 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_LOCKDRIVE,0,0,0,0,0,0);
606
607 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
608
609 /* Read the first byte of the disk */
610 rc = OSLibDosRead(pHMHandleData->hHMHandle, /* File Handle */
611 uchFileData, /* String to be read */
612 1L, /* Length of string to be read */
613 &ulBytesRead); /* Bytes actually read */
614
615 if (rc == 0)
616 {
617 dprintf(("IOCTL_DISK_IS_WRITABLE:OSLibDosRead failed with rc %08xh %x", rc,GetLastError()));
618 SetLastError(ERROR_ACCESS_DENIED);
619 goto writecheckfail;
620 }
621
622 /* Move the file pointer back */
623 rc = OSLibDosSetFilePtr (pHMHandleData->hHMHandle, /* File Handle */
624 -1,OSLIB_SETPTR_FILE_CURRENT);
625 if (rc == -1)
626 {
627 dprintf(("IOCTL_DISK_IS_WRITABLE:OSLibDosSetFilePtr failed with rc %d", rc));
628 SetLastError(ERROR_ACCESS_DENIED);
629 goto writecheckfail;
630 }
631
632 rc = OSLibDosWrite(pHMHandleData->hHMHandle, /* File handle */
633 (PVOID) uchFileData, /* String to be written */
634 1, /* Size of string to be written */
635 &ulWrote); /* Bytes actually written */
636
637 dprintf2(("IOCTL_DISK_IS_WRITABLE:OSLibDosWrite returned with rc %x %x", rc,GetLastError()));
638 if (rc == 0)
639 {
640 if (GetLastError() == ERROR_WRITE_PROTECT)
641 {
642 SetLastError(ERROR_WRITE_PROTECT);
643 goto writecheckfail;
644 }
645 }
646 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_UNLOCKDRIVE,0,0,0,0,0,0);
647 SetErrorMode(oldmode);
648 SetLastError(ERROR_SUCCESS);
649 return TRUE;
650
651writecheckfail:
652 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_UNLOCKDRIVE,0,0,0,0,0,0);
653 SetErrorMode(oldmode);
654 return FALSE;
655 }
656 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
657 case IOCTL_STORAGE_GET_MEDIA_TYPES:
658 case IOCTL_DISK_GET_MEDIA_TYPES:
659 {
660 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)lpOutBuffer;
661 if(nOutBufferSize < sizeof(DISK_GEOMETRY) || !pGeom) {
662 SetLastError(ERROR_INSUFFICIENT_BUFFER);
663 return FALSE;
664 }
665 if(lpBytesReturned) {
666 *lpBytesReturned = 0;
667 }
668
669 ULONG volumelabel;
670 APIRET rc;
671
672 if(!pHMHandleData->hHMHandle) {
673 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
674 if(!pHMHandleData->hHMHandle) {
675 dprintf(("No disk inserted; aborting"));
676 SetLastError(ERROR_NOT_READY);
677 return FALSE;
678 }
679 }
680
681 //Applications can use this IOCTL to check if the floppy has been changed
682 //OSLibDosGetDiskGeometry won't fail when that happens so we read the
683 //volume label from the disk and return ERROR_MEDIA_CHANGED if the volume
684 //label has changed
685 //TODO: Find better way to determine if floppy was removed or switched
686 rc = OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &volumelabel, NULL, 0);
687 if(rc) {
688 dprintf(("IOCTL_DISK_GET_DRIVE_GEOMETRY: OSLibDosQueryVolumeSerialAndName failed with rc %d", GetLastError()));
689 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
690 pHMHandleData->hHMHandle = 0;
691 SetLastError(ERROR_MEDIA_CHANGED);
692 return FALSE;
693 }
694 if(volumelabel != drvInfo->dwVolumelabel) {
695 dprintf(("IOCTL_DISK_GET_DRIVE_GEOMETRY: volume changed %x -> %x", drvInfo->dwVolumelabel, volumelabel));
696 SetLastError(ERROR_MEDIA_CHANGED);
697 return FALSE;
698 }
699
700 if(OSLibDosGetDiskGeometry(pHMHandleData->hHMHandle, drvInfo->driveLetter, pGeom) == FALSE) {
701 return FALSE;
702 }
703 if(lpBytesReturned) {
704 *lpBytesReturned = sizeof(DISK_GEOMETRY);
705 }
706 SetLastError(ERROR_SUCCESS);
707 return TRUE;
708 }
709
710 case IOCTL_DISK_GET_PARTITION_INFO:
711 case IOCTL_DISK_LOAD_MEDIA:
712 case IOCTL_DISK_MEDIA_REMOVAL:
713 case IOCTL_DISK_PERFORMANCE:
714 case IOCTL_DISK_REASSIGN_BLOCKS:
715 case IOCTL_DISK_SET_DRIVE_LAYOUT:
716 case IOCTL_DISK_SET_PARTITION_INFO:
717 case IOCTL_DISK_VERIFY:
718 case IOCTL_SERIAL_LSRMST_INSERT:
719 break;
720
721
722 // -----------
723 // CDROM class
724 // -----------
725 case IOCTL_CDROM_READ_TOC:
726 {
727#pragma pack(1)
728 typedef struct
729 {
730 BYTE ucFirstTrack;
731 BYTE ucLastTrack;
732 DWORD ulLeadOutAddr;
733 } AudioDiskInfo;
734 typedef struct
735 {
736 DWORD ulTrackAddr;
737 BYTE ucTrackControl;
738 } AudioTrackInfo;
739 typedef struct
740 {
741 BYTE signature[4];
742 BYTE ucTrack;
743 } ParameterBlock;
744#pragma pack()
745
746 PCDROM_TOC pTOC = (PCDROM_TOC)lpOutBuffer;
747 DWORD rc, numtracks;
748 DWORD parsize = 4;
749 DWORD datasize;
750 AudioDiskInfo diskinfo;
751 AudioTrackInfo trackinfo;
752 ParameterBlock parm;
753
754 if(lpBytesReturned)
755 *lpBytesReturned = 0;
756
757 if(!pTOC) {
758 SetLastError(ERROR_INVALID_PARAMETER);
759 return FALSE;
760 }
761 if(nOutBufferSize < sizeof(CDROM_TOC)) {
762 SetLastError(ERROR_INSUFFICIENT_BUFFER);
763 return FALSE;
764 }
765 memset(pTOC, 0, nOutBufferSize);
766 //IOCTL_CDROMAUDIO (0x81), CDROMAUDIO_GETAUDIODISK (0x61)
767 datasize = sizeof(diskinfo);
768 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x61, &drvInfo->signature[0], 4, &parsize,
769 &diskinfo, sizeof(diskinfo), &datasize);
770 if(rc != NO_ERROR) {
771 dprintf(("OSLibDosDevIOCtl failed with rc %d", rc));
772 return FALSE;
773 }
774 pTOC->FirstTrack = diskinfo.ucFirstTrack;
775 pTOC->LastTrack = diskinfo.ucLastTrack;
776 numtracks = pTOC->LastTrack - pTOC->FirstTrack + 1;
777 dprintf(("first %d, last %d, num %d", pTOC->FirstTrack, pTOC->LastTrack, numtracks));
778
779 //numtracks+1, because we have to add a track at the end
780 int length = 4 + (numtracks+1)*sizeof(TRACK_DATA);
781 //big endian format
782 pTOC->Length[0] = HIBYTE((length-2)); //minus length itself;
783 pTOC->Length[1] = LOBYTE((length-2)); //minus length itself;
784
785 if(nOutBufferSize < length) {
786 SetLastError(ERROR_INSUFFICIENT_BUFFER);
787 return FALSE;
788 }
789
790 for(int i=0;i<numtracks;i++)
791 {
792 parsize = sizeof(parm);
793 memcpy(parm.signature, drvInfo->signature, 4);
794 parm.ucTrack = i;
795
796 datasize = sizeof(trackinfo);
797
798 //IOCTL_CDROMAUDIO (0x81), CDROMAUDIO_GETAUDIOTRACK (0x62)
799 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x62, &parm, sizeof(parm), &parsize,
800 &trackinfo, sizeof(trackinfo), &datasize);
801 if(rc != NO_ERROR) {
802 dprintf(("OSLibDosDevIOCtl failed with rc %d", rc));
803 return FALSE;
804 }
805 pTOC->TrackData[i].TrackNumber = pTOC->FirstTrack + i;
806 pTOC->TrackData[i].Reserved = 0;
807 pTOC->TrackData[i].Control = trackinfo.ucTrackControl >> 4;
808 pTOC->TrackData[i].Adr = trackinfo.ucTrackControl & 0xF;
809 pTOC->TrackData[i].Reserved1 = 0;
810 //big endian format
811 pTOC->TrackData[i].Address[0] = HIBYTE(HIWORD(trackinfo.ulTrackAddr));
812 pTOC->TrackData[i].Address[1] = LOBYTE(HIWORD(trackinfo.ulTrackAddr));
813 pTOC->TrackData[i].Address[2] = HIBYTE(LOWORD(trackinfo.ulTrackAddr));
814 pTOC->TrackData[i].Address[3] = LOBYTE(LOWORD(trackinfo.ulTrackAddr));
815 }
816
817 //Add a track at the end (presumably so the app can determine the size of the 1st track)
818 //That is what NT4, SP6 does anyway
819 pTOC->TrackData[numtracks].TrackNumber = 0xAA;
820 pTOC->TrackData[numtracks].Reserved = 0;
821 pTOC->TrackData[numtracks].Control = pTOC->TrackData[numtracks-1].Control;
822 pTOC->TrackData[numtracks].Adr = pTOC->TrackData[numtracks-1].Adr;
823 pTOC->TrackData[numtracks].Reserved1 = 0;
824 //big endian format
825 //Address of pseudo track is the address of the lead-out track
826 pTOC->TrackData[numtracks].Address[0] = HIBYTE(HIWORD(diskinfo.ulLeadOutAddr));
827 pTOC->TrackData[numtracks].Address[1] = LOBYTE(HIWORD(diskinfo.ulLeadOutAddr));
828 pTOC->TrackData[numtracks].Address[2] = HIBYTE(LOWORD(diskinfo.ulLeadOutAddr));
829 pTOC->TrackData[numtracks].Address[3] = LOBYTE(LOWORD(diskinfo.ulLeadOutAddr));
830
831 if(lpBytesReturned)
832 *lpBytesReturned = length;
833
834 SetLastError(ERROR_SUCCESS);
835 return TRUE;
836 }
837
838 case IOCTL_CDROM_UNLOAD_DRIVER:
839 case IOCTL_CDROM_GET_CONTROL:
840 break;
841
842 case IOCTL_CDROM_PLAY_AUDIO_MSF:
843 {
844 dprintf(("Play CDROM audio playback"));
845
846#pragma pack(1)
847 struct
848 {
849 DWORD ucSignature;
850 BYTE ucAddressingMode;
851 DWORD ulStartingMSF;
852 DWORD ulEndingMSF;
853 } ParameterBlock;
854#pragma pack()
855
856 PCDROM_PLAY_AUDIO_MSF pPlay = (PCDROM_PLAY_AUDIO_MSF)lpInBuffer;
857
858 // setup the parameter block
859
860 memcpy(&ParameterBlock.ucSignature, drvInfo->signature, 4);
861 ParameterBlock.ucAddressingMode = 1; // MSF format
862
863 // @@@PH unknown if this kind of MSF conversion is correct!
864 ParameterBlock.ulStartingMSF = pPlay->StartingM << 16 |
865 pPlay->StartingS << 8 |
866 pPlay->StartingF;
867 ParameterBlock.ulEndingMSF = pPlay->EndingM << 16 |
868 pPlay->EndingS << 8 |
869 pPlay->EndingF;
870
871 DWORD dwParameterSize = sizeof( ParameterBlock );
872 DWORD dwDataSize = 0;
873 DWORD ret;
874
875 if(lpBytesReturned)
876 *lpBytesReturned = 0;
877
878 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
879 0x81, // IOCTL_CDROMAUDIO
880 0x50, // CDROMAUDIO_PLAYAUDIO
881 &ParameterBlock,
882 sizeof( ParameterBlock ),
883 &dwParameterSize,
884 NULL,
885 0,
886 &dwDataSize);
887 return (ret == ERROR_SUCCESS);
888 }
889
890 case IOCTL_CDROM_SEEK_AUDIO_MSF:
891 break;
892
893 case IOCTL_CDROM_PAUSE_AUDIO:
894 // NO BREAK CASE
895 // Note: for OS/2, pause and stop seems to be the same!
896
897 case IOCTL_CDROM_STOP_AUDIO:
898 {
899 dprintf(("Stop / pause CDROM audio playback"));
900 return ioctlCDROMSimple(pHMHandleData,
901 0x81, // IOCTL_CDROMAUDIO
902 0x51, // CDROMAUDIO_STOPAUDIO
903 lpBytesReturned, drvInfo);
904 }
905
906 case IOCTL_CDROM_RESUME_AUDIO:
907 {
908 dprintf(("Resume CDROM audio playback"));
909 return ioctlCDROMSimple(pHMHandleData,
910 0x81, // IOCTL_CDROMAUDIO
911 0x52, // CDROMAUDIO_RESUMEAUDIO
912 lpBytesReturned, drvInfo);
913 }
914
915 case IOCTL_CDROM_GET_VOLUME:
916 {
917 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpOutBuffer;
918 char volbuf[8];
919 DWORD parsize, datasize, ret;
920
921 if(nOutBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
922 SetLastError(ERROR_INSUFFICIENT_BUFFER);
923 return FALSE;
924 }
925 if(lpBytesReturned) {
926 *lpBytesReturned = 0;
927 }
928 parsize = 4;
929 datasize = 8;
930 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x60, drvInfo->signature, 4, &parsize,
931 volbuf, 8, &datasize);
932
933 if(ret)
934 return FALSE;
935
936 if(lpBytesReturned) {
937 *lpBytesReturned = sizeof(VOLUME_CONTROL);
938 }
939 pVol->PortVolume[0] = volbuf[1];
940 pVol->PortVolume[1] = volbuf[3];
941 pVol->PortVolume[2] = volbuf[5];
942 pVol->PortVolume[3] = volbuf[7];
943 SetLastError(ERROR_SUCCESS);
944 return TRUE;
945 }
946
947 case IOCTL_CDROM_SET_VOLUME:
948 {
949 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpInBuffer;
950 char volbuf[8];
951 DWORD parsize, datasize, ret;
952
953 if(nInBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
954 SetLastError(ERROR_INSUFFICIENT_BUFFER);
955 return FALSE;
956 }
957 if(lpBytesReturned) {
958 *lpBytesReturned = 0;
959 }
960 parsize = 4;
961 datasize = 8;
962 volbuf[0] = 0;
963 volbuf[1] = pVol->PortVolume[0];
964 volbuf[2] = 1;
965 volbuf[3] = pVol->PortVolume[1];
966 volbuf[4] = 2;
967 volbuf[5] = pVol->PortVolume[2];
968 volbuf[6] = 3;
969 volbuf[7] = pVol->PortVolume[3];
970 dprintf(("Set CD volume (%d,%d)(%d,%d)", pVol->PortVolume[0], pVol->PortVolume[1], pVol->PortVolume[2], pVol->PortVolume[3]));
971 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x40, drvInfo->signature, 4, &parsize,
972 volbuf, 8, &datasize);
973
974 if(ret)
975 return FALSE;
976
977 SetLastError(ERROR_SUCCESS);
978 return TRUE;
979 }
980 case IOCTL_CDROM_READ_Q_CHANNEL:
981 case IOCTL_CDROM_GET_LAST_SESSION:
982 case IOCTL_CDROM_RAW_READ:
983 case IOCTL_CDROM_DISK_TYPE:
984 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
985 case IOCTL_CDROM_MEDIA_REMOVAL:
986 break;
987
988 case IOCTL_CDROM_EJECT_MEDIA:
989 {
990 dprintf(("Eject CDROM media"));
991 return ioctlCDROMSimple(pHMHandleData,
992 0x80, // IOCTL_CDROM
993 0x44, // CDROMDISK_EJECTDISK
994 lpBytesReturned, drvInfo);
995 }
996
997 case IOCTL_CDROM_LOAD_MEDIA:
998 {
999 dprintf(("Loading CDROM media"));
1000 return ioctlCDROMSimple(pHMHandleData,
1001 0x80, // IOCTL_CDROM
1002 0x45, // CDROMDISK_CLOSETRAY
1003 lpBytesReturned, drvInfo);
1004 }
1005
1006 case IOCTL_CDROM_RESERVE:
1007 case IOCTL_CDROM_RELEASE:
1008 case IOCTL_CDROM_FIND_NEW_DEVICES:
1009 break;
1010
1011
1012 // -------------
1013 // STORAGE class
1014 // -------------
1015
1016 case IOCTL_CDROM_CHECK_VERIFY:
1017 if(drvInfo->driveType != DRIVE_CDROM) {
1018 SetLastError(ERROR_GEN_FAILURE); //TODO: right error?
1019 return FALSE;
1020 }
1021 //no break;
1022 case IOCTL_DISK_CHECK_VERIFY:
1023 case IOCTL_STORAGE_CHECK_VERIFY:
1024 {
1025 dprintf(("IOCTL_CDROM(DISK/STORAGE)CHECK_VERIFY %s", drvInfo->signature));
1026 if(lpBytesReturned) {
1027 *lpBytesReturned = 0;
1028 }
1029
1030 if(!pHMHandleData->hHMHandle) {
1031 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1032 if(!pHMHandleData->hHMHandle) {
1033 dprintf(("No disk inserted; aborting"));
1034 SetLastError(ERROR_NOT_READY);
1035 return FALSE;
1036 }
1037 }
1038
1039#pragma pack(1)
1040 typedef struct
1041 {
1042 BYTE ucCommandInfo;
1043 WORD usDriveUnit;
1044 } ParameterBlock;
1045#pragma pack()
1046
1047 DWORD parsize = sizeof(ParameterBlock);
1048 DWORD datasize = 2;
1049 WORD status = 0;
1050 DWORD rc;
1051 ParameterBlock parm;
1052
1053 parm.ucCommandInfo = 0;
1054 parm.usDriveUnit = drvInfo->driveLetter - 'A';
1055// rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x08, 0x66, &parm, sizeof(parm), &parsize,
1056 //TODO: this doesn't work for floppies for some reason...
1057 rc = OSLibDosDevIOCtl(-1, IOCTL_DISK, DSK_GETLOCKSTATUS, &parm, sizeof(parm), &parsize,
1058 &status, sizeof(status), &datasize);
1059 if(rc != NO_ERROR) {
1060 dprintf(("OSLibDosDevIOCtl failed with rc %d datasize %d", rc, datasize));
1061 return FALSE;
1062 }
1063 dprintf(("Disk status 0x%x", status));
1064 //if no disk present, return FALSE
1065 if(!(status & (BIT_2))) {
1066 SetLastError(ERROR_NOT_READY); //NT4, SP6 returns this
1067 return FALSE;
1068 }
1069 SetLastError(NO_ERROR);
1070 return TRUE;
1071 }
1072
1073 case IOCTL_DISK_EJECT_MEDIA:
1074 case IOCTL_STORAGE_EJECT_MEDIA:
1075 {
1076 dprintf(("Ejecting storage media"));
1077 return ioctlDISKUnlockEject(pHMHandleData,
1078 0x02, // EJECT media
1079 -1,
1080 lpBytesReturned);
1081 }
1082
1083 case IOCTL_STORAGE_LOAD_MEDIA:
1084 // case IOCTL_STORAGE_LOAD_MEDIA2:
1085 {
1086 dprintf(("Loading storage media"));
1087 return ioctlDISKUnlockEject(pHMHandleData,
1088 0x03, // LOAD media
1089 -1,
1090 lpBytesReturned);
1091 }
1092
1093 // case IOCTL_STORAGE_EJECTION_CONTROL:
1094 case IOCTL_STORAGE_MEDIA_REMOVAL:
1095 break;
1096
1097
1098 // -------------------
1099 // SCSI passthru class
1100 // -------------------
1101
1102 case IOCTL_SCSI_PASS_THROUGH:
1103 case IOCTL_SCSI_MINIPORT:
1104 case IOCTL_SCSI_GET_INQUIRY_DATA:
1105 case IOCTL_SCSI_GET_CAPABILITIES:
1106 break;
1107
1108 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
1109 {
1110 PSCSI_PASS_THROUGH_DIRECT pPacket = (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer;
1111 SRB_ExecSCSICmd *psrb;
1112
1113 if(drvInfo->hInstAspi == NULL)
1114 {
1115 SetLastError(ERROR_ACCESS_DENIED);
1116 return FALSE;
1117 }
1118
1119 if(nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT) ||
1120 !pPacket || pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
1121 {
1122 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1123 return FALSE;
1124 }
1125 if(lpBytesReturned) {
1126 *lpBytesReturned = 0;
1127 }
1128
1129 psrb = (SRB_ExecSCSICmd *)alloca(sizeof(SRB_ExecSCSICmd)+pPacket->SenseInfoLength);
1130 if(psrb == NULL) {
1131 dprintf(("not enough memory!!"));
1132 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1133 return FALSE;
1134 }
1135 memset(psrb, 0, sizeof(*psrb));
1136 psrb->SRB_Cmd = SC_EXEC_SCSI_CMD;
1137 psrb->SRB_Status = pPacket->ScsiStatus;
1138 psrb->SRB_HaId = pPacket->PathId;
1139 psrb->SRB_Target = pPacket->TargetId;
1140 psrb->SRB_Lun = pPacket->Lun;
1141 psrb->SRB_BufLen = pPacket->DataTransferLength;
1142 psrb->SRB_SenseLen = pPacket->SenseInfoLength;
1143 psrb->SRB_CDBLen = pPacket->CdbLength;
1144 switch(pPacket->DataIn) {
1145 case SCSI_IOCTL_DATA_OUT:
1146 psrb->SRB_Flags = 0x2 << 3;
1147 break;
1148 case SCSI_IOCTL_DATA_IN:
1149 psrb->SRB_Flags = 0x1 << 3;
1150 break;
1151 case SCSI_IOCTL_DATA_UNSPECIFIED:
1152 psrb->SRB_Flags = 0x3 << 3;
1153 break;
1154 }
1155 if(pPacket->CdbLength > 16) {
1156 SetLastError(ERROR_INVALID_PARAMETER);
1157 return FALSE;
1158 }
1159 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]));
1160 psrb->SRB_BufPointer = (BYTE *)pPacket->DataBuffer;
1161 memcpy(&psrb->CDBByte[0], &pPacket->Cdb[0], 16);
1162 if(psrb->SRB_SenseLen) {
1163 memcpy(&psrb->SenseArea[0], (char *)pPacket + pPacket->SenseInfoOffset, psrb->SRB_SenseLen);
1164 }
1165 //TODO: pPacket->TimeOutValue ignored
1166 int rc = drvInfo->SendASPI32Command((LPSRB)psrb);
1167 if(rc != SS_COMP) {
1168 dprintf(("SendASPI32Command failed with error %d", rc));
1169 if(rc == SS_ERR) {
1170 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
1171 }
1172 else SetLastError(ERROR_GEN_FAILURE);
1173 return FALSE;
1174 }
1175 pPacket->ScsiStatus = rc;
1176 if(lpBytesReturned) {
1177 *lpBytesReturned = 0;
1178 }
1179 pPacket->DataTransferLength = psrb->SRB_BufLen;
1180 if(psrb->SRB_SenseLen) {
1181 memcpy((char *)pPacket + pPacket->SenseInfoOffset, &psrb->SenseArea[0], psrb->SRB_SenseLen);
1182 }
1183 SetLastError(ERROR_SUCCESS);
1184 return TRUE;
1185 }
1186 case IOCTL_SCSI_GET_ADDRESS:
1187 {
1188 DWORD numAdapters, rc;
1189 SRB srb;
1190 int i, j, k;
1191
1192 if(!lpOutBuffer || nOutBufferSize < 8) {
1193 SetLastError(ERROR_INSUFFICIENT_BUFFER); //todo: right error?
1194 return(FALSE);
1195 }
1196 SCSI_ADDRESS *addr = (SCSI_ADDRESS *)lpOutBuffer;
1197 addr->Length = sizeof(SCSI_ADDRESS);
1198 addr->PortNumber = 0;
1199 addr->PathId = 0;
1200
1201 if(drvInfo->hInstAspi == NULL) {
1202 SetLastError(ERROR_ACCESS_DENIED);
1203 return FALSE;
1204 }
1205
1206 numAdapters = drvInfo->GetASPI32SupportInfo();
1207
1208 memset(&srb, 0, sizeof(srb));
1209 srb.common.SRB_Cmd = SC_HA_INQUIRY;
1210 rc = drvInfo->SendASPI32Command(&srb);
1211
1212 char drivename[3];
1213 drivename[0] = (char)drvInfo->driveLetter;
1214 drivename[1] = ':';
1215 drivename[2] = 0;
1216
1217 for(i=0;i<LOBYTE(numAdapters);i++) {
1218 for(j=0;j<8;j++) {
1219 for(k=0;k<16;k++) {
1220 memset(&srb, 0, sizeof(srb));
1221 srb.common.SRB_Cmd = SC_GET_DEV_TYPE;
1222 srb.devtype.SRB_HaId = i;
1223 srb.devtype.SRB_Target = j;
1224 srb.devtype.SRB_Lun = k;
1225 rc = drvInfo->SendASPI32Command(&srb);
1226 if(rc == SS_COMP) {
1227 if(srb.devtype.SRB_DeviceType == SS_DEVTYPE_CDROM &&
1228 GetDriveTypeA(drivename) == DRIVE_CDROM)
1229 {
1230 goto done;
1231 }
1232 }
1233 }
1234 }
1235 }
1236done:
1237 if(rc == SS_COMP) {
1238 addr->TargetId = j;
1239 addr->Lun = k;
1240 SetLastError(ERROR_SUCCESS);
1241 }
1242 else SetLastError(ERROR_FILE_NOT_FOUND); //todo
1243 return TRUE;
1244failure:
1245 SetLastError(ERROR_INVALID_PARAMETER); //todo
1246 return FALSE;
1247 }
1248
1249 case IOCTL_SCSI_RESCAN_BUS:
1250 case IOCTL_SCSI_GET_DUMP_POINTERS:
1251 case IOCTL_SCSI_FREE_DUMP_POINTERS:
1252 case IOCTL_IDE_PASS_THROUGH:
1253 break;
1254
1255 }
1256 dprintf(("HMDeviceDiskClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
1257 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1258 return FALSE;
1259}
1260/*****************************************************************************
1261 * Name : BOOL HMDeviceDiskClass::ReadFile
1262 * Purpose : read data from handle / device
1263 * Parameters: PHMHANDLEDATA pHMHandleData,
1264 * LPCVOID lpBuffer,
1265 * DWORD nNumberOfBytesToRead,
1266 * LPDWORD lpNumberOfBytesRead,
1267 * LPOVERLAPPED lpOverlapped
1268 * Variables :
1269 * Result : Boolean
1270 * Remark :
1271 * Status :
1272 *
1273 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1274 *****************************************************************************/
1275
1276BOOL HMDeviceDiskClass::ReadFile(PHMHANDLEDATA pHMHandleData,
1277 LPCVOID lpBuffer,
1278 DWORD nNumberOfBytesToRead,
1279 LPDWORD lpNumberOfBytesRead,
1280 LPOVERLAPPED lpOverlapped,
1281 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1282{
1283 LPVOID lpRealBuf;
1284 Win32MemMap *map;
1285 DWORD offset, bytesread;
1286 BOOL bRC;
1287
1288 dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
1289 lpHMDeviceName,
1290 pHMHandleData,
1291 lpBuffer,
1292 nNumberOfBytesToRead,
1293 lpNumberOfBytesRead,
1294 lpOverlapped));
1295
1296 //SvL: It's legal for this pointer to be NULL
1297 if(lpNumberOfBytesRead)
1298 *lpNumberOfBytesRead = 0;
1299 else
1300 lpNumberOfBytesRead = &bytesread;
1301
1302 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1303 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1304 SetLastError(ERROR_INVALID_PARAMETER);
1305 return FALSE;
1306 }
1307
1308 if(lpCompletionRoutine) {
1309 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
1310 }
1311
1312 //If we didn't get an OS/2 handle for the disk before, get one now
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 FALSE;
1320 }
1321 }
1322
1323 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1324 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1325 }
1326
1327 //SvL: DosRead doesn't like writing to memory addresses returned by
1328 // DosAliasMem -> search for original memory mapped pointer and use
1329 // that one + commit pages if not already present
1330 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
1331 if(map) {
1332 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1333 DWORD nrpages = nNumberOfBytesToRead/4096;
1334 if(offset & 0xfff)
1335 nrpages++;
1336 if(nNumberOfBytesToRead & 0xfff)
1337 nrpages++;
1338
1339 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1340 }
1341 else lpRealBuf = (LPVOID)lpBuffer;
1342
1343 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1344 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1345 }
1346// else {
1347 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
1348 (PVOID)lpRealBuf,
1349 nNumberOfBytesToRead,
1350 lpNumberOfBytesRead);
1351// }
1352
1353 if(bRC == 0) {
1354 dprintf(("KERNEL32: HMDeviceDiskClass::ReadFile returned %08xh %x", bRC, GetLastError()));
1355 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
1356 }
1357 else dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile read %x bytes pos %x", *lpNumberOfBytesRead, SetFilePointer(pHMHandleData, 0, NULL, FILE_CURRENT)));
1358
1359 return bRC;
1360}
1361/*****************************************************************************
1362 * Name : DWORD HMDeviceDiskClass::SetFilePointer
1363 * Purpose : set file pointer
1364 * Parameters: PHMHANDLEDATA pHMHandleData
1365 * LONG lDistanceToMove
1366 * PLONG lpDistanceToMoveHigh
1367 * DWORD dwMoveMethod
1368 * Variables :
1369 * Result : API returncode
1370 * Remark :
1371 * Status :
1372 *
1373 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1374 *****************************************************************************/
1375
1376DWORD HMDeviceDiskClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
1377 LONG lDistanceToMove,
1378 PLONG lpDistanceToMoveHigh,
1379 DWORD dwMoveMethod)
1380{
1381 DWORD ret;
1382
1383 dprintf2(("KERNEL32: HMDeviceDiskClass::SetFilePointer %s(%08xh,%08xh,%08xh,%08xh)\n",
1384 lpHMDeviceName,
1385 pHMHandleData,
1386 lDistanceToMove,
1387 lpDistanceToMoveHigh,
1388 dwMoveMethod));
1389
1390 if(!pHMHandleData->hHMHandle) {
1391 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1392 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1393 if(!pHMHandleData->hHMHandle) {
1394 dprintf(("No disk inserted; aborting"));
1395 SetLastError(ERROR_NOT_READY);
1396 return -1;
1397 }
1398 }
1399
1400 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
1401 lDistanceToMove,
1402 (DWORD *)lpDistanceToMoveHigh,
1403 dwMoveMethod);
1404
1405 if(ret == -1) {
1406 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
1407 }
1408 return ret;
1409}
1410
1411/*****************************************************************************
1412 * Name : BOOL HMDeviceDiskClass::WriteFile
1413 * Purpose : write data to handle / device
1414 * Parameters: PHMHANDLEDATA pHMHandleData,
1415 * LPCVOID lpBuffer,
1416 * DWORD nNumberOfBytesToWrite,
1417 * LPDWORD lpNumberOfBytesWritten,
1418 * LPOVERLAPPED lpOverlapped
1419 * Variables :
1420 * Result : Boolean
1421 * Remark :
1422 * Status :
1423 *
1424 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1425 *****************************************************************************/
1426
1427BOOL HMDeviceDiskClass::WriteFile(PHMHANDLEDATA pHMHandleData,
1428 LPCVOID lpBuffer,
1429 DWORD nNumberOfBytesToWrite,
1430 LPDWORD lpNumberOfBytesWritten,
1431 LPOVERLAPPED lpOverlapped,
1432 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1433{
1434 LPVOID lpRealBuf;
1435 Win32MemMap *map;
1436 DWORD offset, byteswritten;
1437 BOOL bRC;
1438
1439 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
1440 lpHMDeviceName,
1441 pHMHandleData,
1442 lpBuffer,
1443 nNumberOfBytesToWrite,
1444 lpNumberOfBytesWritten,
1445 lpOverlapped));
1446
1447 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1448 if(drvInfo == NULL) {
1449 dprintf(("ERROR: DeviceIoControl: drvInfo == NULL!!!"));
1450 DebugInt3();
1451 SetLastError(ERROR_INVALID_HANDLE);
1452 return FALSE;
1453 }
1454
1455 //SvL: It's legal for this pointer to be NULL
1456 if(lpNumberOfBytesWritten)
1457 *lpNumberOfBytesWritten = 0;
1458 else
1459 lpNumberOfBytesWritten = &byteswritten;
1460
1461 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1462 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1463 SetLastError(ERROR_INVALID_PARAMETER);
1464 return FALSE;
1465 }
1466 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1467 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1468 }
1469 if(lpCompletionRoutine) {
1470 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
1471 }
1472
1473 //If we didn't get an OS/2 handle for the disk before, get one now
1474 if(!pHMHandleData->hHMHandle) {
1475 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1476 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1477 if(!pHMHandleData->hHMHandle) {
1478 dprintf(("No disk inserted; aborting"));
1479 SetLastError(ERROR_NOT_READY);
1480 return FALSE;
1481 }
1482 }
1483 //NOTE: For now only allow an application to write to drive A
1484 // Might want to extend this to all removable media, but it's
1485 // too dangerous to allow win32 apps to write to the harddisk directly
1486 if(drvInfo->driveLetter != 'A') {
1487 SetLastError(ERROR_ACCESS_DENIED);
1488 return FALSE;
1489 }
1490
1491
1492 //SvL: DosWrite doesn't like reading from memory addresses returned by
1493 // DosAliasMem -> search for original memory mapped pointer and use
1494 // that one + commit pages if not already present
1495 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_READ);
1496 if(map) {
1497 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1498 DWORD nrpages = nNumberOfBytesToWrite/4096;
1499 if(offset & 0xfff)
1500 nrpages++;
1501 if(nNumberOfBytesToWrite & 0xfff)
1502 nrpages++;
1503
1504 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1505 }
1506 else lpRealBuf = (LPVOID)lpBuffer;
1507
1508 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_LOCKDRIVE,0,0,0,0,0,0);
1509
1510 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1511 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1512 }
1513// else {
1514 bRC = OSLibDosWrite(pHMHandleData->hHMHandle,
1515 (PVOID)lpRealBuf,
1516 nNumberOfBytesToWrite,
1517 lpNumberOfBytesWritten);
1518// }
1519
1520 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_UNLOCKDRIVE,0,0,0,0,0,0);
1521 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile returned %08xh\n",
1522 bRC));
1523
1524 return bRC;
1525}
1526
1527
1528/*****************************************************************************
1529 * Name : DWORD HMDeviceDiskClass::GetFileType
1530 * Purpose : determine the handle type
1531 * Parameters: PHMHANDLEDATA pHMHandleData
1532 * Variables :
1533 * Result : API returncode
1534 * Remark :
1535 * Status :
1536 *
1537 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1538 *****************************************************************************/
1539
1540DWORD HMDeviceDiskClass::GetFileType(PHMHANDLEDATA pHMHandleData)
1541{
1542 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileType %s(%08x)\n",
1543 lpHMDeviceName,
1544 pHMHandleData));
1545
1546 return FILE_TYPE_DISK;
1547}
1548//******************************************************************************
1549//******************************************************************************
Note: See TracBrowser for help on using the repository browser.