Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
afac1c40
Commit
afac1c40
authored
Jan 30, 2019
by
Zhiyi Zhang
Committed by
Alexandre Julliard
Feb 05, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
setupapi: Implement SetupDiSetDevicePropertyW.
Signed-off-by:
Zhiyi Zhang
<
zzhang@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
5e2aac99
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
266 additions
and
1 deletion
+266
-1
devinst.c
dlls/setupapi/devinst.c
+101
-0
setupapi.spec
dlls/setupapi/setupapi.spec
+1
-0
devinst.c
dlls/setupapi/tests/devinst.c
+162
-1
setupapi.h
include/setupapi.h
+2
-0
No files found.
dlls/setupapi/devinst.c
View file @
afac1c40
...
...
@@ -327,6 +327,28 @@ static WCHAR *get_refstr_key_path(struct device_iface *iface)
return
path
;
}
static
BOOL
is_valid_property_type
(
DEVPROPTYPE
prop_type
)
{
DWORD
type
=
prop_type
&
DEVPROP_MASK_TYPE
;
DWORD
typemod
=
prop_type
&
DEVPROP_MASK_TYPEMOD
;
if
(
type
>
MAX_DEVPROP_TYPE
)
return
FALSE
;
if
(
typemod
>
MAX_DEVPROP_TYPEMOD
)
return
FALSE
;
if
(
typemod
==
DEVPROP_TYPEMOD_ARRAY
&&
(
type
==
DEVPROP_TYPE_EMPTY
||
type
==
DEVPROP_TYPE_NULL
||
type
==
DEVPROP_TYPE_STRING
||
type
==
DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING
))
return
FALSE
;
if
(
typemod
==
DEVPROP_TYPEMOD_LIST
&&
!
(
type
==
DEVPROP_TYPE_STRING
||
type
==
DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING
))
return
FALSE
;
return
TRUE
;
}
static
LPWSTR
SETUPDI_CreateSymbolicLinkPath
(
LPCWSTR
instanceId
,
const
GUID
*
InterfaceClassGuid
,
LPCWSTR
ReferenceString
)
{
...
...
@@ -3410,6 +3432,85 @@ BOOL WINAPI SetupDiSetDeviceInstallParamsW(
return
TRUE
;
}
BOOL
WINAPI
SetupDiSetDevicePropertyW
(
HDEVINFO
devinfo
,
PSP_DEVINFO_DATA
device_data
,
const
DEVPROPKEY
*
key
,
DEVPROPTYPE
type
,
const
BYTE
*
buffer
,
DWORD
size
,
DWORD
flags
)
{
static
const
WCHAR
propertiesW
[]
=
{
'P'
,
'r'
,
'o'
,
'p'
,
'e'
,
'r'
,
't'
,
'i'
,
'e'
,
's'
,
0
};
static
const
WCHAR
formatW
[]
=
{
'\\'
,
'%'
,
'0'
,
'4'
,
'X'
,
0
};
struct
device
*
device
;
HKEY
properties_hkey
,
property_hkey
;
WCHAR
property_hkey_path
[
44
];
LSTATUS
ls
;
TRACE
(
"%p %p %p %#x %p %d %#x
\n
"
,
devinfo
,
device_data
,
key
,
type
,
buffer
,
size
,
flags
);
if
(
!
(
device
=
get_device
(
devinfo
,
device_data
)))
return
FALSE
;
if
(
!
key
||
!
is_valid_property_type
(
type
)
||
(
buffer
&&
!
size
&&
!
(
type
==
DEVPROP_TYPE_EMPTY
||
type
==
DEVPROP_TYPE_NULL
))
||
(
buffer
&&
size
&&
(
type
==
DEVPROP_TYPE_EMPTY
||
type
==
DEVPROP_TYPE_NULL
)))
{
SetLastError
(
ERROR_INVALID_DATA
);
return
FALSE
;
}
if
(
size
&&
!
buffer
)
{
SetLastError
(
ERROR_INVALID_USER_BUFFER
);
return
FALSE
;
}
if
(
flags
)
{
SetLastError
(
ERROR_INVALID_FLAGS
);
return
FALSE
;
}
ls
=
RegCreateKeyExW
(
device
->
key
,
propertiesW
,
0
,
NULL
,
0
,
KEY_READ
|
KEY_WRITE
,
NULL
,
&
properties_hkey
,
NULL
);
if
(
ls
)
{
SetLastError
(
ls
);
return
FALSE
;
}
SETUPDI_GuidToString
(
&
key
->
fmtid
,
property_hkey_path
);
sprintfW
(
property_hkey_path
+
38
,
formatW
,
key
->
pid
);
if
(
type
==
DEVPROP_TYPE_EMPTY
)
{
ls
=
RegDeleteKeyW
(
properties_hkey
,
property_hkey_path
);
RegCloseKey
(
properties_hkey
);
SetLastError
(
ls
==
ERROR_FILE_NOT_FOUND
?
ERROR_NOT_FOUND
:
ls
);
return
!
ls
;
}
else
if
(
type
==
DEVPROP_TYPE_NULL
)
{
if
(
!
(
ls
=
RegOpenKeyW
(
properties_hkey
,
property_hkey_path
,
&
property_hkey
)))
{
ls
=
RegDeleteValueW
(
property_hkey
,
NULL
);
RegCloseKey
(
property_hkey
);
}
RegCloseKey
(
properties_hkey
);
SetLastError
(
ls
==
ERROR_FILE_NOT_FOUND
?
ERROR_NOT_FOUND
:
ls
);
return
!
ls
;
}
else
{
if
(
!
(
ls
=
RegCreateKeyExW
(
properties_hkey
,
property_hkey_path
,
0
,
NULL
,
0
,
KEY_READ
|
KEY_WRITE
,
NULL
,
&
property_hkey
,
NULL
)))
{
ls
=
RegSetValueExW
(
property_hkey
,
NULL
,
0
,
0xffff0000
|
(
0xffff
&
type
),
buffer
,
size
);
RegCloseKey
(
property_hkey
);
}
RegCloseKey
(
properties_hkey
);
SetLastError
(
ls
);
return
!
ls
;
}
}
static
HKEY
SETUPDI_OpenDevKey
(
struct
device
*
device
,
REGSAM
samDesired
)
{
HKEY
enumKey
,
key
=
INVALID_HANDLE_VALUE
;
...
...
dlls/setupapi/setupapi.spec
View file @
afac1c40
...
...
@@ -389,6 +389,7 @@
@ stdcall SetupDiSetClassInstallParamsW(ptr ptr ptr long)
@ stdcall SetupDiSetDeviceInstallParamsA(ptr ptr ptr)
@ stdcall SetupDiSetDeviceInstallParamsW(ptr ptr ptr)
@ stdcall SetupDiSetDevicePropertyW(ptr ptr ptr long ptr long long)
@ stdcall SetupDiSetDeviceRegistryPropertyA(ptr ptr long ptr long)
@ stdcall SetupDiSetDeviceRegistryPropertyW(ptr ptr long ptr long)
@ stub SetupDiSetDriverInstallParamsA
...
...
dlls/setupapi/tests/devinst.c
View file @
afac1c40
...
...
@@ -26,7 +26,8 @@
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "guiddef.h"
#include "initguid.h"
#include "devpkey.h"
#include "setupapi.h"
#include "cfgmgr32.h"
...
...
@@ -37,6 +38,8 @@
static
GUID
guid
=
{
0x6a55b5a4
,
0x3f65
,
0x11db
,
{
0xb7
,
0x04
,
0x00
,
0x11
,
0x95
,
0x5c
,
0x2b
,
0xdb
}};
static
GUID
guid2
=
{
0x6a55b5a5
,
0x3f65
,
0x11db
,
{
0xb7
,
0x04
,
0x00
,
0x11
,
0x95
,
0x5c
,
0x2b
,
0xdb
}};
BOOL
(
WINAPI
*
pSetupDiSetDevicePropertyW
)(
HDEVINFO
,
PSP_DEVINFO_DATA
,
const
DEVPROPKEY
*
,
DEVPROPTYPE
,
const
BYTE
*
,
DWORD
,
DWORD
);
static
void
test_create_device_list_ex
(
void
)
{
static
const
WCHAR
machine
[]
=
{
'd'
,
'u'
,
'm'
,
'm'
,
'y'
,
0
};
...
...
@@ -342,6 +345,163 @@ static void test_device_info(void)
SetupDiDestroyDeviceInfoList
(
set
);
}
static
void
test_device_property
(
void
)
{
static
const
WCHAR
valueW
[]
=
{
'd'
,
'e'
,
'a'
,
'd'
,
'b'
,
'e'
,
'e'
,
'f'
,
0
};
SP_DEVINFO_DATA
device_data
=
{
sizeof
(
device_data
)};
HMODULE
hmod
;
HDEVINFO
set
;
DWORD
err
;
BOOL
ret
;
hmod
=
LoadLibraryA
(
"setupapi.dll"
);
pSetupDiSetDevicePropertyW
=
(
void
*
)
GetProcAddress
(
hmod
,
"SetupDiSetDevicePropertyW"
);
if
(
!
pSetupDiSetDevicePropertyW
)
{
win_skip
(
"SetupDiSetDevicePropertyW() are only available on vista+, skipping tests.
\n
"
);
FreeLibrary
(
hmod
);
return
;
}
set
=
SetupDiCreateDeviceInfoList
(
&
guid
,
NULL
);
ok
(
set
!=
INVALID_HANDLE_VALUE
,
"Failed to create device list, error %#x.
\n
"
,
GetLastError
());
ret
=
SetupDiCreateDeviceInfoA
(
set
,
"Root
\\
LEGACY_BOGUS
\\
0000"
,
&
guid
,
NULL
,
NULL
,
0
,
&
device_data
);
ok
(
ret
,
"Failed to create device, error %#x.
\n
"
,
GetLastError
());
/* SetupDiSetDevicePropertyW */
/* #1 Null device info list */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
NULL
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_INVALID_HANDLE
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_INVALID_HANDLE
,
err
);
/* #2 Null device */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
NULL
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_INVALID_PARAMETER
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_INVALID_PARAMETER
,
err
);
/* #3 Null property key pointer */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
NULL
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_INVALID_DATA
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_INVALID_DATA
,
err
);
/* #4 Invalid property key type */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
0xffff
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_INVALID_DATA
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_INVALID_DATA
,
err
);
/* #5 Null buffer pointer */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
NULL
,
sizeof
(
valueW
),
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_INVALID_USER_BUFFER
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_INVALID_USER_BUFFER
,
err
);
/* #6 Zero buffer size */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
0
,
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_INVALID_DATA
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_INVALID_DATA
,
err
);
/* #7 Flags not zero */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
1
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_INVALID_FLAGS
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_INVALID_FLAGS
,
err
);
/* #8 Normal */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
err
=
GetLastError
();
ok
(
ret
,
"Expect success
\n
"
);
ok
(
err
==
NO_ERROR
,
"Expect last error %#x, got %#x
\n
"
,
NO_ERROR
,
err
);
/* #9 Delete property with buffer not null */
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
ok
(
ret
,
"Expect success
\n
"
);
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_EMPTY
,
(
const
BYTE
*
)
valueW
,
0
,
0
);
err
=
GetLastError
();
ok
(
ret
,
"Expect success
\n
"
);
ok
(
err
==
NO_ERROR
,
"Expect last error %#x, got %#x
\n
"
,
NO_ERROR
,
err
);
/* #10 Delete property with size not zero */
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
ok
(
ret
,
"Expect success
\n
"
);
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_EMPTY
,
NULL
,
sizeof
(
valueW
),
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_INVALID_USER_BUFFER
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_INVALID_USER_BUFFER
,
err
);
/* #11 Delete property */
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
ok
(
ret
,
"Expect success
\n
"
);
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_EMPTY
,
NULL
,
0
,
0
);
err
=
GetLastError
();
ok
(
ret
,
"Expect success
\n
"
);
ok
(
err
==
NO_ERROR
,
"Expect last error %#x, got %#x
\n
"
,
NO_ERROR
,
err
);
/* #12 Delete non-existent property */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_EMPTY
,
NULL
,
0
,
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_NOT_FOUND
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_NOT_FOUND
,
err
);
/* #13 Delete property value with buffer not null */
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
ok
(
ret
,
"Expect success
\n
"
);
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_NULL
,
(
const
BYTE
*
)
valueW
,
0
,
0
);
err
=
GetLastError
();
ok
(
ret
,
"Expect success
\n
"
);
ok
(
err
==
NO_ERROR
,
"Expect last error %#x, got %#x
\n
"
,
NO_ERROR
,
err
);
/* #14 Delete property value with size not zero */
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
ok
(
ret
,
"Expect success
\n
"
);
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_NULL
,
NULL
,
sizeof
(
valueW
),
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_INVALID_USER_BUFFER
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_INVALID_USER_BUFFER
,
err
);
/* #15 Delete property value */
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_STRING
,
(
const
BYTE
*
)
valueW
,
sizeof
(
valueW
),
0
);
ok
(
ret
,
"Expect success
\n
"
);
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_NULL
,
NULL
,
0
,
0
);
err
=
GetLastError
();
ok
(
ret
,
"Expect success
\n
"
);
ok
(
err
==
NO_ERROR
,
"Expect last error %#x, got %#x
\n
"
,
NO_ERROR
,
err
);
/* #16 Delete non-existent property value */
SetLastError
(
0xdeadbeef
);
ret
=
pSetupDiSetDevicePropertyW
(
set
,
&
device_data
,
&
DEVPKEY_Device_FriendlyName
,
DEVPROP_TYPE_NULL
,
NULL
,
0
,
0
);
err
=
GetLastError
();
ok
(
!
ret
,
"Expect failure
\n
"
);
ok
(
err
==
ERROR_NOT_FOUND
,
"Expect last error %#x, got %#x
\n
"
,
ERROR_NOT_FOUND
,
err
);
ret
=
SetupDiRemoveDevice
(
set
,
&
device_data
);
ok
(
ret
,
"Got unexpected error %#x.
\n
"
,
GetLastError
());
SetupDiDestroyDeviceInfoList
(
set
);
FreeLibrary
(
hmod
);
}
static
void
test_get_device_instance_id
(
void
)
{
BOOL
ret
;
...
...
@@ -1339,6 +1499,7 @@ START_TEST(devinst)
test_open_class_key
();
test_install_class
();
test_device_info
();
test_device_property
();
test_get_device_instance_id
();
test_register_device_info
();
test_device_iface
();
...
...
include/setupapi.h
View file @
afac1c40
...
...
@@ -1634,6 +1634,8 @@ BOOL WINAPI SetupDiSetDeviceInterfaceDefault(HDEVINFO, PSP_DEVICE_INTERFACE_
BOOL
WINAPI
SetupDiSetDeviceInstallParamsA
(
HDEVINFO
,
PSP_DEVINFO_DATA
,
PSP_DEVINSTALL_PARAMS_A
);
BOOL
WINAPI
SetupDiSetDeviceInstallParamsW
(
HDEVINFO
,
PSP_DEVINFO_DATA
,
PSP_DEVINSTALL_PARAMS_W
);
#define SetupDiSetDeviceInstallParams WINELIB_NAME_AW(SetupDiSetDeviceInstallParams)
BOOL
WINAPI
SetupDiSetDevicePropertyW
(
HDEVINFO
,
PSP_DEVINFO_DATA
,
const
DEVPROPKEY
*
,
DEVPROPTYPE
,
const
BYTE
*
,
DWORD
,
DWORD
);
#define SetupDiSetDeviceProperty WINELIB_NAME_AW(SetupDiSetDeviceProperty)
/* note: A function doesn't exist */
BOOL
WINAPI
SetupDiSetDeviceRegistryPropertyA
(
HDEVINFO
,
PSP_DEVINFO_DATA
,
DWORD
,
const
BYTE
*
,
DWORD
);
BOOL
WINAPI
SetupDiSetDeviceRegistryPropertyW
(
HDEVINFO
,
PSP_DEVINFO_DATA
,
DWORD
,
const
BYTE
*
,
DWORD
);
#define SetupDiSetDeviceRegistryProperty WINELIB_NAME_AW(SetupDiSetDeviceRegistryProperty)
...
...
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