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

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

removed inactive code

File size: 51.4 KB
Line 
1/* $Id: hmdisk.cpp,v 1.33 2001-11-29 19:58:09 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 (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 //Disable error popus. NT allows an app to open a cdrom/dvd drive without a disk inside
126 //OS/2 fails in that case with error ERROR_NOT_READY
127 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
128 hFile = OSLibDosCreateFile((LPSTR)lpFileName,
129 pHMHandleData->dwAccess,
130 pHMHandleData->dwShare,
131 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
132 pHMHandleData->dwCreation,
133 pHMHandleData->dwFlags,
134 hTemplate);
135 SetErrorMode(oldmode);
136
137 if (hFile != INVALID_HANDLE_ERROR || GetLastError() == ERROR_NOT_READY)
138 {
139 if(hFile == INVALID_HANDLE_ERROR) {
140 dprintf(("Drive not ready"));
141 SetLastError(NO_ERROR);
142 pHMHandleData->hHMHandle = 0; //handle lookup fails if this is set to -1
143 }
144 else pHMHandleData->hHMHandle = hFile;
145
146 DRIVE_INFO *drvInfo = (DRIVE_INFO *)malloc(sizeof(DRIVE_INFO));
147 if(drvInfo == NULL) {
148 DebugInt3();
149 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
150 return ERROR_OUTOFMEMORY;
151 }
152 pHMHandleData->dwUserData = (DWORD)drvInfo;
153
154 memset(drvInfo, 0, sizeof(DRIVE_INFO));
155 drvInfo->dwAccess = pHMHandleData->dwAccess;
156 drvInfo->dwAccess = pHMHandleData->dwShare;
157 drvInfo->lpSecurityAttributes = (LPSECURITY_ATTRIBUTES)lpSecurityAttributes;
158 drvInfo->dwAccess = pHMHandleData->dwCreation;
159 drvInfo->dwAccess = pHMHandleData->dwFlags;
160 drvInfo->hTemplate = hTemplate;
161
162 drvInfo->driveLetter = *lpFileName; //save drive letter
163 if(drvInfo->driveLetter >= 'a') {
164 drvInfo->driveLetter = drvInfo->driveLetter - ((int)'a' - (int)'A');
165 }
166
167 drvInfo->driveType = GetDriveTypeA(lpFileName);
168 if(drvInfo->driveType == DRIVE_CDROM)
169 {
170 drvInfo->hInstAspi = LoadLibraryA("WNASPI32.DLL");
171 if(drvInfo->hInstAspi == NULL) {
172 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
173 free(drvInfo);
174 return ERROR_INVALID_PARAMETER;
175 }
176 *(FARPROC *)&drvInfo->GetASPI32SupportInfo = GetProcAddress(drvInfo->hInstAspi, "GetASPI32SupportInfo");
177 *(FARPROC *)&drvInfo->SendASPI32Command = GetProcAddress(drvInfo->hInstAspi, "SendASPI32Command");
178
179 if(drvInfo->GetASPI32SupportInfo() == (SS_FAILED_INIT << 8)) {
180 FreeLibrary(drvInfo->hInstAspi);
181 drvInfo->hInstAspi = 0;
182 }
183
184 //get cdrom signature
185 DWORD parsize = 4;
186 DWORD datasize = 4;
187 strcpy(drvInfo->signature, "CD01");
188 OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x80, 0x61, &drvInfo->signature[0], 4, &parsize,
189 &drvInfo->signature[0], 4, &datasize);
190 }
191
192 if(hFile) {
193 OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &drvInfo->dwVolumelabel, NULL, 0);
194 }
195
196 return (NO_ERROR);
197 }
198 else {
199 dprintf(("CreateFile failed; error %d", GetLastError()));
200 return(GetLastError());
201 }
202}
203//******************************************************************************
204//******************************************************************************
205DWORD HMDeviceDiskClass::OpenDisk(PVOID pDrvInfo)
206{
207 char filename[3];
208 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pDrvInfo;
209 HFILE hFile;
210
211 filename[0] = 'A' + drvInfo->driveLetter;
212 filename[1] = ':';
213 filename[2] = 0;
214
215 //Disable error popus. NT allows an app to open a cdrom/dvd drive without a disk inside
216 //OS/2 fails in that case with error ERROR_NOT_READY
217 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
218 hFile = OSLibDosCreateFile(filename,
219 drvInfo->dwAccess,
220 drvInfo->dwShare,
221 drvInfo->lpSecurityAttributes,
222 drvInfo->dwCreation,
223 drvInfo->dwFlags,
224 drvInfo->hTemplate);
225 SetErrorMode(oldmode);
226
227 if (hFile != INVALID_HANDLE_ERROR || GetLastError() == ERROR_NOT_READY)
228 {
229 if(hFile == INVALID_HANDLE_ERROR) {
230 dprintf(("Drive not ready"));
231 return 0;
232 }
233 OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &drvInfo->dwVolumelabel, NULL, 0);
234 return hFile;
235 }
236 return 0;
237}
238//******************************************************************************
239//******************************************************************************
240BOOL HMDeviceDiskClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
241{
242 BOOL ret = TRUE;
243
244 if(pHMHandleData->hHMHandle) {
245 ret = OSLibDosClose(pHMHandleData->hHMHandle);
246 }
247 if(pHMHandleData->dwUserData) {
248 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
249 if(drvInfo->hInstAspi) FreeLibrary(drvInfo->hInstAspi);
250 free(drvInfo);
251 }
252 return ret;
253}
254//******************************************************************************
255//******************************************************************************
256
257
258// this helper function just calls the specified
259// ioctl function for the CDROM manager with no
260// parameter packet other than the CD01 signature
261// and no data packet.
262static BOOL ioctlCDROMSimple(PHMHANDLEDATA pHMHandleData,
263 DWORD dwCategory,
264 DWORD dwFunction,
265 LPDWORD lpBytesReturned, DRIVE_INFO *pdrvInfo)
266{
267 DWORD dwParameterSize = 4;
268 DWORD dwDataSize = 0;
269 DWORD ret;
270
271 if(lpBytesReturned)
272 *lpBytesReturned = 0;
273
274 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
275 dwCategory,
276 dwFunction,
277 pdrvInfo->signature,
278 4,
279 &dwParameterSize,
280 NULL,
281 0,
282 &dwDataSize);
283 return (ret == ERROR_SUCCESS);
284}
285
286
287// this helper function just calls the specified
288// ioctl function for the DISK manager with the
289// specified function codes
290static BOOL ioctlDISKUnlockEject(PHMHANDLEDATA pHMHandleData,
291 DWORD dwCommand,
292 DWORD dwDiskHandle,
293 LPDWORD lpBytesReturned)
294{
295#pragma pack(1)
296 struct
297 {
298 BYTE ucCommand;
299 BYTE ucHandle;
300 } ParameterBlock;
301#pragma pack()
302
303 DWORD dwParameterSize = sizeof( ParameterBlock );
304 DWORD dwDataSize = 0;
305 DWORD ret;
306
307 ParameterBlock.ucCommand = dwCommand;
308 ParameterBlock.ucHandle = dwDiskHandle;
309
310 if(lpBytesReturned)
311 *lpBytesReturned = 0;
312
313 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
314 0x08, // IOCTL_DISK
315 0x40, // DSK_UNLOCKEJECTMEDIA
316 &ParameterBlock,
317 sizeof( ParameterBlock ),
318 &dwParameterSize,
319 NULL,
320 0,
321 &dwDataSize);
322 return (ret == ERROR_SUCCESS);
323}
324
325
326
327BOOL HMDeviceDiskClass::DeviceIoControl(PHMHANDLEDATA pHMHandleData, DWORD dwIoControlCode,
328 LPVOID lpInBuffer, DWORD nInBufferSize,
329 LPVOID lpOutBuffer, DWORD nOutBufferSize,
330 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
331{
332#ifdef DEBUG
333 char *msg = NULL;
334
335 switch(dwIoControlCode)
336 {
337 case FSCTL_DELETE_REPARSE_POINT:
338 msg = "FSCTL_DELETE_REPARSE_POINT";
339 break;
340 case FSCTL_DISMOUNT_VOLUME:
341 msg = "FSCTL_DISMOUNT_VOLUME";
342 break;
343 case FSCTL_GET_COMPRESSION:
344 msg = "FSCTL_GET_COMPRESSION";
345 break;
346 case FSCTL_GET_REPARSE_POINT:
347 msg = "FSCTL_GET_REPARSE_POINT";
348 break;
349 case FSCTL_LOCK_VOLUME:
350 msg = "FSCTL_LOCK_VOLUME";
351 break;
352 case FSCTL_QUERY_ALLOCATED_RANGES:
353 msg = "FSCTL_QUERY_ALLOCATED_RANGES";
354 break;
355 case FSCTL_SET_COMPRESSION:
356 msg = "FSCTL_SET_COMPRESSION";
357 break;
358 case FSCTL_SET_REPARSE_POINT:
359 msg = "FSCTL_SET_REPARSE_POINT";
360 break;
361 case FSCTL_SET_SPARSE:
362 msg = "FSCTL_SET_SPARSE";
363 break;
364 case FSCTL_SET_ZERO_DATA:
365 msg = "FSCTL_SET_ZERO_DATA";
366 break;
367 case FSCTL_UNLOCK_VOLUME:
368 msg = "FSCTL_UNLOCK_VOLUME";
369 break;
370 case IOCTL_DISK_CHECK_VERIFY:
371 msg = "IOCTL_DISK_CHECK_VERIFY";
372 break;
373 case IOCTL_DISK_EJECT_MEDIA:
374 msg = "IOCTL_DISK_EJECT_MEDIA";
375 break;
376 case IOCTL_DISK_FORMAT_TRACKS:
377 msg = "IOCTL_DISK_FORMAT_TRACKS";
378 break;
379 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
380 msg = "IOCTL_DISK_GET_DRIVE_GEOMETRY";
381 break;
382 case IOCTL_DISK_GET_DRIVE_LAYOUT:
383 msg = "IOCTL_DISK_GET_DRIVE_LAYOUT";
384 break;
385 case IOCTL_DISK_GET_MEDIA_TYPES:
386 msg = "IOCTL_DISK_GET_MEDIA_TYPES";
387 break;
388 case IOCTL_DISK_GET_PARTITION_INFO:
389 msg = "IOCTL_DISK_GET_PARTITION_INFO";
390 break;
391 case IOCTL_DISK_LOAD_MEDIA:
392 msg = "IOCTL_DISK_LOAD_MEDIA";
393 break;
394 case IOCTL_DISK_MEDIA_REMOVAL:
395 msg = "IOCTL_DISK_MEDIA_REMOVAL";
396 break;
397 case IOCTL_DISK_PERFORMANCE:
398 msg = "IOCTL_DISK_PERFORMANCE";
399 break;
400 case IOCTL_DISK_REASSIGN_BLOCKS:
401 msg = "IOCTL_DISK_REASSIGN_BLOCKS";
402 break;
403 case IOCTL_DISK_SET_DRIVE_LAYOUT:
404 msg = "IOCTL_DISK_SET_DRIVE_LAYOUT";
405 break;
406 case IOCTL_DISK_SET_PARTITION_INFO:
407 msg = "IOCTL_DISK_SET_PARTITION_INFO";
408 break;
409 case IOCTL_DISK_VERIFY:
410 msg = "IOCTL_DISK_VERIFY";
411 break;
412 case IOCTL_SERIAL_LSRMST_INSERT:
413 msg = "IOCTL_SERIAL_LSRMST_INSERT";
414 break;
415 case IOCTL_STORAGE_CHECK_VERIFY:
416 msg = "IOCTL_STORAGE_CHECK_VERIFY";
417 break;
418 case IOCTL_STORAGE_EJECT_MEDIA:
419 msg = "IOCTL_STORAGE_EJECT_MEDIA";
420 break;
421 case IOCTL_STORAGE_GET_MEDIA_TYPES:
422 msg = "IOCTL_STORAGE_GET_MEDIA_TYPES";
423 break;
424 case IOCTL_STORAGE_LOAD_MEDIA:
425 msg = "IOCTL_STORAGE_LOAD_MEDIA";
426 break;
427 case IOCTL_STORAGE_MEDIA_REMOVAL:
428 msg = "IOCTL_STORAGE_MEDIA_REMOVAL";
429 break;
430 case IOCTL_SCSI_PASS_THROUGH:
431 msg = "IOCTL_SCSI_PASS_THROUGH";
432 break;
433 case IOCTL_SCSI_MINIPORT:
434 msg = "IOCTL_SCSI_MINIPORT";
435 break;
436 case IOCTL_SCSI_GET_INQUIRY_DATA:
437 msg = "IOCTL_SCSI_GET_INQUIRY_DATA";
438 break;
439 case IOCTL_SCSI_GET_CAPABILITIES:
440 msg = "IOCTL_SCSI_GET_CAPABILITIES";
441 break;
442 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
443 msg = "IOCTL_SCSI_PASS_THROUGH_DIRECT";
444 break;
445 case IOCTL_SCSI_GET_ADDRESS:
446 msg = "IOCTL_SCSI_GET_ADDRESS";
447 break;
448 case IOCTL_SCSI_RESCAN_BUS:
449 msg = "IOCTL_SCSI_RESCAN_BUS";
450 break;
451 case IOCTL_SCSI_GET_DUMP_POINTERS:
452 msg = "IOCTL_SCSI_GET_DUMP_POINTERS";
453 break;
454 case IOCTL_SCSI_FREE_DUMP_POINTERS:
455 msg = "IOCTL_SCSI_FREE_DUMP_POINTERS";
456 break;
457 case IOCTL_IDE_PASS_THROUGH:
458 msg = "IOCTL_IDE_PASS_THROUGH";
459 break;
460 case IOCTL_CDROM_UNLOAD_DRIVER:
461 msg = "IOCTL_CDROM_UNLOAD_DRIVER";
462 break;
463 case IOCTL_CDROM_READ_TOC:
464 msg = "IOCTL_CDROM_READ_TOC";
465 break;
466 case IOCTL_CDROM_GET_CONTROL:
467 msg = "IOCTL_CDROM_GET_CONTROL";
468 break;
469 case IOCTL_CDROM_PLAY_AUDIO_MSF:
470 msg = "IOCTL_CDROM_PLAY_AUDIO_MSF";
471 break;
472 case IOCTL_CDROM_SEEK_AUDIO_MSF:
473 msg = "IOCTL_CDROM_SEEK_AUDIO_MSF";
474 break;
475 case IOCTL_CDROM_STOP_AUDIO:
476 msg = "IOCTL_CDROM_STOP_AUDIO";
477 break;
478 case IOCTL_CDROM_PAUSE_AUDIO:
479 msg = "IOCTL_CDROM_PAUSE_AUDIO";
480 break;
481 case IOCTL_CDROM_RESUME_AUDIO:
482 msg = "IOCTL_CDROM_RESUME_AUDIO";
483 break;
484 case IOCTL_CDROM_GET_VOLUME:
485 msg = "IOCTL_CDROM_GET_VOLUME";
486 break;
487 case IOCTL_CDROM_SET_VOLUME:
488 msg = "IOCTL_CDROM_SET_VOLUME";
489 break;
490 case IOCTL_CDROM_READ_Q_CHANNEL:
491 msg = "IOCTL_CDROM_READ_Q_CHANNEL";
492 break;
493 case IOCTL_CDROM_GET_LAST_SESSION:
494 msg = "IOCTL_CDROM_GET_LAST_SESSION";
495 break;
496 case IOCTL_CDROM_RAW_READ:
497 msg = "IOCTL_CDROM_RAW_READ";
498 break;
499 case IOCTL_CDROM_DISK_TYPE:
500 msg = "IOCTL_CDROM_DISK_TYPE";
501 break;
502 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
503 msg = "IOCTL_CDROM_GET_DRIVE_GEOMETRY";
504 break;
505 case IOCTL_CDROM_CHECK_VERIFY:
506 msg = "IOCTL_CDROM_CHECK_VERIFY";
507 break;
508 case IOCTL_CDROM_MEDIA_REMOVAL:
509 msg = "IOCTL_CDROM_MEDIA_REMOVAL";
510 break;
511 case IOCTL_CDROM_EJECT_MEDIA:
512 msg = "IOCTL_CDROM_EJECT_MEDIA";
513 break;
514 case IOCTL_CDROM_LOAD_MEDIA:
515 msg = "IOCTL_CDROM_LOAD_MEDIA";
516 break;
517 case IOCTL_CDROM_RESERVE:
518 msg = "IOCTL_CDROM_RESERVE";
519 break;
520 case IOCTL_CDROM_RELEASE:
521 msg = "IOCTL_CDROM_RELEASE";
522 break;
523 case IOCTL_CDROM_FIND_NEW_DEVICES:
524 msg = "IOCTL_CDROM_FIND_NEW_DEVICES";
525 break;
526 }
527 if(msg) {
528 dprintf(("HMDeviceDiskClass::DeviceIoControl %s %x %d %x %d %x %x", msg, lpInBuffer, nInBufferSize,
529 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped));
530 }
531#endif
532
533 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
534 if(drvInfo == NULL) {
535 dprintf(("ERROR: DeviceIoControl: drvInfo == NULL!!!"));
536 DebugInt3();
537 SetLastError(ERROR_INVALID_HANDLE);
538 return FALSE;
539 }
540 switch(dwIoControlCode)
541 {
542 case FSCTL_DELETE_REPARSE_POINT:
543 case FSCTL_DISMOUNT_VOLUME:
544 case FSCTL_GET_COMPRESSION:
545 case FSCTL_GET_REPARSE_POINT:
546 case FSCTL_LOCK_VOLUME:
547 case FSCTL_QUERY_ALLOCATED_RANGES:
548 case FSCTL_SET_COMPRESSION:
549 case FSCTL_SET_REPARSE_POINT:
550 case FSCTL_SET_SPARSE:
551 case FSCTL_SET_ZERO_DATA:
552 case FSCTL_UNLOCK_VOLUME:
553 break;
554
555 case IOCTL_DISK_FORMAT_TRACKS:
556 case IOCTL_DISK_GET_DRIVE_LAYOUT:
557 break;
558
559 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
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_GET_MEDIA_TYPES:
987 break;
988
989 case IOCTL_STORAGE_LOAD_MEDIA:
990 // case IOCTL_STORAGE_LOAD_MEDIA2:
991 {
992 dprintf(("Loading storage media"));
993 return ioctlDISKUnlockEject(pHMHandleData,
994 0x03, // LOAD media
995 -1,
996 lpBytesReturned);
997 }
998
999 // case IOCTL_STORAGE_EJECTION_CONTROL:
1000 case IOCTL_STORAGE_MEDIA_REMOVAL:
1001 break;
1002
1003
1004 // -------------------
1005 // SCSI passthru class
1006 // -------------------
1007
1008 case IOCTL_SCSI_PASS_THROUGH:
1009 case IOCTL_SCSI_MINIPORT:
1010 case IOCTL_SCSI_GET_INQUIRY_DATA:
1011 case IOCTL_SCSI_GET_CAPABILITIES:
1012 break;
1013
1014 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
1015 {
1016 PSCSI_PASS_THROUGH_DIRECT pPacket = (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer;
1017 SRB_ExecSCSICmd *psrb;
1018
1019 if(drvInfo->hInstAspi == NULL)
1020 {
1021 SetLastError(ERROR_ACCESS_DENIED);
1022 return FALSE;
1023 }
1024
1025 if(nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT) ||
1026 !pPacket || pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
1027 {
1028 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1029 return FALSE;
1030 }
1031 if(lpBytesReturned) {
1032 *lpBytesReturned = 0;
1033 }
1034
1035 psrb = (SRB_ExecSCSICmd *)alloca(sizeof(SRB_ExecSCSICmd)+pPacket->SenseInfoLength);
1036 if(psrb == NULL) {
1037 dprintf(("not enough memory!!"));
1038 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1039 return FALSE;
1040 }
1041 memset(psrb, 0, sizeof(*psrb));
1042 psrb->SRB_Cmd = SC_EXEC_SCSI_CMD;
1043 psrb->SRB_Status = pPacket->ScsiStatus;
1044 psrb->SRB_HaId = pPacket->PathId;
1045 psrb->SRB_Target = pPacket->TargetId;
1046 psrb->SRB_Lun = pPacket->Lun;
1047 psrb->SRB_BufLen = pPacket->DataTransferLength;
1048 psrb->SRB_SenseLen = pPacket->SenseInfoLength;
1049 psrb->SRB_CDBLen = pPacket->CdbLength;
1050 switch(pPacket->DataIn) {
1051 case SCSI_IOCTL_DATA_OUT:
1052 psrb->SRB_Flags = 0x2 << 3;
1053 break;
1054 case SCSI_IOCTL_DATA_IN:
1055 psrb->SRB_Flags = 0x1 << 3;
1056 break;
1057 case SCSI_IOCTL_DATA_UNSPECIFIED:
1058 psrb->SRB_Flags = 0x3 << 3;
1059 break;
1060 }
1061 if(pPacket->CdbLength > 16) {
1062 SetLastError(ERROR_INVALID_PARAMETER);
1063 return FALSE;
1064 }
1065 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]));
1066 psrb->SRB_BufPointer = (BYTE *)pPacket->DataBuffer;
1067 memcpy(&psrb->CDBByte[0], &pPacket->Cdb[0], 16);
1068 if(psrb->SRB_SenseLen) {
1069 memcpy(&psrb->SenseArea[0], (char *)pPacket + pPacket->SenseInfoOffset, psrb->SRB_SenseLen);
1070 }
1071 //TODO: pPacket->TimeOutValue ignored
1072 int rc = drvInfo->SendASPI32Command((LPSRB)psrb);
1073 if(rc != SS_COMP) {
1074 dprintf(("SendASPI32Command failed with error %d", rc));
1075 if(rc == SS_ERR) {
1076 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
1077 }
1078 else SetLastError(ERROR_GEN_FAILURE);
1079 return FALSE;
1080 }
1081 pPacket->ScsiStatus = rc;
1082 if(lpBytesReturned) {
1083 *lpBytesReturned = 0;
1084 }
1085 pPacket->DataTransferLength = psrb->SRB_BufLen;
1086 if(psrb->SRB_SenseLen) {
1087 memcpy((char *)pPacket + pPacket->SenseInfoOffset, &psrb->SenseArea[0], psrb->SRB_SenseLen);
1088 }
1089 SetLastError(ERROR_SUCCESS);
1090 return TRUE;
1091 }
1092 case IOCTL_SCSI_GET_ADDRESS:
1093 {
1094 DWORD numAdapters, rc;
1095 SRB srb;
1096 int i, j, k;
1097
1098 if(!lpOutBuffer || nOutBufferSize < 8) {
1099 SetLastError(ERROR_INSUFFICIENT_BUFFER); //todo: right error?
1100 return(FALSE);
1101 }
1102 SCSI_ADDRESS *addr = (SCSI_ADDRESS *)lpOutBuffer;
1103 addr->Length = sizeof(SCSI_ADDRESS);
1104 addr->PortNumber = 0;
1105 addr->PathId = 0;
1106
1107 if(drvInfo->hInstAspi == NULL) {
1108 SetLastError(ERROR_ACCESS_DENIED);
1109 return FALSE;
1110 }
1111
1112 numAdapters = drvInfo->GetASPI32SupportInfo();
1113
1114 memset(&srb, 0, sizeof(srb));
1115 srb.common.SRB_Cmd = SC_HA_INQUIRY;
1116 rc = drvInfo->SendASPI32Command(&srb);
1117
1118 char drivename[3];
1119 drivename[0] = (char)drvInfo->driveLetter;
1120 drivename[1] = ':';
1121 drivename[2] = 0;
1122
1123 for(i=0;i<LOBYTE(numAdapters);i++) {
1124 for(j=0;j<8;j++) {
1125 for(k=0;k<16;k++) {
1126 memset(&srb, 0, sizeof(srb));
1127 srb.common.SRB_Cmd = SC_GET_DEV_TYPE;
1128 srb.devtype.SRB_HaId = i;
1129 srb.devtype.SRB_Target = j;
1130 srb.devtype.SRB_Lun = k;
1131 rc = drvInfo->SendASPI32Command(&srb);
1132 if(rc == SS_COMP) {
1133 if(srb.devtype.SRB_DeviceType == SS_DEVTYPE_CDROM &&
1134 GetDriveTypeA(drivename) == DRIVE_CDROM)
1135 {
1136 goto done;
1137 }
1138 }
1139 }
1140 }
1141 }
1142done:
1143 if(rc == SS_COMP) {
1144 addr->TargetId = j;
1145 addr->Lun = k;
1146 SetLastError(ERROR_SUCCESS);
1147 }
1148 else SetLastError(ERROR_FILE_NOT_FOUND); //todo
1149 return TRUE;
1150failure:
1151 SetLastError(ERROR_INVALID_PARAMETER); //todo
1152 return FALSE;
1153 }
1154
1155 case IOCTL_SCSI_RESCAN_BUS:
1156 case IOCTL_SCSI_GET_DUMP_POINTERS:
1157 case IOCTL_SCSI_FREE_DUMP_POINTERS:
1158 case IOCTL_IDE_PASS_THROUGH:
1159 break;
1160
1161 }
1162 dprintf(("HMDeviceDiskClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
1163 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1164 return FALSE;
1165}
1166/*****************************************************************************
1167 * Name : BOOL HMDeviceDiskClass::ReadFile
1168 * Purpose : read data from handle / device
1169 * Parameters: PHMHANDLEDATA pHMHandleData,
1170 * LPCVOID lpBuffer,
1171 * DWORD nNumberOfBytesToRead,
1172 * LPDWORD lpNumberOfBytesRead,
1173 * LPOVERLAPPED lpOverlapped
1174 * Variables :
1175 * Result : Boolean
1176 * Remark :
1177 * Status :
1178 *
1179 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1180 *****************************************************************************/
1181
1182BOOL HMDeviceDiskClass::ReadFile(PHMHANDLEDATA pHMHandleData,
1183 LPCVOID lpBuffer,
1184 DWORD nNumberOfBytesToRead,
1185 LPDWORD lpNumberOfBytesRead,
1186 LPOVERLAPPED lpOverlapped)
1187{
1188 LPVOID lpRealBuf;
1189 Win32MemMap *map;
1190 DWORD offset, bytesread;
1191 BOOL bRC;
1192
1193 dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
1194 lpHMDeviceName,
1195 pHMHandleData,
1196 lpBuffer,
1197 nNumberOfBytesToRead,
1198 lpNumberOfBytesRead,
1199 lpOverlapped));
1200
1201 //SvL: It's legal for this pointer to be NULL
1202 if(lpNumberOfBytesRead)
1203 *lpNumberOfBytesRead = 0;
1204 else
1205 lpNumberOfBytesRead = &bytesread;
1206
1207 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1208 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1209 SetLastError(ERROR_INVALID_PARAMETER);
1210 return FALSE;
1211 }
1212
1213 //If we didn't get an OS/2 handle for the disk before, get one now
1214 if(!pHMHandleData->hHMHandle) {
1215 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1216 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1217 if(!pHMHandleData->hHMHandle) {
1218 dprintf(("No disk inserted; aborting"));
1219 SetLastError(ERROR_NOT_READY);
1220 return -1;
1221 }
1222 }
1223
1224 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1225 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1226 }
1227
1228 //SvL: DosRead doesn't like writing to memory addresses returned by
1229 // DosAliasMem -> search for original memory mapped pointer and use
1230 // that one + commit pages if not already present
1231 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
1232 if(map) {
1233 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1234 DWORD nrpages = nNumberOfBytesToRead/4096;
1235 if(offset & 0xfff)
1236 nrpages++;
1237 if(nNumberOfBytesToRead & 0xfff)
1238 nrpages++;
1239
1240 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1241 }
1242 else lpRealBuf = (LPVOID)lpBuffer;
1243
1244 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1245 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1246 }
1247// else {
1248 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
1249 (PVOID)lpRealBuf,
1250 nNumberOfBytesToRead,
1251 lpNumberOfBytesRead);
1252// }
1253
1254 if(bRC == 0) {
1255 dprintf(("KERNEL32: HMDeviceDiskClass::ReadFile returned %08xh %x", bRC, GetLastError()));
1256 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
1257 }
1258 else dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile read %x bytes pos %x", *lpNumberOfBytesRead, SetFilePointer(pHMHandleData, 0, NULL, FILE_CURRENT)));
1259
1260 return bRC;
1261}
1262/*****************************************************************************
1263 * Name : DWORD HMDeviceDiskClass::SetFilePointer
1264 * Purpose : set file pointer
1265 * Parameters: PHMHANDLEDATA pHMHandleData
1266 * LONG lDistanceToMove
1267 * PLONG lpDistanceToMoveHigh
1268 * DWORD dwMoveMethod
1269 * Variables :
1270 * Result : API returncode
1271 * Remark :
1272 * Status :
1273 *
1274 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1275 *****************************************************************************/
1276
1277DWORD HMDeviceDiskClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
1278 LONG lDistanceToMove,
1279 PLONG lpDistanceToMoveHigh,
1280 DWORD dwMoveMethod)
1281{
1282 DWORD ret;
1283
1284 dprintf2(("KERNEL32: HMDeviceDiskClass::SetFilePointer %s(%08xh,%08xh,%08xh,%08xh)\n",
1285 lpHMDeviceName,
1286 pHMHandleData,
1287 lDistanceToMove,
1288 lpDistanceToMoveHigh,
1289 dwMoveMethod));
1290
1291 if(!pHMHandleData->hHMHandle) {
1292 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1293 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1294 if(!pHMHandleData->hHMHandle) {
1295 dprintf(("No disk inserted; aborting"));
1296 SetLastError(ERROR_NOT_READY);
1297 return -1;
1298 }
1299 }
1300
1301 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
1302 lDistanceToMove,
1303 (DWORD *)lpDistanceToMoveHigh,
1304 dwMoveMethod);
1305
1306 if(ret == -1) {
1307 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
1308 }
1309 return ret;
1310}
1311/*****************************************************************************
1312 * Name : BOOL ReadFileEx
1313 * Purpose : The ReadFileEx function reads data from a file asynchronously.
1314 * It is designed solely for asynchronous operation, unlike the
1315 * ReadFile function, which is designed for both synchronous and
1316 * asynchronous operation. ReadFileEx lets an application perform
1317 * other processing during a file read operation.
1318 * The ReadFileEx function reports its completion status asynchronously,
1319 * calling a specified completion routine when reading is completed
1320 * and the calling thread is in an alertable wait state.
1321 * Parameters: HANDLE hFile handle of file to read
1322 * LPVOID lpBuffer address of buffer
1323 * DWORD nNumberOfBytesToRead number of bytes to read
1324 * LPOVERLAPPED lpOverlapped address of offset
1325 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
1326 * Variables :
1327 * Result : TRUE / FALSE
1328 * Remark :
1329 * Status : UNTESTED STUB
1330 *
1331 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1332 *****************************************************************************/
1333BOOL HMDeviceDiskClass::ReadFileEx(PHMHANDLEDATA pHMHandleData,
1334 LPVOID lpBuffer,
1335 DWORD nNumberOfBytesToRead,
1336 LPOVERLAPPED lpOverlapped,
1337 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1338{
1339 dprintf(("ERROR: ReadFileEx(%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
1340 pHMHandleData->hHMHandle,
1341 lpBuffer,
1342 nNumberOfBytesToRead,
1343 lpOverlapped,
1344 lpCompletionRoutine));
1345 return FALSE;
1346}
1347
1348
1349/*****************************************************************************
1350 * Name : BOOL HMDeviceDiskClass::WriteFile
1351 * Purpose : write data to handle / device
1352 * Parameters: PHMHANDLEDATA pHMHandleData,
1353 * LPCVOID lpBuffer,
1354 * DWORD nNumberOfBytesToWrite,
1355 * LPDWORD lpNumberOfBytesWritten,
1356 * LPOVERLAPPED lpOverlapped
1357 * Variables :
1358 * Result : Boolean
1359 * Remark :
1360 * Status :
1361 *
1362 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1363 *****************************************************************************/
1364
1365BOOL HMDeviceDiskClass::WriteFile(PHMHANDLEDATA pHMHandleData,
1366 LPCVOID lpBuffer,
1367 DWORD nNumberOfBytesToWrite,
1368 LPDWORD lpNumberOfBytesWritten,
1369 LPOVERLAPPED lpOverlapped)
1370{
1371 LPVOID lpRealBuf;
1372 Win32MemMap *map;
1373 DWORD offset, byteswritten;
1374 BOOL bRC;
1375
1376 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
1377 lpHMDeviceName,
1378 pHMHandleData,
1379 lpBuffer,
1380 nNumberOfBytesToWrite,
1381 lpNumberOfBytesWritten,
1382 lpOverlapped));
1383
1384 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1385 if(drvInfo == NULL) {
1386 dprintf(("ERROR: DeviceIoControl: drvInfo == NULL!!!"));
1387 DebugInt3();
1388 SetLastError(ERROR_INVALID_HANDLE);
1389 return FALSE;
1390 }
1391
1392 //SvL: It's legal for this pointer to be NULL
1393 if(lpNumberOfBytesWritten)
1394 *lpNumberOfBytesWritten = 0;
1395 else
1396 lpNumberOfBytesWritten = &byteswritten;
1397
1398 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1399 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1400 SetLastError(ERROR_INVALID_PARAMETER);
1401 return FALSE;
1402 }
1403 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1404 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1405 }
1406
1407 //If we didn't get an OS/2 handle for the disk before, get one now
1408 if(!pHMHandleData->hHMHandle) {
1409 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1410 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1411 if(!pHMHandleData->hHMHandle) {
1412 dprintf(("No disk inserted; aborting"));
1413 SetLastError(ERROR_NOT_READY);
1414 return -1;
1415 }
1416 }
1417 //NOTE: For now only allow an application to write to drive A
1418 // Might want to extend this to all removable media, but it's
1419 // too dangerous to allow win32 apps to write to the harddisk directly
1420 if(drvInfo->driveLetter != 'A') {
1421 SetLastError(ERROR_ACCESS_DENIED);
1422 return -1;
1423 }
1424
1425
1426 //SvL: DosWrite doesn't like reading from memory addresses returned by
1427 // DosAliasMem -> search for original memory mapped pointer and use
1428 // that one + commit pages if not already present
1429 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_READ);
1430 if(map) {
1431 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1432 DWORD nrpages = nNumberOfBytesToWrite/4096;
1433 if(offset & 0xfff)
1434 nrpages++;
1435 if(nNumberOfBytesToWrite & 0xfff)
1436 nrpages++;
1437
1438 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1439 }
1440 else lpRealBuf = (LPVOID)lpBuffer;
1441
1442 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1443 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1444 }
1445// else {
1446 bRC = OSLibDosWrite(pHMHandleData->hHMHandle,
1447 (PVOID)lpRealBuf,
1448 nNumberOfBytesToWrite,
1449 lpNumberOfBytesWritten);
1450// }
1451
1452 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile returned %08xh\n",
1453 bRC));
1454
1455 return bRC;
1456}
1457
1458/*****************************************************************************
1459 * Name : BOOL WriteFileEx
1460 * Purpose : The WriteFileEx function writes data to a file. It is designed
1461 * solely for asynchronous operation, unlike WriteFile, which is
1462 * designed for both synchronous and asynchronous operation.
1463 * WriteFileEx reports its completion status asynchronously,
1464 * calling a specified completion routine when writing is completed
1465 * and the calling thread is in an alertable wait state.
1466 * Parameters: HANDLE hFile handle of file to write
1467 * LPVOID lpBuffer address of buffer
1468 * DWORD nNumberOfBytesToRead number of bytes to write
1469 * LPOVERLAPPED lpOverlapped address of offset
1470 * LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine address of completion routine
1471 * Variables :
1472 * Result : TRUE / FALSE
1473 * Remark :
1474 * Status : UNTESTED STUB
1475 *
1476 * Author : Patrick Haller [Mon, 1998/06/15 08:00]
1477 *****************************************************************************/
1478
1479BOOL HMDeviceDiskClass::WriteFileEx(PHMHANDLEDATA pHMHandleData,
1480 LPVOID lpBuffer,
1481 DWORD nNumberOfBytesToWrite,
1482 LPOVERLAPPED lpOverlapped,
1483 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1484{
1485 dprintf(("ERROR: WriteFileEx(%08xh,%08xh,%08xh,%08xh,%08xh) not implemented.\n",
1486 pHMHandleData->hHMHandle,
1487 lpBuffer,
1488 nNumberOfBytesToWrite,
1489 lpOverlapped,
1490 lpCompletionRoutine));
1491 return FALSE;
1492}
1493
1494/*****************************************************************************
1495 * Name : DWORD HMDeviceDiskClass::GetFileType
1496 * Purpose : determine the handle type
1497 * Parameters: PHMHANDLEDATA pHMHandleData
1498 * Variables :
1499 * Result : API returncode
1500 * Remark :
1501 * Status :
1502 *
1503 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1504 *****************************************************************************/
1505
1506DWORD HMDeviceDiskClass::GetFileType(PHMHANDLEDATA pHMHandleData)
1507{
1508 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileType %s(%08x)\n",
1509 lpHMDeviceName,
1510 pHMHandleData));
1511
1512 return FILE_TYPE_DISK;
1513}
1514//******************************************************************************
1515//******************************************************************************
Note: See TracBrowser for help on using the repository browser.