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

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

PF: Implemented IOCTL_DISK_IS_WRITABLE ioctl & fixes writing to floppy (DASD mode)

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