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

Last change on this file since 8401 was 8401, checked in by sandervl, 23 years ago

hard disk access updates & fixes

File size: 62.8 KB
Line 
1/* $Id: hmdisk.cpp,v 1.44 2002-05-10 14:55:11 sandervl Exp $ */
2
3/*
4 * Win32 Disk API functions for OS/2
5 *
6 * Copyright 2000-2002 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#include <stdio.h>
15#include <versionos2.h>
16
17#include <misc.h>
18#include "hmdisk.h"
19#include "mmap.h"
20#include <win\winioctl.h>
21#include <win\ntddscsi.h>
22#include <win\wnaspi32.h>
23#include <win\aspi.h>
24#include "oslibdos.h"
25#include "osliblvm.h"
26#include "asmutil.h"
27
28#define DBG_LOCALLOG DBG_hmdisk
29#include "dbglocal.h"
30
31#define BIT_0 (1)
32#define BIT_1 (2)
33#define BIT_2 (4)
34#define BIT_11 (1<<11)
35
36typedef struct
37{
38 HINSTANCE hInstAspi;
39 DWORD (WIN32API *GetASPI32SupportInfo)();
40 DWORD (CDECL *SendASPI32Command)(LPSRB lpSRB);
41 ULONG driveLetter;
42 ULONG driveType;
43 ULONG dwVolumelabel;
44 CHAR signature[8];
45 DWORD dwAccess;
46 DWORD dwShare;
47 DWORD dwCreation;
48 DWORD dwFlags;
49 LPSECURITY_ATTRIBUTES lpSecurityAttributes;
50 HFILE hTemplate;
51 BOOL fPhysicalDisk;
52 LARGE_INTEGER StartingOffset;
53 LARGE_INTEGER PartitionSize;
54 LARGE_INTEGER CurrentFilePointer;
55 CHAR szVolumeName[256];
56} DRIVE_INFO;
57
58HMDeviceDiskClass::HMDeviceDiskClass(LPCSTR lpDeviceName) : HMDeviceKernelObjectClass(lpDeviceName)
59{
60 HMDeviceRegisterEx("\\\\.\\PHYSICALDRIVE", this, NULL);
61 HMDeviceRegisterEx(VOLUME_NAME_PREFIX, this, NULL);
62}
63
64/*****************************************************************************
65 * Name : HMDeviceDiskClass::FindDevice
66 * Purpose : Checks if lpDeviceName belongs to this device class
67 * Parameters: LPCSTR lpClassDevName
68 * LPCSTR lpDeviceName
69 * int namelength
70 * Variables :
71 * Result : checks if name is for a drive of physical disk
72 * Remark :
73 * Status :
74 *
75 * Author : SvL
76 *****************************************************************************/
77BOOL HMDeviceDiskClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
78{
79 // check for "x:"
80 if (namelength == 2)
81 {
82 if (lpDeviceName[1] != ':')
83 return FALSE;
84
85 if (!( ((lpDeviceName[0] >= 'A') &&
86 (lpDeviceName[0] <= 'Z')) ||
87 ((lpDeviceName[0] >= 'a') &&
88 (lpDeviceName[0] <= 'z')) ))
89 return FALSE;
90
91 return TRUE;
92 }
93
94 //\\.\x: -> length 6
95 //\\.\PHYSICALDRIVEn -> length 18
96 if(namelength != 6 && namelength != 18) {
97 if(VERSION_IS_WIN2000_OR_HIGHER()) {
98 if(!strncmp(lpDeviceName, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1)) {
99 return TRUE;
100 }
101 }
102 return FALSE;
103 }
104
105 // \\.\x: -> drive x (i.e. \\.\C:)
106 // \\.\PHYSICALDRIVEn -> drive n (n>=0)
107 if((strncmp(lpDeviceName, "\\\\.\\", 4) == 0) &&
108 namelength == 6 && lpDeviceName[5] == ':')
109 {
110 return TRUE;
111 }
112 if((strncmp(lpDeviceName, "\\\\.\\PHYSICALDRIVE", 17) == 0) && namelength == 18) {
113 return TRUE;
114 }
115 return FALSE;
116}
117//******************************************************************************
118//******************************************************************************
119DWORD HMDeviceDiskClass::CreateFile (LPCSTR lpFileName,
120 PHMHANDLEDATA pHMHandleData,
121 PVOID lpSecurityAttributes,
122 PHMHANDLEDATA pHMHandleDataTemplate)
123{
124 HFILE hFile;
125 HFILE hTemplate;
126 DWORD dwDriveType;
127 CHAR szDiskName[256];
128 CHAR szVolumeName[256] = "";
129 VOLUME_DISK_EXTENTS volext = {0};
130 BOOL fPhysicalDisk = FALSE;
131
132 dprintf2(("KERNEL32: HMDeviceDiskClass::CreateFile %s(%s,%08x,%08x,%08x)\n",
133 lpHMDeviceName, lpFileName, pHMHandleData, lpSecurityAttributes, pHMHandleDataTemplate));
134
135 //TODO: check in NT if CREATE_ALWAYS is allowed!!
136 if(pHMHandleData->dwCreation != OPEN_EXISTING) {
137 dprintf(("Invalid creation flags %x!!", pHMHandleData->dwCreation));
138 return ERROR_INVALID_PARAMETER;
139 }
140
141 char szDrive[4];
142 szDrive[1] = ':';
143 szDrive[2] = '\0';
144
145 //if volume name, query
146 if(!strncmp(lpFileName, VOLUME_NAME_PREFIX, sizeof(VOLUME_NAME_PREFIX)-1))
147 {
148 int length;
149
150 if(!VERSION_IS_WIN2000_OR_HIGHER()) {
151 return ERROR_FILE_NOT_FOUND; //not allowed
152 }
153 if(OSLibLVMStripVolumeName(lpFileName, szVolumeName, sizeof(szVolumeName)))
154 {
155 BOOL fLVMVolume;
156
157 dwDriveType = GetDriveTypeA(lpFileName);
158
159 szDrive[0] = OSLibLVMQueryDriveFromVolumeName(szVolumeName);
160 if(szDrive[0] == -1) {
161 return ERROR_FILE_NOT_FOUND; //not found
162 }
163 if((dwDriveType == DRIVE_FIXED) && OSLibLVMGetVolumeExtents(szDrive[0], szVolumeName, &volext, &fLVMVolume) == FALSE) {
164 return ERROR_FILE_NOT_FOUND; //not found
165 }
166 if(szDrive[0] == 0)
167 {
168 //volume isn't mounted
169
170 //Note: this only works on Warp 4.5 and up
171 sprintf(szDiskName, "\\\\.\\Physical_Disk%d", volext.Extents[0].DiskNumber);
172 fPhysicalDisk = TRUE;
173
174 if(fLVMVolume && (pHMHandleData->dwAccess & GENERIC_WRITE)) {
175 //no write access allowed for LVM volumes
176 dprintf(("CreateFile: WARNING: Write access to LVM volume denied!!"));
177 pHMHandleData->dwAccess &= ~GENERIC_WRITE;
178 }
179 }
180 else {
181 //mounted drive, make sure access requested is readonly, else fail
182 if(pHMHandleData->dwAccess & GENERIC_WRITE) {
183 //no write access allowed for mounted partitions
184 dprintf(("CreateFile: WARNING: Write access to mounted partition denied!!"));
185 pHMHandleData->dwAccess &= ~GENERIC_WRITE;
186 }
187 strcpy(szDiskName, szDrive);
188 }
189 }
190 else return ERROR_FILE_NOT_FOUND;
191 }
192 else
193 if(strncmp(lpFileName, "\\\\.\\PHYSICALDRIVE", 17) == 0)
194 {
195 //Note: this only works on Warp 4.5 and up
196 sprintf(szDiskName, "\\\\.\\Physical_Disk%c", lpFileName[17]);
197 fPhysicalDisk = TRUE;
198
199 //TODO: could be removable in theory
200 dwDriveType = DRIVE_FIXED;
201
202 if(pHMHandleData->dwAccess & GENERIC_WRITE) {
203 //no write access allowed for whole disks
204 dprintf(("CreateFile: WARNING: Write access to whole disk denied!!"));
205 pHMHandleData->dwAccess &= ~GENERIC_WRITE;
206 }
207 }
208 else {
209 strcpy(szDiskName, lpFileName);
210 szDrive[0] = *lpFileName;
211 dwDriveType = GetDriveTypeA(szDrive);
212 }
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(szDiskName,
218 pHMHandleData->dwAccess,
219 pHMHandleData->dwShare,
220 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
221 pHMHandleData->dwCreation,
222 pHMHandleData->dwFlags,
223 hTemplate);
224
225 //It is not allowed to open a readonly device with GENERIC_WRITE in OS/2;
226 //try with readonly again if that happened
227 //NOTE: Some applications open it with GENERIC_WRITE as Windows 2000 requires
228 // this for some aspi functions
229 if(hFile == INVALID_HANDLE_ERROR && dwDriveType == DRIVE_CDROM &&
230 (pHMHandleData->dwAccess & GENERIC_WRITE))
231 {
232 pHMHandleData->dwAccess &= ~GENERIC_WRITE;
233 hFile = OSLibDosCreateFile((LPSTR)szDiskName,
234 pHMHandleData->dwAccess,
235 pHMHandleData->dwShare,
236 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
237 pHMHandleData->dwCreation,
238 pHMHandleData->dwFlags,
239 hTemplate);
240 }
241 SetErrorMode(oldmode);
242
243 if (hFile != INVALID_HANDLE_ERROR || GetLastError() == ERROR_NOT_READY)
244 {
245 if(hFile == INVALID_HANDLE_ERROR) {
246 dprintf(("Drive not ready"));
247 SetLastError(NO_ERROR);
248 pHMHandleData->hHMHandle = 0; //handle lookup fails if this is set to -1
249 }
250 else pHMHandleData->hHMHandle = hFile;
251
252 DRIVE_INFO *drvInfo = (DRIVE_INFO *)malloc(sizeof(DRIVE_INFO));
253 if(drvInfo == NULL) {
254 DebugInt3();
255 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
256 return ERROR_OUTOFMEMORY;
257 }
258 pHMHandleData->dwUserData = (DWORD)drvInfo;
259
260 memset(drvInfo, 0, sizeof(DRIVE_INFO));
261 drvInfo->dwAccess = pHMHandleData->dwAccess;
262 drvInfo->dwAccess = pHMHandleData->dwShare;
263 drvInfo->lpSecurityAttributes = (LPSECURITY_ATTRIBUTES)lpSecurityAttributes;
264 drvInfo->dwAccess = pHMHandleData->dwCreation;
265 drvInfo->dwAccess = pHMHandleData->dwFlags;
266 drvInfo->hTemplate = hTemplate;
267
268 //save volume start & length if volume must be accessed through the physical disk
269 //(no other choice for unmounted volumes)
270 drvInfo->fPhysicalDisk = fPhysicalDisk;
271 drvInfo->StartingOffset = volext.Extents[0].StartingOffset;
272 drvInfo->PartitionSize = volext.Extents[0].ExtentLength;
273
274 //save volume name for later (IOCtls)
275 strncpy(drvInfo->szVolumeName, szVolumeName, sizeof(drvInfo->szVolumeName)-1);
276
277 drvInfo->driveLetter = *lpFileName; //save drive letter
278 if(drvInfo->driveLetter >= 'a') {
279 drvInfo->driveLetter = drvInfo->driveLetter - ((int)'a' - (int)'A');
280 }
281
282 drvInfo->driveType = dwDriveType;
283 if(drvInfo->driveType == DRIVE_CDROM)
284 {
285 drvInfo->hInstAspi = LoadLibraryA("WNASPI32.DLL");
286 if(drvInfo->hInstAspi == NULL) {
287 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
288 free(drvInfo);
289 return ERROR_INVALID_PARAMETER;
290 }
291 *(FARPROC *)&drvInfo->GetASPI32SupportInfo = GetProcAddress(drvInfo->hInstAspi, "GetASPI32SupportInfo");
292 *(FARPROC *)&drvInfo->SendASPI32Command = GetProcAddress(drvInfo->hInstAspi, "SendASPI32Command");
293
294 if(drvInfo->GetASPI32SupportInfo() == (SS_FAILED_INIT << 8)) {
295 FreeLibrary(drvInfo->hInstAspi);
296 drvInfo->hInstAspi = 0;
297 }
298
299 //get cdrom signature
300 DWORD parsize = 4;
301 DWORD datasize = 4;
302 strcpy(drvInfo->signature, "CD01");
303 OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x80, 0x61, &drvInfo->signature[0], 4, &parsize,
304 &drvInfo->signature[0], 4, &datasize);
305 }
306
307 if(hFile && drvInfo->driveType != DRIVE_FIXED) {
308 OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &drvInfo->dwVolumelabel, NULL, 0);
309 }
310
311 //for an unmounted partition we open the physical disk that contains it, so we
312 //must set the file pointer to the correct beginning
313 if(drvInfo->fPhysicalDisk && (drvInfo->StartingOffset.HighPart != 0 ||
314 drvInfo->StartingOffset.LowPart != 0))
315 {
316 SetFilePointer(pHMHandleData, 0, NULL, FILE_BEGIN);
317 }
318 return (NO_ERROR);
319 }
320 else {
321 dprintf(("CreateFile failed; error %d", GetLastError()));
322 return(GetLastError());
323 }
324}
325//******************************************************************************
326//******************************************************************************
327DWORD HMDeviceDiskClass::OpenDisk(PVOID pDrvInfo)
328{
329 char filename[3];
330 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pDrvInfo;
331 HFILE hFile;
332
333 filename[0] = drvInfo->driveLetter;
334 filename[1] = ':';
335 filename[2] = 0;
336
337 //Disable error popus. NT allows an app to open a cdrom/dvd drive without a disk inside
338 //OS/2 fails in that case with error ERROR_NOT_READY
339 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
340 hFile = OSLibDosCreateFile(filename,
341 drvInfo->dwAccess,
342 drvInfo->dwShare,
343 drvInfo->lpSecurityAttributes,
344 drvInfo->dwCreation,
345 drvInfo->dwFlags,
346 drvInfo->hTemplate);
347 SetErrorMode(oldmode);
348
349 if (hFile != INVALID_HANDLE_ERROR || GetLastError() == ERROR_NOT_READY)
350 {
351 if(hFile == INVALID_HANDLE_ERROR) {
352 dprintf(("Drive not ready"));
353 return 0;
354 }
355 OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &drvInfo->dwVolumelabel, NULL, 0);
356 return hFile;
357 }
358 return 0;
359}
360//******************************************************************************
361//******************************************************************************
362BOOL HMDeviceDiskClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
363{
364 BOOL ret = TRUE;
365
366 if(pHMHandleData->hHMHandle) {
367 ret = OSLibDosClose(pHMHandleData->hHMHandle);
368 }
369 if(pHMHandleData->dwUserData) {
370 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
371 if(drvInfo->hInstAspi) FreeLibrary(drvInfo->hInstAspi);
372 free(drvInfo);
373 }
374 return ret;
375}
376//******************************************************************************
377//******************************************************************************
378
379
380// this helper function just calls the specified
381// ioctl function for the CDROM manager with no
382// parameter packet other than the CD01 signature
383// and no data packet.
384static BOOL ioctlCDROMSimple(PHMHANDLEDATA pHMHandleData,
385 DWORD dwCategory,
386 DWORD dwFunction,
387 LPDWORD lpBytesReturned, DRIVE_INFO *pdrvInfo)
388{
389 DWORD dwParameterSize = 4;
390 DWORD dwDataSize = 0;
391 DWORD ret;
392
393 if(lpBytesReturned)
394 *lpBytesReturned = 0;
395
396 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
397 dwCategory,
398 dwFunction,
399 pdrvInfo->signature,
400 4,
401 &dwParameterSize,
402 NULL,
403 0,
404 &dwDataSize);
405 return (ret == ERROR_SUCCESS);
406}
407
408
409// this helper function just calls the specified
410// ioctl function for the DISK manager with the
411// specified function codes
412static BOOL ioctlDISKUnlockEject(PHMHANDLEDATA pHMHandleData,
413 DWORD dwCommand,
414 DWORD dwDiskHandle,
415 LPDWORD lpBytesReturned)
416{
417#pragma pack(1)
418 struct
419 {
420 BYTE ucCommand;
421 BYTE ucHandle;
422 } ParameterBlock;
423#pragma pack()
424
425 DWORD dwParameterSize = sizeof( ParameterBlock );
426 DWORD dwDataSize = 0;
427 DWORD ret;
428
429 ParameterBlock.ucCommand = dwCommand;
430 ParameterBlock.ucHandle = dwDiskHandle;
431
432 if(lpBytesReturned)
433 *lpBytesReturned = 0;
434
435 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
436 IOCTL_DISK,
437 DSK_UNLOCKEJECTMEDIA,
438 &ParameterBlock,
439 sizeof( ParameterBlock ),
440 &dwParameterSize,
441 NULL,
442 0,
443 &dwDataSize);
444 return (ret == ERROR_SUCCESS);
445}
446
447
448
449BOOL HMDeviceDiskClass::DeviceIoControl(PHMHANDLEDATA pHMHandleData, DWORD dwIoControlCode,
450 LPVOID lpInBuffer, DWORD nInBufferSize,
451 LPVOID lpOutBuffer, DWORD nOutBufferSize,
452 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
453{
454#ifdef DEBUG
455 char *msg = NULL;
456
457 switch(dwIoControlCode)
458 {
459 case FSCTL_DELETE_REPARSE_POINT:
460 msg = "FSCTL_DELETE_REPARSE_POINT";
461 break;
462 case FSCTL_DISMOUNT_VOLUME:
463 msg = "FSCTL_DISMOUNT_VOLUME";
464 break;
465 case FSCTL_GET_COMPRESSION:
466 msg = "FSCTL_GET_COMPRESSION";
467 break;
468 case FSCTL_GET_REPARSE_POINT:
469 msg = "FSCTL_GET_REPARSE_POINT";
470 break;
471 case FSCTL_LOCK_VOLUME:
472 msg = "FSCTL_LOCK_VOLUME";
473 break;
474 case FSCTL_QUERY_ALLOCATED_RANGES:
475 msg = "FSCTL_QUERY_ALLOCATED_RANGES";
476 break;
477 case FSCTL_SET_COMPRESSION:
478 msg = "FSCTL_SET_COMPRESSION";
479 break;
480 case FSCTL_SET_REPARSE_POINT:
481 msg = "FSCTL_SET_REPARSE_POINT";
482 break;
483 case FSCTL_SET_SPARSE:
484 msg = "FSCTL_SET_SPARSE";
485 break;
486 case FSCTL_SET_ZERO_DATA:
487 msg = "FSCTL_SET_ZERO_DATA";
488 break;
489 case FSCTL_UNLOCK_VOLUME:
490 msg = "FSCTL_UNLOCK_VOLUME";
491 break;
492 case IOCTL_DISK_CHECK_VERIFY:
493 msg = "IOCTL_DISK_CHECK_VERIFY";
494 break;
495 case IOCTL_DISK_EJECT_MEDIA:
496 msg = "IOCTL_DISK_EJECT_MEDIA";
497 break;
498 case IOCTL_DISK_FORMAT_TRACKS:
499 msg = "IOCTL_DISK_FORMAT_TRACKS";
500 break;
501 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
502 msg = "IOCTL_DISK_GET_DRIVE_GEOMETRY";
503 break;
504 case IOCTL_DISK_IS_WRITABLE:
505 msg = "IOCTL_DISK_IS_WRITABLE";
506 break;
507 case IOCTL_DISK_GET_DRIVE_LAYOUT:
508 msg = "IOCTL_DISK_GET_DRIVE_LAYOUT";
509 break;
510 case IOCTL_DISK_GET_MEDIA_TYPES:
511 msg = "IOCTL_DISK_GET_MEDIA_TYPES";
512 break;
513 case IOCTL_DISK_GET_PARTITION_INFO:
514 msg = "IOCTL_DISK_GET_PARTITION_INFO";
515 break;
516 case IOCTL_DISK_LOAD_MEDIA:
517 msg = "IOCTL_DISK_LOAD_MEDIA";
518 break;
519 case IOCTL_DISK_MEDIA_REMOVAL:
520 msg = "IOCTL_DISK_MEDIA_REMOVAL";
521 break;
522 case IOCTL_DISK_PERFORMANCE:
523 msg = "IOCTL_DISK_PERFORMANCE";
524 break;
525 case IOCTL_DISK_REASSIGN_BLOCKS:
526 msg = "IOCTL_DISK_REASSIGN_BLOCKS";
527 break;
528 case IOCTL_DISK_SET_DRIVE_LAYOUT:
529 msg = "IOCTL_DISK_SET_DRIVE_LAYOUT";
530 break;
531 case IOCTL_DISK_SET_PARTITION_INFO:
532 msg = "IOCTL_DISK_SET_PARTITION_INFO";
533 break;
534 case IOCTL_DISK_VERIFY:
535 msg = "IOCTL_DISK_VERIFY";
536 break;
537 case IOCTL_SERIAL_LSRMST_INSERT:
538 msg = "IOCTL_SERIAL_LSRMST_INSERT";
539 break;
540 case IOCTL_STORAGE_CHECK_VERIFY:
541 msg = "IOCTL_STORAGE_CHECK_VERIFY";
542 break;
543 case IOCTL_STORAGE_EJECT_MEDIA:
544 msg = "IOCTL_STORAGE_EJECT_MEDIA";
545 break;
546 case IOCTL_STORAGE_GET_MEDIA_TYPES:
547 msg = "IOCTL_STORAGE_GET_MEDIA_TYPES";
548 break;
549 case IOCTL_STORAGE_LOAD_MEDIA:
550 msg = "IOCTL_STORAGE_LOAD_MEDIA";
551 break;
552 case IOCTL_STORAGE_MEDIA_REMOVAL:
553 msg = "IOCTL_STORAGE_MEDIA_REMOVAL";
554 break;
555 case IOCTL_SCSI_PASS_THROUGH:
556 msg = "IOCTL_SCSI_PASS_THROUGH";
557 break;
558 case IOCTL_SCSI_MINIPORT:
559 msg = "IOCTL_SCSI_MINIPORT";
560 break;
561 case IOCTL_SCSI_GET_INQUIRY_DATA:
562 msg = "IOCTL_SCSI_GET_INQUIRY_DATA";
563 break;
564 case IOCTL_SCSI_GET_CAPABILITIES:
565 msg = "IOCTL_SCSI_GET_CAPABILITIES";
566 break;
567 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
568 msg = "IOCTL_SCSI_PASS_THROUGH_DIRECT";
569 break;
570 case IOCTL_SCSI_GET_ADDRESS:
571 msg = "IOCTL_SCSI_GET_ADDRESS";
572 break;
573 case IOCTL_SCSI_RESCAN_BUS:
574 msg = "IOCTL_SCSI_RESCAN_BUS";
575 break;
576 case IOCTL_SCSI_GET_DUMP_POINTERS:
577 msg = "IOCTL_SCSI_GET_DUMP_POINTERS";
578 break;
579 case IOCTL_SCSI_FREE_DUMP_POINTERS:
580 msg = "IOCTL_SCSI_FREE_DUMP_POINTERS";
581 break;
582 case IOCTL_IDE_PASS_THROUGH:
583 msg = "IOCTL_IDE_PASS_THROUGH";
584 break;
585 case IOCTL_CDROM_UNLOAD_DRIVER:
586 msg = "IOCTL_CDROM_UNLOAD_DRIVER";
587 break;
588 case IOCTL_CDROM_READ_TOC:
589 msg = "IOCTL_CDROM_READ_TOC";
590 break;
591 case IOCTL_CDROM_GET_CONTROL:
592 msg = "IOCTL_CDROM_GET_CONTROL";
593 break;
594 case IOCTL_CDROM_PLAY_AUDIO_MSF:
595 msg = "IOCTL_CDROM_PLAY_AUDIO_MSF";
596 break;
597 case IOCTL_CDROM_SEEK_AUDIO_MSF:
598 msg = "IOCTL_CDROM_SEEK_AUDIO_MSF";
599 break;
600 case IOCTL_CDROM_STOP_AUDIO:
601 msg = "IOCTL_CDROM_STOP_AUDIO";
602 break;
603 case IOCTL_CDROM_PAUSE_AUDIO:
604 msg = "IOCTL_CDROM_PAUSE_AUDIO";
605 break;
606 case IOCTL_CDROM_RESUME_AUDIO:
607 msg = "IOCTL_CDROM_RESUME_AUDIO";
608 break;
609 case IOCTL_CDROM_GET_VOLUME:
610 msg = "IOCTL_CDROM_GET_VOLUME";
611 break;
612 case IOCTL_CDROM_SET_VOLUME:
613 msg = "IOCTL_CDROM_SET_VOLUME";
614 break;
615 case IOCTL_CDROM_READ_Q_CHANNEL:
616 msg = "IOCTL_CDROM_READ_Q_CHANNEL";
617 break;
618 case IOCTL_CDROM_GET_LAST_SESSION:
619 msg = "IOCTL_CDROM_GET_LAST_SESSION";
620 break;
621 case IOCTL_CDROM_RAW_READ:
622 msg = "IOCTL_CDROM_RAW_READ";
623 break;
624 case IOCTL_CDROM_DISK_TYPE:
625 msg = "IOCTL_CDROM_DISK_TYPE";
626 break;
627 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
628 msg = "IOCTL_CDROM_GET_DRIVE_GEOMETRY";
629 break;
630 case IOCTL_CDROM_CHECK_VERIFY:
631 msg = "IOCTL_CDROM_CHECK_VERIFY";
632 break;
633 case IOCTL_CDROM_MEDIA_REMOVAL:
634 msg = "IOCTL_CDROM_MEDIA_REMOVAL";
635 break;
636 case IOCTL_CDROM_EJECT_MEDIA:
637 msg = "IOCTL_CDROM_EJECT_MEDIA";
638 break;
639 case IOCTL_CDROM_LOAD_MEDIA:
640 msg = "IOCTL_CDROM_LOAD_MEDIA";
641 break;
642 case IOCTL_CDROM_RESERVE:
643 msg = "IOCTL_CDROM_RESERVE";
644 break;
645 case IOCTL_CDROM_RELEASE:
646 msg = "IOCTL_CDROM_RELEASE";
647 break;
648 case IOCTL_CDROM_FIND_NEW_DEVICES:
649 msg = "IOCTL_CDROM_FIND_NEW_DEVICES";
650 break;
651 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
652 msg = "IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS";
653 break;
654 }
655 if(msg) {
656 dprintf(("HMDeviceDiskClass::DeviceIoControl %s %x %d %x %d %x %x", msg, lpInBuffer, nInBufferSize,
657 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped));
658 }
659#endif
660
661 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
662 if(drvInfo == NULL) {
663 dprintf(("ERROR: DeviceIoControl: drvInfo == NULL!!!"));
664 DebugInt3();
665 SetLastError(ERROR_INVALID_HANDLE);
666 return FALSE;
667 }
668 switch(dwIoControlCode)
669 {
670 case FSCTL_DELETE_REPARSE_POINT:
671 case FSCTL_DISMOUNT_VOLUME:
672 case FSCTL_GET_COMPRESSION:
673 case FSCTL_GET_REPARSE_POINT:
674 case FSCTL_LOCK_VOLUME:
675 case FSCTL_QUERY_ALLOCATED_RANGES:
676 case FSCTL_SET_COMPRESSION:
677 case FSCTL_SET_REPARSE_POINT:
678 case FSCTL_SET_SPARSE:
679 case FSCTL_SET_ZERO_DATA:
680 case FSCTL_UNLOCK_VOLUME:
681 break;
682
683 case IOCTL_DISK_FORMAT_TRACKS:
684 case IOCTL_DISK_GET_DRIVE_LAYOUT:
685 break;
686
687 case IOCTL_DISK_IS_WRITABLE:
688 {
689 APIRET rc;
690 DWORD ret;
691 ULONG ulBytesRead = 0; /* Number of bytes read by DosRead */
692 ULONG ulWrote = 0; /* Number of bytes written by DosWrite */
693 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
694 UCHAR uchFileData[1] = {'0'}; /* Data to write to file */
695
696 if(!pHMHandleData->hHMHandle)
697 {
698 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
699 if(!pHMHandleData->hHMHandle) {
700 dprintf(("No disk inserted; aborting"));
701 SetLastError(ERROR_NOT_READY);
702 return FALSE;
703 }
704 }
705 if(drvInfo->driveType == DRIVE_CDROM) {
706 //TODO: check behaviour in NT
707 SetLastError(ERROR_WRITE_PROTECT);
708 return FALSE;
709 }
710 else
711 if(drvInfo->driveType == DRIVE_FIXED) {
712 SetLastError(ERROR_SUCCESS);
713 return TRUE;
714 }
715
716 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_LOCKDRIVE,0,0,0,0,0,0);
717
718 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
719
720 /* Read the first byte of the disk */
721 rc = OSLibDosRead(pHMHandleData->hHMHandle, /* File Handle */
722 uchFileData, /* String to be read */
723 1L, /* Length of string to be read */
724 &ulBytesRead); /* Bytes actually read */
725
726 if (rc == 0)
727 {
728 dprintf(("IOCTL_DISK_IS_WRITABLE:OSLibDosRead failed with rc %08xh %x", rc,GetLastError()));
729 SetLastError(ERROR_ACCESS_DENIED);
730 goto writecheckfail;
731 }
732
733 /* Move the file pointer back */
734 rc = OSLibDosSetFilePtr (pHMHandleData->hHMHandle, /* File Handle */
735 -1,OSLIB_SETPTR_FILE_CURRENT);
736 if (rc == -1)
737 {
738 dprintf(("IOCTL_DISK_IS_WRITABLE:OSLibDosSetFilePtr failed with rc %d", rc));
739 SetLastError(ERROR_ACCESS_DENIED);
740 goto writecheckfail;
741 }
742
743 rc = OSLibDosWrite(pHMHandleData->hHMHandle, /* File handle */
744 (PVOID) uchFileData, /* String to be written */
745 1, /* Size of string to be written */
746 &ulWrote); /* Bytes actually written */
747
748 dprintf2(("IOCTL_DISK_IS_WRITABLE:OSLibDosWrite returned with rc %x %x", rc,GetLastError()));
749 if (rc == 0)
750 {
751 if (GetLastError() == ERROR_WRITE_PROTECT)
752 {
753 SetLastError(ERROR_WRITE_PROTECT);
754 goto writecheckfail;
755 }
756 }
757 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_UNLOCKDRIVE,0,0,0,0,0,0);
758 SetErrorMode(oldmode);
759 SetLastError(ERROR_SUCCESS);
760 return TRUE;
761
762writecheckfail:
763 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_UNLOCKDRIVE,0,0,0,0,0,0);
764 SetErrorMode(oldmode);
765 return FALSE;
766 }
767 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
768 case IOCTL_STORAGE_GET_MEDIA_TYPES:
769 case IOCTL_DISK_GET_MEDIA_TYPES:
770 {
771 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)lpOutBuffer;
772 if(nOutBufferSize < sizeof(DISK_GEOMETRY) || !pGeom) {
773 SetLastError(ERROR_INSUFFICIENT_BUFFER);
774 return FALSE;
775 }
776 if(lpBytesReturned) {
777 *lpBytesReturned = 0;
778 }
779
780 ULONG volumelabel;
781 APIRET rc;
782
783 if(!pHMHandleData->hHMHandle) {
784 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
785 if(!pHMHandleData->hHMHandle) {
786 dprintf(("No disk inserted; aborting"));
787 SetLastError(ERROR_NOT_READY);
788 return FALSE;
789 }
790 }
791
792 //Applications can use this IOCTL to check if the floppy has been changed
793 //OSLibDosGetDiskGeometry won't fail when that happens so we read the
794 //volume label from the disk and return ERROR_MEDIA_CHANGED if the volume
795 //label has changed
796 //TODO: Find better way to determine if floppy was removed or switched
797 if(drvInfo->driveType != DRIVE_FIXED)
798 {
799 rc = OSLibDosQueryVolumeSerialAndName(1 + drvInfo->driveLetter - 'A', &volumelabel, NULL, 0);
800 if(rc) {
801 dprintf(("IOCTL_DISK_GET_DRIVE_GEOMETRY: OSLibDosQueryVolumeSerialAndName failed with rc %d", GetLastError()));
802 if(pHMHandleData->hHMHandle) OSLibDosClose(pHMHandleData->hHMHandle);
803 pHMHandleData->hHMHandle = 0;
804 SetLastError(ERROR_MEDIA_CHANGED);
805 return FALSE;
806 }
807 if(volumelabel != drvInfo->dwVolumelabel) {
808 dprintf(("IOCTL_DISK_GET_DRIVE_GEOMETRY: volume changed %x -> %x", drvInfo->dwVolumelabel, volumelabel));
809 SetLastError(ERROR_MEDIA_CHANGED);
810 return FALSE;
811 }
812 }
813
814 if(OSLibDosGetDiskGeometry(pHMHandleData->hHMHandle, drvInfo->driveLetter, pGeom) == FALSE) {
815 return FALSE;
816 }
817 if(lpBytesReturned) {
818 *lpBytesReturned = sizeof(DISK_GEOMETRY);
819 }
820 SetLastError(ERROR_SUCCESS);
821 return TRUE;
822 }
823
824 case IOCTL_DISK_GET_PARTITION_INFO:
825 {
826 PPARTITION_INFORMATION pPartition = (PPARTITION_INFORMATION)lpOutBuffer;
827 if(nOutBufferSize < sizeof(PARTITION_INFORMATION) || !pPartition) {
828 SetLastError(ERROR_INSUFFICIENT_BUFFER);
829 return FALSE;
830 }
831 if(lpBytesReturned) {
832 *lpBytesReturned = sizeof(PARTITION_INFORMATION);
833 }
834 if(OSLibLVMGetPartitionInfo(drvInfo->driveLetter, drvInfo->szVolumeName, pPartition) == FALSE) {
835 SetLastError(ERROR_NOT_ENOUGH_MEMORY); //wrong error, but who cares
836 return FALSE;
837 }
838
839 SetLastError(ERROR_SUCCESS);
840 return TRUE;
841 }
842
843 case IOCTL_DISK_LOAD_MEDIA:
844 case IOCTL_DISK_MEDIA_REMOVAL:
845 case IOCTL_DISK_PERFORMANCE:
846 case IOCTL_DISK_REASSIGN_BLOCKS:
847 case IOCTL_DISK_SET_DRIVE_LAYOUT:
848 case IOCTL_DISK_SET_PARTITION_INFO:
849 case IOCTL_DISK_VERIFY:
850 case IOCTL_SERIAL_LSRMST_INSERT:
851 break;
852
853
854 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
855 {
856 PVOLUME_DISK_EXTENTS pVolExtent = (PVOLUME_DISK_EXTENTS)lpOutBuffer;
857 if(nOutBufferSize < sizeof(VOLUME_DISK_EXTENTS) || !pVolExtent) {
858 SetLastError(ERROR_INSUFFICIENT_BUFFER);
859 return FALSE;
860 }
861 if(OSLibLVMGetVolumeExtents(drvInfo->driveLetter, drvInfo->szVolumeName, pVolExtent) == FALSE) {
862 SetLastError(ERROR_NOT_ENOUGH_MEMORY); //wrong error, but who cares
863 return FALSE;
864 }
865
866 if(lpBytesReturned) {
867 *lpBytesReturned = sizeof(VOLUME_DISK_EXTENTS);
868 }
869 SetLastError(ERROR_SUCCESS);
870 return TRUE;
871 }
872
873 // -----------
874 // CDROM class
875 // -----------
876 case IOCTL_CDROM_READ_TOC:
877 {
878#pragma pack(1)
879 typedef struct
880 {
881 BYTE ucFirstTrack;
882 BYTE ucLastTrack;
883 DWORD ulLeadOutAddr;
884 } AudioDiskInfo;
885 typedef struct
886 {
887 DWORD ulTrackAddr;
888 BYTE ucTrackControl;
889 } AudioTrackInfo;
890 typedef struct
891 {
892 BYTE signature[4];
893 BYTE ucTrack;
894 } ParameterBlock;
895#pragma pack()
896 PCDROM_TOC pTOC = (PCDROM_TOC)lpOutBuffer;
897 DWORD rc, numtracks;
898 DWORD parsize = 4;
899 DWORD datasize;
900 AudioDiskInfo diskinfo;
901 AudioTrackInfo trackinfo;
902 ParameterBlock parm;
903
904 if(lpBytesReturned)
905 *lpBytesReturned = 0;
906
907 if(!pTOC) {
908 SetLastError(ERROR_INVALID_PARAMETER);
909 return FALSE;
910 }
911 if(nOutBufferSize < sizeof(CDROM_TOC)) {
912 SetLastError(ERROR_INSUFFICIENT_BUFFER);
913 return FALSE;
914 }
915 memset(pTOC, 0, nOutBufferSize);
916 //IOCTL_CDROMAUDIO (0x81), CDROMAUDIO_GETAUDIODISK (0x61)
917 datasize = sizeof(diskinfo);
918 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x61, &drvInfo->signature[0], 4, &parsize,
919 &diskinfo, sizeof(diskinfo), &datasize);
920 if(rc != NO_ERROR) {
921 dprintf(("OSLibDosDevIOCtl failed with rc %d", rc));
922 return FALSE;
923 }
924 pTOC->FirstTrack = diskinfo.ucFirstTrack;
925 pTOC->LastTrack = diskinfo.ucLastTrack;
926 numtracks = pTOC->LastTrack - pTOC->FirstTrack + 1;
927 dprintf(("first %d, last %d, num %d", pTOC->FirstTrack, pTOC->LastTrack, numtracks));
928
929 //numtracks+1, because we have to add a track at the end
930 int length = 4 + (numtracks+1)*sizeof(TRACK_DATA);
931 //big endian format
932 pTOC->Length[0] = HIBYTE((length-2)); //minus length itself;
933 pTOC->Length[1] = LOBYTE((length-2)); //minus length itself;
934
935 if(nOutBufferSize < length) {
936 SetLastError(ERROR_INSUFFICIENT_BUFFER);
937 return FALSE;
938 }
939
940 for(int i=0;i<numtracks;i++)
941 {
942 parsize = sizeof(parm);
943 memcpy(parm.signature, drvInfo->signature, 4);
944 parm.ucTrack = i;
945
946 datasize = sizeof(trackinfo);
947
948 //IOCTL_CDROMAUDIO (0x81), CDROMAUDIO_GETAUDIOTRACK (0x62)
949 rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x62, &parm, sizeof(parm), &parsize,
950 &trackinfo, sizeof(trackinfo), &datasize);
951 if(rc != NO_ERROR) {
952 dprintf(("OSLibDosDevIOCtl failed with rc %d", rc));
953 return FALSE;
954 }
955 pTOC->TrackData[i].TrackNumber = pTOC->FirstTrack + i;
956 pTOC->TrackData[i].Reserved = 0;
957 pTOC->TrackData[i].Control = trackinfo.ucTrackControl >> 4;
958 pTOC->TrackData[i].Adr = trackinfo.ucTrackControl & 0xF;
959 pTOC->TrackData[i].Reserved1 = 0;
960 //big endian format
961 pTOC->TrackData[i].Address[0] = HIBYTE(HIWORD(trackinfo.ulTrackAddr));
962 pTOC->TrackData[i].Address[1] = LOBYTE(HIWORD(trackinfo.ulTrackAddr));
963 pTOC->TrackData[i].Address[2] = HIBYTE(LOWORD(trackinfo.ulTrackAddr));
964 pTOC->TrackData[i].Address[3] = LOBYTE(LOWORD(trackinfo.ulTrackAddr));
965 }
966
967 //Add a track at the end (presumably so the app can determine the size of the 1st track)
968 //That is what NT4, SP6 does anyway
969 pTOC->TrackData[numtracks].TrackNumber = 0xAA;
970 pTOC->TrackData[numtracks].Reserved = 0;
971 pTOC->TrackData[numtracks].Control = pTOC->TrackData[numtracks-1].Control;
972 pTOC->TrackData[numtracks].Adr = pTOC->TrackData[numtracks-1].Adr;
973 pTOC->TrackData[numtracks].Reserved1 = 0;
974 //big endian format
975 //Address of pseudo track is the address of the lead-out track
976 pTOC->TrackData[numtracks].Address[0] = HIBYTE(HIWORD(diskinfo.ulLeadOutAddr));
977 pTOC->TrackData[numtracks].Address[1] = LOBYTE(HIWORD(diskinfo.ulLeadOutAddr));
978 pTOC->TrackData[numtracks].Address[2] = HIBYTE(LOWORD(diskinfo.ulLeadOutAddr));
979 pTOC->TrackData[numtracks].Address[3] = LOBYTE(LOWORD(diskinfo.ulLeadOutAddr));
980
981 if(lpBytesReturned)
982 *lpBytesReturned = length;
983
984 SetLastError(ERROR_SUCCESS);
985 return TRUE;
986 }
987
988 case IOCTL_CDROM_UNLOAD_DRIVER:
989 case IOCTL_CDROM_GET_CONTROL:
990 break;
991
992 case IOCTL_CDROM_PLAY_AUDIO_MSF:
993 {
994#pragma pack(1)
995 struct
996 {
997 DWORD ucSignature;
998 BYTE ucAddressingMode;
999 DWORD ulStartingMSF;
1000 DWORD ulEndingMSF;
1001 } ParameterBlock;
1002#pragma pack()
1003 dprintf(("Play CDROM audio playback"));
1004
1005 PCDROM_PLAY_AUDIO_MSF pPlay = (PCDROM_PLAY_AUDIO_MSF)lpInBuffer;
1006
1007 // setup the parameter block
1008
1009 memcpy(&ParameterBlock.ucSignature, drvInfo->signature, 4);
1010 ParameterBlock.ucAddressingMode = 1; // MSF format
1011
1012 // @@@PH unknown if this kind of MSF conversion is correct!
1013 ParameterBlock.ulStartingMSF = pPlay->StartingM << 16 |
1014 pPlay->StartingS << 8 |
1015 pPlay->StartingF;
1016 ParameterBlock.ulEndingMSF = pPlay->EndingM << 16 |
1017 pPlay->EndingS << 8 |
1018 pPlay->EndingF;
1019
1020 DWORD dwParameterSize = sizeof( ParameterBlock );
1021 DWORD dwDataSize = 0;
1022 DWORD ret;
1023
1024 if(lpBytesReturned)
1025 *lpBytesReturned = 0;
1026
1027 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle,
1028 0x81, // IOCTL_CDROMAUDIO
1029 0x50, // CDROMAUDIO_PLAYAUDIO
1030 &ParameterBlock,
1031 sizeof( ParameterBlock ),
1032 &dwParameterSize,
1033 NULL,
1034 0,
1035 &dwDataSize);
1036 return (ret == ERROR_SUCCESS);
1037 }
1038
1039 case IOCTL_CDROM_SEEK_AUDIO_MSF:
1040 break;
1041
1042 case IOCTL_CDROM_PAUSE_AUDIO:
1043 // NO BREAK CASE
1044 // Note: for OS/2, pause and stop seems to be the same!
1045
1046 case IOCTL_CDROM_STOP_AUDIO:
1047 {
1048 dprintf(("Stop / pause CDROM audio playback"));
1049 return ioctlCDROMSimple(pHMHandleData,
1050 0x81, // IOCTL_CDROMAUDIO
1051 0x51, // CDROMAUDIO_STOPAUDIO
1052 lpBytesReturned, drvInfo);
1053 }
1054
1055 case IOCTL_CDROM_RESUME_AUDIO:
1056 {
1057 dprintf(("Resume CDROM audio playback"));
1058 return ioctlCDROMSimple(pHMHandleData,
1059 0x81, // IOCTL_CDROMAUDIO
1060 0x52, // CDROMAUDIO_RESUMEAUDIO
1061 lpBytesReturned, drvInfo);
1062 }
1063
1064 case IOCTL_CDROM_GET_VOLUME:
1065 {
1066 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpOutBuffer;
1067 char volbuf[8];
1068 DWORD parsize, datasize, ret;
1069
1070 if(nOutBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
1071 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1072 return FALSE;
1073 }
1074 if(lpBytesReturned) {
1075 *lpBytesReturned = 0;
1076 }
1077 parsize = 4;
1078 datasize = 8;
1079 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x60, drvInfo->signature, 4, &parsize,
1080 volbuf, 8, &datasize);
1081
1082 if(ret)
1083 return FALSE;
1084
1085 if(lpBytesReturned) {
1086 *lpBytesReturned = sizeof(VOLUME_CONTROL);
1087 }
1088 pVol->PortVolume[0] = volbuf[1];
1089 pVol->PortVolume[1] = volbuf[3];
1090 pVol->PortVolume[2] = volbuf[5];
1091 pVol->PortVolume[3] = volbuf[7];
1092 SetLastError(ERROR_SUCCESS);
1093 return TRUE;
1094 }
1095
1096 case IOCTL_CDROM_SET_VOLUME:
1097 {
1098 PVOLUME_CONTROL pVol = (PVOLUME_CONTROL)lpInBuffer;
1099 char volbuf[8];
1100 DWORD parsize, datasize, ret;
1101
1102 if(nInBufferSize < sizeof(VOLUME_CONTROL) || !pVol) {
1103 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1104 return FALSE;
1105 }
1106 if(lpBytesReturned) {
1107 *lpBytesReturned = 0;
1108 }
1109 parsize = 4;
1110 datasize = 8;
1111 volbuf[0] = 0;
1112 volbuf[1] = pVol->PortVolume[0];
1113 volbuf[2] = 1;
1114 volbuf[3] = pVol->PortVolume[1];
1115 volbuf[4] = 2;
1116 volbuf[5] = pVol->PortVolume[2];
1117 volbuf[6] = 3;
1118 volbuf[7] = pVol->PortVolume[3];
1119 dprintf(("Set CD volume (%d,%d)(%d,%d)", pVol->PortVolume[0], pVol->PortVolume[1], pVol->PortVolume[2], pVol->PortVolume[3]));
1120 ret = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x81, 0x40, drvInfo->signature, 4, &parsize,
1121 volbuf, 8, &datasize);
1122
1123 if(ret)
1124 return FALSE;
1125
1126 SetLastError(ERROR_SUCCESS);
1127 return TRUE;
1128 }
1129 case IOCTL_CDROM_READ_Q_CHANNEL:
1130 case IOCTL_CDROM_GET_LAST_SESSION:
1131 case IOCTL_CDROM_RAW_READ:
1132 case IOCTL_CDROM_DISK_TYPE:
1133 case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
1134 case IOCTL_CDROM_MEDIA_REMOVAL:
1135 break;
1136
1137 case IOCTL_CDROM_EJECT_MEDIA:
1138 {
1139 dprintf(("Eject CDROM media"));
1140 return ioctlCDROMSimple(pHMHandleData,
1141 0x80, // IOCTL_CDROM
1142 0x44, // CDROMDISK_EJECTDISK
1143 lpBytesReturned, drvInfo);
1144 }
1145
1146 case IOCTL_CDROM_LOAD_MEDIA:
1147 {
1148 dprintf(("Loading CDROM media"));
1149 return ioctlCDROMSimple(pHMHandleData,
1150 0x80, // IOCTL_CDROM
1151 0x45, // CDROMDISK_CLOSETRAY
1152 lpBytesReturned, drvInfo);
1153 }
1154
1155 case IOCTL_CDROM_RESERVE:
1156 case IOCTL_CDROM_RELEASE:
1157 case IOCTL_CDROM_FIND_NEW_DEVICES:
1158 break;
1159
1160
1161 // -------------
1162 // STORAGE class
1163 // -------------
1164
1165 case IOCTL_CDROM_CHECK_VERIFY:
1166 if(drvInfo->driveType != DRIVE_CDROM) {
1167 SetLastError(ERROR_GEN_FAILURE); //TODO: right error?
1168 return FALSE;
1169 }
1170 //no break;
1171 case IOCTL_DISK_CHECK_VERIFY:
1172 case IOCTL_STORAGE_CHECK_VERIFY:
1173 {
1174#pragma pack(1)
1175 typedef struct
1176 {
1177 BYTE ucCommandInfo;
1178 WORD usDriveUnit;
1179 } ParameterBlock;
1180#pragma pack()
1181
1182 dprintf(("IOCTL_CDROM(DISK/STORAGE)CHECK_VERIFY %s", drvInfo->signature));
1183 if(lpBytesReturned) {
1184 *lpBytesReturned = 0;
1185 }
1186
1187 if(!pHMHandleData->hHMHandle) {
1188 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1189 if(!pHMHandleData->hHMHandle) {
1190 dprintf(("No disk inserted; aborting"));
1191 SetLastError(ERROR_NOT_READY);
1192 return FALSE;
1193 }
1194 }
1195
1196 DWORD parsize = sizeof(ParameterBlock);
1197 DWORD datasize = 2;
1198 WORD status = 0;
1199 DWORD rc;
1200 ParameterBlock parm;
1201
1202 parm.ucCommandInfo = 0;
1203 parm.usDriveUnit = drvInfo->driveLetter - 'A';
1204// rc = OSLibDosDevIOCtl(pHMHandleData->hHMHandle, 0x08, 0x66, &parm, sizeof(parm), &parsize,
1205 //TODO: this doesn't work for floppies for some reason...
1206 rc = OSLibDosDevIOCtl(-1, IOCTL_DISK, DSK_GETLOCKSTATUS, &parm, sizeof(parm), &parsize,
1207 &status, sizeof(status), &datasize);
1208 if(rc != NO_ERROR) {
1209 dprintf(("OSLibDosDevIOCtl failed with rc %d datasize %d", rc, datasize));
1210 return FALSE;
1211 }
1212 dprintf(("Disk status 0x%x", status));
1213 //if no disk present, return FALSE
1214 if(!(status & (BIT_2))) {
1215 SetLastError(ERROR_NOT_READY); //NT4, SP6 returns this
1216 return FALSE;
1217 }
1218 SetLastError(NO_ERROR);
1219 return TRUE;
1220 }
1221
1222 case IOCTL_DISK_EJECT_MEDIA:
1223 case IOCTL_STORAGE_EJECT_MEDIA:
1224 {
1225 dprintf(("Ejecting storage media"));
1226 return ioctlDISKUnlockEject(pHMHandleData,
1227 0x02, // EJECT media
1228 -1,
1229 lpBytesReturned);
1230 }
1231
1232 case IOCTL_STORAGE_LOAD_MEDIA:
1233 // case IOCTL_STORAGE_LOAD_MEDIA2:
1234 {
1235 dprintf(("Loading storage media"));
1236 return ioctlDISKUnlockEject(pHMHandleData,
1237 0x03, // LOAD media
1238 -1,
1239 lpBytesReturned);
1240 }
1241
1242 // case IOCTL_STORAGE_EJECTION_CONTROL:
1243 case IOCTL_STORAGE_MEDIA_REMOVAL:
1244 break;
1245
1246
1247 // -------------------
1248 // SCSI passthru class
1249 // -------------------
1250
1251 case IOCTL_SCSI_PASS_THROUGH:
1252 case IOCTL_SCSI_MINIPORT:
1253 case IOCTL_SCSI_GET_INQUIRY_DATA:
1254 case IOCTL_SCSI_GET_CAPABILITIES:
1255 break;
1256
1257 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
1258 {
1259 PSCSI_PASS_THROUGH_DIRECT pPacket = (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer;
1260 SRB_ExecSCSICmd *psrb;
1261
1262 if(drvInfo->hInstAspi == NULL)
1263 {
1264 SetLastError(ERROR_ACCESS_DENIED);
1265 return FALSE;
1266 }
1267
1268 if(nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT) ||
1269 !pPacket || pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
1270 {
1271 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1272 return FALSE;
1273 }
1274 if(lpBytesReturned) {
1275 *lpBytesReturned = 0;
1276 }
1277
1278 psrb = (SRB_ExecSCSICmd *)alloca(sizeof(SRB_ExecSCSICmd)+pPacket->SenseInfoLength);
1279 if(psrb == NULL) {
1280 dprintf(("not enough memory!!"));
1281 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1282 return FALSE;
1283 }
1284 memset(psrb, 0, sizeof(*psrb));
1285 psrb->SRB_Cmd = SC_EXEC_SCSI_CMD;
1286 psrb->SRB_Status = pPacket->ScsiStatus;
1287 psrb->SRB_HaId = pPacket->PathId;
1288 psrb->SRB_Target = pPacket->TargetId;
1289 psrb->SRB_Lun = pPacket->Lun;
1290 psrb->SRB_BufLen = pPacket->DataTransferLength;
1291 psrb->SRB_SenseLen = pPacket->SenseInfoLength;
1292 psrb->SRB_CDBLen = pPacket->CdbLength;
1293 switch(pPacket->DataIn) {
1294 case SCSI_IOCTL_DATA_OUT:
1295 psrb->SRB_Flags = 0x2 << 3;
1296 break;
1297 case SCSI_IOCTL_DATA_IN:
1298 psrb->SRB_Flags = 0x1 << 3;
1299 break;
1300 case SCSI_IOCTL_DATA_UNSPECIFIED:
1301 psrb->SRB_Flags = 0x3 << 3;
1302 break;
1303 }
1304 if(pPacket->CdbLength > 16) {
1305 SetLastError(ERROR_INVALID_PARAMETER);
1306 return FALSE;
1307 }
1308 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]));
1309 psrb->SRB_BufPointer = (BYTE *)pPacket->DataBuffer;
1310 memcpy(&psrb->CDBByte[0], &pPacket->Cdb[0], 16);
1311 if(psrb->SRB_SenseLen) {
1312 memcpy(&psrb->SenseArea[0], (char *)pPacket + pPacket->SenseInfoOffset, psrb->SRB_SenseLen);
1313 }
1314 //TODO: pPacket->TimeOutValue ignored
1315 int rc = drvInfo->SendASPI32Command((LPSRB)psrb);
1316 if(rc != SS_COMP) {
1317 dprintf(("SendASPI32Command failed with error %d", rc));
1318 if(rc == SS_ERR) {
1319 SetLastError(ERROR_ADAP_HDW_ERR); //returned by NT4, SP6
1320 }
1321 else SetLastError(ERROR_GEN_FAILURE);
1322 return FALSE;
1323 }
1324 pPacket->ScsiStatus = rc;
1325 if(lpBytesReturned) {
1326 *lpBytesReturned = 0;
1327 }
1328 pPacket->DataTransferLength = psrb->SRB_BufLen;
1329 if(psrb->SRB_SenseLen) {
1330 memcpy((char *)pPacket + pPacket->SenseInfoOffset, &psrb->SenseArea[0], psrb->SRB_SenseLen);
1331 }
1332 SetLastError(ERROR_SUCCESS);
1333 return TRUE;
1334 }
1335 case IOCTL_SCSI_GET_ADDRESS:
1336 {
1337 DWORD numAdapters, rc;
1338 SRB srb;
1339 int i, j, k;
1340
1341 if(!lpOutBuffer || nOutBufferSize < 8) {
1342 SetLastError(ERROR_INSUFFICIENT_BUFFER); //todo: right error?
1343 return(FALSE);
1344 }
1345 SCSI_ADDRESS *addr = (SCSI_ADDRESS *)lpOutBuffer;
1346 addr->Length = sizeof(SCSI_ADDRESS);
1347 addr->PortNumber = 0;
1348 addr->PathId = 0;
1349
1350 if(drvInfo->hInstAspi == NULL) {
1351 SetLastError(ERROR_ACCESS_DENIED);
1352 return FALSE;
1353 }
1354
1355 numAdapters = drvInfo->GetASPI32SupportInfo();
1356
1357 memset(&srb, 0, sizeof(srb));
1358 srb.common.SRB_Cmd = SC_HA_INQUIRY;
1359 rc = drvInfo->SendASPI32Command(&srb);
1360
1361 char drivename[3];
1362 drivename[0] = (char)drvInfo->driveLetter;
1363 drivename[1] = ':';
1364 drivename[2] = 0;
1365
1366 for(i=0;i<LOBYTE(numAdapters);i++) {
1367 for(j=0;j<8;j++) {
1368 for(k=0;k<16;k++) {
1369 memset(&srb, 0, sizeof(srb));
1370 srb.common.SRB_Cmd = SC_GET_DEV_TYPE;
1371 srb.devtype.SRB_HaId = i;
1372 srb.devtype.SRB_Target = j;
1373 srb.devtype.SRB_Lun = k;
1374 rc = drvInfo->SendASPI32Command(&srb);
1375 if(rc == SS_COMP) {
1376 if(srb.devtype.SRB_DeviceType == SS_DEVTYPE_CDROM &&
1377 GetDriveTypeA(drivename) == DRIVE_CDROM)
1378 {
1379 goto done;
1380 }
1381 }
1382 }
1383 }
1384 }
1385done:
1386 if(rc == SS_COMP) {
1387 addr->TargetId = j;
1388 addr->Lun = k;
1389 SetLastError(ERROR_SUCCESS);
1390 }
1391 else SetLastError(ERROR_FILE_NOT_FOUND); //todo
1392 return TRUE;
1393failure:
1394 SetLastError(ERROR_INVALID_PARAMETER); //todo
1395 return FALSE;
1396 }
1397
1398 case IOCTL_SCSI_RESCAN_BUS:
1399 case IOCTL_SCSI_GET_DUMP_POINTERS:
1400 case IOCTL_SCSI_FREE_DUMP_POINTERS:
1401 case IOCTL_IDE_PASS_THROUGH:
1402 break;
1403
1404 }
1405 dprintf(("HMDeviceDiskClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
1406 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1407 return FALSE;
1408}
1409/*****************************************************************************
1410 * Name : BOOL HMDeviceDiskClass::ReadFile
1411 * Purpose : read data from handle / device
1412 * Parameters: PHMHANDLEDATA pHMHandleData,
1413 * LPCVOID lpBuffer,
1414 * DWORD nNumberOfBytesToRead,
1415 * LPDWORD lpNumberOfBytesRead,
1416 * LPOVERLAPPED lpOverlapped
1417 * Variables :
1418 * Result : Boolean
1419 * Remark :
1420 * Status :
1421 *
1422 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1423 *****************************************************************************/
1424
1425BOOL HMDeviceDiskClass::ReadFile(PHMHANDLEDATA pHMHandleData,
1426 LPCVOID lpBuffer,
1427 DWORD nNumberOfBytesToRead,
1428 LPDWORD lpNumberOfBytesRead,
1429 LPOVERLAPPED lpOverlapped,
1430 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1431{
1432 LPVOID lpRealBuf;
1433 Win32MemMap *map;
1434 DWORD offset, bytesread;
1435 BOOL bRC;
1436
1437 dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)",
1438 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped));
1439
1440 //It's legal for this pointer to be NULL
1441 if(lpNumberOfBytesRead)
1442 *lpNumberOfBytesRead = 0;
1443 else
1444 lpNumberOfBytesRead = &bytesread;
1445
1446 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1447 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1448 SetLastError(ERROR_INVALID_PARAMETER);
1449 return FALSE;
1450 }
1451
1452 if(lpCompletionRoutine) {
1453 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
1454 }
1455
1456 //If we didn't get an OS/2 handle for the disk before, get one now
1457 if(!pHMHandleData->hHMHandle) {
1458 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1459 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1460 if(!pHMHandleData->hHMHandle) {
1461 dprintf(("No disk inserted; aborting"));
1462 SetLastError(ERROR_NOT_READY);
1463 return FALSE;
1464 }
1465 }
1466
1467 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1468 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1469 }
1470
1471 //SvL: DosRead doesn't like writing to memory addresses returned by
1472 // DosAliasMem -> search for original memory mapped pointer and use
1473 // that one + commit pages if not already present
1474 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
1475 if(map) {
1476 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1477 DWORD nrpages = nNumberOfBytesToRead/4096;
1478 if(offset & 0xfff)
1479 nrpages++;
1480 if(nNumberOfBytesToRead & 0xfff)
1481 nrpages++;
1482
1483 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1484 }
1485 else lpRealBuf = (LPVOID)lpBuffer;
1486
1487 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1488 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1489 }
1490 // else {
1491 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
1492 (PVOID)lpRealBuf,
1493 nNumberOfBytesToRead,
1494 lpNumberOfBytesRead);
1495// }
1496
1497 if(bRC == 0) {
1498 dprintf(("KERNEL32: HMDeviceDiskClass::ReadFile returned %08xh %x", bRC, GetLastError()));
1499 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
1500 }
1501 else dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile read %x bytes pos %x", *lpNumberOfBytesRead, SetFilePointer(pHMHandleData, 0, NULL, FILE_CURRENT)));
1502
1503 return bRC;
1504}
1505/*****************************************************************************
1506 * Name : DWORD HMDeviceDiskClass::SetFilePointer
1507 * Purpose : set file pointer
1508 * Parameters: PHMHANDLEDATA pHMHandleData
1509 * LONG lDistanceToMove
1510 * PLONG lpDistanceToMoveHigh
1511 * DWORD dwMoveMethod
1512 * Variables :
1513 * Result : API returncode
1514 * Remark :
1515 * Status :
1516 *
1517 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1518 *****************************************************************************/
1519DWORD HMDeviceDiskClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
1520 LONG lDistanceToMove,
1521 PLONG lpDistanceToMoveHigh,
1522 DWORD dwMoveMethod)
1523{
1524 DWORD ret;
1525
1526 if(lpDistanceToMoveHigh) {
1527 dprintf(("KERNEL32: HMDeviceDiskClass::SetFilePointer %s %08x%08x %d",
1528 lpHMDeviceName, *lpDistanceToMoveHigh, lDistanceToMove, dwMoveMethod));
1529 }
1530
1531 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1532 if(drvInfo == NULL) {
1533 dprintf(("ERROR: SetFilePointer: drvInfo == NULL!!!"));
1534 DebugInt3();
1535 SetLastError(ERROR_INVALID_HANDLE);
1536 return FALSE;
1537 }
1538
1539 if(!pHMHandleData->hHMHandle) {
1540 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1541 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1542 if(!pHMHandleData->hHMHandle) {
1543 dprintf(("No disk inserted; aborting"));
1544 SetLastError(ERROR_NOT_READY);
1545 return -1;
1546 }
1547 }
1548
1549 //if unmounted volume, add starting offset to position as we're accessing the entire physical drive
1550 //instead of just the volume
1551 if(drvInfo->fPhysicalDisk && (drvInfo->StartingOffset.HighPart != 0 ||
1552 drvInfo->StartingOffset.LowPart != 0))
1553 {
1554 LARGE_INTEGER distance, result, endpos;
1555 LARGE_INTEGER position;
1556
1557 if(lpDistanceToMoveHigh) {
1558 distance.HighPart = *lpDistanceToMoveHigh;
1559 }
1560 else {
1561 if(lDistanceToMove < 0) {
1562 distance.HighPart = -1;
1563 }
1564 else distance.HighPart = 0;
1565 }
1566 distance.LowPart = lDistanceToMove;
1567
1568 //calculate end position in partition
1569 Add64(&drvInfo->StartingOffset, &drvInfo->PartitionSize, &endpos);
1570 result.HighPart = 0;
1571 result.LowPart = 1;
1572 Sub64(&endpos, &result, &endpos);
1573
1574 switch(dwMoveMethod) {
1575 case FILE_BEGIN:
1576 Add64(&distance, &drvInfo->StartingOffset, &result);
1577 break;
1578 case FILE_CURRENT:
1579 Add64(&distance, &drvInfo->CurrentFilePointer, &result);
1580 break;
1581 case FILE_END:
1582 Add64(&distance, &endpos, &result);
1583 break;
1584 }
1585 //check upper boundary
1586 if(result.HighPart > endpos.HighPart ||
1587 (result.HighPart == endpos.HighPart && result.LowPart > endpos.LowPart) )
1588 {
1589 SetLastError(ERROR_INVALID_PARAMETER);
1590 return -1;
1591 }
1592 //check lower boundary
1593 if(result.HighPart < drvInfo->StartingOffset.HighPart ||
1594 (result.HighPart == drvInfo->StartingOffset.HighPart && result.LowPart < drvInfo->StartingOffset.LowPart))
1595 {
1596 SetLastError(ERROR_NEGATIVE_SEEK);
1597 return -1;
1598 }
1599
1600 dprintf(("SetFilePointer (unmounted partition) %08x%08x -> %08x%08x", distance.HighPart, distance.LowPart, result.HighPart, result.LowPart));
1601 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
1602 result.LowPart,
1603 (DWORD *)&result.HighPart,
1604 FILE_BEGIN);
1605
1606 Sub64(&result, &drvInfo->StartingOffset, &drvInfo->CurrentFilePointer);
1607 ret = drvInfo->CurrentFilePointer.LowPart;
1608 if(lpDistanceToMoveHigh) {
1609 *lpDistanceToMoveHigh = drvInfo->CurrentFilePointer.HighPart;
1610 }
1611 }
1612 else {
1613 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
1614 lDistanceToMove,
1615 (DWORD *)lpDistanceToMoveHigh,
1616 dwMoveMethod);
1617 }
1618
1619 if(ret == -1) {
1620 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
1621 }
1622 return ret;
1623}
1624
1625/*****************************************************************************
1626 * Name : BOOL HMDeviceDiskClass::WriteFile
1627 * Purpose : write data to handle / device
1628 * Parameters: PHMHANDLEDATA pHMHandleData,
1629 * LPCVOID lpBuffer,
1630 * DWORD nNumberOfBytesToWrite,
1631 * LPDWORD lpNumberOfBytesWritten,
1632 * LPOVERLAPPED lpOverlapped
1633 * Variables :
1634 * Result : Boolean
1635 * Remark :
1636 * Status :
1637 *
1638 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1639 *****************************************************************************/
1640
1641BOOL HMDeviceDiskClass::WriteFile(PHMHANDLEDATA pHMHandleData,
1642 LPCVOID lpBuffer,
1643 DWORD nNumberOfBytesToWrite,
1644 LPDWORD lpNumberOfBytesWritten,
1645 LPOVERLAPPED lpOverlapped,
1646 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1647{
1648 LPVOID lpRealBuf;
1649 Win32MemMap *map;
1650 DWORD offset, byteswritten;
1651 BOOL bRC;
1652
1653 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
1654 lpHMDeviceName, pHMHandleData, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
1655 lpOverlapped));
1656
1657 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1658 if(drvInfo == NULL) {
1659 dprintf(("ERROR: WriteFile: drvInfo == NULL!!!"));
1660 DebugInt3();
1661 SetLastError(ERROR_INVALID_HANDLE);
1662 return FALSE;
1663 }
1664 if(!(drvInfo->dwAccess & GENERIC_WRITE)) {
1665 dprintf(("ERROR: WriteFile: write access denied!"));
1666 SetLastError(ERROR_ACCESS_DENIED);
1667 return FALSE;
1668 }
1669 //It's legal for this pointer to be NULL
1670 if(lpNumberOfBytesWritten)
1671 *lpNumberOfBytesWritten = 0;
1672 else
1673 lpNumberOfBytesWritten = &byteswritten;
1674
1675 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
1676 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
1677 SetLastError(ERROR_INVALID_PARAMETER);
1678 return FALSE;
1679 }
1680 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
1681 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
1682 }
1683 if(lpCompletionRoutine) {
1684 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
1685 }
1686
1687 //If we didn't get an OS/2 handle for the disk before, get one now
1688 if(!pHMHandleData->hHMHandle) {
1689 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1690 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1691 if(!pHMHandleData->hHMHandle) {
1692 dprintf(("No disk inserted; aborting"));
1693 SetLastError(ERROR_NOT_READY);
1694 return FALSE;
1695 }
1696 }
1697
1698 //SvL: DosWrite doesn't like reading from memory addresses returned by
1699 // DosAliasMem -> search for original memory mapped pointer and use
1700 // that one + commit pages if not already present
1701 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_READ);
1702 if(map) {
1703 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
1704 DWORD nrpages = nNumberOfBytesToWrite/4096;
1705 if(offset & 0xfff)
1706 nrpages++;
1707 if(nNumberOfBytesToWrite & 0xfff)
1708 nrpages++;
1709
1710 map->commitPage(offset & ~0xfff, TRUE, nrpages);
1711 }
1712 else lpRealBuf = (LPVOID)lpBuffer;
1713
1714 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_LOCKDRIVE,0,0,0,0,0,0);
1715
1716 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
1717 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
1718 }
1719// else {
1720 bRC = OSLibDosWrite(pHMHandleData->hHMHandle,
1721 (PVOID)lpRealBuf,
1722 nNumberOfBytesToWrite,
1723 lpNumberOfBytesWritten);
1724// }
1725
1726 OSLibDosDevIOCtl(pHMHandleData->hHMHandle,IOCTL_DISK,DSK_UNLOCKDRIVE,0,0,0,0,0,0);
1727 dprintf2(("KERNEL32: HMDeviceDiskClass::WriteFile returned %08xh\n",
1728 bRC));
1729
1730 return bRC;
1731}
1732
1733/*****************************************************************************
1734 * Name : DWORD HMDeviceDiskClass::GetFileSize
1735 * Purpose : set file time
1736 * Parameters: PHMHANDLEDATA pHMHandleData
1737 * PDWORD pSize
1738 * Variables :
1739 * Result : API returncode
1740 * Remark :
1741 * Status :
1742 *
1743 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1744 *****************************************************************************/
1745
1746DWORD HMDeviceDiskClass::GetFileSize(PHMHANDLEDATA pHMHandleData,
1747 PDWORD lpdwFileSizeHigh)
1748{
1749 DRIVE_INFO *drvInfo = (DRIVE_INFO*)pHMHandleData->dwUserData;
1750 if(drvInfo == NULL) {
1751 dprintf(("ERROR: GetFileSize: drvInfo == NULL!!!"));
1752 DebugInt3();
1753 SetLastError(ERROR_INVALID_HANDLE);
1754 return -1; //INVALID_SET_FILE_POINTER
1755 }
1756
1757 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileSize %s(%08xh,%08xh)\n",
1758 lpHMDeviceName, pHMHandleData, lpdwFileSizeHigh));
1759
1760 //If we didn't get an OS/2 handle for the disk before, get one now
1761 if(!pHMHandleData->hHMHandle) {
1762 pHMHandleData->hHMHandle = OpenDisk(drvInfo);
1763 if(!pHMHandleData->hHMHandle) {
1764 dprintf(("No disk inserted; aborting"));
1765 SetLastError(ERROR_NOT_READY);
1766 return -1; //INVALID_SET_FILE_POINTER
1767 }
1768 }
1769
1770 if(drvInfo->PartitionSize.HighPart || drvInfo->PartitionSize.LowPart) {
1771 if(lpdwFileSizeHigh)
1772 *lpdwFileSizeHigh = drvInfo->PartitionSize.HighPart;
1773
1774 return drvInfo->PartitionSize.LowPart;
1775 }
1776 else {
1777 LARGE_INTEGER position, size;
1778
1779 //get current position
1780 position.HighPart = 0;
1781 position.LowPart = SetFilePointer(pHMHandleData, 0, (PLONG)&position.HighPart, FILE_CURRENT);
1782 SetFilePointer(pHMHandleData, 0, NULL, FILE_BEGIN);
1783 size.HighPart = 0;
1784 size.LowPart = SetFilePointer(pHMHandleData, 0, (PLONG)&size.HighPart, FILE_END);
1785
1786 //restore old position
1787 SetFilePointer(pHMHandleData, position.LowPart, (PLONG)&position.HighPart, FILE_BEGIN);
1788
1789 if(lpdwFileSizeHigh)
1790 *lpdwFileSizeHigh = size.HighPart;
1791
1792 return size.LowPart;
1793 }
1794}
1795
1796/*****************************************************************************
1797 * Name : DWORD HMDeviceDiskClass::GetFileType
1798 * Purpose : determine the handle type
1799 * Parameters: PHMHANDLEDATA pHMHandleData
1800 * Variables :
1801 * Result : API returncode
1802 * Remark :
1803 * Status :
1804 *
1805 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1806 *****************************************************************************/
1807
1808DWORD HMDeviceDiskClass::GetFileType(PHMHANDLEDATA pHMHandleData)
1809{
1810 dprintf2(("KERNEL32: HMDeviceDiskClass::GetFileType %s(%08x)\n",
1811 lpHMDeviceName, pHMHandleData));
1812
1813 return FILE_TYPE_DISK;
1814}
1815//******************************************************************************
1816//******************************************************************************
Note: See TracBrowser for help on using the repository browser.