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

Last change on this file since 6982 was 6978, checked in by phaller, 24 years ago

added further IOCTL_STORAGE and IOCTL_CDROM calls

File size: 31.2 KB
Line 
1/* $Id: hmdisk.cpp,v 1.14 2001-10-10 11:01:17 phaller 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
27typedef struct
28{
29 HINSTANCE hInstAspi;
30 DWORD (WIN32API *GetASPI32SupportInfo)();
31 DWORD (CDECL *SendASPI32Command)(LPSRB lpSRB);
32 ULONG driveLetter;
33 CHAR signature[8];
34} DRIVE_INFO;
35
36HMDeviceDiskClass::HMDeviceDiskClass(LPCSTR lpDeviceName) : HMDeviceKernelObjectClass(lpDeviceName)
37{
38 HMDeviceRegisterEx("\\\\.\\PHYSICALDRIVE", this, NULL);
39}
40
41/*****************************************************************************
42 * Name : HMDeviceDiskClass::FindDevice
43 * Purpose : Checks if lpDeviceName belongs to this device class
44 * Parameters: LPCSTR lpClassDevName
45 * LPCSTR lpDeviceName
46 * int namelength
47 * Variables :
48 * Result : checks if name is for a drive of physical disk
49 * Remark :
50 * Status :
51 *
52 * Author : SvL
53 *****************************************************************************/
54BOOL HMDeviceDiskClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
55{
56 //\\.\x: -> length 6
57 //\\.\PHYSICALDRIVEn -> length 18
58 if(namelength != 6 && namelength != 18) {
59 return FALSE;
60 }
61
62 //SvL: \\.\x: -> drive x (i.e. \\.\C:)
63 // \\.\PHYSICALDRIVEn -> drive n (n>=0)
64 if((strncmp(lpDeviceName, "\\\\.\\", 4) == 0) &&
65 namelength == 6 && lpDeviceName[5] == ':')
66 {
67 return TRUE;
68 }
69 if((strncmp(lpDeviceName, "\\\\.\\PHYSICALDRIVE", 17) == 0) && namelength == 18) {
70 return TRUE;
71 }
72 return FALSE;
73}
74//******************************************************************************
75//TODO: PHYSICALDRIVEn!!
76//******************************************************************************
77DWORD HMDeviceDiskClass::CreateFile (LPCSTR lpFileName,
78 PHMHANDLEDATA pHMHandleData,
79 PVOID lpSecurityAttributes,
80 PHMHANDLEDATA pHMHandleDataTemplate)
81{
82 HFILE hFile;
83 HFILE hTemplate;
84
85 dprintf2(("KERNEL32: HMDeviceDiskClass::CreateFile %s(%s,%08x,%08x,%08x)\n",
86 lpHMDeviceName,
87 lpFileName,
88 pHMHandleData,
89 lpSecurityAttributes,
90 pHMHandleDataTemplate));
91
92 //TODO: check in NT if CREATE_ALWAYS is allowed!!
93 if(pHMHandleData->dwCreation != OPEN_EXISTING) {
94 dprintf(("Invalid creation flags %x!!", pHMHandleData->dwCreation));
95 return ERROR_INVALID_PARAMETER;
96 }
97 if(strncmp(lpFileName, // "support" for local unc names
98 "\\\\.\\",
99 4) == 0)
100 {
101 lpFileName+=4;
102 }
103
104 //Disable error popus. NT allows an app to open a cdrom/dvd drive without a disk inside
105 //OS/2 fails in that case with error ERROR_NOT_READY
106 OSLibDosDisableHardError(TRUE);
107 hFile = OSLibDosCreateFile((LPSTR)lpFileName,
108 pHMHandleData->dwAccess,
109 pHMHandleData->dwShare,
110 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
111 pHMHandleData->dwCreation,
112 pHMHandleData->dwFlags,
113 hTemplate);
114 OSLibDosDisableHardError(FALSE);
115
116 if (hFile != INVALID_HANDLE_ERROR || GetLastError() == ERROR_NOT_READY)
117 {
118 if(hFile == INVALID_HANDLE_ERROR) {
119 SetLastError(NO_ERROR);
120 pHMHandleData->hHMHandle = 0; //handle lookup fails if this is set to -1
121 }
122 else pHMHandleData->hHMHandle = hFile;
123
124 DRIVE_INFO *drvInfo = (DRIVE_INFO *)malloc(sizeof(DRIVE_INFO));
125 if(drvInfo == NULL) {
126 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
127 return ERROR_OUTOFMEMORY;
128 }
129 pHMHandleData->dwUserData = (DWORD)drvInfo;
130
131 memset(drvInfo, 0, sizeof(DRIVE_INFO));
132 drvInfo->driveLetter = *lpFileName; //save drive letter
133 if(drvInfo->driveLetter >= 'a') {
134 drvInfo->driveLetter = drvInfo->driveLetter - ((int)'a' - (int)'A');
135 }
136
137 if(GetDriveTypeA(lpFileName) == DRIVE_CDROM) {
138 drvInfo->hInstAspi = LoadLibraryA("WNASPI32.DLL");
139 if(drvInfo->hInstAspi == NULL) {
140 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
141 free(drvInfo);
142 return ERROR_INVALID_PARAMETER;
143 }
144 *(FARPROC *)&drvInfo->GetASPI32SupportInfo = GetProcAddress(drvInfo->hInstAspi, "GetASPI32SupportInfo");
145 *(FARPROC *)&drvInfo->SendASPI32Command = GetProcAddress(drvInfo->hInstAspi, "SendASPI32Command");
146
147 //get cdrom signature (TODO: why doesn't this work???)
148 DWORD parsize = 4;
149 DWORD datasize = 4;
150 strcpy(drvInfo->signature, "CD01");
151 OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x60, &drvInfo->signature[0], 4, &parsize,
152 &drvInfo->signature[0], 4, &datasize);
153 }
154 return (NO_ERROR);
155 }
156 else {
157 dprintf(("CreateFile failed; error %d", GetLastError()));
158 return(GetLastError());
159 }
160}
161//******************************************************************************
162//******************************************************************************
163BOOL HMDeviceDiskClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
164{
165 BOOL ret = TRUE;
166
167 if(pHMHandleData->hHMHandle) {
168 ret = OSLibDosClose(pHMHandleData->hHMHandle);
169 }
170 if(pHMHandleData->dwUserData) {
171 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
172 if(drvInfo->hInstAspi) FreeLibrary(drvInfo->hInstAspi);
173 free(drvInfo);
174 }
175 return ret;
176}
177//******************************************************************************
178//******************************************************************************
179
180// this helper function just calls the specified
181// ioctl function for the CDROM manager with no
182// parameter packet other than the CD01 signature
183// and no data packet.
184static BOOL ioctlCDROMSimple(PHMHANDLEDATA pHMHandleData,
185 DWORD dwCategory,
186 DWORD dwFunction,
187 LPDWORD lpBytesReturned)
188{
189 DWORD dwParameterSize = 4;
190 DWORD dwDataSize = 0;
191 DWORD ret;
192
193 if(lpBytesReturned)
194 *lpBytesReturned = 0;
195
196 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
197 dwCategory,
198 dwFunction,
199 "CD01",
200 4,
201 &dwParameterSize,
202 NULL,
203 0,
204 &dwDataSize);
205 if(ret)
206 {
207 SetLastError(error2WinError(ret));
208 return FALSE;
209 }
210 SetLastError(ERROR_SUCCESS);
211 return TRUE;
212}
213
214
215// this helper function just calls the specified
216// ioctl function for the DISK manager with the
217// specified function codes
218static BOOL ioctlDISKUnlockEject(PHMHANDLEDATA pHMHandleData,
219 DWORD dwCommand,
220 DWORD dwDiskHandle,
221 LPDWORD lpBytesReturned)
222{
223#pragma pack(1)
224 struct
225 {
226 BYTE ucCommand;
227 BYTE ucHandle;
228 } ParameterBlock;
229#pragma pack()
230
231 DWORD dwParameterSize = sizeof( ParameterBlock );
232 DWORD dwDataSize = 0;
233 DWORD ret;
234
235 ParameterBlock.ucCommand = dwCommand;
236 ParameterBlock.ucHandle = dwDiskHandle;
237
238 if(lpBytesReturned)
239 *lpBytesReturned = 0;
240
241 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
242 0x08, // IOCTL_DISK
243 0x40, // DSK_UNLOCKEJECTMEDIA
244 &ParameterBlock,
245 sizeof( ParameterBlock ),
246 &dwParameterSize,
247 NULL,
248 0,
249 &dwDataSize);
250 if(ret)
251 {
252 SetLastError(error2WinError(ret));
253 return FALSE;
254 }
255 SetLastError(ERROR_SUCCESS);
256 return TRUE;
257}
258
259
260
261BOOL HMDeviceDiskClass::DeviceIoControl(PHMHANDLEDATA pHMHandleData, DWORD dwIoControlCode,
262 LPVOID lpInBuffer, DWORD nInBufferSize,
263 LPVOID lpOutBuffer, DWORD nOutBufferSize,
264 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
265{
266#ifdef DEBUG
267 char *msg = NULL;
268
269 switch(dwIoControlCode)
270 {
271 case FSCTL_DELETE_REPARSE_POINT:
272 msg = "FSCTL_DELETE_REPARSE_POINT";
273 break;
274 case FSCTL_DISMOUNT_VOLUME:
275 msg = "FSCTL_DISMOUNT_VOLUME";
276 break;
277 case FSCTL_GET_COMPRESSION:
278 msg = "FSCTL_GET_COMPRESSION";
279 break;
280 case FSCTL_GET_REPARSE_POINT:
281 msg = "FSCTL_GET_REPARSE_POINT";
282 break;
283 case FSCTL_LOCK_VOLUME:
284 msg = "FSCTL_LOCK_VOLUME";
285 break;
286 case FSCTL_QUERY_ALLOCATED_RANGES:
287 msg = "FSCTL_QUERY_ALLOCATED_RANGES";
288 break;
289 case FSCTL_SET_COMPRESSION:
290 msg = "FSCTL_SET_COMPRESSION";
291 break;
292 case FSCTL_SET_REPARSE_POINT:
293 msg = "FSCTL_SET_REPARSE_POINT";
294 break;
295 case FSCTL_SET_SPARSE:
296 msg = "FSCTL_SET_SPARSE";
297 break;
298 case FSCTL_SET_ZERO_DATA:
299 msg = "FSCTL_SET_ZERO_DATA";
300 break;
301 case FSCTL_UNLOCK_VOLUME:
302 msg = "FSCTL_UNLOCK_VOLUME";
303 break;
304 case IOCTL_DISK_CHECK_VERIFY:
305 msg = "IOCTL_DISK_CHECK_VERIFY";
306 break;
307 case IOCTL_DISK_EJECT_MEDIA:
308 msg = "IOCTL_DISK_EJECT_MEDIA";
309 break;
310 case IOCTL_DISK_FORMAT_TRACKS:
311 msg = "IOCTL_DISK_FORMAT_TRACKS";
312 break;
313 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
314 msg = "IOCTL_DISK_GET_DRIVE_GEOMETRY";
315 break;
316 case IOCTL_DISK_GET_DRIVE_LAYOUT:
317 msg = "IOCTL_DISK_GET_DRIVE_LAYOUT";
318 break;
319 case IOCTL_DISK_GET_MEDIA_TYPES:
320 msg = "IOCTL_DISK_GET_MEDIA_TYPES";
321 break;
322 case IOCTL_DISK_GET_PARTITION_INFO:
323 msg = "IOCTL_DISK_GET_PARTITION_INFO";
324 break;
325 case IOCTL_DISK_LOAD_MEDIA:
326 msg = "IOCTL_DISK_LOAD_MEDIA";
327 break;
328 case IOCTL_DISK_MEDIA_REMOVAL:
329 msg = "IOCTL_DISK_MEDIA_REMOVAL";
330 break;
331 case IOCTL_DISK_PERFORMANCE:
332 msg = "IOCTL_DISK_PERFORMANCE";
333 break;
334 case IOCTL_DISK_REASSIGN_BLOCKS:
335 msg = "IOCTL_DISK_REASSIGN_BLOCKS";
336 break;
337 case IOCTL_DISK_SET_DRIVE_LAYOUT:
338 msg = "IOCTL_DISK_SET_DRIVE_LAYOUT";
339 break;
340 case IOCTL_DISK_SET_PARTITION_INFO:
341 msg = "IOCTL_DISK_SET_PARTITION_INFO";
342 break;
343 case IOCTL_DISK_VERIFY:
344 msg = "IOCTL_DISK_VERIFY";
345 break;
346 case IOCTL_SERIAL_LSRMST_INSERT:
347 msg = "IOCTL_SERIAL_LSRMST_INSERT";
348 break;
349 case IOCTL_STORAGE_CHECK_VERIFY:
350 msg = "IOCTL_STORAGE_CHECK_VERIFY";
351 break;
352 case IOCTL_STORAGE_EJECT_MEDIA:
353 msg = "IOCTL_STORAGE_EJECT_MEDIA";
354 break;
355 case IOCTL_STORAGE_GET_MEDIA_TYPES:
356 msg = "IOCTL_STORAGE_GET_MEDIA_TYPES";
357 break;
358 case IOCTL_STORAGE_LOAD_MEDIA:
359 msg = "IOCTL_STORAGE_LOAD_MEDIA";
360 break;
361 case IOCTL_STORAGE_MEDIA_REMOVAL:
362 msg = "IOCTL_STORAGE_MEDIA_REMOVAL";
363 break;
364 case IOCTL_SCSI_PASS_THROUGH:
365 msg = "IOCTL_SCSI_PASS_THROUGH";
366 break;
367 case IOCTL_SCSI_MINIPORT:
368 msg = "IOCTL_SCSI_MINIPORT";
369 break;
370 case IOCTL_SCSI_GET_INQUIRY_DATA:
371 msg = "IOCTL_SCSI_GET_INQUIRY_DATA";
372 break;
373 case IOCTL_SCSI_GET_CAPABILITIES:
374 msg = "IOCTL_SCSI_GET_CAPABILITIES";
375 break;
376 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
377 msg = "IOCTL_SCSI_PASS_THROUGH_DIRECT";
378 break;
379 case IOCTL_SCSI_GET_ADDRESS:
380 msg = "IOCTL_SCSI_GET_ADDRESS";
381 break;
382 case IOCTL_SCSI_RESCAN_BUS:
383 msg = "IOCTL_SCSI_RESCAN_BUS";
384 break;
385 case IOCTL_SCSI_GET_DUMP_POINTERS:
386 msg = "IOCTL_SCSI_GET_DUMP_POINTERS";
387 break;
388 case IOCTL_SCSI_FREE_DUMP_POINTERS:
389 msg = "IOCTL_SCSI_FREE_DUMP_POINTERS";
390 break;
391 case IOCTL_IDE_PASS_THROUGH:
392 msg = "IOCTL_IDE_PASS_THROUGH";
393 break;
394 case IOCTL_CDROM_UNLOAD_DRIVER:
395 msg = "IOCTL_CDROM_UNLOAD_DRIVER";
396 break;
397 case IOCTL_CDROM_READ_TOC:
398 msg = "IOCTL_CDROM_READ_TOC";
399 break;
400 case IOCTL_CDROM_GET_CONTROL:
401 msg = "IOCTL_CDROM_GET_CONTROL";
402 break;
403 case IOCTL_CDROM_PLAY_AUDIO_MSF:
404 msg = "IOCTL_CDROM_PLAY_AUDIO_MSF";
405 break;
406 case IOCTL_CDROM_SEEK_AUDIO_MSF:
407 msg = "IOCTL_CDROM_SEEK_AUDIO_MSF";
408 break;
409 case IOCTL_CDROM_STOP_AUDIO:
410 msg = "IOCTL_CDROM_STOP_AUDIO";
411 break;
412 case IOCTL_CDROM_PAUSE_AUDIO:
413 msg = "IOCTL_CDROM_PAUSE_AUDIO";
414 break;
415 case IOCTL_CDROM_RESUME_AUDIO:
416 msg = "IOCTL_CDROM_RESUME_AUDIO";
417 break;
418 case IOCTL_CDROM_GET_VOLUME:
419 msg = "IOCTL_CDROM_GET_VOLUME";
420 break;
421 case IOCTL_CDROM_SET_VOLUME:
422 msg = "IOCTL_CDROM_SET_VOLUME";
423 break;
424 case IOCTL_CDROM_READ_Q_CHANNEL:
425 msg = "IOCTL_CDROM_READ_Q_CHANNEL";
426 break;
427 case IOCTL_CDROM_GET_LAST_SESSION:
428 msg = "IOCTL_CDROM_GET_LAST_SESSION";
429 break;
430 case IOCTL_CDROM_RAW_READ:
431 msg = "IOCTL_CDROM_RAW_READ";
432 break;
433 case IOCTL_CDROM_DISK_TYPE:
434 msg = "IOCTL_CDROM_DISK_TYPE";
435 break;
436 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
437 msg = "IOCTL_CDROM_GET_DRIVE_GEOMETRY";
438 break;
439 case IOCTL_CDROM_CHECK_VERIFY:
440 msg = "IOCTL_CDROM_CHECK_VERIFY";
441 break;
442 case IOCTL_CDROM_MEDIA_REMOVAL:
443 msg = "IOCTL_CDROM_MEDIA_REMOVAL";
444 break;
445 case IOCTL_CDROM_EJECT_MEDIA:
446 msg = "IOCTL_CDROM_EJECT_MEDIA";
447 break;
448 case IOCTL_CDROM_LOAD_MEDIA:
449 msg = "IOCTL_CDROM_LOAD_MEDIA";
450 break;
451 case IOCTL_CDROM_RESERVE:
452 msg = "IOCTL_CDROM_RESERVE";
453 break;
454 case IOCTL_CDROM_RELEASE:
455 msg = "IOCTL_CDROM_RELEASE";
456 break;
457 case IOCTL_CDROM_FIND_NEW_DEVICES:
458 msg = "IOCTL_CDROM_FIND_NEW_DEVICES";
459 break;
460 }
461 if(msg) {
462 dprintf(("HMDeviceDiskClass::DeviceIoControl %s %x %d %x %d %x %x", msg, lpInBuffer, nInBufferSize,
463 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped));
464 }
465#endif
466
467 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
468 if(drvInfo == NULL) {
469 dprintf(("ERROR: DeviceIoControl: drvInfo == NULL!!!"));
470 DebugInt3();
471 SetLastError(ERROR_INVALID_HANDLE);
472 return FALSE;
473 }
474 switch(dwIoControlCode)
475 {
476 case FSCTL_DELETE_REPARSE_POINT:
477 case FSCTL_DISMOUNT_VOLUME:
478 case FSCTL_GET_COMPRESSION:
479 case FSCTL_GET_REPARSE_POINT:
480 case FSCTL_LOCK_VOLUME:
481 case FSCTL_QUERY_ALLOCATED_RANGES:
482 case FSCTL_SET_COMPRESSION:
483 case FSCTL_SET_REPARSE_POINT:
484 case FSCTL_SET_SPARSE:
485 case FSCTL_SET_ZERO_DATA:
486 case FSCTL_UNLOCK_VOLUME:
487 break;
488
489 case IOCTL_DISK_CHECK_VERIFY:
490 case IOCTL_DISK_EJECT_MEDIA:
491 case IOCTL_DISK_FORMAT_TRACKS:
492 case IOCTL_DISK_GET_DRIVE_LAYOUT:
493 break;
494
495 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
496 case IOCTL_DISK_GET_MEDIA_TYPES:
497 {
498 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)lpOutBuffer;
499 if(nOutBufferSize < sizeof(DISK_GEOMETRY) || !pGeom) {
500 SetLastError(ERROR_INSUFFICIENT_BUFFER);
501 return FALSE;
502 }
503 if(lpBytesReturned) {
504 *lpBytesReturned = 0;
505 }
506 if(OSLibDosGetDiskGeometry(pHMHandleData->hHMHandle, drvInfo->driveLetter, pGeom) == FALSE) {
507 return FALSE;
508 }
509 if(lpBytesReturned) {
510 *lpBytesReturned = sizeof(DISK_GEOMETRY);
511 }
512 SetLastError(ERROR_SUCCESS);
513 return TRUE;
514 }
515
516 case IOCTL_DISK_GET_PARTITION_INFO:
517 case IOCTL_DISK_LOAD_MEDIA:
518 case IOCTL_DISK_MEDIA_REMOVAL:
519 case IOCTL_DISK_PERFORMANCE:
520 case IOCTL_DISK_REASSIGN_BLOCKS:
521 case IOCTL_DISK_SET_DRIVE_LAYOUT:
522 case IOCTL_DISK_SET_PARTITION_INFO:
523 case IOCTL_DISK_VERIFY:
524 case IOCTL_SERIAL_LSRMST_INSERT:
525 break;
526
527
528 // -----------
529 // CDROM class
530 // -----------
531
532 case IOCTL_CDROM_UNLOAD_DRIVER:
533 case IOCTL_CDROM_READ_TOC:
534 case IOCTL_CDROM_GET_CONTROL:
535 case IOCTL_CDROM_PLAY_AUDIO_MSF:
536 case IOCTL_CDROM_SEEK_AUDIO_MSF:
537 break;
538
539 case IOCTL_CDROM_PAUSE_AUDIO:
540 // NO BREAK CASE
541 // Note: for OS/2, pause and stop seems to be the same!
542
543 case IOCTL_CDROM_STOP_AUDIO:
544 {
545 dprintf(("Stop / pause CDROM audio playback"));
546 return ioctlCDROMSimple(pHMHandleData,
547 0x81, // IOCTL_CDROMAUDIO
548 0x51, // CDROMAUDIO_STOPAUDIO
549 lpBytesReturned);
550 }
551
552 case IOCTL_CDROM_RESUME_AUDIO:
553 {
554 dprintf(("Resume CDROM audio playback"));
555 return ioctlCDROMSimple(pHMHandleData,
556 0x81, // IOCTL_CDROMAUDIO
557 0x52, // CDROMAUDIO_RESUMEAUDIO
558 lpBytesReturned);
559 }
560
561 case IOCTL_CDROM_GET_VOLUME:
562 {
563 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpOutBuffer;
564 char volbuf[8];
565 DWORD parsize, datasize, ret;
566
567 if(nOutBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
568 SetLastError(ERROR_INSUFFICIENT_BUFFER);
569 return FALSE;
570 }
571 if(lpBytesReturned) {
572 *lpBytesReturned = 0;
573 }
574 parsize = 4;
575 datasize = 8;
576 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x60, "CD01", 4, &parsize,
577 volbuf, 8, &datasize);
578
579 if(ret) {
580 SetLastError(error2WinError(ret));
581 return FALSE;
582 }
583 if(lpBytesReturned) {
584 *lpBytesReturned = sizeof(VOLUME_CONTROL);
585 }
586 pVol->PortVolume[0] = volbuf[1];
587 pVol->PortVolume[1] = volbuf[3];
588 pVol->PortVolume[2] = volbuf[5];
589 pVol->PortVolume[3] = volbuf[7];
590 SetLastError(ERROR_SUCCESS);
591 return TRUE;
592 }
593
594 case IOCTL_CDROM_SET_VOLUME:
595 {
596 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpInBuffer;
597 char volbuf[8];
598 DWORD parsize, datasize, ret;
599
600 if(nInBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
601 SetLastError(ERROR_INSUFFICIENT_BUFFER);
602 return FALSE;
603 }
604 if(lpBytesReturned) {
605 *lpBytesReturned = 0;
606 }
607 parsize = 4;
608 datasize = 8;
609 volbuf[0] = 0;
610 volbuf[1] = pVol->PortVolume[0];
611 volbuf[2] = 1;
612 volbuf[3] = pVol->PortVolume[1];
613 volbuf[4] = 2;
614 volbuf[5] = pVol->PortVolume[2];
615 volbuf[6] = 3;
616 volbuf[7] = pVol->PortVolume[3];
617 dprintf(("Set CD volume (%d,%d)(%d,%d)", pVol->PortVolume[0], pVol->PortVolume[1], pVol->PortVolume[2], pVol->PortVolume[3]));
618 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x40, "CD01", 4, &parsize,
619 volbuf, 8, &datasize);
620
621 if(ret) {
622 SetLastError(error2WinError(ret));
623 return FALSE;
624 }
625 SetLastError(ERROR_SUCCESS);
626 return TRUE;
627 }
628 case IOCTL_CDROM_READ_Q_CHANNEL:
629 case IOCTL_CDROM_GET_LAST_SESSION:
630 case IOCTL_CDROM_RAW_READ:
631 case IOCTL_CDROM_DISK_TYPE:
632 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
633 case IOCTL_CDROM_CHECK_VERIFY:
634 case IOCTL_CDROM_MEDIA_REMOVAL:
635 break;
636
637 case IOCTL_CDROM_EJECT_MEDIA:
638 {
639 dprintf(("Eject CDROM media"));
640 return ioctlCDROMSimple(pHMHandleData,
641 0x80, // IOCTL_CDROM
642 0x44, // CDROMDISK_EJECTDISK
643 lpBytesReturned);
644 }
645
646 case IOCTL_CDROM_LOAD_MEDIA:
647 {
648 dprintf(("Loading CDROM media"));
649 return ioctlCDROMSimple(pHMHandleData,
650 0x80, // IOCTL_CDROM
651 0x45, // CDROMDISK_CLOSETRAY
652 lpBytesReturned);
653 }
654
655 case IOCTL_CDROM_RESERVE:
656 case IOCTL_CDROM_RELEASE:
657 case IOCTL_CDROM_FIND_NEW_DEVICES:
658 break;
659
660
661 // -------------
662 // STORAGE class
663 // -------------
664
665 case IOCTL_STORAGE_CHECK_VERIFY:
666 if(lpBytesReturned) {
667 *lpBytesReturned = 0;
668 }
669 //TODO: check if disk has been inserted or removed
670 if(pHMHandleData->hHMHandle == 0) {
671 SetLastError(ERROR_NOT_READY);
672 return FALSE;
673 }
674 SetLastError(NO_ERROR);
675 return TRUE;
676
677 case IOCTL_STORAGE_EJECT_MEDIA:
678 {
679 dprintf(("Ejecting storage media"));
680 return ioctlDISKUnlockEject(pHMHandleData,
681 0x02, // EJECT media
682 -1,
683 lpBytesReturned);
684 }
685
686 case IOCTL_STORAGE_GET_MEDIA_TYPES:
687 break;
688
689 case IOCTL_STORAGE_LOAD_MEDIA:
690 // case IOCTL_STORAGE_LOAD_MEDIA2:
691 {
692 dprintf(("Loading storage media"));
693 return ioctlDISKUnlockEject(pHMHandleData,
694 0x03, // LOAD media
695 -1,
696 lpBytesReturned);
697 }
698
699 // case IOCTL_STORAGE_EJECTION_CONTROL:
700 case IOCTL_STORAGE_MEDIA_REMOVAL:
701 break;
702
703
704 // -------------------
705 // SCSI passthru class
706 // -------------------
707
708 case IOCTL_SCSI_PASS_THROUGH:
709 case IOCTL_SCSI_MINIPORT:
710 case IOCTL_SCSI_GET_INQUIRY_DATA:
711 case IOCTL_SCSI_GET_CAPABILITIES:
712 break;
713
714 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
715 {
716 PSCSI_PASS_THROUGH_DIRECT pPacket = (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer;
717 SRB_ExecSCSICmd *psrb;
718
719 if(drvInfo->hInstAspi == NULL) {
720 SetLastError(ERROR_ACCESS_DENIED);
721 return FALSE;
722 }
723
724 if(nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT) ||
725 !pPacket || pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
726 {
727 SetLastError(ERROR_INSUFFICIENT_BUFFER);
728 return FALSE;
729 }
730 if(lpBytesReturned) {
731 *lpBytesReturned = 0;
732 }
733 psrb = (SRB_ExecSCSICmd *)alloca(sizeof(SRB_ExecSCSICmd)+pPacket->SenseInfoLength);
734 if(psrb == NULL) {
735 dprintf(("not enough memory!!"));
736 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
737 return FALSE;
738 }
739 memset(psrb, 0, sizeof(*psrb));
740 psrb->SRB_Cmd = SC_EXEC_SCSI_CMD;
741 psrb->SRB_Status = pPacket->ScsiStatus;
742 psrb->SRB_HaId = pPacket->PathId;
743 psrb->SRB_Target = pPacket->TargetId;
744 psrb->SRB_Lun = pPacket->Lun;
745 psrb->SRB_BufLen = pPacket->DataTransferLength;
746 psrb->SRB_SenseLen = pPacket->SenseInfoLength;
747 psrb->SRB_CDBLen = pPacket->CdbLength;
748 switch(pPacket->DataIn) {
749 case SCSI_IOCTL_DATA_OUT:
750 psrb->SRB_Flags = 0x2 << 3;
751 break;
752 case SCSI_IOCTL_DATA_IN:
753 psrb->SRB_Flags = 0x1 << 3;
754 break;
755 case SCSI_IOCTL_DATA_UNSPECIFIED:
756 psrb->SRB_Flags = 0x3 << 3;
757 break;
758 }
759 if(pPacket->CdbLength > 16) {
760 SetLastError(ERROR_INVALID_PARAMETER);
761 return FALSE;
762 }
763 psrb->SRB_BufPointer = (BYTE *)pPacket->DataBuffer;
764 memcpy(&psrb->CDBByte[0], &pPacket->Cdb[0], 16);
765 if(psrb->SRB_SenseLen) {
766 memcpy(&psrb->SenseArea[0], (char *)pPacket + pPacket->SenseInfoOffset, psrb->SRB_SenseLen);
767 }
768 //TODO: pPacket->TimeOutValue ignored
769 int rc = drvInfo->SendASPI32Command((LPSRB)psrb);
770 if(rc != SS_COMP) {
771 dprintf(("SendASPI32Command failed with error %d", rc));
772 if(rc == SS_ERR) {
773 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
774 }
775 else SetLastError(ERROR_GEN_FAILURE);
776 return FALSE;
777 }
778 pPacket->ScsiStatus = rc;
779 if(lpBytesReturned) {
780 *lpBytesReturned = 0;
781 }
782 pPacket->DataTransferLength = psrb->SRB_BufLen;
783 if(psrb->SRB_SenseLen) {
784 memcpy((char *)pPacket + pPacket->SenseInfoOffset, &psrb->SenseArea[0], psrb->SRB_SenseLen);
785 }
786 SetLastError(ERROR_SUCCESS);
787 return TRUE;
788 }
789 case IOCTL_SCSI_GET_ADDRESS:
790 {
791 DWORD numAdapters, rc;
792 SRB srb;
793 int i, j, k;
794
795 if(!lpOutBuffer || nOutBufferSize < 8) {
796 SetLastError(ERROR_INSUFFICIENT_BUFFER); //todo: right error?
797 return(FALSE);
798 }
799 SCSI_ADDRESS *addr = (SCSI_ADDRESS *)lpOutBuffer;
800 addr->Length = sizeof(SCSI_ADDRESS);
801 addr->PortNumber = 0;
802 addr->PathId = 0;
803 numAdapters = drvInfo->GetASPI32SupportInfo();
804 if(LOBYTE(numAdapters) == 0) goto failure;
805
806 memset(&srb, 0, sizeof(srb));
807 srb.common.SRB_Cmd = SC_HA_INQUIRY;
808 rc = drvInfo->SendASPI32Command(&srb);
809
810 char drivename[3];
811 drivename[0] = (char)drvInfo->driveLetter;
812 drivename[1] = ':';
813 drivename[2] = 0;
814
815 for(i=0;i<LOBYTE(numAdapters);i++) {
816 for(j=0;j<8;j++) {
817 for(k=0;k<16;k++) {
818 memset(&srb, 0, sizeof(srb));
819 srb.common.SRB_Cmd = SC_GET_DEV_TYPE;
820 srb.devtype.SRB_HaId = i;
821 srb.devtype.SRB_Target = j;
822 srb.devtype.SRB_Lun = k;
823 rc = drvInfo->SendASPI32Command(&srb);
824 if(rc == SS_COMP) {
825 if(srb.devtype.SRB_DeviceType == SS_DEVTYPE_CDROM &&
826 GetDriveTypeA(drivename) == DRIVE_CDROM)
827 {
828 goto done;
829 }
830 }
831 }
832 }
833 }
834done:
835 if(rc == SS_COMP) {
836 addr->TargetId = j;
837 addr->Lun = k;
838 SetLastError(ERROR_SUCCESS);
839 }
840 else SetLastError(ERROR_FILE_NOT_FOUND); //todo
841 return TRUE;
842failure:
843 SetLastError(ERROR_INVALID_PARAMETER); //todo
844 return FALSE;
845 }
846
847 case IOCTL_SCSI_RESCAN_BUS:
848 case IOCTL_SCSI_GET_DUMP_POINTERS:
849 case IOCTL_SCSI_FREE_DUMP_POINTERS:
850 case IOCTL_IDE_PASS_THROUGH:
851 break;
852
853 }
854 dprintf(("HMDeviceDiskClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
855 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
856 return FALSE;
857}
858/*****************************************************************************
859 * Name : BOOL HMDeviceDiskClass::ReadFile
860 * Purpose : read data from handle / device
861 * Parameters: PHMHANDLEDATA pHMHandleData,
862 * LPCVOID lpBuffer,
863 * DWORD nNumberOfBytesToRead,
864 * LPDWORD lpNumberOfBytesRead,
865 * LPOVERLAPPED lpOverlapped
866 * Variables :
867 * Result : Boolean
868 * Remark :
869 * Status :
870 *
871 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
872 *****************************************************************************/
873
874BOOL HMDeviceDiskClass::ReadFile(PHMHANDLEDATA pHMHandleData,
875 LPCVOID lpBuffer,
876 DWORD nNumberOfBytesToRead,
877 LPDWORD lpNumberOfBytesRead,
878 LPOVERLAPPED lpOverlapped)
879{
880 LPVOID lpRealBuf;
881 Win32MemMap *map;
882 DWORD offset, bytesread;
883 BOOL bRC;
884
885 dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
886 lpHMDeviceName,
887 pHMHandleData,
888 lpBuffer,
889 nNumberOfBytesToRead,
890 lpNumberOfBytesRead,
891 lpOverlapped));
892
893 //SvL: It's legal for this pointer to be NULL
894 if(lpNumberOfBytesRead)
895 *lpNumberOfBytesRead = 0;
896 else
897 lpNumberOfBytesRead = &bytesread;
898
899 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
900 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
901 SetLastError(ERROR_INVALID_PARAMETER);
902 return FALSE;
903 }
904 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
905 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
906 }
907
908 //SvL: DosRead doesn't like writing to memory addresses returned by
909 // DosAliasMem -> search for original memory mapped pointer and use
910 // that one + commit pages if not already present
911 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
912 if(map) {
913 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
914 DWORD nrpages = nNumberOfBytesToRead/4096;
915 if(offset & 0xfff)
916 nrpages++;
917 if(nNumberOfBytesToRead & 0xfff)
918 nrpages++;
919
920 map->commitPage(offset & ~0xfff, TRUE, nrpages);
921 }
922 else lpRealBuf = (LPVOID)lpBuffer;
923
924 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
925 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
926 }
927// else {
928 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
929 (PVOID)lpRealBuf,
930 nNumberOfBytesToRead,
931 lpNumberOfBytesRead);
932// }
933
934 if(bRC == 0) {
935 dprintf(("KERNEL32: HMDeviceDiskClass::ReadFile returned %08xh %x", bRC, GetLastError()));
936 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
937 }
938
939 return bRC;
940}
941/*****************************************************************************
942 * Name : DWORD HMDeviceDiskClass::SetFilePointer
943 * Purpose : set file pointer
944 * Parameters: PHMHANDLEDATA pHMHandleData
945 * LONG lDistanceToMove
946 * PLONG lpDistanceToMoveHigh
947 * DWORD dwMoveMethod
948 * Variables :
949 * Result : API returncode
950 * Remark :
951 * Status :
952 *
953 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
954 *****************************************************************************/
955
956DWORD HMDeviceDiskClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
957 LONG lDistanceToMove,
958 PLONG lpDistanceToMoveHigh,
959 DWORD dwMoveMethod)
960{
961 DWORD ret;
962
963 dprintf2(("KERNEL32: HMDeviceDiskClass::SetFilePointer %s(%08xh,%08xh,%08xh,%08xh)\n",
964 lpHMDeviceName,
965 pHMHandleData,
966 lDistanceToMove,
967 lpDistanceToMoveHigh,
968 dwMoveMethod));
969
970 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
971 lDistanceToMove,
972 (DWORD *)lpDistanceToMoveHigh,
973 dwMoveMethod);
974
975 if(ret == -1) {
976 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
977 }
978 return ret;
979}
980//******************************************************************************
981//******************************************************************************
Note: See TracBrowser for help on using the repository browser.