Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
4d984fd9
Commit
4d984fd9
authored
Feb 20, 2004
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create real file handles for VxDs instead of using the server device
object hack (partly based on a patch by Eric Pouech).
parent
64d68b10
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
246 additions
and
354 deletions
+246
-354
Makefile.in
dlls/kernel/Makefile.in
+0
-1
device.c
dlls/kernel/device.c
+0
-350
vxd.c
dlls/kernel/vxd.c
+243
-0
file.c
files/file.c
+1
-1
file.h
include/file.h
+2
-2
No files found.
dlls/kernel/Makefile.in
View file @
4d984fd9
...
...
@@ -33,7 +33,6 @@ C_SRCS = \
console.c
\
cpu.c
\
debugger.c
\
device.c
\
dosmem.c
\
editline.c
\
environ.c
\
...
...
dlls/kernel/device.c
deleted
100644 → 0
View file @
64d68b10
/*
* Win32 device functions
*
* Copyright 1998 Marcus Meissner
* Copyright 1998 Ulrich Weigand
* Copyright 1998 Patrik Stridvall
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include "ntstatus.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winerror.h"
#include "winnls.h"
#include "file.h"
#include "kernel_private.h"
#include "wine/server.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
file
);
/*
* VxD names are taken from the Win95 DDK
*/
struct
VxDInfo
{
LPCSTR
name
;
WORD
id
;
HMODULE
module
;
BOOL
(
*
deviceio
)(
DWORD
,
LPVOID
,
DWORD
,
LPVOID
,
DWORD
,
LPDWORD
,
LPOVERLAPPED
);
};
static
struct
VxDInfo
VxDList
[]
=
{
/* Standard VxD IDs */
{
"VMM"
,
0x0001
,
NULL
,
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
},
{
"VCD"
,
0x000E
,
NULL
,
NULL
},
{
"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
},
{
"VWIN32"
,
0x002A
,
NULL
,
NULL
},
{
"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
},
{
"IFSMgr"
,
0x0040
,
NULL
,
NULL
},
{
"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
,
NULL
},
{
"MMDEVLDR"
,
0x044A
,
NULL
,
NULL
},
/* 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
},
{
"PCCARD"
,
0x097C
,
NULL
,
NULL
},
{
"HASP95"
,
0x3721
,
NULL
,
NULL
},
/* WINE additions, ids unknown */
{
"MONODEBG"
,
0x4242
,
NULL
,
NULL
},
{
NULL
,
0
,
NULL
,
NULL
}
};
HANDLE
DEVICE_Open
(
LPCWSTR
filenameW
,
DWORD
access
,
LPSECURITY_ATTRIBUTES
sa
)
{
static
const
WCHAR
dotVxDW
[]
=
{
'.'
,
'v'
,
'x'
,
'd'
,
0
};
struct
VxDInfo
*
info
;
WCHAR
*
p
,
buffer
[
16
];
char
filename
[
32
];
if
(
strlenW
(
filenameW
)
>=
sizeof
(
buffer
)
/
sizeof
(
WCHAR
)
-
4
||
strchrW
(
filenameW
,
'/'
)
||
strchrW
(
filenameW
,
'\\'
))
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
0
;
}
strcpyW
(
buffer
,
filenameW
);
p
=
strchrW
(
buffer
,
'.'
);
if
(
!
p
)
strcatW
(
buffer
,
dotVxDW
);
else
if
(
strcmpiW
(
p
,
dotVxDW
))
/* existing extension has to be .vxd */
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
0
;
}
if
(
!
WideCharToMultiByte
(
CP_ACP
,
0
,
buffer
,
-
1
,
filename
,
sizeof
(
filename
),
NULL
,
NULL
))
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
0
;
}
for
(
info
=
VxDList
;
info
->
name
;
info
++
)
if
(
!
strncasecmp
(
info
->
name
,
filename
,
strlen
(
info
->
name
)
))
{
if
(
!
info
->
module
)
{
info
->
module
=
LoadLibraryW
(
buffer
);
if
(
info
->
module
)
info
->
deviceio
=
(
void
*
)
GetProcAddress
(
info
->
module
,
"DeviceIoControl"
);
}
return
FILE_CreateDevice
(
info
->
id
|
0x10000
,
access
,
sa
);
}
FIXME
(
"Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.
\n
"
,
filename
);
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
0
;
}
static
DWORD
DEVICE_GetClientID
(
HANDLE
handle
)
{
DWORD
ret
=
0
;
SERVER_START_REQ
(
get_device_id
)
{
req
->
handle
=
handle
;
if
(
!
wine_server_call
(
req
))
ret
=
reply
->
id
;
}
SERVER_END_REQ
;
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
;
}
return
info
;
}
/****************************************************************************
* DeviceIoControl (KERNEL32.@)
* 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
* GetLastError can decipher.
*/
BOOL
WINAPI
DeviceIoControl
(
HANDLE
hDevice
,
DWORD
dwIoControlCode
,
LPVOID
lpvInBuffer
,
DWORD
cbInBuffer
,
LPVOID
lpvOutBuffer
,
DWORD
cbOutBuffer
,
LPDWORD
lpcbBytesReturned
,
LPOVERLAPPED
lpOverlapped
)
{
DWORD
clientID
;
TRACE
(
"(%p,%ld,%p,%ld,%p,%ld,%p,%p)
\n
"
,
hDevice
,
dwIoControlCode
,
lpvInBuffer
,
cbInBuffer
,
lpvOutBuffer
,
cbOutBuffer
,
lpcbBytesReturned
,
lpOverlapped
);
if
(
!
(
clientID
=
DEVICE_GetClientID
(
hDevice
)))
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
/* Check if this is a user defined control code for a VxD */
if
(
HIWORD
(
dwIoControlCode
)
==
0
)
{
const
struct
VxDInfo
*
info
;
if
(
!
(
info
=
DEVICE_GetInfo
(
clientID
)))
{
FIXME
(
"No device found for id %lx
\n
"
,
clientID
);
}
else
if
(
info
->
deviceio
)
{
return
info
->
deviceio
(
dwIoControlCode
,
lpvInBuffer
,
cbInBuffer
,
lpvOutBuffer
,
cbOutBuffer
,
lpcbBytesReturned
,
lpOverlapped
);
}
else
{
FIXME
(
"Unimplemented control %ld for VxD device %s
\n
"
,
dwIoControlCode
,
info
->
name
?
info
->
name
:
"???"
);
/* FIXME: this is for invalid calls on W98SE,
* but maybe we should use ERROR_CALL_NOT_IMPLEMENTED
* instead ? */
SetLastError
(
ERROR_INVALID_FUNCTION
);
}
}
else
{
NTSTATUS
status
;
if
(
lpOverlapped
)
{
status
=
NtDeviceIoControlFile
(
hDevice
,
lpOverlapped
->
hEvent
,
NULL
,
NULL
,
(
PIO_STATUS_BLOCK
)
lpOverlapped
,
dwIoControlCode
,
lpvInBuffer
,
cbInBuffer
,
lpvOutBuffer
,
cbOutBuffer
);
if
(
status
)
SetLastError
(
RtlNtStatusToDosError
(
status
));
if
(
lpcbBytesReturned
)
*
lpcbBytesReturned
=
lpOverlapped
->
InternalHigh
;
return
!
status
;
}
else
{
IO_STATUS_BLOCK
iosb
;
status
=
NtDeviceIoControlFile
(
hDevice
,
NULL
,
NULL
,
NULL
,
&
iosb
,
dwIoControlCode
,
lpvInBuffer
,
cbInBuffer
,
lpvOutBuffer
,
cbOutBuffer
);
if
(
status
)
SetLastError
(
RtlNtStatusToDosError
(
status
));
if
(
lpcbBytesReturned
)
*
lpcbBytesReturned
=
iosb
.
Information
;
return
!
status
;
}
}
return
FALSE
;
}
dlls/kernel/vxd.c
View file @
4d984fd9
...
...
@@ -28,6 +28,7 @@
# include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdarg.h>
...
...
@@ -40,11 +41,198 @@
#include "winnt.h"
#include "winternl.h"
#include "wine/winbase16.h"
#include "file.h"
#include "kernel_private.h"
#include "wine/unicode.h"
#include "wine/server.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
vxd
);
typedef
BOOL
(
WINAPI
*
DeviceIoProc
)(
DWORD
,
LPVOID
,
DWORD
,
LPVOID
,
DWORD
,
LPDWORD
,
LPOVERLAPPED
);
struct
vxd_module
{
dev_t
dev
;
ino_t
ino
;
HANDLE
handle
;
HMODULE
module
;
DeviceIoProc
proc
;
};
#define MAX_VXD_MODULES 32
static
struct
vxd_module
vxd_modules
[
MAX_VXD_MODULES
];
static
CRITICAL_SECTION
vxd_section
;
static
CRITICAL_SECTION_DEBUG
critsect_debug
=
{
0
,
0
,
&
vxd_section
,
{
&
critsect_debug
.
ProcessLocksList
,
&
critsect_debug
.
ProcessLocksList
},
0
,
0
,
{
0
,
(
DWORD
)(
__FILE__
": vxd_section"
)
}
};
static
CRITICAL_SECTION
vxd_section
=
{
&
critsect_debug
,
-
1
,
0
,
0
,
0
,
0
};
/* create a file handle to represent a VxD, by opening a dummy file in the wineserver directory */
static
HANDLE
open_vxd_handle
(
LPCWSTR
name
)
{
const
char
*
dir
=
wine_get_server_dir
();
char
*
unix_name
;
int
len1
,
len2
;
HANDLE
ret
;
len1
=
strlen
(
dir
);
len2
=
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
name
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
!
(
unix_name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len1
+
len2
+
1
)))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
strcpy
(
unix_name
,
dir
);
unix_name
[
len1
]
=
'/'
;
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
name
,
-
1
,
unix_name
+
len1
+
1
,
len2
,
NULL
,
NULL
);
ret
=
FILE_CreateFile
(
unix_name
,
0
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_ALWAYS
,
0
,
0
,
TRUE
,
DRIVE_FIXED
);
HeapFree
(
GetProcessHeap
(),
0
,
unix_name
);
return
ret
;
}
/* retrieve the DeviceIoControl function for a Vxd given a file handle */
static
DeviceIoProc
get_vxd_proc
(
HANDLE
handle
)
{
struct
stat
st
;
DeviceIoProc
ret
=
NULL
;
int
status
,
i
,
fd
;
status
=
wine_server_handle_to_fd
(
handle
,
0
,
&
fd
,
NULL
,
NULL
);
if
(
status
)
{
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
return
NULL
;
}
if
(
fstat
(
fd
,
&
st
)
==
-
1
)
{
wine_server_release_fd
(
handle
,
fd
);
SetLastError
(
ERROR_INVALID_HANDLE
);
return
NULL
;
}
RtlEnterCriticalSection
(
&
vxd_section
);
for
(
i
=
0
;
i
<
MAX_VXD_MODULES
;
i
++
)
{
if
(
!
vxd_modules
[
i
].
module
)
break
;
if
(
vxd_modules
[
i
].
dev
==
st
.
st_dev
&&
vxd_modules
[
i
].
ino
==
st
.
st_ino
)
{
if
(
!
(
ret
=
vxd_modules
[
i
].
proc
))
SetLastError
(
ERROR_INVALID_FUNCTION
);
goto
done
;
}
}
/* FIXME: Here we could go through the directory to find the VxD name and load it. */
/* Let's wait to find out if there are actually apps out there that try to share */
/* VxD handles between processes, before we go to the trouble of implementing it. */
ERR
(
"handle %p not found in module list, inherited from another process?
\n
"
,
handle
);
done:
RtlLeaveCriticalSection
(
&
vxd_section
);
return
ret
;
}
/* load a VxD and return a file handle to it */
HANDLE
VXD_Open
(
LPCWSTR
filenameW
,
DWORD
access
,
SECURITY_ATTRIBUTES
*
sa
)
{
static
const
WCHAR
dotVxDW
[]
=
{
'.'
,
'v'
,
'x'
,
'd'
,
0
};
int
i
;
HANDLE
handle
;
HMODULE
module
;
WCHAR
*
p
,
name
[
16
];
if
(
!
(
GetVersion
()
&
0x80000000
))
/* there are no VxDs on NT */
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
/* normalize the filename */
if
(
strlenW
(
filenameW
)
>=
sizeof
(
name
)
/
sizeof
(
WCHAR
)
-
4
||
strchrW
(
filenameW
,
'/'
)
||
strchrW
(
filenameW
,
'\\'
))
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
0
;
}
strcpyW
(
name
,
filenameW
);
strlwrW
(
name
);
p
=
strchrW
(
name
,
'.'
);
if
(
!
p
)
strcatW
(
name
,
dotVxDW
);
else
if
(
strcmpW
(
p
,
dotVxDW
))
/* existing extension has to be .vxd */
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
0
;
}
/* try to load the module first */
if
(
!
(
module
=
LoadLibraryW
(
name
)))
{
FIXME
(
"Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.
\n
"
,
debugstr_w
(
name
)
);
return
0
;
}
/* register the module in the global list if necessary */
RtlEnterCriticalSection
(
&
vxd_section
);
for
(
i
=
0
;
i
<
MAX_VXD_MODULES
;
i
++
)
{
if
(
vxd_modules
[
i
].
module
==
module
)
{
handle
=
vxd_modules
[
i
].
handle
;
goto
done
;
/* already registered */
}
if
(
!
vxd_modules
[
i
].
module
)
/* new one, register it */
{
struct
stat
st
;
int
fd
;
/* get a file handle to the dummy file */
if
(
!
(
handle
=
open_vxd_handle
(
name
)))
{
FreeLibrary
(
module
);
goto
done
;
}
wine_server_handle_to_fd
(
handle
,
0
,
&
fd
,
NULL
,
NULL
);
if
(
fstat
(
fd
,
&
st
)
!=
-
1
)
{
vxd_modules
[
i
].
dev
=
st
.
st_dev
;
vxd_modules
[
i
].
ino
=
st
.
st_ino
;
}
vxd_modules
[
i
].
module
=
module
;
vxd_modules
[
i
].
handle
=
handle
;
vxd_modules
[
i
].
proc
=
(
DeviceIoProc
)
GetProcAddress
(
module
,
"DeviceIoControl"
);
wine_server_release_fd
(
handle
,
fd
);
goto
done
;
}
}
ERR
(
"too many open VxD modules, please report
\n
"
);
CloseHandle
(
handle
);
FreeLibrary
(
module
);
handle
=
0
;
done:
RtlLeaveCriticalSection
(
&
vxd_section
);
if
(
!
DuplicateHandle
(
GetCurrentProcess
(),
handle
,
GetCurrentProcess
(),
&
handle
,
0
,
(
sa
&&
(
sa
->
nLength
>=
sizeof
(
*
sa
))
&&
sa
->
bInheritHandle
),
DUP_HANDLE_SAME_ACCESS
))
handle
=
0
;
return
handle
;
}
/*
* VMM VxDCall service names are (mostly) taken from Stan Mitchell's
* "Inside the Windows 95 File System"
...
...
@@ -1164,3 +1352,58 @@ HANDLE WINAPI OpenVxDHandle(HANDLE hHandleRing3)
FIXME
(
"(%p), stub! (returning Ring 3 handle instead of Ring 0)
\n
"
,
hHandleRing3
);
return
hHandleRing3
;
}
/****************************************************************************
* DeviceIoControl (KERNEL32.@)
* 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
* GetLastError can decipher.
*/
BOOL
WINAPI
DeviceIoControl
(
HANDLE
hDevice
,
DWORD
dwIoControlCode
,
LPVOID
lpvInBuffer
,
DWORD
cbInBuffer
,
LPVOID
lpvOutBuffer
,
DWORD
cbOutBuffer
,
LPDWORD
lpcbBytesReturned
,
LPOVERLAPPED
lpOverlapped
)
{
NTSTATUS
status
;
TRACE
(
"(%p,%lx,%p,%ld,%p,%ld,%p,%p)
\n
"
,
hDevice
,
dwIoControlCode
,
lpvInBuffer
,
cbInBuffer
,
lpvOutBuffer
,
cbOutBuffer
,
lpcbBytesReturned
,
lpOverlapped
);
/* Check if this is a user defined control code for a VxD */
if
(
HIWORD
(
dwIoControlCode
)
==
0
)
{
DeviceIoProc
proc
=
get_vxd_proc
(
hDevice
);
if
(
proc
)
return
proc
(
dwIoControlCode
,
lpvInBuffer
,
cbInBuffer
,
lpvOutBuffer
,
cbOutBuffer
,
lpcbBytesReturned
,
lpOverlapped
);
return
FALSE
;
}
/* Not a VxD, let ntdll handle it */
if
(
lpOverlapped
)
{
status
=
NtDeviceIoControlFile
(
hDevice
,
lpOverlapped
->
hEvent
,
NULL
,
NULL
,
(
PIO_STATUS_BLOCK
)
lpOverlapped
,
dwIoControlCode
,
lpvInBuffer
,
cbInBuffer
,
lpvOutBuffer
,
cbOutBuffer
);
if
(
lpcbBytesReturned
)
*
lpcbBytesReturned
=
lpOverlapped
->
InternalHigh
;
}
else
{
IO_STATUS_BLOCK
iosb
;
status
=
NtDeviceIoControlFile
(
hDevice
,
NULL
,
NULL
,
NULL
,
&
iosb
,
dwIoControlCode
,
lpvInBuffer
,
cbInBuffer
,
lpvOutBuffer
,
cbOutBuffer
);
if
(
lpcbBytesReturned
)
*
lpcbBytesReturned
=
iosb
.
Information
;
}
if
(
status
)
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
return
!
status
;
}
files/file.c
View file @
4d984fd9
...
...
@@ -397,7 +397,7 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
}
else
if
(
!
DOSFS_GetDevice
(
filename
))
{
ret
=
DEVICE
_Open
(
filename
+
4
,
access
,
sa
);
ret
=
VXD
_Open
(
filename
+
4
,
access
,
sa
);
goto
done
;
}
else
...
...
include/file.h
View file @
4d984fd9
...
...
@@ -97,7 +97,7 @@ extern BOOL DOSFS_FindUnixName( const DOS_FULL_NAME *path, LPCWSTR name, char *l
extern
BOOL
DOSFS_GetFullName
(
LPCWSTR
name
,
BOOL
check_last
,
DOS_FULL_NAME
*
full
);
/*
win32/device
.c */
extern
HANDLE
DEVICE
_Open
(
LPCWSTR
filename
,
DWORD
access
,
LPSECURITY_ATTRIBUTES
sa
);
/*
vxd
.c */
extern
HANDLE
VXD
_Open
(
LPCWSTR
filename
,
DWORD
access
,
LPSECURITY_ATTRIBUTES
sa
);
#endif
/* __WINE_FILE_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment