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

Last change on this file since 8258 was 8258, checked in by bird, 23 years ago

Corrected call to GetDriveType. (paranoia)

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