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

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

IOCTL_STORAGE_GET_MEDIA_TYPES is identical to IOCTL_DISK_GET_MEDIA_TYPES

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