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

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

overlapped io updates

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