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

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

No longer use DosError; IOCTL_DISK_GET_DRIVE_GEOMETRY must return ERROR_MEDIA_CHANGED when floppy has been changed

File size: 33.9 KB
Line 
1/* $Id: hmdisk.cpp,v 1.18 2001-10-25 13:19:05 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
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 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
107 hFile = OSLibDosCreateFile((LPSTR)lpFileName,
108 pHMHandleData->dwAccess,
109 pHMHandleData->dwShare,
110 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
111 pHMHandleData->dwCreation,
112 pHMHandleData->dwFlags,
113 hTemplate);
114 SetErrorMode(oldmode);
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
181// this helper function just calls the specified
182// ioctl function for the CDROM manager with no
183// parameter packet other than the CD01 signature
184// and no data packet.
185static BOOL ioctlCDROMSimple(PHMHANDLEDATA pHMHandleData,
186 DWORD dwCategory,
187 DWORD dwFunction,
188 LPDWORD lpBytesReturned)
189{
190 DWORD dwParameterSize = 4;
191 DWORD dwDataSize = 0;
192 DWORD ret;
193
194 if(lpBytesReturned)
195 *lpBytesReturned = 0;
196
197 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
198 dwCategory,
199 dwFunction,
200 "CD01",
201 4,
202 &dwParameterSize,
203 NULL,
204 0,
205 &dwDataSize);
206 if(ret)
207 {
208 SetLastError(error2WinError(ret));
209 return FALSE;
210 }
211 SetLastError(ERROR_SUCCESS);
212 return TRUE;
213}
214
215
216// this helper function just calls the specified
217// ioctl function for the DISK manager with the
218// specified function codes
219static BOOL ioctlDISKUnlockEject(PHMHANDLEDATA pHMHandleData,
220 DWORD dwCommand,
221 DWORD dwDiskHandle,
222 LPDWORD lpBytesReturned)
223{
224#pragma pack(1)
225 struct
226 {
227 BYTE ucCommand;
228 BYTE ucHandle;
229 } ParameterBlock;
230#pragma pack()
231
232 DWORD dwParameterSize = sizeof( ParameterBlock );
233 DWORD dwDataSize = 0;
234 DWORD ret;
235
236 ParameterBlock.ucCommand = dwCommand;
237 ParameterBlock.ucHandle = dwDiskHandle;
238
239 if(lpBytesReturned)
240 *lpBytesReturned = 0;
241
242 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
243 0x08, // IOCTL_DISK
244 0x40, // DSK_UNLOCKEJECTMEDIA
245 &ParameterBlock,
246 sizeof( ParameterBlock ),
247 &dwParameterSize,
248 NULL,
249 0,
250 &dwDataSize);
251 if(ret)
252 {
253 SetLastError(error2WinError(ret));
254 return FALSE;
255 }
256 SetLastError(ERROR_SUCCESS);
257 return TRUE;
258}
259
260
261
262BOOL HMDeviceDiskClass::DeviceIoControl(PHMHANDLEDATA pHMHandleData, DWORD dwIoControlCode,
263 LPVOID lpInBuffer, DWORD nInBufferSize,
264 LPVOID lpOutBuffer, DWORD nOutBufferSize,
265 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
266{
267#ifdef DEBUG
268 char *msg = NULL;
269
270 switch(dwIoControlCode)
271 {
272 case FSCTL_DELETE_REPARSE_POINT:
273 msg = "FSCTL_DELETE_REPARSE_POINT";
274 break;
275 case FSCTL_DISMOUNT_VOLUME:
276 msg = "FSCTL_DISMOUNT_VOLUME";
277 break;
278 case FSCTL_GET_COMPRESSION:
279 msg = "FSCTL_GET_COMPRESSION";
280 break;
281 case FSCTL_GET_REPARSE_POINT:
282 msg = "FSCTL_GET_REPARSE_POINT";
283 break;
284 case FSCTL_LOCK_VOLUME:
285 msg = "FSCTL_LOCK_VOLUME";
286 break;
287 case FSCTL_QUERY_ALLOCATED_RANGES:
288 msg = "FSCTL_QUERY_ALLOCATED_RANGES";
289 break;
290 case FSCTL_SET_COMPRESSION:
291 msg = "FSCTL_SET_COMPRESSION";
292 break;
293 case FSCTL_SET_REPARSE_POINT:
294 msg = "FSCTL_SET_REPARSE_POINT";
295 break;
296 case FSCTL_SET_SPARSE:
297 msg = "FSCTL_SET_SPARSE";
298 break;
299 case FSCTL_SET_ZERO_DATA:
300 msg = "FSCTL_SET_ZERO_DATA";
301 break;
302 case FSCTL_UNLOCK_VOLUME:
303 msg = "FSCTL_UNLOCK_VOLUME";
304 break;
305 case IOCTL_DISK_CHECK_VERIFY:
306 msg = "IOCTL_DISK_CHECK_VERIFY";
307 break;
308 case IOCTL_DISK_EJECT_MEDIA:
309 msg = "IOCTL_DISK_EJECT_MEDIA";
310 break;
311 case IOCTL_DISK_FORMAT_TRACKS:
312 msg = "IOCTL_DISK_FORMAT_TRACKS";
313 break;
314 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
315 msg = "IOCTL_DISK_GET_DRIVE_GEOMETRY";
316 break;
317 case IOCTL_DISK_GET_DRIVE_LAYOUT:
318 msg = "IOCTL_DISK_GET_DRIVE_LAYOUT";
319 break;
320 case IOCTL_DISK_GET_MEDIA_TYPES:
321 msg = "IOCTL_DISK_GET_MEDIA_TYPES";
322 break;
323 case IOCTL_DISK_GET_PARTITION_INFO:
324 msg = "IOCTL_DISK_GET_PARTITION_INFO";
325 break;
326 case IOCTL_DISK_LOAD_MEDIA:
327 msg = "IOCTL_DISK_LOAD_MEDIA";
328 break;
329 case IOCTL_DISK_MEDIA_REMOVAL:
330 msg = "IOCTL_DISK_MEDIA_REMOVAL";
331 break;
332 case IOCTL_DISK_PERFORMANCE:
333 msg = "IOCTL_DISK_PERFORMANCE";
334 break;
335 case IOCTL_DISK_REASSIGN_BLOCKS:
336 msg = "IOCTL_DISK_REASSIGN_BLOCKS";
337 break;
338 case IOCTL_DISK_SET_DRIVE_LAYOUT:
339 msg = "IOCTL_DISK_SET_DRIVE_LAYOUT";
340 break;
341 case IOCTL_DISK_SET_PARTITION_INFO:
342 msg = "IOCTL_DISK_SET_PARTITION_INFO";
343 break;
344 case IOCTL_DISK_VERIFY:
345 msg = "IOCTL_DISK_VERIFY";
346 break;
347 case IOCTL_SERIAL_LSRMST_INSERT:
348 msg = "IOCTL_SERIAL_LSRMST_INSERT";
349 break;
350 case IOCTL_STORAGE_CHECK_VERIFY:
351 msg = "IOCTL_STORAGE_CHECK_VERIFY";
352 break;
353 case IOCTL_STORAGE_EJECT_MEDIA:
354 msg = "IOCTL_STORAGE_EJECT_MEDIA";
355 break;
356 case IOCTL_STORAGE_GET_MEDIA_TYPES:
357 msg = "IOCTL_STORAGE_GET_MEDIA_TYPES";
358 break;
359 case IOCTL_STORAGE_LOAD_MEDIA:
360 msg = "IOCTL_STORAGE_LOAD_MEDIA";
361 break;
362 case IOCTL_STORAGE_MEDIA_REMOVAL:
363 msg = "IOCTL_STORAGE_MEDIA_REMOVAL";
364 break;
365 case IOCTL_SCSI_PASS_THROUGH:
366 msg = "IOCTL_SCSI_PASS_THROUGH";
367 break;
368 case IOCTL_SCSI_MINIPORT:
369 msg = "IOCTL_SCSI_MINIPORT";
370 break;
371 case IOCTL_SCSI_GET_INQUIRY_DATA:
372 msg = "IOCTL_SCSI_GET_INQUIRY_DATA";
373 break;
374 case IOCTL_SCSI_GET_CAPABILITIES:
375 msg = "IOCTL_SCSI_GET_CAPABILITIES";
376 break;
377 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
378 msg = "IOCTL_SCSI_PASS_THROUGH_DIRECT";
379 break;
380 case IOCTL_SCSI_GET_ADDRESS:
381 msg = "IOCTL_SCSI_GET_ADDRESS";
382 break;
383 case IOCTL_SCSI_RESCAN_BUS:
384 msg = "IOCTL_SCSI_RESCAN_BUS";
385 break;
386 case IOCTL_SCSI_GET_DUMP_POINTERS:
387 msg = "IOCTL_SCSI_GET_DUMP_POINTERS";
388 break;
389 case IOCTL_SCSI_FREE_DUMP_POINTERS:
390 msg = "IOCTL_SCSI_FREE_DUMP_POINTERS";
391 break;
392 case IOCTL_IDE_PASS_THROUGH:
393 msg = "IOCTL_IDE_PASS_THROUGH";
394 break;
395 case IOCTL_CDROM_UNLOAD_DRIVER:
396 msg = "IOCTL_CDROM_UNLOAD_DRIVER";
397 break;
398 case IOCTL_CDROM_READ_TOC:
399 msg = "IOCTL_CDROM_READ_TOC";
400 break;
401 case IOCTL_CDROM_GET_CONTROL:
402 msg = "IOCTL_CDROM_GET_CONTROL";
403 break;
404 case IOCTL_CDROM_PLAY_AUDIO_MSF:
405 msg = "IOCTL_CDROM_PLAY_AUDIO_MSF";
406 break;
407 case IOCTL_CDROM_SEEK_AUDIO_MSF:
408 msg = "IOCTL_CDROM_SEEK_AUDIO_MSF";
409 break;
410 case IOCTL_CDROM_STOP_AUDIO:
411 msg = "IOCTL_CDROM_STOP_AUDIO";
412 break;
413 case IOCTL_CDROM_PAUSE_AUDIO:
414 msg = "IOCTL_CDROM_PAUSE_AUDIO";
415 break;
416 case IOCTL_CDROM_RESUME_AUDIO:
417 msg = "IOCTL_CDROM_RESUME_AUDIO";
418 break;
419 case IOCTL_CDROM_GET_VOLUME:
420 msg = "IOCTL_CDROM_GET_VOLUME";
421 break;
422 case IOCTL_CDROM_SET_VOLUME:
423 msg = "IOCTL_CDROM_SET_VOLUME";
424 break;
425 case IOCTL_CDROM_READ_Q_CHANNEL:
426 msg = "IOCTL_CDROM_READ_Q_CHANNEL";
427 break;
428 case IOCTL_CDROM_GET_LAST_SESSION:
429 msg = "IOCTL_CDROM_GET_LAST_SESSION";
430 break;
431 case IOCTL_CDROM_RAW_READ:
432 msg = "IOCTL_CDROM_RAW_READ";
433 break;
434 case IOCTL_CDROM_DISK_TYPE:
435 msg = "IOCTL_CDROM_DISK_TYPE";
436 break;
437 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
438 msg = "IOCTL_CDROM_GET_DRIVE_GEOMETRY";
439 break;
440 case IOCTL_CDROM_CHECK_VERIFY:
441 msg = "IOCTL_CDROM_CHECK_VERIFY";
442 break;
443 case IOCTL_CDROM_MEDIA_REMOVAL:
444 msg = "IOCTL_CDROM_MEDIA_REMOVAL";
445 break;
446 case IOCTL_CDROM_EJECT_MEDIA:
447 msg = "IOCTL_CDROM_EJECT_MEDIA";
448 break;
449 case IOCTL_CDROM_LOAD_MEDIA:
450 msg = "IOCTL_CDROM_LOAD_MEDIA";
451 break;
452 case IOCTL_CDROM_RESERVE:
453 msg = "IOCTL_CDROM_RESERVE";
454 break;
455 case IOCTL_CDROM_RELEASE:
456 msg = "IOCTL_CDROM_RELEASE";
457 break;
458 case IOCTL_CDROM_FIND_NEW_DEVICES:
459 msg = "IOCTL_CDROM_FIND_NEW_DEVICES";
460 break;
461 }
462 if(msg) {
463 dprintf(("HMDeviceDiskClass::DeviceIoControl %s %x %d %x %d %x %x", msg, lpInBuffer, nInBufferSize,
464 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped));
465 }
466#endif
467
468 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
469 if(drvInfo == NULL) {
470 dprintf(("ERROR: DeviceIoControl: drvInfo == NULL!!!"));
471 DebugInt3();
472 SetLastError(ERROR_INVALID_HANDLE);
473 return FALSE;
474 }
475 switch(dwIoControlCode)
476 {
477 case FSCTL_DELETE_REPARSE_POINT:
478 case FSCTL_DISMOUNT_VOLUME:
479 case FSCTL_GET_COMPRESSION:
480 case FSCTL_GET_REPARSE_POINT:
481 case FSCTL_LOCK_VOLUME:
482 case FSCTL_QUERY_ALLOCATED_RANGES:
483 case FSCTL_SET_COMPRESSION:
484 case FSCTL_SET_REPARSE_POINT:
485 case FSCTL_SET_SPARSE:
486 case FSCTL_SET_ZERO_DATA:
487 case FSCTL_UNLOCK_VOLUME:
488 break;
489
490 case IOCTL_DISK_FORMAT_TRACKS:
491 case IOCTL_DISK_GET_DRIVE_LAYOUT:
492 break;
493
494 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
495 case IOCTL_DISK_GET_MEDIA_TYPES:
496 {
497 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)lpOutBuffer;
498 if(nOutBufferSize < sizeof(DISK_GEOMETRY) || !pGeom) {
499 SetLastError(ERROR_INSUFFICIENT_BUFFER);
500 return FALSE;
501 }
502 if(lpBytesReturned) {
503 *lpBytesReturned = 0;
504 }
505
506 char temp;
507 ULONG bytesread, oldmode;
508 APIRET rc;
509
510 //Applications can use this IOCTL to check if the floppy has been changed
511 //OSLibDosGetDiskGeometry won't fail when that happens so we read one
512 //byte from the disk and return ERROR_MEDIA_CHANGED if it fails with
513 //ERROR_WRONG_DISK
514 oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
515 rc = OSLibDosRead(pHMHandleData->hHMHandle, (PVOID)&temp,
516 1, &bytesread);
517 SetErrorMode(oldmode);
518 if(rc == FALSE) {
519 dprintf(("IOCTL_DISK_GET_DRIVE_GEOMETRY: DosRead failed with rc %d", GetLastError()));
520 if(GetLastError() == ERROR_WRONG_DISK) {
521 SetLastError(ERROR_MEDIA_CHANGED);
522 return FALSE;
523 }
524 }
525 else OSLibDosSetFilePtr(pHMHandleData->hHMHandle, -1, OSLIB_SETPTR_FILE_CURRENT);
526
527 if(OSLibDosGetDiskGeometry(pHMHandleData->hHMHandle, drvInfo->driveLetter, pGeom) == FALSE) {
528 return FALSE;
529 }
530 if(lpBytesReturned) {
531 *lpBytesReturned = sizeof(DISK_GEOMETRY);
532 }
533 SetLastError(ERROR_SUCCESS);
534 return TRUE;
535 }
536
537 case IOCTL_DISK_GET_PARTITION_INFO:
538 case IOCTL_DISK_LOAD_MEDIA:
539 case IOCTL_DISK_MEDIA_REMOVAL:
540 case IOCTL_DISK_PERFORMANCE:
541 case IOCTL_DISK_REASSIGN_BLOCKS:
542 case IOCTL_DISK_SET_DRIVE_LAYOUT:
543 case IOCTL_DISK_SET_PARTITION_INFO:
544 case IOCTL_DISK_VERIFY:
545 case IOCTL_SERIAL_LSRMST_INSERT:
546 break;
547
548
549 // -----------
550 // CDROM class
551 // -----------
552
553 case IOCTL_CDROM_UNLOAD_DRIVER:
554 case IOCTL_CDROM_READ_TOC:
555 case IOCTL_CDROM_GET_CONTROL:
556 break;
557
558 case IOCTL_CDROM_PLAY_AUDIO_MSF:
559 {
560 dprintf(("Play CDROM audio playback"));
561
562#pragma pack(1)
563 struct
564 {
565 DWORD ucSignature;
566 BYTE ucAddressingMode;
567 DWORD ulStartingMSF;
568 DWORD ulEndingMSF;
569 } ParameterBlock;
570#pragma pack()
571
572 PCDROM_PLAY_AUDIO_MSF pPlay = (PCDROM_PLAY_AUDIO_MSF)lpInBuffer;
573
574 // setup the parameter block
575
576 ParameterBlock.ucSignature = 0x31304443; // 'CD01'
577 ParameterBlock.ucAddressingMode = 1; // MSF format
578
579 // @@@PH unknown if this kind of MSF conversion is correct!
580 ParameterBlock.ulStartingMSF = pPlay->StartingM << 16 |
581 pPlay->StartingS << 8 |
582 pPlay->StartingF;
583 ParameterBlock.ulEndingMSF = pPlay->EndingM << 16 |
584 pPlay->EndingS << 8 |
585 pPlay->EndingF;
586
587 DWORD dwParameterSize = sizeof( ParameterBlock );
588 DWORD dwDataSize = 0;
589 DWORD ret;
590
591 if(lpBytesReturned)
592 *lpBytesReturned = 0;
593
594 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
595 0x81, // IOCTL_CDROMAUDIO
596 0x50, // CDROMAUDIO_PLAYAUDIO
597 &ParameterBlock,
598 sizeof( ParameterBlock ),
599 &dwParameterSize,
600 NULL,
601 0,
602 &dwDataSize);
603 if(ret)
604 {
605 SetLastError(error2WinError(ret));
606 return FALSE;
607 }
608 SetLastError(ERROR_SUCCESS);
609 return TRUE;
610 }
611
612 case IOCTL_CDROM_SEEK_AUDIO_MSF:
613 break;
614
615 case IOCTL_CDROM_PAUSE_AUDIO:
616 // NO BREAK CASE
617 // Note: for OS/2, pause and stop seems to be the same!
618
619 case IOCTL_CDROM_STOP_AUDIO:
620 {
621 dprintf(("Stop / pause CDROM audio playback"));
622 return ioctlCDROMSimple(pHMHandleData,
623 0x81, // IOCTL_CDROMAUDIO
624 0x51, // CDROMAUDIO_STOPAUDIO
625 lpBytesReturned);
626 }
627
628 case IOCTL_CDROM_RESUME_AUDIO:
629 {
630 dprintf(("Resume CDROM audio playback"));
631 return ioctlCDROMSimple(pHMHandleData,
632 0x81, // IOCTL_CDROMAUDIO
633 0x52, // CDROMAUDIO_RESUMEAUDIO
634 lpBytesReturned);
635 }
636
637 case IOCTL_CDROM_GET_VOLUME:
638 {
639 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpOutBuffer;
640 char volbuf[8];
641 DWORD parsize, datasize, ret;
642
643 if(nOutBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
644 SetLastError(ERROR_INSUFFICIENT_BUFFER);
645 return FALSE;
646 }
647 if(lpBytesReturned) {
648 *lpBytesReturned = 0;
649 }
650 parsize = 4;
651 datasize = 8;
652 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x60, "CD01", 4, &parsize,
653 volbuf, 8, &datasize);
654
655 if(ret) {
656 SetLastError(error2WinError(ret));
657 return FALSE;
658 }
659 if(lpBytesReturned) {
660 *lpBytesReturned = sizeof(VOLUME_CONTROL);
661 }
662 pVol->PortVolume[0] = volbuf[1];
663 pVol->PortVolume[1] = volbuf[3];
664 pVol->PortVolume[2] = volbuf[5];
665 pVol->PortVolume[3] = volbuf[7];
666 SetLastError(ERROR_SUCCESS);
667 return TRUE;
668 }
669
670 case IOCTL_CDROM_SET_VOLUME:
671 {
672 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpInBuffer;
673 char volbuf[8];
674 DWORD parsize, datasize, ret;
675
676 if(nInBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
677 SetLastError(ERROR_INSUFFICIENT_BUFFER);
678 return FALSE;
679 }
680 if(lpBytesReturned) {
681 *lpBytesReturned = 0;
682 }
683 parsize = 4;
684 datasize = 8;
685 volbuf[0] = 0;
686 volbuf[1] = pVol->PortVolume[0];
687 volbuf[2] = 1;
688 volbuf[3] = pVol->PortVolume[1];
689 volbuf[4] = 2;
690 volbuf[5] = pVol->PortVolume[2];
691 volbuf[6] = 3;
692 volbuf[7] = pVol->PortVolume[3];
693 dprintf(("Set CD volume (%d,%d)(%d,%d)", pVol->PortVolume[0], pVol->PortVolume[1], pVol->PortVolume[2], pVol->PortVolume[3]));
694 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x40, "CD01", 4, &parsize,
695 volbuf, 8, &datasize);
696
697 if(ret) {
698 SetLastError(error2WinError(ret));
699 return FALSE;
700 }
701 SetLastError(ERROR_SUCCESS);
702 return TRUE;
703 }
704 case IOCTL_CDROM_READ_Q_CHANNEL:
705 case IOCTL_CDROM_GET_LAST_SESSION:
706 case IOCTL_CDROM_RAW_READ:
707 case IOCTL_CDROM_DISK_TYPE:
708 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
709 case IOCTL_CDROM_CHECK_VERIFY:
710 case IOCTL_CDROM_MEDIA_REMOVAL:
711 break;
712
713 case IOCTL_CDROM_EJECT_MEDIA:
714 {
715 dprintf(("Eject CDROM media"));
716 return ioctlCDROMSimple(pHMHandleData,
717 0x80, // IOCTL_CDROM
718 0x44, // CDROMDISK_EJECTDISK
719 lpBytesReturned);
720 }
721
722 case IOCTL_CDROM_LOAD_MEDIA:
723 {
724 dprintf(("Loading CDROM media"));
725 return ioctlCDROMSimple(pHMHandleData,
726 0x80, // IOCTL_CDROM
727 0x45, // CDROMDISK_CLOSETRAY
728 lpBytesReturned);
729 }
730
731 case IOCTL_CDROM_RESERVE:
732 case IOCTL_CDROM_RELEASE:
733 case IOCTL_CDROM_FIND_NEW_DEVICES:
734 break;
735
736
737 // -------------
738 // STORAGE class
739 // -------------
740
741 case IOCTL_DISK_CHECK_VERIFY:
742 case IOCTL_STORAGE_CHECK_VERIFY:
743 dprintf(("IOCTL_STORAGE_CHECK_VERIFY incompletely implemented"));
744 if(lpBytesReturned) {
745 *lpBytesReturned = 0;
746 }
747 //TODO: check if disk has been inserted or removed
748 if(pHMHandleData->hHMHandle == 0) {
749 SetLastError(ERROR_NOT_READY);
750 return FALSE;
751 }
752 SetLastError(NO_ERROR);
753 return TRUE;
754
755 case IOCTL_DISK_EJECT_MEDIA:
756 case IOCTL_STORAGE_EJECT_MEDIA:
757 {
758 dprintf(("Ejecting storage media"));
759 return ioctlDISKUnlockEject(pHMHandleData,
760 0x02, // EJECT media
761 -1,
762 lpBytesReturned);
763 }
764
765 case IOCTL_STORAGE_GET_MEDIA_TYPES:
766 break;
767
768 case IOCTL_STORAGE_LOAD_MEDIA:
769 // case IOCTL_STORAGE_LOAD_MEDIA2:
770 {
771 dprintf(("Loading storage media"));
772 return ioctlDISKUnlockEject(pHMHandleData,
773 0x03, // LOAD media
774 -1,
775 lpBytesReturned);
776 }
777
778 // case IOCTL_STORAGE_EJECTION_CONTROL:
779 case IOCTL_STORAGE_MEDIA_REMOVAL:
780 break;
781
782
783 // -------------------
784 // SCSI passthru class
785 // -------------------
786
787 case IOCTL_SCSI_PASS_THROUGH:
788 case IOCTL_SCSI_MINIPORT:
789 case IOCTL_SCSI_GET_INQUIRY_DATA:
790 case IOCTL_SCSI_GET_CAPABILITIES:
791 break;
792
793 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
794 {
795 PSCSI_PASS_THROUGH_DIRECT pPacket = (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer;
796 SRB_ExecSCSICmd *psrb;
797
798 if(drvInfo->hInstAspi == NULL) {
799 SetLastError(ERROR_ACCESS_DENIED);
800 return FALSE;
801 }
802
803 if(nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT) ||
804 !pPacket || pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
805 {
806 SetLastError(ERROR_INSUFFICIENT_BUFFER);
807 return FALSE;
808 }
809 if(lpBytesReturned) {
810 *lpBytesReturned = 0;
811 }
812 psrb = (SRB_ExecSCSICmd *)alloca(sizeof(SRB_ExecSCSICmd)+pPacket->SenseInfoLength);
813 if(psrb == NULL) {
814 dprintf(("not enough memory!!"));
815 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
816 return FALSE;
817 }
818 memset(psrb, 0, sizeof(*psrb));
819 psrb->SRB_Cmd = SC_EXEC_SCSI_CMD;
820 psrb->SRB_Status = pPacket->ScsiStatus;
821 psrb->SRB_HaId = pPacket->PathId;
822 psrb->SRB_Target = pPacket->TargetId;
823 psrb->SRB_Lun = pPacket->Lun;
824 psrb->SRB_BufLen = pPacket->DataTransferLength;
825 psrb->SRB_SenseLen = pPacket->SenseInfoLength;
826 psrb->SRB_CDBLen = pPacket->CdbLength;
827 switch(pPacket->DataIn) {
828 case SCSI_IOCTL_DATA_OUT:
829 psrb->SRB_Flags = 0x2 << 3;
830 break;
831 case SCSI_IOCTL_DATA_IN:
832 psrb->SRB_Flags = 0x1 << 3;
833 break;
834 case SCSI_IOCTL_DATA_UNSPECIFIED:
835 psrb->SRB_Flags = 0x3 << 3;
836 break;
837 }
838 if(pPacket->CdbLength > 16) {
839 SetLastError(ERROR_INVALID_PARAMETER);
840 return FALSE;
841 }
842 psrb->SRB_BufPointer = (BYTE *)pPacket->DataBuffer;
843 memcpy(&psrb->CDBByte[0], &pPacket->Cdb[0], 16);
844 if(psrb->SRB_SenseLen) {
845 memcpy(&psrb->SenseArea[0], (char *)pPacket + pPacket->SenseInfoOffset, psrb->SRB_SenseLen);
846 }
847 //TODO: pPacket->TimeOutValue ignored
848 int rc = drvInfo->SendASPI32Command((LPSRB)psrb);
849 if(rc != SS_COMP) {
850 dprintf(("SendASPI32Command failed with error %d", rc));
851 if(rc == SS_ERR) {
852 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
853 }
854 else SetLastError(ERROR_GEN_FAILURE);
855 return FALSE;
856 }
857 pPacket->ScsiStatus = rc;
858 if(lpBytesReturned) {
859 *lpBytesReturned = 0;
860 }
861 pPacket->DataTransferLength = psrb->SRB_BufLen;
862 if(psrb->SRB_SenseLen) {
863 memcpy((char *)pPacket + pPacket->SenseInfoOffset, &psrb->SenseArea[0], psrb->SRB_SenseLen);
864 }
865 SetLastError(ERROR_SUCCESS);
866 return TRUE;
867 }
868 case IOCTL_SCSI_GET_ADDRESS:
869 {
870 DWORD numAdapters, rc;
871 SRB srb;
872 int i, j, k;
873
874 if(!lpOutBuffer || nOutBufferSize < 8) {
875 SetLastError(ERROR_INSUFFICIENT_BUFFER); //todo: right error?
876 return(FALSE);
877 }
878 SCSI_ADDRESS *addr = (SCSI_ADDRESS *)lpOutBuffer;
879 addr->Length = sizeof(SCSI_ADDRESS);
880 addr->PortNumber = 0;
881 addr->PathId = 0;
882 numAdapters = drvInfo->GetASPI32SupportInfo();
883 if(LOBYTE(numAdapters) == 0) goto failure;
884
885 memset(&srb, 0, sizeof(srb));
886 srb.common.SRB_Cmd = SC_HA_INQUIRY;
887 rc = drvInfo->SendASPI32Command(&srb);
888
889 char drivename[3];
890 drivename[0] = (char)drvInfo->driveLetter;
891 drivename[1] = ':';
892 drivename[2] = 0;
893
894 for(i=0;i<LOBYTE(numAdapters);i++) {
895 for(j=0;j<8;j++) {
896 for(k=0;k<16;k++) {
897 memset(&srb, 0, sizeof(srb));
898 srb.common.SRB_Cmd = SC_GET_DEV_TYPE;
899 srb.devtype.SRB_HaId = i;
900 srb.devtype.SRB_Target = j;
901 srb.devtype.SRB_Lun = k;
902 rc = drvInfo->SendASPI32Command(&srb);
903 if(rc == SS_COMP) {
904 if(srb.devtype.SRB_DeviceType == SS_DEVTYPE_CDROM &&
905 GetDriveTypeA(drivename) == DRIVE_CDROM)
906 {
907 goto done;
908 }
909 }
910 }
911 }
912 }
913done:
914 if(rc == SS_COMP) {
915 addr->TargetId = j;
916 addr->Lun = k;
917 SetLastError(ERROR_SUCCESS);
918 }
919 else SetLastError(ERROR_FILE_NOT_FOUND); //todo
920 return TRUE;
921failure:
922 SetLastError(ERROR_INVALID_PARAMETER); //todo
923 return FALSE;
924 }
925
926 case IOCTL_SCSI_RESCAN_BUS:
927 case IOCTL_SCSI_GET_DUMP_POINTERS:
928 case IOCTL_SCSI_FREE_DUMP_POINTERS:
929 case IOCTL_IDE_PASS_THROUGH:
930 break;
931
932 }
933 dprintf(("HMDeviceDiskClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
934 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
935 return FALSE;
936}
937/*****************************************************************************
938 * Name : BOOL HMDeviceDiskClass::ReadFile
939 * Purpose : read data from handle / device
940 * Parameters: PHMHANDLEDATA pHMHandleData,
941 * LPCVOID lpBuffer,
942 * DWORD nNumberOfBytesToRead,
943 * LPDWORD lpNumberOfBytesRead,
944 * LPOVERLAPPED lpOverlapped
945 * Variables :
946 * Result : Boolean
947 * Remark :
948 * Status :
949 *
950 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
951 *****************************************************************************/
952
953BOOL HMDeviceDiskClass::ReadFile(PHMHANDLEDATA pHMHandleData,
954 LPCVOID lpBuffer,
955 DWORD nNumberOfBytesToRead,
956 LPDWORD lpNumberOfBytesRead,
957 LPOVERLAPPED lpOverlapped)
958{
959 LPVOID lpRealBuf;
960 Win32MemMap *map;
961 DWORD offset, bytesread;
962 BOOL bRC;
963
964 dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
965 lpHMDeviceName,
966 pHMHandleData,
967 lpBuffer,
968 nNumberOfBytesToRead,
969 lpNumberOfBytesRead,
970 lpOverlapped));
971
972 //SvL: It's legal for this pointer to be NULL
973 if(lpNumberOfBytesRead)
974 *lpNumberOfBytesRead = 0;
975 else
976 lpNumberOfBytesRead = &bytesread;
977
978 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
979 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
980 SetLastError(ERROR_INVALID_PARAMETER);
981 return FALSE;
982 }
983 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
984 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
985 }
986
987 //SvL: DosRead doesn't like writing to memory addresses returned by
988 // DosAliasMem -> search for original memory mapped pointer and use
989 // that one + commit pages if not already present
990 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
991 if(map) {
992 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
993 DWORD nrpages = nNumberOfBytesToRead/4096;
994 if(offset & 0xfff)
995 nrpages++;
996 if(nNumberOfBytesToRead & 0xfff)
997 nrpages++;
998
999 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1000 }
1001 else lpRealBuf = (LPVOID)lpBuffer;
1002
1003 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1004 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1005 }
1006// else {
1007 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
1008 (PVOID)lpRealBuf,
1009 nNumberOfBytesToRead,
1010 lpNumberOfBytesRead);
1011// }
1012
1013 if(bRC == 0) {
1014 dprintf(("KERNEL32: HMDeviceDiskClass::ReadFile returned %08xh %x", bRC, GetLastError()));
1015 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
1016 }
1017
1018 return bRC;
1019}
1020/*****************************************************************************
1021 * Name : DWORD HMDeviceDiskClass::SetFilePointer
1022 * Purpose : set file pointer
1023 * Parameters: PHMHANDLEDATA pHMHandleData
1024 * LONG lDistanceToMove
1025 * PLONG lpDistanceToMoveHigh
1026 * DWORD dwMoveMethod
1027 * Variables :
1028 * Result : API returncode
1029 * Remark :
1030 * Status :
1031 *
1032 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1033 *****************************************************************************/
1034
1035DWORD HMDeviceDiskClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
1036 LONG lDistanceToMove,
1037 PLONG lpDistanceToMoveHigh,
1038 DWORD dwMoveMethod)
1039{
1040 DWORD ret;
1041
1042 dprintf2(("KERNEL32: HMDeviceDiskClass::SetFilePointer %s(%08xh,%08xh,%08xh,%08xh)\n",
1043 lpHMDeviceName,
1044 pHMHandleData,
1045 lDistanceToMove,
1046 lpDistanceToMoveHigh,
1047 dwMoveMethod));
1048
1049 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
1050 lDistanceToMove,
1051 (DWORD *)lpDistanceToMoveHigh,
1052 dwMoveMethod);
1053
1054 if(ret == -1) {
1055 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
1056 }
1057 return ret;
1058}
1059//******************************************************************************
1060//******************************************************************************
Note: See TracBrowser for help on using the repository browser.