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

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

disk updates

File size: 18.1 KB
Line 
1/* $Id: hmdisk.cpp,v 1.8 2001-06-16 16:10:12 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
27HMDeviceDiskClass::HMDeviceDiskClass(LPCSTR lpDeviceName) : HMDeviceKernelObjectClass(lpDeviceName)
28{
29 HMDeviceRegisterEx("\\\\.\\PHYSICALDRIVE", this, NULL);
30}
31
32/*****************************************************************************
33 * Name : HMDeviceDiskClass::FindDevice
34 * Purpose : Checks if lpDeviceName belongs to this device class
35 * Parameters: LPCSTR lpClassDevName
36 * LPCSTR lpDeviceName
37 * int namelength
38 * Variables :
39 * Result : checks if name is for a drive of physical disk
40 * Remark :
41 * Status :
42 *
43 * Author : SvL
44 *****************************************************************************/
45BOOL HMDeviceDiskClass::FindDevice(LPCSTR lpClassDevName, LPCSTR lpDeviceName, int namelength)
46{
47 //\\.\x: -> length 6
48 //\\.\PHYSICALDRIVEn -> length 18
49 if(namelength != 6 && namelength != 18) {
50 return FALSE;
51 }
52
53 //SvL: \\.\x: -> drive x (i.e. \\.\C:)
54 // \\.\PHYSICALDRIVEn -> drive n (n>=0)
55 if((strncmp(lpDeviceName, "\\\\.\\", 4) == 0) &&
56 namelength == 6 && lpDeviceName[5] == ':')
57 {
58 return TRUE;
59 }
60 if((strncmp(lpDeviceName, "\\\\.\\PHYSICALDRIVE", 17) == 0) && namelength == 18) {
61 return TRUE;
62 }
63 return FALSE;
64}
65//******************************************************************************
66//TODO: PHYSICALDRIVEn!!
67//******************************************************************************
68DWORD HMDeviceDiskClass::CreateFile (LPCSTR lpFileName,
69 PHMHANDLEDATA pHMHandleData,
70 PVOID lpSecurityAttributes,
71 PHMHANDLEDATA pHMHandleDataTemplate)
72{
73 HFILE hFile;
74 HFILE hTemplate;
75
76 dprintf2(("KERNEL32: HMDeviceDiskClass::CreateFile %s(%s,%08x,%08x,%08x)\n",
77 lpHMDeviceName,
78 lpFileName,
79 pHMHandleData,
80 lpSecurityAttributes,
81 pHMHandleDataTemplate));
82
83 //TODO: check in NT if CREATE_ALWAYS is allowed!!
84 if(pHMHandleData->dwCreation != OPEN_EXISTING) {
85 dprintf(("Invalid creation flags %x!!", pHMHandleData->dwCreation));
86 return ERROR_INVALID_PARAMETER;
87 }
88 if(strncmp(lpFileName, // "support" for local unc names
89 "\\\\.\\",
90 4) == 0)
91 {
92 lpFileName+=4;
93 }
94
95 //Disable error popus. NT allows an app to open a cdrom/dvd drive without a disk inside
96 //OS/2 fails in that case with error ERROR_NOT_READY
97 OSLibDosDisableHardError(TRUE);
98 hFile = OSLibDosCreateFile((LPSTR)lpFileName,
99 pHMHandleData->dwAccess,
100 pHMHandleData->dwShare,
101 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
102 pHMHandleData->dwCreation,
103 pHMHandleData->dwFlags,
104 hTemplate);
105 OSLibDosDisableHardError(FALSE);
106
107 if (hFile != INVALID_HANDLE_ERROR || GetLastError() == ERROR_NOT_READY)
108 {
109 if(hFile == INVALID_HANDLE_ERROR) {
110 SetLastError(NO_ERROR);
111 pHMHandleData->hHMHandle = 0; //handle lookup fails if this is set to -1
112 }
113 else pHMHandleData->hHMHandle = hFile;
114
115 pHMHandleData->dwUserData = *lpFileName; //save drive letter
116 if(pHMHandleData->dwUserData >= 'a') {
117 pHMHandleData->dwUserData = pHMHandleData->dwUserData - ((int)'a' - (int)'A');
118 }
119 return (NO_ERROR);
120 }
121 else {
122 dprintf(("CreateFile failed; error %d", GetLastError()));
123 return(GetLastError());
124 }
125}
126//******************************************************************************
127//******************************************************************************
128BOOL HMDeviceDiskClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
129{
130 if(pHMHandleData->hHMHandle) {
131 return OSLibDosClose(pHMHandleData->hHMHandle);
132 }
133 return TRUE;
134}
135//******************************************************************************
136//******************************************************************************
137BOOL HMDeviceDiskClass::DeviceIoControl(PHMHANDLEDATA pHMHandleData, DWORD dwIoControlCode,
138 LPVOID lpInBuffer, DWORD nInBufferSize,
139 LPVOID lpOutBuffer, DWORD nOutBufferSize,
140 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
141{
142#ifdef DEBUG
143 char *msg = NULL;
144
145 switch(dwIoControlCode)
146 {
147 case FSCTL_DELETE_REPARSE_POINT:
148 msg = "FSCTL_DELETE_REPARSE_POINT";
149 break;
150 case FSCTL_DISMOUNT_VOLUME:
151 msg = "FSCTL_DISMOUNT_VOLUME";
152 break;
153 case FSCTL_GET_COMPRESSION:
154 msg = "FSCTL_GET_COMPRESSION";
155 break;
156 case FSCTL_GET_REPARSE_POINT:
157 msg = "FSCTL_GET_REPARSE_POINT";
158 break;
159 case FSCTL_LOCK_VOLUME:
160 msg = "FSCTL_LOCK_VOLUME";
161 break;
162 case FSCTL_QUERY_ALLOCATED_RANGES:
163 msg = "FSCTL_QUERY_ALLOCATED_RANGES";
164 break;
165 case FSCTL_SET_COMPRESSION:
166 msg = "FSCTL_SET_COMPRESSION";
167 break;
168 case FSCTL_SET_REPARSE_POINT:
169 msg = "FSCTL_SET_REPARSE_POINT";
170 break;
171 case FSCTL_SET_SPARSE:
172 msg = "FSCTL_SET_SPARSE";
173 break;
174 case FSCTL_SET_ZERO_DATA:
175 msg = "FSCTL_SET_ZERO_DATA";
176 break;
177 case FSCTL_UNLOCK_VOLUME:
178 msg = "FSCTL_UNLOCK_VOLUME";
179 break;
180 case IOCTL_DISK_CHECK_VERIFY:
181 msg = "IOCTL_DISK_CHECK_VERIFY";
182 break;
183 case IOCTL_DISK_EJECT_MEDIA:
184 msg = "IOCTL_DISK_EJECT_MEDIA";
185 break;
186 case IOCTL_DISK_FORMAT_TRACKS:
187 msg = "IOCTL_DISK_FORMAT_TRACKS";
188 break;
189 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
190 msg = "IOCTL_DISK_GET_DRIVE_GEOMETRY";
191 break;
192 case IOCTL_DISK_GET_DRIVE_LAYOUT:
193 msg = "IOCTL_DISK_GET_DRIVE_LAYOUT";
194 break;
195 case IOCTL_DISK_GET_MEDIA_TYPES:
196 msg = "IOCTL_DISK_GET_MEDIA_TYPES";
197 break;
198 case IOCTL_DISK_GET_PARTITION_INFO:
199 msg = "IOCTL_DISK_GET_PARTITION_INFO";
200 break;
201 case IOCTL_DISK_LOAD_MEDIA:
202 msg = "IOCTL_DISK_LOAD_MEDIA";
203 break;
204 case IOCTL_DISK_MEDIA_REMOVAL:
205 msg = "IOCTL_DISK_MEDIA_REMOVAL";
206 break;
207 case IOCTL_DISK_PERFORMANCE:
208 msg = "IOCTL_DISK_PERFORMANCE";
209 break;
210 case IOCTL_DISK_REASSIGN_BLOCKS:
211 msg = "IOCTL_DISK_REASSIGN_BLOCKS";
212 break;
213 case IOCTL_DISK_SET_DRIVE_LAYOUT:
214 msg = "IOCTL_DISK_SET_DRIVE_LAYOUT";
215 break;
216 case IOCTL_DISK_SET_PARTITION_INFO:
217 msg = "IOCTL_DISK_SET_PARTITION_INFO";
218 break;
219 case IOCTL_DISK_VERIFY:
220 msg = "IOCTL_DISK_VERIFY";
221 break;
222 case IOCTL_SERIAL_LSRMST_INSERT:
223 msg = "IOCTL_SERIAL_LSRMST_INSERT";
224 break;
225 case IOCTL_STORAGE_CHECK_VERIFY:
226 msg = "IOCTL_STORAGE_CHECK_VERIFY";
227 break;
228 case IOCTL_STORAGE_EJECT_MEDIA:
229 msg = "IOCTL_STORAGE_EJECT_MEDIA";
230 break;
231 case IOCTL_STORAGE_GET_MEDIA_TYPES:
232 msg = "IOCTL_STORAGE_GET_MEDIA_TYPES";
233 break;
234 case IOCTL_STORAGE_LOAD_MEDIA:
235 msg = "IOCTL_STORAGE_LOAD_MEDIA";
236 break;
237 case IOCTL_STORAGE_MEDIA_REMOVAL:
238 msg = "IOCTL_STORAGE_MEDIA_REMOVAL";
239 break;
240 case IOCTL_SCSI_PASS_THROUGH:
241 msg = "IOCTL_SCSI_PASS_THROUGH";
242 break;
243 case IOCTL_SCSI_MINIPORT:
244 msg = "IOCTL_SCSI_MINIPORT";
245 break;
246 case IOCTL_SCSI_GET_INQUIRY_DATA:
247 msg = "IOCTL_SCSI_GET_INQUIRY_DATA";
248 break;
249 case IOCTL_SCSI_GET_CAPABILITIES:
250 msg = "IOCTL_SCSI_GET_CAPABILITIES";
251 break;
252 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
253 msg = "IOCTL_SCSI_PASS_THROUGH_DIRECT";
254 break;
255 case IOCTL_SCSI_GET_ADDRESS:
256 msg = "IOCTL_SCSI_GET_ADDRESS";
257 break;
258 case IOCTL_SCSI_RESCAN_BUS:
259 msg = "IOCTL_SCSI_RESCAN_BUS";
260 break;
261 case IOCTL_SCSI_GET_DUMP_POINTERS:
262 msg = "IOCTL_SCSI_GET_DUMP_POINTERS";
263 break;
264 case IOCTL_SCSI_FREE_DUMP_POINTERS:
265 msg = "IOCTL_SCSI_FREE_DUMP_POINTERS";
266 break;
267 case IOCTL_IDE_PASS_THROUGH:
268 msg = "IOCTL_IDE_PASS_THROUGH";
269 break;
270 }
271 if(msg) {
272 dprintf(("HMDeviceDiskClass::DeviceIoControl %s", msg));
273 }
274#endif
275
276 switch(dwIoControlCode)
277 {
278 case FSCTL_DELETE_REPARSE_POINT:
279 case FSCTL_DISMOUNT_VOLUME:
280 case FSCTL_GET_COMPRESSION:
281 case FSCTL_GET_REPARSE_POINT:
282 case FSCTL_LOCK_VOLUME:
283 case FSCTL_QUERY_ALLOCATED_RANGES:
284 case FSCTL_SET_COMPRESSION:
285 case FSCTL_SET_REPARSE_POINT:
286 case FSCTL_SET_SPARSE:
287 case FSCTL_SET_ZERO_DATA:
288 case FSCTL_UNLOCK_VOLUME:
289 break;
290
291 case IOCTL_DISK_CHECK_VERIFY:
292 case IOCTL_DISK_EJECT_MEDIA:
293 case IOCTL_DISK_FORMAT_TRACKS:
294 case IOCTL_DISK_GET_DRIVE_LAYOUT:
295 break;
296
297 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
298 case IOCTL_DISK_GET_MEDIA_TYPES:
299 {
300 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)lpOutBuffer;
301 if(nOutBufferSize < sizeof(DISK_GEOMETRY)) {
302 SetLastError(ERROR_INSUFFICIENT_BUFFER);
303 return FALSE;
304 }
305 if(lpBytesReturned) {
306 *lpBytesReturned = 0;
307 }
308 if(OSLibDosGetDiskGeometry(pHMHandleData->dwUserData, pGeom) == FALSE) {
309 return FALSE;
310 }
311 if(lpBytesReturned) {
312 *lpBytesReturned = sizeof(DISK_GEOMETRY);
313 }
314 return TRUE;
315 }
316
317 case IOCTL_DISK_GET_PARTITION_INFO:
318 case IOCTL_DISK_LOAD_MEDIA:
319 case IOCTL_DISK_MEDIA_REMOVAL:
320 case IOCTL_DISK_PERFORMANCE:
321 case IOCTL_DISK_REASSIGN_BLOCKS:
322 case IOCTL_DISK_SET_DRIVE_LAYOUT:
323 case IOCTL_DISK_SET_PARTITION_INFO:
324 case IOCTL_DISK_VERIFY:
325 case IOCTL_SERIAL_LSRMST_INSERT:
326 break;
327
328 case IOCTL_STORAGE_CHECK_VERIFY:
329 if(lpBytesReturned) {
330 lpBytesReturned = 0;
331 }
332 //TODO: check if disk has been inserted or removed
333 if(pHMHandleData->hHMHandle == 0) {
334 SetLastError(ERROR_NOT_READY);
335 return FALSE;
336 }
337 SetLastError(NO_ERROR);
338 return TRUE;
339
340 case IOCTL_STORAGE_EJECT_MEDIA:
341 case IOCTL_STORAGE_GET_MEDIA_TYPES:
342 case IOCTL_STORAGE_LOAD_MEDIA:
343 case IOCTL_STORAGE_MEDIA_REMOVAL:
344 break;
345 case IOCTL_SCSI_PASS_THROUGH:
346 case IOCTL_SCSI_MINIPORT:
347 case IOCTL_SCSI_GET_INQUIRY_DATA:
348 case IOCTL_SCSI_GET_CAPABILITIES:
349 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
350 break;
351
352 case IOCTL_SCSI_GET_ADDRESS:
353 {
354 HINSTANCE hInstAspi;
355 DWORD (WIN32API *GetASPI32SupportInfo)();
356 DWORD (CDECL *SendASPI32Command)(LPSRB lpSRB);
357 DWORD numAdapters, rc;
358 SRB srb;
359 int i, j, k;
360
361 if(!lpOutBuffer || nOutBufferSize < 8) {
362 SetLastError(ERROR_INSUFFICIENT_BUFFER); //todo: right error?
363 return(FALSE);
364 }
365 SCSI_ADDRESS *addr = (SCSI_ADDRESS *)lpOutBuffer;
366 addr->Length = sizeof(SCSI_ADDRESS);
367 addr->PortNumber = 0;
368 addr->PathId = 0;
369 hInstAspi = LoadLibraryA("WNASPI32.DLL");
370 if(hInstAspi == NULL) {
371 SetLastError(ERROR_INVALID_PARAMETER); //todo
372 return FALSE;
373 }
374 *(FARPROC *)&GetASPI32SupportInfo = GetProcAddress(hInstAspi, "GetASPI32SupportInfo");
375 *(FARPROC *)&SendASPI32Command = GetProcAddress(hInstAspi, "SendASPI32Command");
376 numAdapters = GetASPI32SupportInfo();
377 if(LOBYTE(numAdapters) == 0) goto failure;
378
379 memset(&srb, 0, sizeof(srb));
380 srb.common.SRB_Cmd = SC_HA_INQUIRY;
381 rc = SendASPI32Command(&srb);
382
383 char drivename[3];
384 drivename[0] = (char)pHMHandleData->dwUserData;
385 drivename[1] = ':';
386 drivename[2] = 0;
387
388 for(i=0;i<LOBYTE(numAdapters);i++) {
389 for(j=0;j<8;j++) {
390 for(k=0;k<16;k++) {
391 memset(&srb, 0, sizeof(srb));
392 srb.common.SRB_Cmd = SC_GET_DEV_TYPE;
393 srb.devtype.SRB_HaId = i;
394 srb.devtype.SRB_Target = j;
395 srb.devtype.SRB_Lun = k;
396 rc = SendASPI32Command(&srb);
397 if(rc == SS_COMP) {
398 if(srb.devtype.SRB_DeviceType == SS_DEVTYPE_CDROM &&
399 GetDriveTypeA(drivename) == DRIVE_CDROM)
400 {
401 goto done;
402 }
403 }
404 }
405 }
406 }
407done:
408 if(rc == SS_COMP) {
409 addr->TargetId = j;
410 addr->Lun = k;
411 SetLastError(ERROR_SUCCESS);
412 }
413 else SetLastError(ERROR_FILE_NOT_FOUND); //todo
414 FreeLibrary(hInstAspi);
415 return TRUE;
416failure:
417 FreeLibrary(hInstAspi);
418 SetLastError(ERROR_INVALID_PARAMETER); //todo
419 return FALSE;
420 }
421
422 case IOCTL_SCSI_RESCAN_BUS:
423 case IOCTL_SCSI_GET_DUMP_POINTERS:
424 case IOCTL_SCSI_FREE_DUMP_POINTERS:
425 case IOCTL_IDE_PASS_THROUGH:
426 break;
427
428 }
429 dprintf(("HMDeviceDiskClass::DeviceIoControl: unimplemented dwIoControlCode=%08lx\n", dwIoControlCode));
430 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
431 return FALSE;
432}
433/*****************************************************************************
434 * Name : BOOL HMDeviceDiskClass::ReadFile
435 * Purpose : read data from handle / device
436 * Parameters: PHMHANDLEDATA pHMHandleData,
437 * LPCVOID lpBuffer,
438 * DWORD nNumberOfBytesToRead,
439 * LPDWORD lpNumberOfBytesRead,
440 * LPOVERLAPPED lpOverlapped
441 * Variables :
442 * Result : Boolean
443 * Remark :
444 * Status :
445 *
446 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
447 *****************************************************************************/
448
449BOOL HMDeviceDiskClass::ReadFile(PHMHANDLEDATA pHMHandleData,
450 LPCVOID lpBuffer,
451 DWORD nNumberOfBytesToRead,
452 LPDWORD lpNumberOfBytesRead,
453 LPOVERLAPPED lpOverlapped)
454{
455 LPVOID lpRealBuf;
456 Win32MemMap *map;
457 DWORD offset, bytesread;
458 BOOL bRC;
459
460 dprintf2(("KERNEL32: HMDeviceDiskClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
461 lpHMDeviceName,
462 pHMHandleData,
463 lpBuffer,
464 nNumberOfBytesToRead,
465 lpNumberOfBytesRead,
466 lpOverlapped));
467
468 //SvL: It's legal for this pointer to be NULL
469 if(lpNumberOfBytesRead)
470 *lpNumberOfBytesRead = 0;
471 else
472 lpNumberOfBytesRead = &bytesread;
473
474 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
475 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
476 SetLastError(ERROR_INVALID_PARAMETER);
477 return FALSE;
478 }
479 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
480 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
481 }
482
483 //SvL: DosRead doesn't like writing to memory addresses returned by
484 // DosAliasMem -> search for original memory mapped pointer and use
485 // that one + commit pages if not already present
486 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
487 if(map) {
488 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
489 DWORD nrpages = nNumberOfBytesToRead/4096;
490 if(offset & 0xfff)
491 nrpages++;
492 if(nNumberOfBytesToRead & 0xfff)
493 nrpages++;
494
495 map->commitPage(offset & ~0xfff, TRUE, nrpages);
496 }
497 else lpRealBuf = (LPVOID)lpBuffer;
498
499 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
500 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
501 }
502// else {
503 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
504 (PVOID)lpRealBuf,
505 nNumberOfBytesToRead,
506 lpNumberOfBytesRead);
507// }
508
509 if(bRC == 0) {
510 dprintf(("KERNEL32: HMDeviceDiskClass::ReadFile returned %08xh %x", bRC, GetLastError()));
511 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
512 }
513
514 return bRC;
515}
516/*****************************************************************************
517 * Name : DWORD HMDeviceDiskClass::SetFilePointer
518 * Purpose : set file pointer
519 * Parameters: PHMHANDLEDATA pHMHandleData
520 * LONG lDistanceToMove
521 * PLONG lpDistanceToMoveHigh
522 * DWORD dwMoveMethod
523 * Variables :
524 * Result : API returncode
525 * Remark :
526 * Status :
527 *
528 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
529 *****************************************************************************/
530
531DWORD HMDeviceDiskClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
532 LONG lDistanceToMove,
533 PLONG lpDistanceToMoveHigh,
534 DWORD dwMoveMethod)
535{
536 DWORD ret;
537
538 dprintf2(("KERNEL32: HMDeviceDiskClass::SetFilePointer %s(%08xh,%08xh,%08xh,%08xh)\n",
539 lpHMDeviceName,
540 pHMHandleData,
541 lDistanceToMove,
542 lpDistanceToMoveHigh,
543 dwMoveMethod));
544
545 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
546 lDistanceToMove,
547 (DWORD *)lpDistanceToMoveHigh,
548 dwMoveMethod);
549
550 if(ret == -1) {
551 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
552 }
553 return ret;
554}
555//******************************************************************************
556//******************************************************************************
Note: See TracBrowser for help on using the repository browser.