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

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

preliminary work on overlapped serial comm IO

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