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

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

floppy change fixes

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