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

Last change on this file since 7492 was 7492, checked in by phaller, 24 years ago

fix issues caused by OSLibDosDevIOCtl return code change and hmdisk's FindDevice()

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