device.c 40.2 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * Win32 device functions
 *
 * Copyright 1998 Marcus Meissner
Alexandre Julliard's avatar
Alexandre Julliard committed
5
 * Copyright 1998 Ulrich Weigand
Alexandre Julliard's avatar
Alexandre Julliard committed
6
 * Copyright 1998 Patrik Stridvall
Alexandre Julliard's avatar
Alexandre Julliard committed
7
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
8 9
 */

10
#include "config.h"
11
#include "wine/port.h"
12

Alexandre Julliard's avatar
Alexandre Julliard committed
13 14 15 16
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
17
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
18
#include <time.h>
19

20
#include "windef.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
21
#include "winbase.h"
22
#include "winreg.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
23 24
#include "winerror.h"
#include "file.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
25
#include "winioctl.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
26 27 28
#include "winnt.h"
#include "msdos.h"
#include "miscemu.h"
29
#include "stackframe.h"
30
#include "wine/server.h"
31
#include "debugtools.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
32

33
DEFAULT_DEBUG_CHANNEL(win32);
34

35

36
static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, 
Alexandre Julliard's avatar
Alexandre Julliard committed
37 38 39 40
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped);
41
static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode, 
42 43 44 45
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped);
46 47 48 49 50
static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode, 
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped);
Alexandre Julliard's avatar
Alexandre Julliard committed
51

52
static DWORD VxDCall_VMM( DWORD service, CONTEXT86 *context );
Alexandre Julliard's avatar
Alexandre Julliard committed
53

54
static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, 
Alexandre Julliard's avatar
Alexandre Julliard committed
55 56 57 58 59
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped);

60 61 62 63 64 65
static BOOL DeviceIo_VCD(DWORD dwIoControlCode, 
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped);

66
static DWORD VxDCall_VWin32( DWORD service, CONTEXT86 *context );
67

68
static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, 
69 70 71 72 73
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped);

74 75 76 77 78
static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode, 
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped);
79 80 81 82 83 84

static BOOL DeviceIo_HASP (DWORD dwIoControlCode, 
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped);
Alexandre Julliard's avatar
Alexandre Julliard committed
85 86 87 88 89 90 91 92
/*
 * VxD names are taken from the Win95 DDK
 */

struct VxDInfo
{
    LPCSTR  name;
    WORD    id;
93
    DWORD (*vxdcall)(DWORD, CONTEXT86 *);
94
    BOOL  (*deviceio)(DWORD, LPVOID, DWORD, 
Alexandre Julliard's avatar
Alexandre Julliard committed
95
                        LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
96 97 98
};

static const struct VxDInfo VxDList[] = 
Alexandre Julliard's avatar
Alexandre Julliard committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
{
    /* Standard VxD IDs */
    { "VMM",      0x0001, VxDCall_VMM, NULL },
    { "DEBUG",    0x0002, NULL, NULL },
    { "VPICD",    0x0003, NULL, NULL },
    { "VDMAD",    0x0004, NULL, NULL },
    { "VTD",      0x0005, NULL, NULL },
    { "V86MMGR",  0x0006, NULL, NULL },
    { "PAGESWAP", 0x0007, NULL, NULL },
    { "PARITY",   0x0008, NULL, NULL },
    { "REBOOT",   0x0009, NULL, NULL },
    { "VDD",      0x000A, NULL, NULL },
    { "VSD",      0x000B, NULL, NULL },
    { "VMD",      0x000C, NULL, NULL },
    { "VKD",      0x000D, NULL, NULL },
114
    { "VCD",      0x000E, NULL, DeviceIo_VCD },
Alexandre Julliard's avatar
Alexandre Julliard committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    { "VPD",      0x000F, NULL, NULL },
    { "BLOCKDEV", 0x0010, NULL, NULL },
    { "VMCPD",    0x0011, NULL, NULL },
    { "EBIOS",    0x0012, NULL, NULL },
    { "BIOSXLAT", 0x0013, NULL, NULL },
    { "VNETBIOS", 0x0014, NULL, NULL },
    { "DOSMGR",   0x0015, NULL, NULL },
    { "WINLOAD",  0x0016, NULL, NULL },
    { "SHELL",    0x0017, NULL, NULL },
    { "VMPOLL",   0x0018, NULL, NULL },
    { "VPROD",    0x0019, NULL, NULL },
    { "DOSNET",   0x001A, NULL, NULL },
    { "VFD",      0x001B, NULL, NULL },
    { "VDD2",     0x001C, NULL, NULL },
    { "WINDEBUG", 0x001D, NULL, NULL },
    { "TSRLOAD",  0x001E, NULL, NULL },
    { "BIOSHOOK", 0x001F, NULL, NULL },
    { "INT13",    0x0020, NULL, NULL },
    { "PAGEFILE", 0x0021, NULL, NULL },
    { "SCSI",     0x0022, NULL, NULL },
    { "MCA_POS",  0x0023, NULL, NULL },
    { "SCSIFD",   0x0024, NULL, NULL },
    { "VPEND",    0x0025, NULL, NULL },
    { "VPOWERD",  0x0026, NULL, NULL },
    { "VXDLDR",   0x0027, NULL, NULL },
    { "NDIS",     0x0028, NULL, NULL },
    { "BIOS_EXT", 0x0029, NULL, NULL },
142
    { "VWIN32",   0x002A, VxDCall_VWin32, DeviceIo_VWin32 },
Alexandre Julliard's avatar
Alexandre Julliard committed
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
    { "VCOMM",    0x002B, NULL, NULL },
    { "SPOOLER",  0x002C, NULL, NULL },
    { "WIN32S",   0x002D, NULL, NULL },
    { "DEBUGCMD", 0x002E, NULL, NULL },

    { "VNB",      0x0031, NULL, NULL },
    { "SERVER",   0x0032, NULL, NULL },
    { "CONFIGMG", 0x0033, NULL, NULL },
    { "DWCFGMG",  0x0034, NULL, NULL },
    { "SCSIPORT", 0x0035, NULL, NULL },
    { "VFBACKUP", 0x0036, NULL, NULL },
    { "ENABLE",   0x0037, NULL, NULL },
    { "VCOND",    0x0038, NULL, NULL },

    { "EFAX",     0x003A, NULL, NULL },
    { "DSVXD",    0x003B, NULL, NULL },
    { "ISAPNP",   0x003C, NULL, NULL },
    { "BIOS",     0x003D, NULL, NULL },
    { "WINSOCK",  0x003E, NULL, NULL },
    { "WSOCK",    0x003E, NULL, NULL },
    { "WSIPX",    0x003F, NULL, NULL },
164
    { "IFSMgr",   0x0040, NULL, DeviceIo_IFSMgr },
Alexandre Julliard's avatar
Alexandre Julliard committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
    { "VCDFSD",   0x0041, NULL, NULL },
    { "MRCI2",    0x0042, NULL, NULL },
    { "PCI",      0x0043, NULL, NULL },
    { "PELOADER", 0x0044, NULL, NULL },
    { "EISA",     0x0045, NULL, NULL },
    { "DRAGCLI",  0x0046, NULL, NULL },
    { "DRAGSRV",  0x0047, NULL, NULL },
    { "PERF",     0x0048, NULL, NULL },
    { "AWREDIR",  0x0049, NULL, NULL },

    /* Far East support */
    { "ETEN",     0x0060, NULL, NULL },
    { "CHBIOS",   0x0061, NULL, NULL },
    { "VMSGD",    0x0062, NULL, NULL },
    { "VPPID",    0x0063, NULL, NULL },
    { "VIME",     0x0064, NULL, NULL },
    { "VHBIOSD",  0x0065, NULL, NULL },

    /* Multimedia OEM IDs */
    { "VTDAPI",   0x0442, NULL, DeviceIo_VTDAPI },
185
    { "MMDEVLDR", 0x044A, NULL, DeviceIo_MMDEVLDR },
Alexandre Julliard's avatar
Alexandre Julliard committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224

    /* Network Device IDs */
    { "VNetSup",  0x0480, NULL, NULL },
    { "VRedir",   0x0481, NULL, NULL },
    { "VBrowse",  0x0482, NULL, NULL },
    { "VSHARE",   0x0483, NULL, NULL },
    { "IFSMgr",   0x0484, NULL, NULL },
    { "MEMPROBE", 0x0485, NULL, NULL },
    { "VFAT",     0x0486, NULL, NULL },
    { "NWLINK",   0x0487, NULL, NULL },
    { "VNWLINK",  0x0487, NULL, NULL },
    { "NWSUP",    0x0487, NULL, NULL },
    { "VTDI",     0x0488, NULL, NULL },
    { "VIP",      0x0489, NULL, NULL },
    { "VTCP",     0x048A, NULL, NULL },
    { "VCache",   0x048B, NULL, NULL },
    { "VUDP",     0x048C, NULL, NULL },
    { "VAsync",   0x048D, NULL, NULL },
    { "NWREDIR",  0x048E, NULL, NULL },
    { "STAT80",   0x048F, NULL, NULL },
    { "SCSIPORT", 0x0490, NULL, NULL },
    { "FILESEC",  0x0491, NULL, NULL },
    { "NWSERVER", 0x0492, NULL, NULL },
    { "SECPROV",  0x0493, NULL, NULL },
    { "NSCL",     0x0494, NULL, NULL },
    { "WSTCP",    0x0495, NULL, NULL },
    { "NDIS2SUP", 0x0496, NULL, NULL },
    { "MSODISUP", 0x0497, NULL, NULL },
    { "Splitter", 0x0498, NULL, NULL },
    { "PPP",      0x0499, NULL, NULL },
    { "VDHCP",    0x049A, NULL, NULL },
    { "VNBT",     0x049B, NULL, NULL },
    { "LOGGER",   0x049D, NULL, NULL },
    { "EFILTER",  0x049E, NULL, NULL },
    { "FFILTER",  0x049F, NULL, NULL },
    { "TFILTER",  0x04A0, NULL, NULL },
    { "AFILTER",  0x04A1, NULL, NULL },
    { "IRLAMP",   0x04A2, NULL, NULL },

225
    { "PCCARD",   0x097C, NULL, DeviceIo_PCCARD },
226
    { "HASP95",   0x3721, NULL, DeviceIo_HASP },
227

228
    /* WINE additions, ids unknown */
229 230
    { "MONODEBG.VXD", 0x4242, NULL, DeviceIo_MONODEBG },

Alexandre Julliard's avatar
Alexandre Julliard committed
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    { NULL,       0,      NULL, NULL }
};

/*
 * VMM VxDCall service names are (mostly) taken from Stan Mitchell's
 * "Inside the Windows 95 File System"
 */

#define N_VMM_SERVICE 41

LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
{ 
    "PageReserve",            /* 0x0000 */
    "PageCommit",             /* 0x0001 */
    "PageDecommit",           /* 0x0002 */
    "PagerRegister",          /* 0x0003 */
    "PagerQuery",             /* 0x0004 */
    "HeapAllocate",           /* 0x0005 */
    "ContextCreate",          /* 0x0006 */
    "ContextDestroy",         /* 0x0007 */
    "PageAttach",             /* 0x0008 */
    "PageFlush",              /* 0x0009 */
    "PageFree",               /* 0x000A */
    "ContextSwitch",          /* 0x000B */
    "HeapReAllocate",         /* 0x000C */
256
    "PageModifyPermissions",  /* 0x000D */
Alexandre Julliard's avatar
Alexandre Julliard committed
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
    "PageQuery",              /* 0x000E */
    "GetCurrentContext",      /* 0x000F */
    "HeapFree",               /* 0x0010 */
    "RegOpenKey",             /* 0x0011 */
    "RegCreateKey",           /* 0x0012 */
    "RegCloseKey",            /* 0x0013 */
    "RegDeleteKey",           /* 0x0014 */
    "RegSetValue",            /* 0x0015 */
    "RegDeleteValue",         /* 0x0016 */
    "RegQueryValue",          /* 0x0017 */
    "RegEnumKey",             /* 0x0018 */
    "RegEnumValue",           /* 0x0019 */
    "RegQueryValueEx",        /* 0x001A */
    "RegSetValueEx",          /* 0x001B */
    "RegFlushKey",            /* 0x001C */
    "RegQueryInfoKey",        /* 0x001D */
    "GetDemandPageInfo",      /* 0x001E */
    "BlockOnID",              /* 0x001F */
    "SignalID",               /* 0x0020 */
    "RegLoadKey",             /* 0x0021 */
    "RegUnLoadKey",           /* 0x0022 */
    "RegSaveKey",             /* 0x0023 */
    "RegRemapPreDefKey",      /* 0x0024 */
    "PageChangePager",        /* 0x0025 */
    "RegQueryMultipleValues", /* 0x0026 */
    "RegReplaceKey",          /* 0x0027 */
    "<KERNEL32.101>"          /* 0x0028 -- What does this do??? */
};

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
/* PageReserve arena values */
#define PR_PRIVATE  0x80000400	/* anywhere in private arena */
#define PR_SHARED   0x80060000	/* anywhere in shared arena */
#define PR_SYSTEM   0x80080000	/* anywhere in system arena */

/* PageReserve flags */
#define PR_FIXED    0x00000008	/* don't move during PageReAllocate */
#define PR_4MEG     0x00000001	/* allocate on 4mb boundary */
#define PR_STATIC   0x00000010	/* see PageReserve documentation */

/* PageCommit default pager handle values */
#define PD_ZEROINIT 0x00000001	/* swappable zero-initialized pages */
#define PD_NOINIT   0x00000002	/* swappable uninitialized pages */
#define PD_FIXEDZERO	0x00000003  /* fixed zero-initialized pages */
#define PD_FIXED    0x00000004	/* fixed uninitialized pages */

/* PageCommit flags */
#define PC_FIXED    0x00000008	/* pages are permanently locked */
304
#define PC_LOCKED   0x00000080	/* pages are made present and locked */
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
#define PC_LOCKEDIFDP	0x00000100  /* pages are locked if swap via DOS */
#define PC_WRITEABLE	0x00020000  /* make the pages writeable */
#define PC_USER     0x00040000	/* make the pages ring 3 accessible */
#define PC_INCR     0x40000000	/* increment "pagerdata" each page */
#define PC_PRESENT  0x80000000	/* make pages initially present */
#define PC_STATIC   0x20000000	/* allow commit in PR_STATIC object */
#define PC_DIRTY    0x08000000	/* make pages initially dirty */
#define PC_CACHEDIS 0x00100000  /* Allocate uncached pages - new for WDM */
#define PC_CACHEWT  0x00080000  /* Allocate write through cache pages - new for WDM */
#define PC_PAGEFLUSH 0x00008000 /* Touch device mapped pages on alloc - new for WDM */

/* PageCommitContig additional flags */
#define PCC_ZEROINIT	0x00000001  /* zero-initialize new pages */
#define PCC_NOLIN   0x10000000	/* don't map to any linear address */



322
HANDLE DEVICE_Open( LPCSTR filename, DWORD access, LPSECURITY_ATTRIBUTES sa )
Alexandre Julliard's avatar
Alexandre Julliard committed
323
{
324
    const struct VxDInfo *info;
Alexandre Julliard's avatar
Alexandre Julliard committed
325

326
    for (info = VxDList; info->name; info++)
327
        if (!strncasecmp( info->name, filename, strlen(info->name) ))
328
            return FILE_CreateDevice( info->id | 0x10000, access, sa );
Alexandre Julliard's avatar
Alexandre Julliard committed
329

330
    FIXME( "Unknown/unsupported VxD %s. Try --winver nt40 or win31 !\n", filename);
331
    SetLastError( ERROR_FILE_NOT_FOUND );
332
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
333 334
}

335
static DWORD DEVICE_GetClientID( HANDLE handle )
Alexandre Julliard's avatar
Alexandre Julliard committed
336
{
337
    DWORD       ret = 0;
338
    SERVER_START_REQ( get_file_info )
339
    {
340
        req->handle = handle;
341 342
        if (!wine_server_call( req ) && (reply->type == FILE_TYPE_UNKNOWN))
            ret = reply->attr;
343
    }
344
    SERVER_END_REQ;
345 346 347 348 349 350 351 352 353 354 355 356
    return ret;
}

static const struct VxDInfo *DEVICE_GetInfo( DWORD clientID )
{
    const struct VxDInfo *info = NULL;
    
    if (clientID & 0x10000)
    {
        for (info = VxDList; info->name; info++)
            if (info->id == LOWORD(clientID)) break;
    }
357
    return info;
Alexandre Julliard's avatar
Alexandre Julliard committed
358 359 360
}

/****************************************************************************
361
 *		DeviceIoControl (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
362 363 364 365 366
 * This is one of those big ugly nasty procedure which can do
 * a million and one things when it comes to devices. It can also be
 * used for VxD communication.
 *
 * A return value of FALSE indicates that something has gone wrong which
367
 * GetLastError can decipher.
Alexandre Julliard's avatar
Alexandre Julliard committed
368
 */
369
BOOL WINAPI DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, 
Alexandre Julliard's avatar
Alexandre Julliard committed
370
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
Alexandre Julliard's avatar
Alexandre Julliard committed
371 372 373 374
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped)
{
375
        DWORD clientID;
Alexandre Julliard's avatar
Alexandre Julliard committed
376

377 378 379
        TRACE( "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n",
               hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
               lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped	);
Alexandre Julliard's avatar
Alexandre Julliard committed
380

381
	if (!(clientID = DEVICE_GetClientID( hDevice )))
Alexandre Julliard's avatar
Alexandre Julliard committed
382 383
	{
		SetLastError( ERROR_INVALID_PARAMETER );
Alexandre Julliard's avatar
Alexandre Julliard committed
384
		return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
385 386 387
	}

	/* Check if this is a user defined control code for a VxD */
Alexandre Julliard's avatar
Alexandre Julliard committed
388 389
	if( HIWORD( dwIoControlCode ) == 0 )
	{
390 391 392 393 394 395
                const struct VxDInfo *info;
                if (!(info = DEVICE_GetInfo( clientID )))
                {
                        FIXME( "No device found for id %lx\n", clientID);
                }
                else if ( info->deviceio )
Alexandre Julliard's avatar
Alexandre Julliard committed
396
		{
397
			return info->deviceio( dwIoControlCode, 
Alexandre Julliard's avatar
Alexandre Julliard committed
398 399 400 401 402 403
                                        lpvInBuffer, cbInBuffer, 
                                        lpvOutBuffer, cbOutBuffer, 
                                        lpcbBytesReturned, lpOverlapped );
		}
		else
		{
404
			FIXME( "Unimplemented control %ld for VxD device %s\n", 
405
                               dwIoControlCode, info->name ? info->name : "???" );
406 407 408 409
			/* FIXME: this is for invalid calls on W98SE,
			 * but maybe we should use ERROR_CALL_NOT_IMPLEMENTED
			 * instead ? */
			SetLastError( ERROR_INVALID_FUNCTION );
Alexandre Julliard's avatar
Alexandre Julliard committed
410
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
411 412 413
	}
	else
	{
414 415 416 417 418 419 420 421 422
                char str[3];

                strcpy(str,  "A:");
                str[0] += LOBYTE(clientID);
                if (GetDriveTypeA(str) == DRIVE_CDROM)
                    return CDROM_DeviceIoControl(clientID, hDevice, dwIoControlCode, lpvInBuffer, cbInBuffer,
                                                 lpvOutBuffer, cbOutBuffer, lpcbBytesReturned,
                                                 lpOverlapped);
                else switch( dwIoControlCode )
Alexandre Julliard's avatar
Alexandre Julliard committed
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
		{
		case FSCTL_DELETE_REPARSE_POINT:
		case FSCTL_DISMOUNT_VOLUME:
		case FSCTL_GET_COMPRESSION:
		case FSCTL_GET_REPARSE_POINT:
		case FSCTL_LOCK_VOLUME:
		case FSCTL_QUERY_ALLOCATED_RANGES:
		case FSCTL_SET_COMPRESSION:
		case FSCTL_SET_REPARSE_POINT:
		case FSCTL_SET_SPARSE:
		case FSCTL_SET_ZERO_DATA:
		case FSCTL_UNLOCK_VOLUME:
		case IOCTL_DISK_CHECK_VERIFY:
		case IOCTL_DISK_EJECT_MEDIA:
		case IOCTL_DISK_FORMAT_TRACKS:
		case IOCTL_DISK_GET_DRIVE_GEOMETRY:
		case IOCTL_DISK_GET_DRIVE_LAYOUT:
		case IOCTL_DISK_GET_MEDIA_TYPES:
		case IOCTL_DISK_GET_PARTITION_INFO:
		case IOCTL_DISK_LOAD_MEDIA:
		case IOCTL_DISK_MEDIA_REMOVAL:
		case IOCTL_DISK_PERFORMANCE:
		case IOCTL_DISK_REASSIGN_BLOCKS:
		case IOCTL_DISK_SET_DRIVE_LAYOUT:
		case IOCTL_DISK_SET_PARTITION_INFO:
		case IOCTL_DISK_VERIFY:
		case IOCTL_SERIAL_LSRMST_INSERT:
		case IOCTL_STORAGE_CHECK_VERIFY:
		case IOCTL_STORAGE_EJECT_MEDIA:
		case IOCTL_STORAGE_GET_MEDIA_TYPES:
		case IOCTL_STORAGE_LOAD_MEDIA:
		case IOCTL_STORAGE_MEDIA_REMOVAL:
455
    			FIXME( "unimplemented dwIoControlCode=%08lx\n", dwIoControlCode);
Alexandre Julliard's avatar
Alexandre Julliard committed
456 457 458 459
    			SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
    			return FALSE;
    			break;
		default:
460
    			FIXME( "ignored dwIoControlCode=%08lx\n",dwIoControlCode);
Alexandre Julliard's avatar
Alexandre Julliard committed
461 462 463 464
    			SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
    			return FALSE;
    			break;
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
465
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
466
   	return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
467
}
Alexandre Julliard's avatar
Alexandre Julliard committed
468 469 470 471
 
/***********************************************************************
 *           DeviceIo_VTDAPI
 */
472
static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
Alexandre Julliard's avatar
Alexandre Julliard committed
473 474 475 476
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped)
{
477
    BOOL retv = TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
478 479 480 481 482

    switch (dwIoControlCode)
    {
    case 5:
        if (lpvOutBuffer && (cbOutBuffer>=4))
483
            *(DWORD*)lpvOutBuffer = GetTickCount();
Alexandre Julliard's avatar
Alexandre Julliard committed
484 485 486 487 488 489 490

        if (lpcbBytesReturned)
            *lpcbBytesReturned = 4;

        break;

    default:
491
        FIXME( "Control %ld not implemented\n", dwIoControlCode);
Alexandre Julliard's avatar
Alexandre Julliard committed
492 493 494 495 496 497 498 499
        retv = FALSE;
        break;
    }

    return retv;
}

/***********************************************************************
500 501 502 503 504 505 506 507 508
 *		VxDCall0 (KERNEL32.1)
 *		VxDCall1 (KERNEL32.2)
 *		VxDCall2 (KERNEL32.3)
 *		VxDCall3 (KERNEL32.4)
 *		VxDCall4 (KERNEL32.5)
 *		VxDCall5 (KERNEL32.6)
 *		VxDCall6 (KERNEL32.7)
 *		VxDCall7 (KERNEL32.8)
 *		VxDCall8 (KERNEL32.9)
Alexandre Julliard's avatar
Alexandre Julliard committed
509
 */
510
void VxDCall( DWORD service, CONTEXT86 *context )
Alexandre Julliard's avatar
Alexandre Julliard committed
511
{
512 513
    DWORD ret = 0xffffffff; /* FIXME */
    int i;
Alexandre Julliard's avatar
Alexandre Julliard committed
514

515
    TRACE( "(%08lx, ...)\n", service);
Alexandre Julliard's avatar
Alexandre Julliard committed
516 517 518 519 520 521

    for (i = 0; VxDList[i].name; i++)
        if (VxDList[i].id == HIWORD(service))
            break;

    if (!VxDList[i].name)
522
        FIXME( "Unknown VxD (%08lx)\n", service);
Alexandre Julliard's avatar
Alexandre Julliard committed
523
    else if (!VxDList[i].vxdcall)
524
        FIXME( "Unimplemented VxD (%08lx)\n", service);
Alexandre Julliard's avatar
Alexandre Julliard committed
525
    else
526
        ret = VxDList[i].vxdcall( service, context );
527

528
    context->Eax = ret;
529 530
}

Alexandre Julliard's avatar
Alexandre Julliard committed
531 532 533 534

/***********************************************************************
 *           VxDCall_VMM
 */
535
static DWORD VxDCall_VMM( DWORD service, CONTEXT86 *context )
Alexandre Julliard's avatar
Alexandre Julliard committed
536 537 538 539 540
{
    switch ( LOWORD(service) )
    {
    case 0x0011:  /* RegOpenKey */
    {
541 542 543
        HKEY    hkey       = (HKEY)  stack32_pop( context );
        LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
        LPHKEY  retkey     = (LPHKEY)stack32_pop( context );
544
        return RegOpenKeyA( hkey, lpszSubKey, retkey );
Alexandre Julliard's avatar
Alexandre Julliard committed
545 546 547 548
    }

    case 0x0012:  /* RegCreateKey */
    {
549 550 551
        HKEY    hkey       = (HKEY)  stack32_pop( context );
        LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
        LPHKEY  retkey     = (LPHKEY)stack32_pop( context );
552
        return RegCreateKeyA( hkey, lpszSubKey, retkey );
Alexandre Julliard's avatar
Alexandre Julliard committed
553 554 555 556
    }

    case 0x0013:  /* RegCloseKey */
    {
557
        HKEY    hkey       = (HKEY)stack32_pop( context );
558
        return RegCloseKey( hkey );
Alexandre Julliard's avatar
Alexandre Julliard committed
559 560 561 562
    }

    case 0x0014:  /* RegDeleteKey */
    {
563 564
        HKEY    hkey       = (HKEY)  stack32_pop( context );
        LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
565
        return RegDeleteKeyA( hkey, lpszSubKey );
Alexandre Julliard's avatar
Alexandre Julliard committed
566 567 568 569
    }

    case 0x0015:  /* RegSetValue */
    {
570 571 572 573 574
        HKEY    hkey       = (HKEY)  stack32_pop( context );
        LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
        DWORD   dwType     = (DWORD) stack32_pop( context );
        LPCSTR  lpszData   = (LPCSTR)stack32_pop( context );
        DWORD   cbData     = (DWORD) stack32_pop( context );
575
        return RegSetValueA( hkey, lpszSubKey, dwType, lpszData, cbData );
Alexandre Julliard's avatar
Alexandre Julliard committed
576 577 578 579
    }

    case 0x0016:  /* RegDeleteValue */
    {
580 581
        HKEY    hkey       = (HKEY) stack32_pop( context );
        LPSTR   lpszValue  = (LPSTR)stack32_pop( context );
582
        return RegDeleteValueA( hkey, lpszValue );
Alexandre Julliard's avatar
Alexandre Julliard committed
583 584 585 586
    }

    case 0x0017:  /* RegQueryValue */
    {
587 588 589 590
        HKEY    hkey       = (HKEY)   stack32_pop( context );
        LPSTR   lpszSubKey = (LPSTR)  stack32_pop( context );
        LPSTR   lpszData   = (LPSTR)  stack32_pop( context );
        LPDWORD lpcbData   = (LPDWORD)stack32_pop( context );
591
        return RegQueryValueA( hkey, lpszSubKey, lpszData, lpcbData );
Alexandre Julliard's avatar
Alexandre Julliard committed
592 593 594 595
    }

    case 0x0018:  /* RegEnumKey */
    {
596 597 598 599
        HKEY    hkey       = (HKEY) stack32_pop( context );
        DWORD   iSubkey    = (DWORD)stack32_pop( context );
        LPSTR   lpszName   = (LPSTR)stack32_pop( context );
        DWORD   lpcchName  = (DWORD)stack32_pop( context );
600
        return RegEnumKeyA( hkey, iSubkey, lpszName, lpcchName );
Alexandre Julliard's avatar
Alexandre Julliard committed
601 602 603 604
    }

    case 0x0019:  /* RegEnumValue */
    {
605 606 607 608 609 610 611 612
        HKEY    hkey       = (HKEY)   stack32_pop( context );
        DWORD   iValue     = (DWORD)  stack32_pop( context );
        LPSTR   lpszValue  = (LPSTR)  stack32_pop( context );
        LPDWORD lpcchValue = (LPDWORD)stack32_pop( context );
        LPDWORD lpReserved = (LPDWORD)stack32_pop( context );
        LPDWORD lpdwType   = (LPDWORD)stack32_pop( context );
        LPBYTE  lpbData    = (LPBYTE) stack32_pop( context );
        LPDWORD lpcbData   = (LPDWORD)stack32_pop( context );
613 614
        return RegEnumValueA( hkey, iValue, lpszValue, lpcchValue, 
                              lpReserved, lpdwType, lpbData, lpcbData );
Alexandre Julliard's avatar
Alexandre Julliard committed
615 616 617 618
    }

    case 0x001A:  /* RegQueryValueEx */
    {
619 620 621 622 623 624
        HKEY    hkey       = (HKEY)   stack32_pop( context );
        LPSTR   lpszValue  = (LPSTR)  stack32_pop( context );
        LPDWORD lpReserved = (LPDWORD)stack32_pop( context );
        LPDWORD lpdwType   = (LPDWORD)stack32_pop( context );
        LPBYTE  lpbData    = (LPBYTE) stack32_pop( context );
        LPDWORD lpcbData   = (LPDWORD)stack32_pop( context );
625 626
        return RegQueryValueExA( hkey, lpszValue, lpReserved, 
                                 lpdwType, lpbData, lpcbData );
Alexandre Julliard's avatar
Alexandre Julliard committed
627 628 629 630
    }

    case 0x001B:  /* RegSetValueEx */
    {
631 632 633 634 635 636
        HKEY    hkey       = (HKEY)  stack32_pop( context );
        LPSTR   lpszValue  = (LPSTR) stack32_pop( context );
        DWORD   dwReserved = (DWORD) stack32_pop( context );
        DWORD   dwType     = (DWORD) stack32_pop( context );
        LPBYTE  lpbData    = (LPBYTE)stack32_pop( context );
        DWORD   cbData     = (DWORD) stack32_pop( context );
637 638
        return RegSetValueExA( hkey, lpszValue, dwReserved, 
                               dwType, lpbData, cbData );
Alexandre Julliard's avatar
Alexandre Julliard committed
639 640 641 642
    }

    case 0x001C:  /* RegFlushKey */
    {
643
        HKEY    hkey       = (HKEY)stack32_pop( context );
644
        return RegFlushKey( hkey );
Alexandre Julliard's avatar
Alexandre Julliard committed
645 646 647 648 649 650 651 652
    }

    case 0x001D:  /* RegQueryInfoKey */
    {
        /* NOTE: This VxDCall takes only a subset of the parameters that the
                 corresponding Win32 API call does. The implementation in Win95
                 ADVAPI32 sets all output parameters not mentioned here to zero. */

653 654 655 656 657 658
        HKEY    hkey              = (HKEY)   stack32_pop( context );
        LPDWORD lpcSubKeys        = (LPDWORD)stack32_pop( context );
        LPDWORD lpcchMaxSubKey    = (LPDWORD)stack32_pop( context );
        LPDWORD lpcValues         = (LPDWORD)stack32_pop( context );
        LPDWORD lpcchMaxValueName = (LPDWORD)stack32_pop( context );
        LPDWORD lpcchMaxValueData = (LPDWORD)stack32_pop( context );
659 660 661
        return RegQueryInfoKeyA( hkey, NULL, NULL, NULL, lpcSubKeys, lpcchMaxSubKey,
                                 NULL, lpcValues, lpcchMaxValueName, lpcchMaxValueData,
                                 NULL, NULL );
Alexandre Julliard's avatar
Alexandre Julliard committed
662 663 664 665
    }

    case 0x0021:  /* RegLoadKey */
    {
666 667 668
        HKEY    hkey       = (HKEY)  stack32_pop( context );
        LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
        LPCSTR  lpszFile   = (LPCSTR)stack32_pop( context );
669
        return RegLoadKeyA( hkey, lpszSubKey, lpszFile );
Alexandre Julliard's avatar
Alexandre Julliard committed
670 671 672 673
    }

    case 0x0022:  /* RegUnLoadKey */
    {
674 675
        HKEY    hkey       = (HKEY)  stack32_pop( context );
        LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
676
        return RegUnLoadKeyA( hkey, lpszSubKey );
Alexandre Julliard's avatar
Alexandre Julliard committed
677 678 679 680
    }

    case 0x0023:  /* RegSaveKey */
    {
681 682 683
        HKEY    hkey       = (HKEY)  stack32_pop( context );
        LPCSTR  lpszFile   = (LPCSTR)stack32_pop( context );
        LPSECURITY_ATTRIBUTES sa = (LPSECURITY_ATTRIBUTES)stack32_pop( context );
684
        return RegSaveKeyA( hkey, lpszFile, sa );
Alexandre Julliard's avatar
Alexandre Julliard committed
685 686 687 688 689 690 691 692 693
    }

#if 0 /* Functions are not yet implemented in misc/registry.c */
    case 0x0024:  /* RegRemapPreDefKey */
    case 0x0026:  /* RegQueryMultipleValues */
#endif

    case 0x0027:  /* RegReplaceKey */
    {
694 695 696 697
        HKEY    hkey       = (HKEY)  stack32_pop( context );
        LPCSTR  lpszSubKey = (LPCSTR)stack32_pop( context );
        LPCSTR  lpszNewFile= (LPCSTR)stack32_pop( context );
        LPCSTR  lpszOldFile= (LPCSTR)stack32_pop( context );
698
        return RegReplaceKeyA( hkey, lpszSubKey, lpszNewFile, lpszOldFile );
Alexandre Julliard's avatar
Alexandre Julliard committed
699
    }
700 701 702 703
    case 0x0000: /* PageReserve */
      {
	LPVOID address;
	LPVOID ret;
704
	DWORD psize = getpagesize();
705 706 707 708
	ULONG page   = (ULONG) stack32_pop( context );
	ULONG npages = (ULONG) stack32_pop( context );
	ULONG flags  = (ULONG) stack32_pop( context );

709
	TRACE("PageReserve: page: %08lx, npages: %08lx, flags: %08lx partial stub!\n",
710 711 712 713 714 715
	      page, npages, flags );

	if ( page == PR_SYSTEM ) {
	  ERR("Can't reserve ring 1 memory\n");
	  return -1;
	}
716 717
	/* FIXME: This has to be handled separately for the separate
	   address-spaces we now have */
718 719 720 721
	if ( page == PR_PRIVATE || page == PR_SHARED ) page = 0;
	/* FIXME: Handle flags in some way */
	address = (LPVOID )(page * psize); 
	ret = VirtualAlloc ( address, ( npages * psize ), MEM_RESERVE, 0 );
722
	TRACE("PageReserve: returning: %08lx\n", (DWORD )ret );
723 724 725 726 727 728 729 730 731 732 733
	if ( ret == NULL )
	  return -1;
	else
	  return (DWORD )ret;
      }

    case 0x0001: /* PageCommit */
      {
	LPVOID address;
	LPVOID ret;
	DWORD virt_perm;
734
	DWORD psize = getpagesize();
735 736 737 738 739 740
	ULONG page   = (ULONG) stack32_pop( context );
	ULONG npages = (ULONG) stack32_pop( context );
	ULONG hpd  = (ULONG) stack32_pop( context );
	ULONG pagerdata   = (ULONG) stack32_pop( context );
	ULONG flags  = (ULONG) stack32_pop( context );

741
	TRACE("PageCommit: page: %08lx, npages: %08lx, hpd: %08lx pagerdata: "
742 743 744 745 746 747 748 749 750 751 752 753 754
	      "%08lx, flags: %08lx partial stub\n",
	      page, npages, hpd, pagerdata, flags );
	
	if ( flags & PC_USER )
	  if ( flags & PC_WRITEABLE )
	    virt_perm = PAGE_EXECUTE_READWRITE;
	  else
	    virt_perm = PAGE_EXECUTE_READ;
	else
	  virt_perm = PAGE_NOACCESS;

	address = (LPVOID )(page * psize); 
	ret = VirtualAlloc ( address, ( npages * psize ), MEM_COMMIT, virt_perm );
755
	TRACE("PageCommit: Returning: %08lx\n", (DWORD )ret );
756 757 758 759 760 761 762
	return (DWORD )ret;

      }
    case 0x0002: /* PageDecommit */
      {
	LPVOID address;
	BOOL ret;
763
	DWORD psize = getpagesize();
764 765 766 767
	ULONG page = (ULONG) stack32_pop( context );
	ULONG npages = (ULONG) stack32_pop( context );
	ULONG flags = (ULONG) stack32_pop( context );

768
	TRACE("PageDecommit: page: %08lx, npages: %08lx, flags: %08lx partial stub\n",
769 770 771
	      page, npages, flags );
	address = (LPVOID )( page * psize );
	ret = VirtualFree ( address, ( npages * psize ), MEM_DECOMMIT ); 
772
	TRACE("PageDecommit: Returning: %s\n", ret ? "TRUE" : "FALSE" );
773 774 775 776 777 778 779 780 781 782
	return ret;
      }
    case 0x000d: /* PageModifyPermissions */
      {	
	DWORD pg_old_perm;
	DWORD pg_new_perm;
	DWORD virt_old_perm;
	DWORD virt_new_perm;
	MEMORY_BASIC_INFORMATION mbi;
	LPVOID address;
783
	DWORD psize = getpagesize();
784 785 786 787 788
	ULONG page = stack32_pop ( context );
	ULONG npages = stack32_pop ( context );
	ULONG permand = stack32_pop ( context );
	ULONG permor = stack32_pop ( context );

789
	TRACE("PageModifyPermissions %08lx %08lx %08lx %08lx partial stub\n",
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
	      page, npages, permand, permor );
	address = (LPVOID )( page * psize );

	VirtualQuery ( address, &mbi, sizeof ( MEMORY_BASIC_INFORMATION ));
	virt_old_perm = mbi.Protect;

	switch ( virt_old_perm & mbi.Protect ) {
	case PAGE_READONLY:
	case PAGE_EXECUTE:
	case PAGE_EXECUTE_READ:
	  pg_old_perm = PC_USER;
	  break;
	case PAGE_READWRITE:
	case PAGE_WRITECOPY:
	case PAGE_EXECUTE_READWRITE:
	case PAGE_EXECUTE_WRITECOPY:
	  pg_old_perm = PC_USER | PC_WRITEABLE;
	  break; 
	case PAGE_NOACCESS:
	default:
	  pg_old_perm = 0;
	  break;
	}	
	pg_new_perm = pg_old_perm;
	pg_new_perm &= permand & ~PC_STATIC;
	pg_new_perm |= permor  & ~PC_STATIC;

	virt_new_perm = ( virt_old_perm )  & ~0xff;
	if ( pg_new_perm & PC_USER )
819
	{
820 821 822 823
	  if ( pg_new_perm & PC_WRITEABLE )
	    virt_new_perm |= PAGE_EXECUTE_READWRITE;
	  else
	    virt_new_perm |= PAGE_EXECUTE_READ;
824
	}
825 826 827 828 829
  
	if ( ! VirtualProtect ( address, ( npages * psize ), virt_new_perm, &virt_old_perm ) ) {
	  ERR("Can't change page permissions for %08lx\n", (DWORD )address );
	  return 0xffffffff;
	}
830
	TRACE("Returning: %08lx\n", pg_old_perm );
831 832 833 834 835 836 837 838
	return pg_old_perm;
      }
    case 0x000a: /* PageFree */
      {
	BOOL ret;
	LPVOID hmem = (LPVOID) stack32_pop( context );
	DWORD flags = (DWORD ) stack32_pop( context );
	
839
	TRACE("PageFree: hmem: %08lx, flags: %08lx partial stub\n",
840 841 842
	      (DWORD )hmem, flags );

	ret = VirtualFree ( hmem, 0, MEM_RELEASE );
843
	context->Eax = ret;
844
	TRACE("Returning: %d\n", ret );
845 846 847

	return 0;
      }
848 849 850 851
    case 0x001e: /* GetDemandPageInfo */
      {
	 DWORD dinfo = (DWORD)stack32_pop( context );
         DWORD flags = (DWORD)stack32_pop( context );   
852

853 854 855 856 857 858 859
	 /* GetDemandPageInfo is supposed to fill out the struct at
          * "dinfo" with various low-level memory management information.
          * Apps are certainly not supposed to call this, although it's
          * demoed and documented by Pietrek on pages 441-443 of "Windows
          * 95 System Programming Secrets" if any program needs a real
          * implementation of this.
	  */
Alexandre Julliard's avatar
Alexandre Julliard committed
860

861 862 863 864
	 FIXME("GetDemandPageInfo(%08lx %08lx): stub!\n", dinfo, flags);

	 return 0;
      }
Alexandre Julliard's avatar
Alexandre Julliard committed
865 866
    default:
        if (LOWORD(service) < N_VMM_SERVICE)
867
            FIXME( "Unimplemented service %s (%08lx)\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
868 869
                          VMM_Service_Name[LOWORD(service)], service);
        else
870
            FIXME( "Unknown service %08lx\n", service);
Alexandre Julliard's avatar
Alexandre Julliard committed
871 872 873
        break;
    }

874
    return 0xffffffff;  /* FIXME */
Alexandre Julliard's avatar
Alexandre Julliard committed
875 876
}

Alexandre Julliard's avatar
Alexandre Julliard committed
877 878 879
/***********************************************************************
 *           DeviceIo_IFSMgr
 * NOTES
880
 *   These ioctls are used by 'MSNET32.DLL'.
Alexandre Julliard's avatar
Alexandre Julliard committed
881 882 883
 *
 *   I have been unable to uncover any documentation about the ioctls so 
 *   the implementation of the cases IFS_IOCTL_21 and IFS_IOCTL_2F are
884
 *   based on reasonable guesses on information found in the Windows 95 DDK.
Alexandre Julliard's avatar
Alexandre Julliard committed
885 886 887
 *   
 */

888 889 890 891 892 893 894 895 896
/*
 * IFSMgr DeviceIO service
 */

#define IFS_IOCTL_21                100
#define IFS_IOCTL_2F                101
#define	IFS_IOCTL_GET_RES           102
#define IFS_IOCTL_GET_NETPRO_NAME_A 103

Alexandre Julliard's avatar
Alexandre Julliard committed
897 898 899 900 901 902 903 904 905 906 907 908 909
struct win32apireq {
	unsigned long 	ar_proid;
	unsigned long  	ar_eax;		
	unsigned long  	ar_ebx;	
	unsigned long  	ar_ecx;	
	unsigned long  	ar_edx;	
	unsigned long  	ar_esi;	
	unsigned long  	ar_edi;
	unsigned long  	ar_ebp;		
	unsigned short 	ar_error;
	unsigned short  ar_pad;
};

910
static void win32apieq_2_CONTEXT(struct win32apireq *pIn,CONTEXT86 *pCxt)
Alexandre Julliard's avatar
Alexandre Julliard committed
911
{
912
	memset(pCxt,0,sizeof(*pCxt));
Alexandre Julliard's avatar
Alexandre Julliard committed
913

914
	pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
Alexandre Julliard's avatar
Alexandre Julliard committed
915 916 917 918 919 920 921
	pCxt->Eax = pIn->ar_eax;
	pCxt->Ebx = pIn->ar_ebx;
	pCxt->Ecx = pIn->ar_ecx;
	pCxt->Edx = pIn->ar_edx;
	pCxt->Esi = pIn->ar_esi;
	pCxt->Edi = pIn->ar_edi;

922
	/* FIXME: Only partial CONTEXT86_CONTROL */
Alexandre Julliard's avatar
Alexandre Julliard committed
923 924 925 926 927 928 929
	pCxt->Ebp = pIn->ar_ebp;

	/* FIXME: pIn->ar_proid ignored */
	/* FIXME: pIn->ar_error ignored */
	/* FIXME: pIn->ar_pad ignored */
}

930
static void CONTEXT_2_win32apieq(CONTEXT86 *pCxt,struct win32apireq *pOut)
Alexandre Julliard's avatar
Alexandre Julliard committed
931 932 933 934 935 936 937 938 939 940
{
	memset(pOut,0,sizeof(struct win32apireq));

	pOut->ar_eax = pCxt->Eax;
	pOut->ar_ebx = pCxt->Ebx;
	pOut->ar_ecx = pCxt->Ecx;
	pOut->ar_edx = pCxt->Edx;
	pOut->ar_esi = pCxt->Esi;
	pOut->ar_edi = pCxt->Edi;

941
	/* FIXME: Only partial CONTEXT86_CONTROL */
Alexandre Julliard's avatar
Alexandre Julliard committed
942 943 944 945 946 947 948
	pOut->ar_ebp = pCxt->Ebp;

	/* FIXME: pOut->ar_proid ignored */
	/* FIXME: pOut->ar_error ignored */
	/* FIXME: pOut->ar_pad ignored */
}

949
static BOOL DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
Alexandre Julliard's avatar
Alexandre Julliard committed
950 951 952 953
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped)
{
954
    BOOL retv = TRUE;
955
	TRACE("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
956
			dwIoControlCode,
Alexandre Julliard's avatar
Alexandre Julliard committed
957 958 959 960 961 962 963 964 965
			lpvInBuffer,cbInBuffer,
			lpvOutBuffer,cbOutBuffer,
			lpcbBytesReturned,
			lpOverlapped);

    switch (dwIoControlCode)
    {
	case IFS_IOCTL_21:
	case IFS_IOCTL_2F:{
966
		CONTEXT86 cxt;
Alexandre Julliard's avatar
Alexandre Julliard committed
967 968 969
		struct win32apireq *pIn=(struct win32apireq *) lpvInBuffer;
		struct win32apireq *pOut=(struct win32apireq *) lpvOutBuffer;

970
		TRACE(
Alexandre Julliard's avatar
Alexandre Julliard committed
971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
			"Control '%s': "
			"proid=0x%08lx, eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
			"edx=0x%08lx, esi=0x%08lx, edi=0x%08lx, ebp=0x%08lx, "
			"error=0x%04x, pad=0x%04x\n",
			(dwIoControlCode==IFS_IOCTL_21)?"IFS_IOCTL_21":"IFS_IOCTL_2F",
			pIn->ar_proid, pIn->ar_eax, pIn->ar_ebx, pIn->ar_ecx,
			pIn->ar_edx, pIn->ar_esi, pIn->ar_edi, pIn->ar_ebp,
			pIn->ar_error, pIn->ar_pad
		);				
		
		win32apieq_2_CONTEXT(pIn,&cxt);

		if(dwIoControlCode==IFS_IOCTL_21)
		{
			DOS3Call(&cxt); /* Call int 21h */
		} else {
			INT_Int2fHandler(&cxt); /* Call int 2Fh */
		}
		
		CONTEXT_2_win32apieq(&cxt,pOut);
			
        retv = TRUE;
	} break;
	case IFS_IOCTL_GET_RES:{
995
        FIXME( "Control 'IFS_IOCTL_GET_RES' not implemented\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
996 997 998
        retv = FALSE;
	} break;
	case IFS_IOCTL_GET_NETPRO_NAME_A:{
999
        FIXME( "Control 'IFS_IOCTL_GET_NETPRO_NAME_A' not implemented\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1000 1001 1002
        retv = FALSE;
	} break;	 
    default:
1003
        FIXME( "Control %ld not implemented\n", dwIoControlCode);
Alexandre Julliard's avatar
Alexandre Julliard committed
1004 1005 1006 1007 1008
        retv = FALSE;
    }

    return retv;
}
1009

1010 1011 1012 1013
/********************************************************************************
 *      VxDCall_VWin32
 *
 *  Service numbers taken from page 448 of Pietrek's "Windows 95 System
1014
 *  Programming Secrets".  Parameters from experimentation on real Win98.
1015 1016 1017
 *
 */

1018
static DWORD VxDCall_VWin32( DWORD service, CONTEXT86 *context )
1019 1020 1021 1022 1023
{
  switch ( LOWORD(service) )
    {
    case 0x0000: /* GetVersion */
    {
1024 1025
        DWORD vers = GetVersion();
        return (LOBYTE(vers) << 8) | HIBYTE(vers);
1026 1027 1028
    }
    break;

1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
    case 0x0020: /* Get VMCPD Version */
    {
	DWORD parm = (DWORD) stack32_pop(context);

	FIXME("Get VMCPD Version(%08lx): partial stub!\n", parm);

	/* FIXME: This is what Win98 returns, it may
         *        not be correct in all situations.
         *        It makes Bleem! happy though.
         */

	return 0x0405;
    }

    case 0x0029: /* Int31/DPMI dispatch */
    {
	DWORD callnum = (DWORD) stack32_pop(context);
        DWORD parm    = (DWORD) stack32_pop(context);
 
        TRACE("Int31/DPMI dispatch(%08lx)\n", callnum);

	AX_reg(context) = callnum;
        CX_reg(context) = parm;  
	INT_Int31Handler(context);

1054
	return LOWORD(context->Eax);
1055 1056 1057
    }
    break;

1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
    case 0x002a: /* Int41 dispatch - parm = int41 service number */
    {
	DWORD callnum = (DWORD) stack32_pop(context);

	return callnum; /* FIXME: should really call INT_Int41Handler() */
    }
    break;

    default:
      FIXME("Unknown VWin32 service %08lx\n", service);
      break;
    }

  return 0xffffffff;
}
                         

1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
/***********************************************************************
 *           DeviceIo_VCD
 */
static BOOL DeviceIo_VCD(DWORD dwIoControlCode, 
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped)
{
    BOOL retv = TRUE;

    switch (dwIoControlCode)
    {
    case IOCTL_SERIAL_LSRMST_INSERT:
    {
        FIXME( "IOCTL_SERIAL_LSRMST_INSERT NIY !\n");
        retv = FALSE;
    }
    break;

    default:
        FIXME( "Unknown Control %ld\n", dwIoControlCode);
        retv = FALSE;
        break;
    }

    return retv;
}

1104 1105 1106 1107 1108
 
/***********************************************************************
 *           DeviceIo_VWin32
 */

1109
static void DIOCRegs_2_CONTEXT( DIOC_REGISTERS *pIn, CONTEXT86 *pCxt )
1110
{
1111
    memset( pCxt, 0, sizeof(*pCxt) );
1112 1113 1114
    /* Note: segment registers == 0 means that CTX_SEG_OFF_TO_LIN
             will interpret 32-bit register contents as linear pointers */

1115
    pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL;
1116 1117 1118 1119 1120 1121 1122
    pCxt->Eax = pIn->reg_EAX;
    pCxt->Ebx = pIn->reg_EBX;
    pCxt->Ecx = pIn->reg_ECX;
    pCxt->Edx = pIn->reg_EDX;
    pCxt->Esi = pIn->reg_ESI;
    pCxt->Edi = pIn->reg_EDI;

1123
    /* FIXME: Only partial CONTEXT86_CONTROL */
1124 1125 1126
    pCxt->EFlags = pIn->reg_Flags;
}

1127
static void CONTEXT_2_DIOCRegs( CONTEXT86 *pCxt, DIOC_REGISTERS *pOut )
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
{
    memset( pOut, 0, sizeof(DIOC_REGISTERS) );

    pOut->reg_EAX = pCxt->Eax;
    pOut->reg_EBX = pCxt->Ebx;
    pOut->reg_ECX = pCxt->Ecx;
    pOut->reg_EDX = pCxt->Edx;
    pOut->reg_ESI = pCxt->Esi;
    pOut->reg_EDI = pCxt->Edi;

1138
    /* FIXME: Only partial CONTEXT86_CONTROL */
1139 1140 1141 1142
    pOut->reg_Flags = pCxt->EFlags;
}


1143
static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, 
1144 1145 1146 1147 1148
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped)
{
1149
    BOOL retv = TRUE;
1150 1151 1152 1153 1154 1155 1156

    switch (dwIoControlCode)
    {
    case VWIN32_DIOC_DOS_IOCTL:
    case VWIN32_DIOC_DOS_INT13:
    case VWIN32_DIOC_DOS_INT25:
    case VWIN32_DIOC_DOS_INT26:
1157
    case VWIN32_DIOC_DOS_DRIVEINFO:
1158
    {
1159
        CONTEXT86 cxt;
1160 1161 1162
        DIOC_REGISTERS *pIn  = (DIOC_REGISTERS *)lpvInBuffer;
        DIOC_REGISTERS *pOut = (DIOC_REGISTERS *)lpvOutBuffer;

1163 1164 1165 1166 1167 1168
        TRACE( "Control '%s': "
               "eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, "
               "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx ",
               (dwIoControlCode == VWIN32_DIOC_DOS_IOCTL)? "VWIN32_DIOC_DOS_IOCTL" :
               (dwIoControlCode == VWIN32_DIOC_DOS_INT13)? "VWIN32_DIOC_DOS_INT13" :
               (dwIoControlCode == VWIN32_DIOC_DOS_INT25)? "VWIN32_DIOC_DOS_INT25" :
1169 1170
               (dwIoControlCode == VWIN32_DIOC_DOS_INT26)? "VWIN32_DIOC_DOS_INT26" : 
               (dwIoControlCode == VWIN32_DIOC_DOS_DRIVEINFO)? "VWIN32_DIOC_DOS_DRIVEINFO" :  "???",
1171 1172
               pIn->reg_EAX, pIn->reg_EBX, pIn->reg_ECX,
               pIn->reg_EDX, pIn->reg_ESI, pIn->reg_EDI );
1173 1174 1175 1176 1177 1178 1179 1180 1181

        DIOCRegs_2_CONTEXT( pIn, &cxt );

        switch (dwIoControlCode)
        {
        case VWIN32_DIOC_DOS_IOCTL: DOS3Call( &cxt ); break; /* Call int 21h */
        case VWIN32_DIOC_DOS_INT13: INT_Int13Handler( &cxt ); break;
        case VWIN32_DIOC_DOS_INT25: INT_Int25Handler( &cxt ); break;
        case VWIN32_DIOC_DOS_INT26: INT_Int26Handler( &cxt ); break;
1182
        case VWIN32_DIOC_DOS_DRIVEINFO:	DOS3Call( &cxt ); break; /* Call int 21h 730x */
1183 1184 1185 1186 1187 1188 1189
        }

        CONTEXT_2_DIOCRegs( &cxt, pOut );
    }
    break;

    case VWIN32_DIOC_SIMCTRLC:
1190
        FIXME( "Control VWIN32_DIOC_SIMCTRLC not implemented\n");
1191 1192 1193 1194
        retv = FALSE;
        break;

    default:
1195
        FIXME( "Unknown Control %ld\n", dwIoControlCode);
1196 1197 1198 1199 1200 1201 1202
        retv = FALSE;
        break;
    }

    return retv;
}

1203 1204 1205 1206 1207 1208 1209
/* this is the main multimedia device loader */
static BOOL DeviceIo_MMDEVLDR(DWORD dwIoControlCode, 
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped)
{
1210
	FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
	    dwIoControlCode,
	    lpvInBuffer,cbInBuffer,
	    lpvOutBuffer,cbOutBuffer,
	    lpcbBytesReturned,
	    lpOverlapped
	);
	switch (dwIoControlCode) {
	case 5:
		/* Hmm. */
		*(DWORD*)lpvOutBuffer=0;
		*lpcbBytesReturned=4;
		return TRUE;
	}
	return FALSE;
}
1226
/* this is used by some Origin games */
1227
static BOOL DeviceIo_MONODEBG(DWORD dwIoControlCode, 
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped)
{
	switch (dwIoControlCode) {
	case 1:	/* version */
		*(LPDWORD)lpvOutBuffer = 0x20004; /* WC SecretOps */
		break;
	case 9: /* debug output */
1238
		ERR("MONODEBG: %s\n",debugstr_a(lpvInBuffer));
1239 1240
		break;
	default:
1241
		FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
1242
			dwIoControlCode,
1243 1244 1245 1246 1247 1248 1249 1250 1251
			lpvInBuffer,cbInBuffer,
			lpvOutBuffer,cbOutBuffer,
			lpcbBytesReturned,
			lpOverlapped
		);
		break;
	}
	return TRUE;
}
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
/* pccard */
static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode, 
			      LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped)
{
	switch (dwIoControlCode) {
	case 0x0000: /* PCCARD_Get_Version */
	case 0x0001: /* PCCARD_Card_Services */
	default:
		FIXME( "(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
			dwIoControlCode,
			lpvInBuffer,cbInBuffer,
			lpvOutBuffer,cbOutBuffer,
			lpcbBytesReturned,
			lpOverlapped
		);
		break;
	}
	return FALSE;
}
1274

1275
/***********************************************************************
1276
 *		OpenVxDHandle (KERNEL32.@)
1277
 */
1278 1279
DWORD	WINAPI	OpenVxDHandle(DWORD pmt)
{
1280
	FIXME( "(0x%08lx) stub!\n", pmt);
1281 1282
	return 0;
}
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299

static BOOL DeviceIo_HASP(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
			      LPDWORD lpcbBytesReturned,
			      LPOVERLAPPED lpOverlapped)
{
    BOOL retv = TRUE;
	FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
			dwIoControlCode,
			lpvInBuffer,cbInBuffer,
			lpvOutBuffer,cbOutBuffer,
			lpcbBytesReturned,
			lpOverlapped);

    return retv;
}