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
8b1050c7
Commit
8b1050c7
authored
May 22, 2019
by
Zebediah Figura
Committed by
Alexandre Julliard
May 22, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
setupapi: Implement class co-installers in SetupDiCallClassInstaller().
Signed-off-by:
Zebediah Figura
<
z.figura12@gmail.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
afba7d9d
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
215 additions
and
1 deletion
+215
-1
devinst.c
dlls/setupapi/devinst.c
+71
-1
coinst.c
dlls/setupapi/tests/coinst.c
+20
-0
coinst.spec
dlls/setupapi/tests/coinst.spec
+3
-0
devinst.c
dlls/setupapi/tests/devinst.c
+121
-0
No files found.
dlls/setupapi/devinst.c
View file @
8b1050c7
...
...
@@ -3524,19 +3524,73 @@ BOOL WINAPI SetupDiSetClassInstallParamsW(
return
FALSE
;
}
static
BOOL
call_coinstallers
(
WCHAR
*
list
,
DI_FUNCTION
function
,
HDEVINFO
devinfo
,
SP_DEVINFO_DATA
*
device_data
)
{
DWORD
(
CALLBACK
*
coinst_proc
)(
DI_FUNCTION
,
HDEVINFO
,
SP_DEVINFO_DATA
*
,
COINSTALLER_CONTEXT_DATA
*
);
COINSTALLER_CONTEXT_DATA
coinst_ctx
;
WCHAR
*
p
,
*
procnameW
;
HMODULE
module
;
char
*
procname
;
DWORD
ret
;
for
(
p
=
list
;
*
p
;
p
+=
strlenW
(
p
)
+
1
)
{
TRACE
(
"Found co-installer %s.
\n
"
,
debugstr_w
(
p
));
if
((
procnameW
=
strchrW
(
p
,
','
)))
*
procnameW
=
0
;
if
((
module
=
LoadLibraryExW
(
p
,
NULL
,
LOAD_LIBRARY_SEARCH_SYSTEM32
)))
{
if
(
procnameW
)
{
procname
=
strdupWtoA
(
procnameW
+
1
);
coinst_proc
=
(
void
*
)
GetProcAddress
(
module
,
procname
);
heap_free
(
procname
);
}
else
coinst_proc
=
(
void
*
)
GetProcAddress
(
module
,
"CoDeviceInstall"
);
if
(
coinst_proc
)
{
memset
(
&
coinst_ctx
,
0
,
sizeof
(
coinst_ctx
));
TRACE
(
"Calling co-installer %p.
\n
"
,
coinst_proc
);
ret
=
coinst_proc
(
function
,
devinfo
,
device_data
,
&
coinst_ctx
);
TRACE
(
"Co-installer %p returned %#x.
\n
"
,
coinst_proc
,
ret
);
if
(
ret
==
ERROR_DI_POSTPROCESSING_REQUIRED
)
FIXME
(
"Co-installer postprocessing not implemented.
\n
"
);
else
if
(
ret
)
{
ERR
(
"Co-installer returned error %#x.
\n
"
,
ret
);
FreeLibrary
(
module
);
SetLastError
(
ret
);
return
FALSE
;
}
}
FreeLibrary
(
module
);
}
}
return
TRUE
;
}
/***********************************************************************
* SetupDiCallClassInstaller (SETUPAPI.@)
*/
BOOL
WINAPI
SetupDiCallClassInstaller
(
DI_FUNCTION
function
,
HDEVINFO
devinfo
,
SP_DEVINFO_DATA
*
device_data
)
{
static
const
WCHAR
class_coinst_pathW
[]
=
{
'S'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
'\\'
,
'C'
,
'u'
,
'r'
,
'r'
,
'e'
,
'n'
,
't'
,
'C'
,
'o'
,
'n'
,
't'
,
'r'
,
'o'
,
'l'
,
'S'
,
'e'
,
't'
,
'\\'
,
'C'
,
'o'
,
'n'
,
't'
,
'r'
,
'o'
,
'l'
,
'\\'
,
'C'
,
'o'
,
'D'
,
'e'
,
'v'
,
'i'
,
'c'
,
'e'
,
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'l'
,
'l'
,
'e'
,
'r'
,
's'
,
0
};
static
const
WCHAR
installer32W
[]
=
{
'I'
,
'n'
,
's'
,
't'
,
'a'
,
'l'
,
'l'
,
'e'
,
'r'
,
'3'
,
'2'
,
0
};
DWORD
(
CALLBACK
*
classinst_proc
)(
DI_FUNCTION
,
HDEVINFO
,
SP_DEVINFO_DATA
*
);
DWORD
ret
=
ERROR_DI_DO_DEFAULT
;
HKEY
class_key
,
coinst_key
;
WCHAR
*
path
,
*
procnameW
;
struct
device
*
device
;
WCHAR
guidstr
[
39
];
BOOL
coret
=
TRUE
;
HMODULE
module
;
char
*
procname
;
HKEY
class_key
;
DWORD
size
;
TRACE
(
"function %#x, devinfo %p, device_data %p.
\n
"
,
function
,
devinfo
,
device_data
);
...
...
@@ -3544,6 +3598,22 @@ BOOL WINAPI SetupDiCallClassInstaller(DI_FUNCTION function, HDEVINFO devinfo, SP
if
(
!
(
device
=
get_device
(
devinfo
,
device_data
)))
return
FALSE
;
if
(
!
RegOpenKeyExW
(
HKEY_LOCAL_MACHINE
,
class_coinst_pathW
,
0
,
KEY_READ
,
&
coinst_key
))
{
SETUPDI_GuidToString
(
&
device
->
class
,
guidstr
);
if
(
!
RegGetValueW
(
coinst_key
,
NULL
,
guidstr
,
RRF_RT_REG_MULTI_SZ
,
NULL
,
NULL
,
&
size
))
{
path
=
heap_alloc
(
size
);
if
(
!
RegGetValueW
(
coinst_key
,
NULL
,
guidstr
,
RRF_RT_REG_MULTI_SZ
,
NULL
,
path
,
&
size
))
coret
=
call_coinstallers
(
path
,
function
,
devinfo
,
device_data
);
heap_free
(
path
);
}
RegCloseKey
(
coinst_key
);
}
if
(
!
coret
)
return
FALSE
;
if
((
class_key
=
SetupDiOpenClassRegKey
(
&
device
->
class
,
KEY_READ
))
!=
INVALID_HANDLE_VALUE
)
{
if
(
!
RegGetValueW
(
class_key
,
NULL
,
installer32W
,
RRF_RT_REG_SZ
,
NULL
,
NULL
,
&
size
))
...
...
dlls/setupapi/tests/coinst.c
View file @
8b1050c7
...
...
@@ -49,3 +49,23 @@ DWORD WINAPI class_error(DI_FUNCTION function, HDEVINFO set, SP_DEVINFO_DATA *de
{
return
0xdeadbeef
;
}
DWORD
WINAPI
co_success
(
DI_FUNCTION
function
,
HDEVINFO
set
,
SP_DEVINFO_DATA
*
device
,
COINSTALLER_CONTEXT_DATA
*
context
)
{
callback_count
++
;
last_message
=
function
;
return
ERROR_SUCCESS
;
}
DWORD
WINAPI
CoDeviceInstall
(
DI_FUNCTION
function
,
HDEVINFO
set
,
SP_DEVINFO_DATA
*
device
,
COINSTALLER_CONTEXT_DATA
*
context
)
{
return
co_success
(
function
,
set
,
device
,
context
);
}
DWORD
WINAPI
co_error
(
DI_FUNCTION
function
,
HDEVINFO
set
,
SP_DEVINFO_DATA
*
device
,
COINSTALLER_CONTEXT_DATA
*
context
)
{
return
0xdeadbeef
;
}
dlls/setupapi/tests/coinst.spec
View file @
8b1050c7
...
...
@@ -2,5 +2,8 @@
@ stdcall ClassInstall(long ptr ptr)
@ stdcall class_default(long ptr ptr)
@ stdcall class_error(long ptr ptr)
@ stdcall co_success(long ptr ptr ptr)
@ stdcall CoDeviceInstall(long ptr ptr ptr)
@ stdcall co_error(long ptr ptr ptr)
@ extern callback_count
@ extern last_message
dlls/setupapi/tests/devinst.c
View file @
8b1050c7
...
...
@@ -2507,6 +2507,126 @@ static void test_class_installer(void)
RegCloseKey
(
class_key
);
}
static
void
test_class_coinstaller
(
void
)
{
SP_DEVINFO_DATA
device
=
{
sizeof
(
device
)};
char
regdata
[
200
];
HKEY
coinst_key
;
HDEVINFO
set
;
BOOL
ret
;
LONG
res
;
res
=
RegCreateKeyA
(
HKEY_LOCAL_MACHINE
,
"System
\\
CurrentControlSet
\\
Control
\\
CoDeviceInstallers"
,
&
coinst_key
);
ok
(
!
res
,
"Failed to open CoDeviceInstallers key, error %u.
\n
"
,
res
);
strcpy
(
regdata
,
"winetest_coinst.dll,co_success"
);
regdata
[
strlen
(
regdata
)
+
1
]
=
0
;
res
=
RegSetValueExA
(
coinst_key
,
"{6a55b5a4-3f65-11db-b704-0011955c2bdb}"
,
0
,
REG_MULTI_SZ
,
(
BYTE
*
)
regdata
,
strlen
(
regdata
)
+
2
);
ok
(
!
res
,
"Failed to set registry value, error %u.
\n
"
,
res
);
/* We must recreate the device list, or Windows will not recognize that the
* class co-installer exists. */
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
);
ok
(
ret
,
"Failed to create device, error %#x.
\n
"
,
GetLastError
());
ret
=
SetupDiCallClassInstaller
(
DIF_ALLOW_INSTALL
,
set
,
&
device
);
ok
(
!
ret
,
"Expected failure.
\n
"
);
ok
(
GetLastError
()
==
ERROR_DI_DO_DEFAULT
,
"Got unexpected error %#x.
\n
"
,
GetLastError
());
ok
(
*
coinst_callback_count
==
1
,
"Got %d callbacks.
\n
"
,
*
coinst_callback_count
);
ok
(
*
coinst_last_message
==
DIF_ALLOW_INSTALL
,
"Got unexpected message %#x.
\n
"
,
*
coinst_last_message
);
*
coinst_callback_count
=
0
;
ret
=
SetupDiCallClassInstaller
(
0xdeadbeef
,
set
,
&
device
);
ok
(
!
ret
,
"Expected failure.
\n
"
);
ok
(
GetLastError
()
==
ERROR_DI_DO_DEFAULT
,
"Got unexpected error %#x.
\n
"
,
GetLastError
());
ok
(
*
coinst_callback_count
==
1
,
"Got %d callbacks.
\n
"
,
*
coinst_callback_count
);
ok
(
*
coinst_last_message
==
0xdeadbeef
,
"Got unexpected message %#x.
\n
"
,
*
coinst_last_message
);
*
coinst_callback_count
=
0
;
ok
(
!
device_is_registered
(
set
,
&
device
),
"Expected device not to be registered.
\n
"
);
ret
=
SetupDiCallClassInstaller
(
DIF_REGISTERDEVICE
,
set
,
&
device
);
ok
(
ret
,
"Failed to call class installer, error %#x.
\n
"
,
GetLastError
());
ok
(
device_is_registered
(
set
,
&
device
),
"Expected device to be registered.
\n
"
);
ok
(
*
coinst_callback_count
==
1
,
"Got %d callbacks.
\n
"
,
*
coinst_callback_count
);
ok
(
*
coinst_last_message
==
DIF_REGISTERDEVICE
,
"Got unexpected message %#x.
\n
"
,
*
coinst_last_message
);
*
coinst_callback_count
=
0
;
ret
=
SetupDiCallClassInstaller
(
DIF_REMOVE
,
set
,
&
device
);
ok
(
ret
,
"Failed to call class installer, error %#x.
\n
"
,
GetLastError
());
ok
(
!
device_is_registered
(
set
,
&
device
),
"Expected device not to be registered.
\n
"
);
ok
(
*
coinst_callback_count
==
1
,
"Got %d callbacks.
\n
"
,
*
coinst_callback_count
);
ok
(
*
coinst_last_message
==
DIF_REMOVE
,
"Got unexpected message %#x.
\n
"
,
*
coinst_last_message
);
*
coinst_callback_count
=
0
;
SetupDiDestroyDeviceInfoList
(
set
);
todo_wine
ok
(
*
coinst_callback_count
==
1
,
"Got %d callbacks.
\n
"
,
*
coinst_callback_count
);
todo_wine
ok
(
*
coinst_last_message
==
DIF_DESTROYPRIVATEDATA
,
"Got unexpected message %#x.
\n
"
,
*
coinst_last_message
);
*
coinst_callback_count
=
0
;
/* Test returning an error from the co-installer. */
strcpy
(
regdata
,
"winetest_coinst.dll,co_error"
);
regdata
[
strlen
(
regdata
)
+
1
]
=
0
;
res
=
RegSetValueExA
(
coinst_key
,
"{6a55b5a4-3f65-11db-b704-0011955c2bdb}"
,
0
,
REG_MULTI_SZ
,
(
BYTE
*
)
regdata
,
strlen
(
regdata
)
+
2
);
ok
(
!
res
,
"Failed to set registry value, error %u.
\n
"
,
res
);
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
);
ok
(
ret
,
"Failed to create device, error %#x.
\n
"
,
GetLastError
());
ret
=
SetupDiCallClassInstaller
(
DIF_ALLOW_INSTALL
,
set
,
&
device
);
ok
(
!
ret
,
"Expected failure.
\n
"
);
ok
(
GetLastError
()
==
0xdeadbeef
,
"Got unexpected error %#x.
\n
"
,
GetLastError
());
ok
(
!
device_is_registered
(
set
,
&
device
),
"Expected device not to be registered.
\n
"
);
ret
=
SetupDiCallClassInstaller
(
DIF_REGISTERDEVICE
,
set
,
&
device
);
ok
(
!
ret
,
"Expected failure.
\n
"
);
ok
(
GetLastError
()
==
0xdeadbeef
,
"Got unexpected error %#x.
\n
"
,
GetLastError
());
ok
(
!
device_is_registered
(
set
,
&
device
),
"Expected device not to be registered.
\n
"
);
SetupDiDestroyDeviceInfoList
(
set
);
/* The default entry point is CoDeviceInstall(). */
strcpy
(
regdata
,
"winetest_coinst.dll"
);
regdata
[
strlen
(
regdata
)
+
1
]
=
0
;
res
=
RegSetValueExA
(
coinst_key
,
"{6a55b5a4-3f65-11db-b704-0011955c2bdb}"
,
0
,
REG_MULTI_SZ
,
(
BYTE
*
)
regdata
,
strlen
(
regdata
)
+
2
);
ok
(
!
res
,
"Failed to set registry value, error %u.
\n
"
,
res
);
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
);
ok
(
ret
,
"Failed to create device, error %#x.
\n
"
,
GetLastError
());
ret
=
SetupDiCallClassInstaller
(
DIF_ALLOW_INSTALL
,
set
,
&
device
);
ok
(
!
ret
,
"Expected failure.
\n
"
);
ok
(
GetLastError
()
==
ERROR_DI_DO_DEFAULT
,
"Got unexpected error %#x.
\n
"
,
GetLastError
());
ok
(
*
coinst_callback_count
==
1
,
"Got %d callbacks.
\n
"
,
*
coinst_callback_count
);
ok
(
*
coinst_last_message
==
DIF_ALLOW_INSTALL
,
"Got unexpected message %#x.
\n
"
,
*
coinst_last_message
);
*
coinst_callback_count
=
0
;
SetupDiDestroyDeviceInfoList
(
set
);
ok
(
*
coinst_callback_count
==
1
,
"Got %d callbacks.
\n
"
,
*
coinst_callback_count
);
ok
(
*
coinst_last_message
==
DIF_DESTROYPRIVATEDATA
,
"Got unexpected message %#x.
\n
"
,
*
coinst_last_message
);
*
coinst_callback_count
=
0
;
res
=
RegDeleteValueA
(
coinst_key
,
"{6a55b5a4-3f65-11db-b704-0011955c2bdb}"
);
ok
(
!
res
,
"Failed to delete value, error %u.
\n
"
,
res
);
RegCloseKey
(
coinst_key
);
}
static
void
test_call_class_installer
(
void
)
{
SP_DEVINFO_DATA
device
=
{
sizeof
(
device
)};
...
...
@@ -2553,6 +2673,7 @@ static void test_call_class_installer(void)
coinst_last_message
=
(
void
*
)
GetProcAddress
(
coinst
,
"last_message"
);
test_class_installer
();
test_class_coinstaller
();
FreeLibrary
(
coinst
);
...
...
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