source: trunk/src/kernel32/hmdevio.cpp@ 6086

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

added cdrom get/setvolume ioctls

File size: 19.1 KB
Line 
1/* $Id: hmdevio.cpp,v 1.14 2001-06-23 19:43:49 sandervl Exp $ */
2
3/*
4 * Win32 Device IOCTL API functions for OS/2
5 *
6 * Copyright 1998 Sander van Leeuwen
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_DOSPROFILE
13#define INCL_DOSDEVICES
14#define INCL_DOSDEVIOCTL
15#define INCL_GPI
16#define INCL_DOSFILEMGR /* File Manager values */
17#define INCL_DOSERRORS /* DOS Error values */
18#define INCL_DOSPROCESS /* DOS Process values */
19#define INCL_DOSMISC /* DOS Miscellanous values */
20#include <os2wrap.h> //Odin32 OS/2 api wrappers
21#include <string.h>
22#include <stdio.h>
23
24#include <win32type.h>
25#include <win32api.h>
26#include <misc.h>
27#include <win\winioctl.h>
28#include "hmdevio.h"
29#include "cio.h"
30#include "map.h"
31#include "exceptutil.h"
32
33#define DBG_LOCALLOG DBG_hmdevio
34#include "dbglocal.h"
35
36static BOOL fX86Init = FALSE;
37//SvL: Used in iccio.asm (how can you put these in the .asm data segment without messing things up?)
38ULONG ioentry = 0;
39USHORT gdt = 0;
40char devname[] = "/dev/fastio$";
41
42static BOOL GpdDevIOCtl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
43static BOOL MAPMEMIOCtl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
44static BOOL FXMEMMAPIOCtl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
45static BOOL VPCIOCtl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
46
47static WIN32DRV knownDriver[] =
48 {{"\\\\.\\GpdDev", "", TRUE, 666, GpdDevIOCtl},
49 { "\\\\.\\MAPMEM", "PMAP$", FALSE, 0, MAPMEMIOCtl},
50 { "FXMEMMAP.VXD", "PMAP$", FALSE, 0, FXMEMMAPIOCtl},
51#if 1
52 { "\\\\.\\VPCAppSv", "", TRUE, 667, VPCIOCtl}};
53#else
54 };
55#endif
56
57static int nrKnownDrivers = sizeof(knownDriver)/sizeof(WIN32DRV);
58BOOL fVirtualPC = FALSE;
59
60//******************************************************************************
61//******************************************************************************
62void RegisterDevices()
63{
64 HMDeviceDriver *driver;
65 DWORD rc;
66
67 for(int i=0;i<nrKnownDrivers;i++)
68 {
69 driver = new HMDeviceDriver(knownDriver[i].szWin32Name,
70 knownDriver[i].szOS2Name,
71 knownDriver[i].fCreateFile,
72 knownDriver[i].devIOCtl);
73
74 rc = HMDeviceRegister(knownDriver[i].szWin32Name, driver);
75 if (rc != NO_ERROR) /* check for errors */
76 dprintf(("KERNEL32:RegisterDevices: registering %s failed with %u.\n",
77 knownDriver[i].szWin32Name, rc));
78 }
79
80 //check registry for Odin driver plugin dlls
81 HKEY hkDrivers, hkDrvDll;
82
83 rc = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
84 "System\\CurrentControlSet\\Services",
85 0, KEY_READ, &hkDrivers);
86
87 if(rc == 0) {
88 char szDllName[CCHMAXPATH];
89 char szKeyName[CCHMAXPATH];
90 char szDrvName[CCHMAXPATH];
91 DWORD dwType, dwSize;
92 int iSubKey = 0;
93
94 while(rc == 0) {
95 rc = RegEnumKeyA(hkDrivers, iSubKey++, szKeyName, sizeof(szKeyName));
96 if(rc) break;
97
98 rc = RegOpenKeyExA(hkDrivers, szKeyName,
99 0, KEY_READ, &hkDrvDll);
100 if(rc == 0) {
101 dwSize = sizeof(szDllName);
102 rc = RegQueryValueExA(hkDrvDll,
103 "DllName",
104 NULL,
105 &dwType,
106 (LPBYTE)szDllName,
107 &dwSize);
108
109 RegCloseKey(hkDrvDll);
110 if(rc == 0 && dwType == REG_SZ)
111 {
112 HINSTANCE hDrvDll = LoadLibraryA(szDllName);
113 if(hDrvDll) {
114 sprintf(szDrvName, "\\\\.\\%s", szKeyName);
115 driver = new HMCustomDriver(hDrvDll, szDrvName);
116
117 rc = HMDeviceRegister(szDrvName, driver);
118 if (rc != NO_ERROR) /* check for errors */
119 dprintf(("KERNEL32:RegisterDevices: registering %s failed with %u.\n", szDrvName, rc));
120 }
121 }
122 rc = 0;
123 }
124 }
125 RegCloseKey(hkDrivers);
126 }
127
128 return;
129}
130//******************************************************************************
131//******************************************************************************
132HMDeviceDriver::HMDeviceDriver(LPCSTR lpDeviceName, LPSTR lpOS2DevName, BOOL fCreate,
133 WINIOCTL pDevIOCtl)
134 : HMDeviceKernelObjectClass(lpDeviceName)
135{
136 this->fCreateFile = fCreateFile;
137 this->szOS2Name = lpOS2DevName;
138 this->devIOCtl = pDevIOCtl;
139}
140//******************************************************************************
141//******************************************************************************
142HMDeviceDriver::HMDeviceDriver(LPCSTR lpDeviceName)
143 : HMDeviceKernelObjectClass(lpDeviceName)
144{
145}
146//******************************************************************************
147//******************************************************************************
148DWORD HMDeviceDriver::CreateFile (LPCSTR lpFileName,
149 PHMHANDLEDATA pHMHandleData,
150 PVOID lpSecurityAttributes,
151 PHMHANDLEDATA pHMHandleDataTemplate)
152{
153 APIRET rc;
154 HFILE hfFileHandle = 0L; /* Handle for file being manipulated */
155 ULONG ulAction = 0; /* Action taken by DosOpen */
156 ULONG sharetype = 0;
157
158 if(pHMHandleData->dwAccess & (GENERIC_READ | GENERIC_WRITE))
159 sharetype |= OPEN_ACCESS_READWRITE;
160 else
161 if(pHMHandleData->dwAccess & GENERIC_WRITE)
162 sharetype |= OPEN_ACCESS_WRITEONLY;
163
164 if(pHMHandleData->dwShare == 0)
165 sharetype |= OPEN_SHARE_DENYREADWRITE;
166 else
167 if(pHMHandleData->dwShare & (FILE_SHARE_READ | FILE_SHARE_WRITE))
168 sharetype |= OPEN_SHARE_DENYNONE;
169 else
170 if(pHMHandleData->dwShare & FILE_SHARE_WRITE)
171 sharetype |= OPEN_SHARE_DENYREAD;
172 else
173 if(pHMHandleData->dwShare & FILE_SHARE_READ)
174 sharetype |= OPEN_SHARE_DENYWRITE;
175
176 if(szOS2Name[0] == 0) {
177 pHMHandleData->hHMHandle = 0;
178 return (NO_ERROR);
179 }
180
181tryopen:
182 rc = DosOpen( szOS2Name, /* File path name */
183 &hfFileHandle, /* File handle */
184 &ulAction, /* Action taken */
185 0,
186 FILE_NORMAL,
187 FILE_OPEN,
188 sharetype,
189 0L); /* No extended attribute */
190
191 if(rc == ERROR_TOO_MANY_OPEN_FILES) {
192 ULONG CurMaxFH;
193 LONG ReqCount = 32;
194
195 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
196 if(rc) {
197 dprintf(("DosSetRelMaxFH returned %d", rc));
198 return rc;
199 }
200 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
201 goto tryopen;
202 }
203
204 dprintf(("DosOpen %s returned %d\n", szOS2Name, rc));
205
206 if(rc == NO_ERROR) {
207 pHMHandleData->hHMHandle = hfFileHandle;
208 return (NO_ERROR);
209 }
210 else return(rc);
211}
212//******************************************************************************
213//******************************************************************************
214BOOL HMDeviceDriver::CloseHandle(PHMHANDLEDATA pHMHandleData)
215{
216 DWORD rc = 0;
217
218 if(pHMHandleData->hHMHandle) {
219 rc = DosClose(pHMHandleData->hHMHandle);
220 }
221 pHMHandleData->hHMHandle = 0;
222 return rc;
223}
224//******************************************************************************
225//******************************************************************************
226BOOL HMDeviceDriver::DeviceIoControl(PHMHANDLEDATA pHMHandleData, DWORD dwIoControlCode,
227 LPVOID lpInBuffer, DWORD nInBufferSize,
228 LPVOID lpOutBuffer, DWORD nOutBufferSize,
229 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
230{
231 return devIOCtl(pHMHandleData->hHMHandle, dwIoControlCode, lpInBuffer, nInBufferSize,
232 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
233}
234//******************************************************************************
235//******************************************************************************
236static BOOL GpdDevIOCtl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
237{
238 ULONG port, val = 0;
239
240 if(fX86Init == FALSE) {
241 if(io_init() == 0)
242 fX86Init = TRUE;
243 else return(FALSE);
244 }
245
246 *lpBytesReturned = 0;
247
248 port = ((GENPORT_WRITE_INPUT *)lpInBuffer)->PortNumber;
249
250 switch((dwIoControlCode >> 2) & 0xFFF) {
251 case IOCTL_GPD_READ_PORT_UCHAR:
252 if(nOutBufferSize < sizeof(char))
253 return(FALSE);
254
255 val = c_inb(port);
256 *(char *)lpOutBuffer = val;
257 *lpBytesReturned = sizeof(char);
258 break;
259 case IOCTL_GPD_READ_PORT_USHORT:
260 if(nOutBufferSize < sizeof(USHORT))
261 return(FALSE);
262
263 val = c_inw(port);
264 *(USHORT *)lpOutBuffer = val;
265 *lpBytesReturned = sizeof(USHORT);
266 break;
267 case IOCTL_GPD_READ_PORT_ULONG:
268 if(nOutBufferSize < sizeof(ULONG))
269 return(FALSE);
270
271 val = c_inl(port);
272 *(ULONG *)lpOutBuffer = val;
273 *lpBytesReturned = sizeof(ULONG);
274 break;
275 case IOCTL_GPD_WRITE_PORT_UCHAR:
276 val = ((GENPORT_WRITE_INPUT *)lpInBuffer)->CharData;
277 c_outb(port, val);
278 break;
279 case IOCTL_GPD_WRITE_PORT_USHORT:
280 val = ((GENPORT_WRITE_INPUT *)lpInBuffer)->ShortData;
281 c_outw(port, val);
282 break;
283 case IOCTL_GPD_WRITE_PORT_ULONG:
284 val = ((GENPORT_WRITE_INPUT *)lpInBuffer)->LongData;
285 c_outl(port, val);
286 break;
287 default:
288 dprintf(("GpdDevIOCtl unknown func %X\n", (dwIoControlCode >> 2) & 0xFFF));
289 return(FALSE);
290 }
291
292 return(TRUE);
293}
294//******************************************************************************
295//******************************************************************************
296static BOOL MAPMEMIOCtl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
297{
298 PHYSICAL_MEMORY_INFO *meminfo = (PHYSICAL_MEMORY_INFO *)lpInBuffer;
299 struct map_ioctl memmap;
300
301 *lpBytesReturned = 0;
302
303 switch((dwIoControlCode >> 2) & 0xFFF) {
304 case IOCTL_MAPMEM_MAP_USER_PHYSICAL_MEMORY:
305 if(nInBufferSize != sizeof(PHYSICAL_MEMORY_INFO))
306 return(FALSE);
307
308 memmap.a.phys = meminfo->BusAddress.u.LowPart;
309 memmap.size = meminfo->Length;
310 dprintf(("DeviceIoControl map phys address %X length %X\n", memmap.a.phys, memmap.size));
311 if(mpioctl((HFILE)hDevice, IOCTL_MAP, &memmap) == -1) {
312 dprintf(("mpioctl failed!\n"));
313 return(FALSE);
314 }
315
316 dprintf(("DeviceIoControl map virt address = %X\n", memmap.a.user));
317 *(ULONG *)lpOutBuffer = (ULONG)memmap.a.user;
318 break;
319 case IOCTL_MAPMEM_UNMAP_USER_PHYSICAL_MEMORY:
320 dprintf(("Unmap mapping %X\n", *(ULONG *)lpInBuffer));
321 memmap.a.phys = *(ULONG *)lpInBuffer;
322 memmap.size = 0;
323 if(mpioctl((HFILE)hDevice, IOCTL_MAP, &memmap) == -1)
324 return(FALSE);
325 break;
326 default:
327 dprintf(("MAPMEMIOCtl unknown func %X\n", (dwIoControlCode >> 2) & 0xFFF));
328 return(FALSE);
329 }
330
331 return(TRUE);
332}
333//******************************************************************************
334//******************************************************************************
335static BOOL FXMEMMAPIOCtl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
336{
337 struct map_ioctl memmap;
338 MAPDEVREQUEST *vxdmem = (MAPDEVREQUEST *)lpInBuffer;
339
340 switch(dwIoControlCode) {
341 case 1:
342 break;
343 case 2:
344 memmap.a.phys = (DWORD)vxdmem->mdr_PhysicalAddress;
345 memmap.size = vxdmem->mdr_SizeInBytes;
346 dprintf(("DeviceIoControl map phys address %X length %X\n", memmap.a.phys, memmap.size));
347 if(mpioctl((HFILE)hDevice, IOCTL_MAP, &memmap) == -1) {
348 dprintf(("mpioctl failed!\n"));
349 return(FALSE);
350 }
351
352 dprintf(("DeviceIoControl map virt address = %X\n", memmap.a.user));
353 vxdmem->mdr_LinearAddress = (PVOID)memmap.a.user;
354 break;
355 default:
356 dprintf(("FXMEMMAPIOCtl unknown func %X\n", (dwIoControlCode >> 2) & 0xFFF));
357 return(FALSE);
358 }
359
360 return(TRUE);
361}
362//******************************************************************************
363//******************************************************************************
364static BOOL VPCIOCtl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
365{
366 APIRET rc;
367
368 dprintf(("VPCIOCtl func %x: %x %d %x %d %x %x", dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped));
369 switch(dwIoControlCode) {
370 case 0x9C402880: //0x00
371 if(nOutBufferSize < 4) {
372 SetLastError(ERROR_BAD_LENGTH);
373 return FALSE;
374 }
375 *(DWORD *)lpOutBuffer = 0x60001;
376 *lpBytesReturned = 4;
377 return TRUE;
378
379 case 0x9C402894: //0x14 (get IDT table)
380 {
381 DWORD *lpBuffer = (DWORD *)lpOutBuffer;
382 if(nOutBufferSize < 0x800) {
383 SetLastError(ERROR_BAD_LENGTH);
384 return FALSE;
385 }
386 memset(lpOutBuffer, 0, nOutBufferSize);
387 for(int i=0;i<32;i++) {
388 lpBuffer[i*2] = 0x0178c4c8;
389 lpBuffer[i*2+1] = 0xfff18F00;
390 }
391 for(i=0x50;i<0x57;i++) {
392 lpBuffer[i*2] = 0x0178c4c8;
393 lpBuffer[i*2+1] = 0xfff18E00;
394 }
395 for(i=0x70;i<0x77;i++) {
396 lpBuffer[i*2] = 0x0178c4c8;
397 lpBuffer[i*2+1] = 0xfff18E00;
398 }
399 lpBuffer[0x4F*2] = 0x0178c4c8;
400 lpBuffer[0x4F*2+1] = 0xfff18E00;
401 lpBuffer[0xEF*2] = 0x0178c4c8;
402 lpBuffer[0xEF*2+1] = 0xfff18E00;
403 *lpBytesReturned = 0xFF*8;
404 return TRUE;
405 }
406 case 0x9C40288C: //0x0C change IDT
407 if(nInBufferSize < 0x22) {
408 SetLastError(ERROR_BAD_LENGTH);
409 return FALSE;
410 }
411 fVirtualPC = TRUE;
412 return TRUE;
413
414 case 0x9C402884: //0x04 ExAllocatePoolWithTag
415 {
416 DWORD *lpBuffer = (DWORD *)lpInBuffer;
417 if(nInBufferSize < 0x08) {
418 SetLastError(ERROR_BAD_LENGTH);
419 return FALSE;
420 }
421 dprintf(("In: %x %x", lpBuffer[0], lpBuffer[1]));
422 return TRUE;
423 }
424
425 case 0x9C402898: //0x18 Remove IDT patch
426 if(nInBufferSize < 0x01) {
427 SetLastError(ERROR_BAD_LENGTH);
428 return FALSE;
429 }
430 fVirtualPC = FALSE;
431 return TRUE;
432 default:
433 dprintf(("VPCIOCtl unknown func %X\n", dwIoControlCode));
434 return FALSE;
435 }
436}
437//******************************************************************************
438//******************************************************************************
439HMCustomDriver::HMCustomDriver(HINSTANCE hInstance, LPCSTR lpDeviceName)
440 : HMDeviceDriver(lpDeviceName)
441{
442 hDrvDll = hInstance ;
443 *(ULONG *)&driverOpen = (ULONG)GetProcAddress(hDrvDll, "DrvOpen");
444 *(ULONG *)&driverClose = (ULONG)GetProcAddress(hDrvDll, "DrvClose");
445 *(ULONG *)&driverIOCtl = (ULONG)GetProcAddress(hDrvDll, "DrvIOCtl");
446}
447//******************************************************************************
448//******************************************************************************
449HMCustomDriver::~HMCustomDriver()
450{
451 FreeLibrary(hDrvDll);
452}
453//******************************************************************************
454//******************************************************************************
455DWORD HMCustomDriver::CreateFile (LPCSTR lpFileName,
456 PHMHANDLEDATA pHMHandleData,
457 PVOID lpSecurityAttributes,
458 PHMHANDLEDATA pHMHandleDataTemplate)
459{
460 pHMHandleData->hHMHandle = driverOpen(pHMHandleData->dwAccess, pHMHandleData->dwShare);
461 if(pHMHandleData->hHMHandle == 0) {
462 return 2;
463 }
464 return 0;
465}
466//******************************************************************************
467//******************************************************************************
468BOOL HMCustomDriver::CloseHandle(PHMHANDLEDATA pHMHandleData)
469{
470 if(pHMHandleData->hHMHandle) {
471 driverClose(pHMHandleData->hHMHandle);
472 }
473 pHMHandleData->hHMHandle = 0;
474 return TRUE;
475}
476//******************************************************************************
477//******************************************************************************
478BOOL HMCustomDriver::DeviceIoControl(PHMHANDLEDATA pHMHandleData, DWORD dwIoControlCode,
479 LPVOID lpInBuffer, DWORD nInBufferSize,
480 LPVOID lpOutBuffer, DWORD nOutBufferSize,
481 LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)
482{
483 BOOL ret;
484
485 ret = driverIOCtl(pHMHandleData->hHMHandle, dwIoControlCode, lpInBuffer, nInBufferSize,
486 lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
487 dprintf(("DeviceIoControl %x returned %d", dwIoControlCode, ret));
488 return ret;
489}
490//******************************************************************************
491//******************************************************************************
492BOOL WIN32API QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)
493{
494 QWORD time;
495 APIRET rc;
496
497 rc = DosTmrQueryTime(&time);
498 if(rc) {
499 dprintf(("DosTmrQueryTime returned %d\n", rc));
500 return(FALSE);
501 }
502 lpPerformanceCount->u.LowPart = time.ulLo;
503 lpPerformanceCount->u.HighPart = time.ulHi;
504 return(TRUE);
505}
506//******************************************************************************
507//******************************************************************************
508BOOL WIN32API QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)
509{
510 APIRET rc;
511 ULONG freq;
512
513 rc = DosTmrQueryFreq(&freq);
514 if(rc) {
515 dprintf(("DosTmrQueryFreq returned %d\n", rc));
516 return(FALSE);
517 }
518 lpFrequency->u.LowPart = freq;
519 lpFrequency->u.HighPart = 0;
520 dprintf2(("QueryPerformanceFrequency returned 0x%X%X\n", lpFrequency->u.HighPart, lpFrequency->u.LowPart));
521 return(TRUE);
522}
523//******************************************************************************
524//******************************************************************************
Note: See TracBrowser for help on using the repository browser.