v3 has the following changes since v2 based on the feedback from Alistair Leslie-Hughes:
- Make functions in advapi32 that are no longer in the header static - Remove SERV_dup() entirely, and add strdupAW() in service.c when it is moved into sechost
Micah N Gorrell (8): advapi32: Replace usage of internal SERV_ functions with exported functions advapi32: Replace SERV_dup() with strdupAW() advapi32: Move RPC interfaces from advapi32 into sechost sechost: Implement I_ScRegisterDeviceNotification() ntoskrnl.exe: Implement sending of device notifications user32: Implement RegisterDeviceNotification() user32/tests: Add test for RegisterDeviceNotification() sechost/tests: Add test for I_ScRegisterDeviceNotification()
configure.ac | 2 + dlls/advapi32/Makefile.in | 5 +- dlls/advapi32/advapi32.spec | 92 +++--- dlls/advapi32/advapi32_misc.h | 4 - dlls/advapi32/eventlog.c | 12 +- dlls/advapi32/security.c | 54 ++-- dlls/ntoskrnl.exe/Makefile.in | 4 +- dlls/ntoskrnl.exe/ntoskrnl_private.h | 5 + dlls/ntoskrnl.exe/pnp.c | 1 + dlls/ntoskrnl.exe/rpc.c | 182 ++++++++++++ dlls/{advapi32 => ntoskrnl.exe}/svcctl.idl | 0 dlls/sechost/Makefile.in | 8 + dlls/sechost/sechost.spec | 48 ++++ dlls/{advapi32 => sechost}/service.c | 310 +++++++++++++++------ dlls/sechost/svcctl.idl | 3 + dlls/sechost/tests/Makefile.in | 5 + dlls/sechost/tests/devnotify.c | 102 +++++++ dlls/user32/Makefile.in | 2 +- dlls/user32/misc.c | 73 ++++- dlls/user32/tests/input.c | 70 ++++- include/wine/svcctl.idl | 20 ++ include/winsvc.h | 14 + include/winuser.h | 4 +- programs/services/rpc.c | 169 ++++++++++- 24 files changed, 1008 insertions(+), 181 deletions(-) create mode 100644 dlls/ntoskrnl.exe/rpc.c rename dlls/{advapi32 => ntoskrnl.exe}/svcctl.idl (100%) create mode 100644 dlls/sechost/Makefile.in create mode 100644 dlls/sechost/sechost.spec rename dlls/{advapi32 => sechost}/service.c (91%) create mode 100644 dlls/sechost/svcctl.idl create mode 100644 dlls/sechost/tests/Makefile.in create mode 100644 dlls/sechost/tests/devnotify.c
This is in preparation for moving the services RPC functions into sechost.
Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- dlls/advapi32/advapi32_misc.h | 3 --- dlls/advapi32/security.c | 32 +++++++++++++++++++++++++------- dlls/advapi32/service.c | 6 +++--- 3 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/dlls/advapi32/advapi32_misc.h b/dlls/advapi32/advapi32_misc.h index 4ced1e8a64..77b56420ba 100644 --- a/dlls/advapi32/advapi32_misc.h +++ b/dlls/advapi32/advapi32_misc.h @@ -32,9 +32,6 @@ BOOL ADVAPI_GetComputerSid(PSID sid) DECLSPEC_HIDDEN; BOOL lookup_local_wellknown_name(const LSA_UNICODE_STRING*, PSID, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE, BOOL*) DECLSPEC_HIDDEN; BOOL lookup_local_user_name(const LSA_UNICODE_STRING*, PSID, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE, BOOL*) DECLSPEC_HIDDEN; WCHAR *SERV_dup(const char *str) DECLSPEC_HIDDEN; -DWORD SERV_OpenSCManagerW(LPCWSTR, LPCWSTR, DWORD, SC_HANDLE*) DECLSPEC_HIDDEN; -DWORD SERV_OpenServiceW(SC_HANDLE, LPCWSTR, DWORD, SC_HANDLE*) DECLSPEC_HIDDEN; -NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD) DECLSPEC_HIDDEN; const WCHAR *get_wellknown_privilege_name(const LUID *) DECLSPEC_HIDDEN;
/* memory allocation functions */ diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index a7707f15d3..74eda93282 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -416,15 +416,19 @@ static inline DWORD get_security_file( LPCWSTR full_file_name, DWORD access, HAN static inline DWORD get_security_service( LPWSTR full_service_name, DWORD access, HANDLE *service ) { SC_HANDLE manager = 0; - DWORD err;
- err = SERV_OpenSCManagerW( NULL, NULL, access, (SC_HANDLE *)&manager ); - if (err == ERROR_SUCCESS) + manager = OpenSCManagerW( NULL, NULL, access ); + if (manager) { - err = SERV_OpenServiceW( manager, full_service_name, access, (SC_HANDLE *)service ); + *service = OpenServiceW( manager, full_service_name, access); CloseServiceHandle( manager ); + + if (*service) + { + return ERROR_SUCCESS; + } } - return err; + return GetLastError(); }
/* helper function for SE_REGISTRY_KEY objects in [Get|Set]NamedSecurityInfo */ @@ -1804,7 +1808,14 @@ DWORD WINAPI GetSecurityInfo( switch (ObjectType) { case SE_SERVICE: - status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1); + if (QueryServiceObjectSecurity(hObject, SecurityInfo, NULL, 0, &n1)) + { + status = STATUS_SUCCESS; + } + else + { + status = RtlGetLastNtStatus(); + } break; default: status = NtQuerySecurityObject(hObject, SecurityInfo, NULL, 0, &n1); @@ -1820,7 +1831,14 @@ DWORD WINAPI GetSecurityInfo( switch (ObjectType) { case SE_SERVICE: - status = SERV_QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2); + if (QueryServiceObjectSecurity(hObject, SecurityInfo, sd, n1, &n2)) + { + status = STATUS_SUCCESS; + } + else + { + status = RtlGetLastNtStatus(); + } break; default: status = NtQuerySecurityObject(hObject, SecurityInfo, sd, n1, &n2); diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 231f0267e9..2781a12823 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -897,7 +897,7 @@ SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName, * * See OpenSCManagerA. */ -DWORD SERV_OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, +static DWORD SERV_OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess, SC_HANDLE *handle ) { DWORD r; @@ -1049,7 +1049,7 @@ SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, * * See OpenServiceA. */ -DWORD SERV_OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, +static DWORD SERV_OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, DWORD dwDesiredAccess, SC_HANDLE *handle ) { DWORD err; @@ -2484,7 +2484,7 @@ BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel, return err == ERROR_SUCCESS; }
-NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE hService, +static NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE hService, SECURITY_INFORMATION dwSecurityInformation, PSECURITY_DESCRIPTOR lpSecurityDescriptor, DWORD cbBufSize, LPDWORD pcbBytesNeeded)
The strdupAW() function in advapi32_misc.h behaves exactly the same as SERV_dup(). Switching calls to strdupAW() will reduce the complexity when moving the services RPC functions into sechost by allowing moving the service.c file with few changes.
Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- dlls/advapi32/advapi32_misc.h | 1 - dlls/advapi32/eventlog.c | 12 +++---- dlls/advapi32/security.c | 22 ++++++------- dlls/advapi32/service.c | 60 ++++++++++++----------------------- 4 files changed, 38 insertions(+), 57 deletions(-)
diff --git a/dlls/advapi32/advapi32_misc.h b/dlls/advapi32/advapi32_misc.h index 77b56420ba..65bd8aa852 100644 --- a/dlls/advapi32/advapi32_misc.h +++ b/dlls/advapi32/advapi32_misc.h @@ -31,7 +31,6 @@ BOOL ADVAPI_GetComputerSid(PSID sid) DECLSPEC_HIDDEN;
BOOL lookup_local_wellknown_name(const LSA_UNICODE_STRING*, PSID, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE, BOOL*) DECLSPEC_HIDDEN; BOOL lookup_local_user_name(const LSA_UNICODE_STRING*, PSID, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE, BOOL*) DECLSPEC_HIDDEN; -WCHAR *SERV_dup(const char *str) DECLSPEC_HIDDEN; const WCHAR *get_wellknown_privilege_name(const LUID *) DECLSPEC_HIDDEN;
/* memory allocation functions */ diff --git a/dlls/advapi32/eventlog.c b/dlls/advapi32/eventlog.c index 6f8d26b516..4349408a00 100644 --- a/dlls/advapi32/eventlog.c +++ b/dlls/advapi32/eventlog.c @@ -57,7 +57,7 @@ BOOL WINAPI BackupEventLogA( HANDLE hEventLog, LPCSTR lpBackupFileName ) LPWSTR backupW; BOOL ret;
- backupW = SERV_dup(lpBackupFileName); + backupW = strdupAW(lpBackupFileName); ret = BackupEventLogW(hEventLog, backupW); heap_free(backupW);
@@ -114,7 +114,7 @@ BOOL WINAPI ClearEventLogA( HANDLE hEventLog, LPCSTR lpBackupFileName ) LPWSTR backupW; BOOL ret;
- backupW = SERV_dup(lpBackupFileName); + backupW = strdupAW(lpBackupFileName); ret = ClearEventLogW(hEventLog, backupW); heap_free(backupW);
@@ -430,8 +430,8 @@ HANDLE WINAPI OpenBackupEventLogA( LPCSTR lpUNCServerName, LPCSTR lpFileName ) LPWSTR uncnameW, filenameW; HANDLE handle;
- uncnameW = SERV_dup(lpUNCServerName); - filenameW = SERV_dup(lpFileName); + uncnameW = strdupAW(lpUNCServerName); + filenameW = strdupAW(lpFileName); handle = OpenBackupEventLogW(uncnameW, filenameW); heap_free(uncnameW); heap_free(filenameW); @@ -489,8 +489,8 @@ HANDLE WINAPI OpenEventLogA( LPCSTR uncname, LPCSTR source ) LPWSTR uncnameW, sourceW; HANDLE handle;
- uncnameW = SERV_dup(uncname); - sourceW = SERV_dup(source); + uncnameW = strdupAW(uncname); + sourceW = strdupAW(source); handle = OpenEventLogW(uncnameW, sourceW); heap_free(uncnameW); heap_free(sourceW); diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index 74eda93282..326058e2f7 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -1020,7 +1020,7 @@ GetFileSecurityA( LPCSTR lpFileName, BOOL r; LPWSTR name;
- name = SERV_dup(lpFileName); + name = strdupAW(lpFileName); r = GetFileSecurityW( name, RequestedInformation, pSecurityDescriptor, nLength, lpnLengthNeeded ); heap_free( name ); @@ -1049,7 +1049,7 @@ LookupAccountSidA( DWORD accountSizeW = *accountSize; DWORD domainSizeW = *domainSize;
- systemW = SERV_dup(system); + systemW = strdupAW(system); if (account) accountW = heap_alloc( accountSizeW * sizeof(WCHAR) ); if (domain) @@ -1303,7 +1303,7 @@ BOOL WINAPI SetFileSecurityA( LPCSTR lpFileName, BOOL r; LPWSTR name;
- name = SERV_dup(lpFileName); + name = strdupAW(lpFileName); r = SetFileSecurityW( name, RequestedInformation, pSecurityDescriptor ); heap_free( name );
@@ -2251,7 +2251,7 @@ static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR * { case TRUSTEE_IS_NAME: { - *ptrustee_nameW = SERV_dup(trustee_nameA); + *ptrustee_nameW = strdupAW(trustee_nameA); return ERROR_SUCCESS; } case TRUSTEE_IS_OBJECTS_AND_NAME: @@ -2266,9 +2266,9 @@ static DWORD trustee_name_A_to_W(TRUSTEE_FORM form, char *trustee_nameA, WCHAR *
objW->ObjectsPresent = objA->ObjectsPresent; objW->ObjectType = objA->ObjectType; - objW->ObjectTypeName = SERV_dup(objA->ObjectTypeName); - objW->InheritedObjectTypeName = SERV_dup(objA->InheritedObjectTypeName); - objW->ptstrName = SERV_dup(objA->ptstrName); + objW->ObjectTypeName = strdupAW(objA->ObjectTypeName); + objW->InheritedObjectTypeName = strdupAW(objA->InheritedObjectTypeName); + objW->ptstrName = strdupAW(objA->ptstrName); }
*ptrustee_nameW = (WCHAR *)objW; @@ -2648,7 +2648,7 @@ DWORD WINAPI SetNamedSecurityInfoA(LPSTR pObjectName, TRACE("%s %d %d %p %p %p %p\n", debugstr_a(pObjectName), ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl);
- wstr = SERV_dup(pObjectName); + wstr = strdupAW(pObjectName); r = SetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl );
@@ -3323,7 +3323,7 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA( if(!StringSecurityDescriptor) return FALSE;
- StringSecurityDescriptorW = SERV_dup(StringSecurityDescriptor); + StringSecurityDescriptorW = strdupAW(StringSecurityDescriptor); ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW, StringSDRevision, SecurityDescriptor, SecurityDescriptorSize); @@ -3833,7 +3833,7 @@ BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid) SetLastError(ERROR_INVALID_PARAMETER); else { - WCHAR *wStringSid = SERV_dup(StringSid); + WCHAR *wStringSid = strdupAW(StringSid); bret = ConvertStringSidToSidW(wStringSid, Sid); heap_free(wStringSid); } @@ -4096,7 +4096,7 @@ DWORD WINAPI GetNamedSecurityInfoA(LPSTR pObjectName, TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo, ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor);
- wstr = SERV_dup(pObjectName); + wstr = strdupAW(pObjectName); r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor );
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 2781a12823..3bf6fdfd47 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -113,24 +113,6 @@ static BOOL stop_service;
extern HANDLE CDECL __wine_make_process_system(void);
-/****************************************************************************** - * String management functions (same behaviour as strdup) - * NOTE: the caller of those functions is responsible for calling HeapFree - * in order to release the memory allocated by those functions. - */ -LPWSTR SERV_dup( LPCSTR str ) -{ - UINT len; - LPWSTR wstr; - - if( !str ) - return NULL; - len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); - wstr = heap_alloc( len*sizeof (WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len ); - return wstr; -} - static inline LPWSTR SERV_dupmulti(LPCSTR str) { UINT len = 0, n = 0; @@ -884,8 +866,8 @@ SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName, LPWSTR machineW, databaseW; SC_HANDLE ret;
- machineW = SERV_dup(lpMachineName); - databaseW = SERV_dup(lpDatabaseName); + machineW = strdupAW(lpMachineName); + databaseW = strdupAW(lpDatabaseName); ret = OpenSCManagerW(machineW, databaseW, dwDesiredAccess); heap_free(databaseW); heap_free(machineW); @@ -1037,7 +1019,7 @@ SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
TRACE("%p %s 0x%08x\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
- lpServiceNameW = SERV_dup(lpServiceName); + lpServiceNameW = strdupAW(lpServiceName); ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess); heap_free(lpServiceNameW); return ret; @@ -1171,13 +1153,13 @@ CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, TRACE("%p %s %s\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
- lpServiceNameW = SERV_dup( lpServiceName ); - lpDisplayNameW = SERV_dup( lpDisplayName ); - lpBinaryPathNameW = SERV_dup( lpBinaryPathName ); - lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup ); + lpServiceNameW = strdupAW( lpServiceName ); + lpDisplayNameW = strdupAW( lpDisplayName ); + lpBinaryPathNameW = strdupAW( lpBinaryPathName ); + lpLoadOrderGroupW = strdupAW( lpLoadOrderGroup ); lpDependenciesW = SERV_dupmulti( lpDependencies ); - lpServiceStartNameW = SERV_dup( lpServiceStartName ); - lpPasswordW = SERV_dup( lpPassword ); + lpServiceStartNameW = strdupAW( lpServiceStartName ); + lpPasswordW = strdupAW( lpPassword );
r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, @@ -1269,7 +1251,7 @@ BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs, lpwstr = heap_alloc( dwNumServiceArgs*sizeof(LPWSTR) );
for(i=0; i<dwNumServiceArgs; i++) - lpwstr[i]=SERV_dup(lpServiceArgVectors[i]); + lpwstr[i]=strdupAW(lpServiceArgVectors[i]);
r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
@@ -2108,7 +2090,7 @@ BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName, TRACE("%p %s %p %p\n", hSCManager, debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
- lpDisplayNameW = SERV_dup(lpDisplayName); + lpDisplayNameW = strdupAW(lpDisplayName); if (lpServiceName) lpServiceNameW = heap_alloc(*lpcchBuffer * sizeof(WCHAR)); else @@ -2231,7 +2213,7 @@ BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName, TRACE("%p %s %p %p\n", hSCManager, debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
- lpServiceNameW = SERV_dup(lpServiceName); + lpServiceNameW = strdupAW(lpServiceName); if (lpDisplayName) lpDisplayNameW = heap_alloc(*lpcchBuffer * sizeof(WCHAR)); else @@ -2374,12 +2356,12 @@ BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType, lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName), debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
- wBinaryPathName = SERV_dup( lpBinaryPathName ); - wLoadOrderGroup = SERV_dup( lpLoadOrderGroup ); + wBinaryPathName = strdupAW( lpBinaryPathName ); + wLoadOrderGroup = strdupAW( lpLoadOrderGroup ); wDependencies = SERV_dupmulti( lpDependencies ); - wServiceStartName = SERV_dup( lpServiceStartName ); - wPassword = SERV_dup( lpPassword ); - wDisplayName = SERV_dup( lpDisplayName ); + wServiceStartName = strdupAW( lpServiceStartName ); + wPassword = strdupAW( lpPassword ); + wDisplayName = strdupAW( lpDisplayName );
r = ChangeServiceConfigW( hService, dwServiceType, dwStartType, dwErrorControl, wBinaryPathName, @@ -2411,7 +2393,7 @@ BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel, LPSERVICE_DESCRIPTIONA sd = lpInfo; SERVICE_DESCRIPTIONW sdw;
- sdw.lpDescription = SERV_dup( sd->lpDescription ); + sdw.lpDescription = strdupAW( sd->lpDescription );
r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
@@ -2423,8 +2405,8 @@ BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel, SERVICE_FAILURE_ACTIONSW faw;
faw.dwResetPeriod = fa->dwResetPeriod; - faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg ); - faw.lpCommand = SERV_dup( fa->lpCommand ); + faw.lpRebootMsg = strdupAW( fa->lpRebootMsg ); + faw.lpCommand = strdupAW( fa->lpCommand ); faw.cActions = fa->cActions; faw.lpsaActions = fa->lpsaActions;
@@ -2589,7 +2571,7 @@ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDL LPWSTR nameW; SERVICE_STATUS_HANDLE ret;
- nameW = SERV_dup(name); + nameW = strdupAW(name); ret = RegisterServiceCtrlHandlerExW( nameW, handler, context ); heap_free( nameW ); return ret;
Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- configure.ac | 1 + dlls/advapi32/Makefile.in | 5 +- dlls/advapi32/advapi32.spec | 92 +++++++++++----------- dlls/sechost/Makefile.in | 8 ++ dlls/sechost/sechost.spec | 46 +++++++++++ dlls/{advapi32 => sechost}/service.c | 109 ++++++++++++++------------ dlls/{advapi32 => sechost}/svcctl.idl | 0 7 files changed, 162 insertions(+), 99 deletions(-) create mode 100644 dlls/sechost/Makefile.in create mode 100644 dlls/sechost/sechost.spec rename dlls/{advapi32 => sechost}/service.c (97%) rename dlls/{advapi32 => sechost}/svcctl.idl (100%)
diff --git a/configure.ac b/configure.ac index b39b6b2c90..b4040ccd27 100644 --- a/configure.ac +++ b/configure.ac @@ -3644,6 +3644,7 @@ WINE_CONFIG_MAKEFILE(dlls/scrobj) WINE_CONFIG_MAKEFILE(dlls/scrrun) WINE_CONFIG_MAKEFILE(dlls/scrrun/tests) WINE_CONFIG_MAKEFILE(dlls/scsiport.sys) +WINE_CONFIG_MAKEFILE(dlls/sechost) WINE_CONFIG_MAKEFILE(dlls/secur32) WINE_CONFIG_MAKEFILE(dlls/secur32/tests) WINE_CONFIG_MAKEFILE(dlls/security) diff --git a/dlls/advapi32/Makefile.in b/dlls/advapi32/Makefile.in index e530adac4e..f8f9c567e5 100644 --- a/dlls/advapi32/Makefile.in +++ b/dlls/advapi32/Makefile.in @@ -1,7 +1,7 @@ EXTRADEFS = -D_ADVAPI32_ MODULE = advapi32.dll IMPORTLIB = advapi32 -IMPORTS = kernelbase +IMPORTS = kernelbase sechost DELAYIMPORTS = rpcrt4 EXTRALIBS = $(SECURITY_LIBS)
@@ -16,9 +16,6 @@ C_SRCS = \ lsa.c \ registry.c \ security.c \ - service.c \ wmi.c
-IDL_SRCS = svcctl.idl - RC_SRCS = version.rc diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index 3db5612c61..ea5cb54e16 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -89,10 +89,10 @@ @ stdcall BuildTrusteeWithSidA(ptr ptr) @ stdcall BuildTrusteeWithSidW(ptr ptr) # @ stub CancelOverlappedAccess -@ stdcall ChangeServiceConfig2A(long long ptr) -@ stdcall ChangeServiceConfig2W(long long ptr) -@ stdcall ChangeServiceConfigA(long long long long wstr str ptr str str str str) -@ stdcall ChangeServiceConfigW(long long long long wstr wstr ptr wstr wstr wstr wstr) +@ stdcall -import ChangeServiceConfig2A(long long ptr) +@ stdcall -import ChangeServiceConfig2W(long long ptr) +@ stdcall -import ChangeServiceConfigA(long long long long wstr str ptr str str str str) +@ stdcall -import ChangeServiceConfigW(long long long long wstr wstr ptr wstr wstr wstr wstr) # @ stub CheckForHiberboot @ stdcall -import CheckTokenMembership(long ptr ptr) @ stdcall ClearEventLogA (long str) @@ -100,12 +100,12 @@ # @ stub CloseCodeAuthzLevel @ stdcall CloseEncryptedFileRaw(ptr) @ stdcall CloseEventLog (long) -@ stdcall CloseServiceHandle(long) +@ stdcall -import CloseServiceHandle(long) # @ stub CloseThreadWaitChainSession @ stdcall CloseTrace(int64) @ stdcall CommandLineFromMsiDescriptor(wstr ptr ptr) # @ stub ComputeAccessTokenFromCodeAuthzLevel -@ stdcall ControlService(long long ptr) +@ stdcall -import ControlService(long long ptr) # @ stub ControlServiceExA # @ stub ControlServiceExW @ stdcall ControlTraceA(int64 str ptr long) @@ -143,8 +143,8 @@ @ stdcall CreateProcessWithLogonW(wstr wstr wstr long wstr wstr long ptr wstr ptr ptr) @ stdcall CreateProcessWithTokenW(long long wstr wstr long ptr wstr ptr ptr) @ stdcall -import CreateRestrictedToken(long long long ptr long ptr long ptr ptr) -@ stdcall CreateServiceA(long str str long long long long str str ptr str str str) -@ stdcall CreateServiceW(long wstr wstr long long long long wstr wstr ptr wstr wstr wstr) +@ stdcall -import CreateServiceA(long str str long long long long str str ptr str str str) +@ stdcall -import CreateServiceW(long wstr wstr long long long long wstr wstr ptr wstr wstr wstr) # @ stub CreateTraceInstanceId @ stdcall -import CreateWellKnownSid(long ptr ptr ptr) # @ stub CredBackupCredentials @@ -235,7 +235,7 @@ @ stdcall DecryptFileA(str long) @ stdcall DecryptFileW(wstr long) @ stdcall -import DeleteAce(ptr long) -@ stdcall DeleteService(long) +@ stdcall -import DeleteService(long) @ stdcall DeregisterEventSource(long) @ stdcall -import DestroyPrivateObjectSecurity(ptr) # @ stub DuplicateEncryptionInfoFile @@ -270,15 +270,15 @@ @ stdcall EncryptFileW(wstr) # @ stub EncryptedFileKeyInfo # @ stub EncryptionDisable -@ stdcall EnumDependentServicesA(long long ptr long ptr ptr) -@ stdcall EnumDependentServicesW(long long ptr long ptr ptr) +@ stdcall -import EnumDependentServicesA(long long ptr long ptr ptr) +@ stdcall -import EnumDependentServicesW(long long ptr long ptr ptr) @ stdcall -import EnumDynamicTimeZoneInformation(long ptr) @ stub EnumServiceGroupA @ stub EnumServiceGroupW -@ stdcall EnumServicesStatusA (long long long ptr long ptr ptr ptr) -@ stdcall EnumServicesStatusExA(long long long long ptr long ptr ptr ptr str) -@ stdcall EnumServicesStatusExW(long long long long ptr long ptr ptr ptr wstr) -@ stdcall EnumServicesStatusW (long long long ptr long ptr ptr ptr) +@ stdcall -import EnumServicesStatusA (long long long ptr long ptr ptr ptr) +@ stdcall -import EnumServicesStatusExA(long long long long ptr long ptr ptr ptr str) +@ stdcall -import EnumServicesStatusExW(long long long long ptr long ptr ptr ptr wstr) +@ stdcall -import EnumServicesStatusW (long long long ptr long ptr ptr ptr) @ stdcall EnumerateTraceGuids(ptr long ptr) # @ stub EnumerateTraceGuidsEx # @ stub EqualDomainSid @@ -360,10 +360,10 @@ @ stdcall GetSecurityInfo (long long long ptr ptr ptr ptr ptr) @ stdcall GetSecurityInfoExA (long long long str str ptr ptr ptr ptr) @ stdcall GetSecurityInfoExW (long long long wstr wstr ptr ptr ptr ptr) -@ stdcall GetServiceDisplayNameA(ptr str ptr ptr) -@ stdcall GetServiceDisplayNameW(ptr wstr ptr ptr) -@ stdcall GetServiceKeyNameA(long str ptr ptr) -@ stdcall GetServiceKeyNameW(long wstr ptr ptr) +@ stdcall -import GetServiceDisplayNameA(ptr str ptr ptr) +@ stdcall -import GetServiceDisplayNameW(ptr wstr ptr ptr) +@ stdcall -import GetServiceKeyNameA(long str ptr ptr) +@ stdcall -import GetServiceKeyNameW(long wstr ptr ptr) @ stdcall -import GetSidIdentifierAuthority(ptr) @ stdcall -import GetSidLengthRequired(long) @ stdcall -import GetSidSubAuthority(ptr long) @@ -421,7 +421,7 @@ @ stdcall -import IsValidSecurityDescriptor(ptr) @ stdcall -import IsValidSid(ptr) @ stdcall -import IsWellKnownSid(ptr long) -@ stdcall LockServiceDatabase(ptr) +@ stdcall -import LockServiceDatabase(ptr) @ stdcall LogonUserA(str str str long long ptr) # @ stub LogonUserExA # @ stub LogonUserExExW @@ -526,7 +526,7 @@ @ stdcall NotifyChangeEventLog (long long) # @ stub NotifyServiceStatusChange # @ stub NotifyServiceStatusChangeA -@ stdcall NotifyServiceStatusChangeW(ptr long ptr) +@ stdcall -import NotifyServiceStatusChangeW(ptr long ptr) # @ stub NpGetUserName @ stdcall ObjectCloseAuditAlarmA(str ptr long) @ stdcall -import ObjectCloseAuditAlarmW(wstr ptr long) @@ -543,10 +543,10 @@ @ stdcall OpenEventLogA (str str) @ stdcall OpenEventLogW (wstr wstr) @ stdcall -import OpenProcessToken(long long ptr) -@ stdcall OpenSCManagerA(str str long) -@ stdcall OpenSCManagerW(wstr wstr long) -@ stdcall OpenServiceA(long str long) -@ stdcall OpenServiceW(long wstr long) +@ stdcall -import OpenSCManagerA(str str long) +@ stdcall -import OpenSCManagerW(wstr wstr long) +@ stdcall -import OpenServiceA(long str long) +@ stdcall -import OpenServiceW(long wstr long) @ stdcall -import OpenThreadToken(long long long ptr) # @ stub OpenThreadWaitChainSession @ stdcall -ret64 OpenTraceA(ptr) @@ -593,16 +593,16 @@ # @ stub QueryLocalUserServiceName # @ stub QueryRecoveryAgentsOnEncryptedFile # @ stub QuerySecurityAccessMask -@ stdcall QueryServiceConfig2A(long long ptr long ptr) -@ stdcall QueryServiceConfig2W(long long ptr long ptr) -@ stdcall QueryServiceConfigA(long ptr long ptr) -@ stdcall QueryServiceConfigW(long ptr long ptr) +@ stdcall -import QueryServiceConfig2A(long long ptr long ptr) +@ stdcall -import QueryServiceConfig2W(long long ptr long ptr) +@ stdcall -import QueryServiceConfigA(long ptr long ptr) +@ stdcall -import QueryServiceConfigW(long ptr long ptr) # @ stub QueryServiceDynamicInformation -@ stdcall QueryServiceLockStatusA(long ptr long ptr) -@ stdcall QueryServiceLockStatusW(long ptr long ptr) -@ stdcall QueryServiceObjectSecurity(long long ptr long ptr) -@ stdcall QueryServiceStatus(long ptr) -@ stdcall QueryServiceStatusEx (long long ptr long ptr) +@ stdcall -import QueryServiceLockStatusA(long ptr long ptr) +@ stdcall -import QueryServiceLockStatusW(long ptr long ptr) +@ stdcall -import QueryServiceObjectSecurity(long long ptr long ptr) +@ stdcall -import QueryServiceStatus(long ptr) +@ stdcall -import QueryServiceStatusEx (long long ptr long ptr) # @ stub QueryTraceA @ stdcall QueryTraceW(int64 wstr ptr) # @ stub QueryUserServiceName @@ -697,10 +697,10 @@ @ stdcall RegisterEventSourceA(str str) @ stdcall RegisterEventSourceW(wstr wstr) # @ stub RegisterIdleTask -@ stdcall RegisterServiceCtrlHandlerA(str ptr) -@ stdcall RegisterServiceCtrlHandlerExA(str ptr ptr) -@ stdcall RegisterServiceCtrlHandlerExW(wstr ptr ptr) -@ stdcall RegisterServiceCtrlHandlerW(wstr ptr) +@ stdcall -import RegisterServiceCtrlHandlerA(str ptr) +@ stdcall -import RegisterServiceCtrlHandlerExA(str ptr ptr) +@ stdcall -import RegisterServiceCtrlHandlerExW(wstr ptr ptr) +@ stdcall -import RegisterServiceCtrlHandlerW(wstr ptr) @ stdcall RegisterTraceGuidsA(ptr ptr ptr long ptr str str ptr) ntdll.EtwRegisterTraceGuidsA @ stdcall RegisterTraceGuidsW(ptr ptr ptr long ptr wstr wstr ptr) ntdll.EtwRegisterTraceGuidsW @ stdcall RegisterWaitChainCOMCallback(ptr ptr) @@ -760,18 +760,18 @@ @ stdcall SetSecurityInfo (long long long ptr ptr ptr ptr) # @ stub SetSecurityInfoExA # @ stub SetSecurityInfoExW -@ stdcall SetServiceBits(long long long long) -@ stdcall SetServiceObjectSecurity(long long ptr) -@ stdcall SetServiceStatus(long ptr) +@ stdcall -import SetServiceBits(long long long long) +@ stdcall -import SetServiceObjectSecurity(long long ptr) +@ stdcall -import SetServiceStatus(long ptr) @ stdcall -import SetThreadToken(ptr ptr) @ stdcall -import SetTokenInformation(long long ptr long) # @ stub SetTraceCallback # @ stub SetUserFileEncryptionKey # @ stub SetUserFileEncryptionKeyEx -@ stdcall StartServiceA(long long ptr) -@ stdcall StartServiceCtrlDispatcherA(ptr) -@ stdcall StartServiceCtrlDispatcherW(ptr) -@ stdcall StartServiceW(long long ptr) +@ stdcall -import StartServiceA(long long ptr) +@ stdcall -import StartServiceCtrlDispatcherA(ptr) +@ stdcall -import StartServiceCtrlDispatcherW(ptr) +@ stdcall -import StartServiceW(long long ptr) @ stdcall StartTraceA(ptr str ptr) @ stdcall StartTraceW(ptr wstr ptr) @ stdcall StopTraceA(int64 str ptr) @@ -828,7 +828,7 @@ # @ stub TrusteeAccessToObjectA # @ stub TrusteeAccessToObjectW # @ stub UninstallApplication -@ stdcall UnlockServiceDatabase (ptr) +@ stdcall -import UnlockServiceDatabase (ptr) # @ stub UnregisterIdleTask @ stdcall UnregisterTraceGuids(int64) ntdll.EtwUnregisterTraceGuids @ stub UpdateTraceA diff --git a/dlls/sechost/Makefile.in b/dlls/sechost/Makefile.in new file mode 100644 index 0000000000..e2d525ade8 --- /dev/null +++ b/dlls/sechost/Makefile.in @@ -0,0 +1,8 @@ +EXTRADEFS = -D_SECHOST_ +MODULE = sechost.dll +IMPORTLIB = sechost +IMPORTS = kernelbase +DELAYIMPORTS = rpcrt4 + +C_SRCS = service.c +IDL_SRCS = svcctl.idl diff --git a/dlls/sechost/sechost.spec b/dlls/sechost/sechost.spec new file mode 100644 index 0000000000..985f638f8f --- /dev/null +++ b/dlls/sechost/sechost.spec @@ -0,0 +1,46 @@ +@ stdcall ChangeServiceConfig2A(long long ptr) +@ stdcall ChangeServiceConfig2W(long long ptr) +@ stdcall ChangeServiceConfigA(long long long long wstr str ptr str str str str) +@ stdcall ChangeServiceConfigW(long long long long wstr wstr ptr wstr wstr wstr wstr) +@ stdcall CloseServiceHandle(long) +@ stdcall ControlService(long long ptr) +@ stdcall CreateServiceA(long str str long long long long str str ptr str str str) +@ stdcall CreateServiceW(long wstr wstr long long long long wstr wstr ptr wstr wstr wstr) +@ stdcall DeleteService(long) +@ stdcall EnumDependentServicesA(long long ptr long ptr ptr) +@ stdcall EnumDependentServicesW(long long ptr long ptr ptr) +@ stdcall EnumServicesStatusA (long long long ptr long ptr ptr ptr) +@ stdcall EnumServicesStatusExA(long long long long ptr long ptr ptr ptr str) +@ stdcall EnumServicesStatusExW(long long long long ptr long ptr ptr ptr wstr) +@ stdcall EnumServicesStatusW (long long long ptr long ptr ptr ptr) +@ stdcall GetServiceDisplayNameA(ptr str ptr ptr) +@ stdcall GetServiceDisplayNameW(ptr wstr ptr ptr) +@ stdcall GetServiceKeyNameA(long str ptr ptr) +@ stdcall GetServiceKeyNameW(long wstr ptr ptr) +@ stdcall LockServiceDatabase(ptr) +@ stdcall NotifyServiceStatusChangeW(ptr long ptr) +@ stdcall OpenSCManagerA(str str long) +@ stdcall OpenSCManagerW(wstr wstr long) +@ stdcall OpenServiceA(long str long) +@ stdcall OpenServiceW(long wstr long) +@ stdcall QueryServiceConfig2A(long long ptr long ptr) +@ stdcall QueryServiceConfig2W(long long ptr long ptr) +@ stdcall QueryServiceConfigA(long ptr long ptr) +@ stdcall QueryServiceConfigW(long ptr long ptr) +@ stdcall QueryServiceLockStatusA(long ptr long ptr) +@ stdcall QueryServiceLockStatusW(long ptr long ptr) +@ stdcall QueryServiceObjectSecurity(long long ptr long ptr) +@ stdcall QueryServiceStatusEx (long long ptr long ptr) +@ stdcall QueryServiceStatus(long ptr) +@ stdcall RegisterServiceCtrlHandlerA(str ptr) +@ stdcall RegisterServiceCtrlHandlerExA(str ptr ptr) +@ stdcall RegisterServiceCtrlHandlerExW(wstr ptr ptr) +@ stdcall RegisterServiceCtrlHandlerW(wstr ptr) +@ stdcall SetServiceBits(long long long long) +@ stdcall SetServiceObjectSecurity(long long ptr) +@ stdcall SetServiceStatus(long ptr) +@ stdcall StartServiceA(long long ptr) +@ stdcall StartServiceCtrlDispatcherA(ptr) +@ stdcall StartServiceCtrlDispatcherW(ptr) +@ stdcall StartServiceW(long long ptr) +@ stdcall UnlockServiceDatabase (ptr) diff --git a/dlls/advapi32/service.c b/dlls/sechost/service.c similarity index 97% rename from dlls/advapi32/service.c rename to dlls/sechost/service.c index 3bf6fdfd47..71eda08605 100644 --- a/dlls/advapi32/service.c +++ b/dlls/sechost/service.c @@ -1,5 +1,5 @@ /* - * Win32 advapi functions + * Win32 sechost functions * * Copyright 1995 Sven Verdoolaege * Copyright 2005 Mike McCormack @@ -44,11 +44,11 @@ #include "lmserver.h"
#include "svcctl.h" - -#include "advapi32_misc.h" +#include "dbt.h"
#include "wine/exception.h" #include "wine/list.h" +#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(service);
@@ -113,6 +113,17 @@ static BOOL stop_service;
extern HANDLE CDECL __wine_make_process_system(void);
+static inline WCHAR *strdupAW( const char *src ) +{ + WCHAR *dst = NULL; + if (src) + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 ); + if ((dst = heap_alloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len ); + } + return dst; +} + static inline LPWSTR SERV_dupmulti(LPCSTR str) { UINT len = 0, n = 0; @@ -651,7 +662,7 @@ static BOOL service_run_main_thread(void) }
/****************************************************************************** - * StartServiceCtrlDispatcherA [ADVAPI32.@] + * StartServiceCtrlDispatcherA [SECHOST.@] * * See StartServiceCtrlDispatcherW. */ @@ -691,7 +702,7 @@ BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent ) }
/****************************************************************************** - * StartServiceCtrlDispatcherW [ADVAPI32.@] + * StartServiceCtrlDispatcherW [SECHOST.@] * * Connects a process containing one or more services to the service control * manager. @@ -739,7 +750,7 @@ BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent ) }
/****************************************************************************** - * LockServiceDatabase [ADVAPI32.@] + * LockServiceDatabase [SECHOST.@] */ SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager) { @@ -766,7 +777,7 @@ SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager) }
/****************************************************************************** - * UnlockServiceDatabase [ADVAPI32.@] + * UnlockServiceDatabase [SECHOST.@] */ BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock) { @@ -793,7 +804,7 @@ BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock) }
/****************************************************************************** - * SetServiceStatus [ADVAPI32.@] + * SetServiceStatus [SECHOST.@] * * PARAMS * hService [] @@ -847,7 +858,7 @@ SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
/****************************************************************************** - * OpenSCManagerA [ADVAPI32.@] + * OpenSCManagerA [SECHOST.@] * * Establish a connection to the service control manager and open its database. * @@ -875,7 +886,7 @@ SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName, }
/****************************************************************************** - * OpenSCManagerW [ADVAPI32.@] + * OpenSCManagerW [SECHOST.@] * * See OpenSCManagerA. */ @@ -917,7 +928,7 @@ SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, }
/****************************************************************************** - * ControlService [ADVAPI32.@] + * ControlService [SECHOST.@] * * Send a control code to a service. * @@ -960,7 +971,7 @@ BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl, }
/****************************************************************************** - * CloseServiceHandle [ADVAPI32.@] + * CloseServiceHandle [SECHOST.@] * * Close a handle to a service or the service control manager database. * @@ -998,7 +1009,7 @@ CloseServiceHandle( SC_HANDLE hSCObject )
/****************************************************************************** - * OpenServiceA [ADVAPI32.@] + * OpenServiceA [SECHOST.@] * * Open a handle to a service. * @@ -1027,7 +1038,7 @@ SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
/****************************************************************************** - * OpenServiceW [ADVAPI32.@] + * OpenServiceW [SECHOST.@] * * See OpenServiceA. */ @@ -1071,7 +1082,7 @@ SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, }
/****************************************************************************** - * CreateServiceW [ADVAPI32.@] + * CreateServiceW [SECHOST.@] */ SC_HANDLE WINAPI CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, @@ -1135,7 +1146,7 @@ CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
/****************************************************************************** - * CreateServiceA [ADVAPI32.@] + * CreateServiceA [SECHOST.@] */ SC_HANDLE WINAPI CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName, @@ -1179,7 +1190,7 @@ CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
/****************************************************************************** - * DeleteService [ADVAPI32.@] + * DeleteService [SECHOST.@] * * Delete a service from the service control manager database. * @@ -1216,7 +1227,7 @@ BOOL WINAPI DeleteService( SC_HANDLE hService )
/****************************************************************************** - * StartServiceA [ADVAPI32.@] + * StartServiceA [SECHOST.@] * * Start a service * @@ -1267,7 +1278,7 @@ BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
/****************************************************************************** - * StartServiceW [ADVAPI32.@] + * StartServiceW [SECHOST.@] * * See StartServiceA. */ @@ -1297,7 +1308,7 @@ BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs, }
/****************************************************************************** - * QueryServiceStatus [ADVAPI32.@] + * QueryServiceStatus [SECHOST.@] * * PARAMS * hService [I] Handle to service to get information about @@ -1332,7 +1343,7 @@ BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
/****************************************************************************** - * QueryServiceStatusEx [ADVAPI32.@] + * QueryServiceStatusEx [SECHOST.@] * * Get information about a service. * @@ -1385,7 +1396,7 @@ BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel, }
/****************************************************************************** - * QueryServiceConfigA [ADVAPI32.@] + * QueryServiceConfigA [SECHOST.@] */ BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config, DWORD size, LPDWORD needed ) @@ -1475,7 +1486,7 @@ static DWORD size_string(LPCWSTR string) }
/****************************************************************************** - * QueryServiceConfigW [ADVAPI32.@] + * QueryServiceConfigW [SECHOST.@] */ BOOL WINAPI QueryServiceConfigW( SC_HANDLE hService, @@ -1549,7 +1560,7 @@ QueryServiceConfigW( SC_HANDLE hService, }
/****************************************************************************** - * QueryServiceConfig2A [ADVAPI32.@] + * QueryServiceConfig2A [SECHOST.@] * * Note * observed under win2k: @@ -1605,7 +1616,7 @@ cleanup: }
/****************************************************************************** - * QueryServiceConfig2W [ADVAPI32.@] + * QueryServiceConfig2W [SECHOST.@] * * See QueryServiceConfig2A. */ @@ -1713,7 +1724,7 @@ BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffe }
/****************************************************************************** - * EnumServicesStatusA [ADVAPI32.@] + * EnumServicesStatusA [SECHOST.@] */ BOOL WINAPI EnumServicesStatusA( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSA @@ -1780,7 +1791,7 @@ done: }
/****************************************************************************** - * EnumServicesStatusW [ADVAPI32.@] + * EnumServicesStatusW [SECHOST.@] */ BOOL WINAPI EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_STATUSW @@ -1890,7 +1901,7 @@ EnumServicesStatusW( SC_HANDLE hmngr, DWORD type, DWORD state, LPENUM_SERVICE_ST }
/****************************************************************************** - * EnumServicesStatusExA [ADVAPI32.@] + * EnumServicesStatusExA [SECHOST.@] */ BOOL WINAPI EnumServicesStatusExA( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state, @@ -1961,7 +1972,7 @@ done: }
/****************************************************************************** - * EnumServicesStatusExW [ADVAPI32.@] + * EnumServicesStatusExW [SECHOST.@] */ BOOL WINAPI EnumServicesStatusExW( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD state, @@ -2078,7 +2089,7 @@ EnumServicesStatusExW( SC_HANDLE hmngr, SC_ENUM_TYPE level, DWORD type, DWORD st }
/****************************************************************************** - * GetServiceKeyNameA [ADVAPI32.@] + * GetServiceKeyNameA [SECHOST.@] */ BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName, LPSTR lpServiceName, LPDWORD lpcchBuffer ) @@ -2124,7 +2135,7 @@ cleanup: }
/****************************************************************************** - * GetServiceKeyNameW [ADVAPI32.@] + * GetServiceKeyNameW [SECHOST.@] */ BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName, LPWSTR lpServiceName, LPDWORD lpcchBuffer ) @@ -2177,7 +2188,7 @@ BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName, }
/****************************************************************************** - * QueryServiceLockStatusA [ADVAPI32.@] + * QueryServiceLockStatusA [SECHOST.@] */ BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager, LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus, @@ -2189,7 +2200,7 @@ BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager, }
/****************************************************************************** - * QueryServiceLockStatusW [ADVAPI32.@] + * QueryServiceLockStatusW [SECHOST.@] */ BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager, LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus, @@ -2201,7 +2212,7 @@ BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager, }
/****************************************************************************** - * GetServiceDisplayNameA [ADVAPI32.@] + * GetServiceDisplayNameA [SECHOST.@] */ BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName, LPSTR lpDisplayName, LPDWORD lpcchBuffer) @@ -2248,7 +2259,7 @@ cleanup: }
/****************************************************************************** - * GetServiceDisplayNameW [ADVAPI32.@] + * GetServiceDisplayNameW [SECHOST.@] */ BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, LPWSTR lpDisplayName, LPDWORD lpcchBuffer) @@ -2301,7 +2312,7 @@ BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, }
/****************************************************************************** - * ChangeServiceConfigW [ADVAPI32.@] + * ChangeServiceConfigW [SECHOST.@] */ BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName, @@ -2339,7 +2350,7 @@ BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType, }
/****************************************************************************** - * ChangeServiceConfigA [ADVAPI32.@] + * ChangeServiceConfigA [SECHOST.@] */ BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName, @@ -2379,7 +2390,7 @@ BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType, }
/****************************************************************************** - * ChangeServiceConfig2A [ADVAPI32.@] + * ChangeServiceConfig2A [SECHOST.@] */ BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel, LPVOID lpInfo) @@ -2426,7 +2437,7 @@ BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel, }
/****************************************************************************** - * ChangeServiceConfig2W [ADVAPI32.@] + * ChangeServiceConfig2W [SECHOST.@] */ BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel, LPVOID lpInfo) @@ -2494,7 +2505,7 @@ static NTSTATUS SERV_QueryServiceObjectSecurity(SC_HANDLE hService, }
/****************************************************************************** - * QueryServiceObjectSecurity [ADVAPI32.@] + * QueryServiceObjectSecurity [SECHOST.@] */ BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService, SECURITY_INFORMATION dwSecurityInformation, @@ -2512,7 +2523,7 @@ BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService, }
/****************************************************************************** - * SetServiceObjectSecurity [ADVAPI32.@] + * SetServiceObjectSecurity [SECHOST.@] * * NOTES * - SetSecurityInfo should be updated to call this function once it's implemented. @@ -2526,7 +2537,7 @@ BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService, }
/****************************************************************************** - * SetServiceBits [ADVAPI32.@] + * SetServiceBits [SECHOST.@] */ BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus, DWORD dwServiceBits, @@ -2548,7 +2559,7 @@ static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, v }
/****************************************************************************** - * RegisterServiceCtrlHandlerA [ADVAPI32.@] + * RegisterServiceCtrlHandlerA [SECHOST.@] */ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler ) { @@ -2556,7 +2567,7 @@ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER }
/****************************************************************************** - * RegisterServiceCtrlHandlerW [ADVAPI32.@] + * RegisterServiceCtrlHandlerW [SECHOST.@] */ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler ) { @@ -2564,7 +2575,7 @@ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLE }
/****************************************************************************** - * RegisterServiceCtrlHandlerExA [ADVAPI32.@] + * RegisterServiceCtrlHandlerExA [SECHOST.@] */ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context ) { @@ -2578,7 +2589,7 @@ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDL }
/****************************************************************************** - * RegisterServiceCtrlHandlerExW [ADVAPI32.@] + * RegisterServiceCtrlHandlerExW [SECHOST.@] */ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName, LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext ) @@ -2602,7 +2613,7 @@ SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceNam }
/****************************************************************************** - * EnumDependentServicesA [ADVAPI32.@] + * EnumDependentServicesA [SECHOST.@] */ BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize, @@ -2616,7 +2627,7 @@ BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState, }
/****************************************************************************** - * EnumDependentServicesW [ADVAPI32.@] + * EnumDependentServicesW [SECHOST.@] */ BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize, @@ -2693,7 +2704,7 @@ static DWORD WINAPI notify_thread(void *user) }
/****************************************************************************** - * NotifyServiceStatusChangeW [ADVAPI32.@] + * NotifyServiceStatusChangeW [SECHOST.@] */ DWORD WINAPI NotifyServiceStatusChangeW(SC_HANDLE hService, DWORD dwNotifyMask, SERVICE_NOTIFYW *pNotifyBuffer) diff --git a/dlls/advapi32/svcctl.idl b/dlls/sechost/svcctl.idl similarity index 100% rename from dlls/advapi32/svcctl.idl rename to dlls/sechost/svcctl.idl
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=56479
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
I am very confused. The testbot failed to apply the patch, and after some experimentation I was able to reproduce the failure but I don't understand why git is behaving like it is.
I normally test a patch with: git apply 0001*.patch git apply 0002*.patch git apply 0003*.patch ...
That worked properly with this patchset, and I thought that would be the same as running it all at once like: git apply *.patch
It appears that I was wrong though. Lesson learned. I will run the latter command from now on.
That being said, I have a tweak to the patch that does appear to make it apply cleanly for me, but I don't want to spam the list.
- Micah
Implement I_ScRegisterDeviceNotification and I_ScUnregisterDeviceNotification in sechost via RPC to services.exe
Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- dlls/sechost/sechost.spec | 2 + dlls/sechost/service.c | 141 ++++++++++++++++++++++++++++++++++++++ include/wine/svcctl.idl | 13 ++++ include/winsvc.h | 14 ++++ programs/services/rpc.c | 124 ++++++++++++++++++++++++++++++++- 5 files changed, 293 insertions(+), 1 deletion(-)
diff --git a/dlls/sechost/sechost.spec b/dlls/sechost/sechost.spec index 985f638f8f..1deb340619 100644 --- a/dlls/sechost/sechost.spec +++ b/dlls/sechost/sechost.spec @@ -17,6 +17,8 @@ @ stdcall GetServiceDisplayNameW(ptr wstr ptr ptr) @ stdcall GetServiceKeyNameA(long str ptr ptr) @ stdcall GetServiceKeyNameW(long wstr ptr ptr) +@ stdcall I_ScRegisterDeviceNotification(ptr ptr long) +@ stdcall I_ScUnregisterDeviceNotification(ptr) @ stdcall LockServiceDatabase(ptr) @ stdcall NotifyServiceStatusChangeW(ptr long ptr) @ stdcall OpenSCManagerA(str str long) diff --git a/dlls/sechost/service.c b/dlls/sechost/service.c index 71eda08605..ac9d868499 100644 --- a/dlls/sechost/service.c +++ b/dlls/sechost/service.c @@ -96,6 +96,14 @@ typedef struct notify_data_t {
static struct list notify_list = LIST_INIT(notify_list);
+struct device_notify_registration { + DEVICE_NOTIFICATION_DETAILS details; + struct list entry; +}; + +static struct list device_notify_list = LIST_INIT(device_notify_list); +HANDLE device_notify_thread = NULL; + static CRITICAL_SECTION service_cs; static CRITICAL_SECTION_DEBUG service_cs_debug = { @@ -2767,3 +2775,136 @@ DWORD WINAPI NotifyServiceStatusChangeW(SC_HANDLE hService, DWORD dwNotifyMask,
return ERROR_SUCCESS; } + +static DWORD WINAPI device_notification_thread(void *user) +{ + DWORD err; + struct device_notify_registration *registration; + SC_DEV_NOTIFY_RPC_HANDLE handle = NULL; + DWORD code; + DWORD buf_size; + BYTE *buf; + + __TRY + { + err = svcctl_OpenDeviceNotificationHandle(NULL, &handle); + } + __EXCEPT(rpc_filter) + { + err = map_exception_code(GetExceptionCode()); + } + __ENDTRY + + if (!handle) + { + WARN("OpenDeviceNotificationHandle server call failed: %d\n", err); + return 1; + } + + for (;;) + { + buf = NULL; + __TRY + { + /* GetDeviceNotificationResults blocks until there is an event */ + err = svcctl_GetDeviceNotificationResults(handle, &code, &buf, &buf_size); + } + __EXCEPT(rpc_filter) + { + err = map_exception_code(GetExceptionCode()); + } + __ENDTRY + + if (err != ERROR_SUCCESS) + { + WARN("GetDeviceNotificationResults server call failed: %d\n", err); + if (buf) + MIDL_user_free(buf); + Sleep(100); + continue; + } + + EnterCriticalSection(&service_cs); + LIST_FOR_EACH_ENTRY(registration, &device_notify_list, struct device_notify_registration, entry) + { + registration->details.pNotificationCallback(registration->details.hRecipient, + code, (DEV_BROADCAST_HDR *) buf); + } + LeaveCriticalSection(&service_cs); + MIDL_user_free(buf); + } +} + +/****************************************************************************** + * I_ScRegisterDeviceNotification [SECHOST.@] + */ +HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification(DEVICE_NOTIFICATION_DETAILS *details, LPVOID filter, DWORD flags) +{ + struct device_notify_registration *registration; + + TRACE("(%p)\n", details->hRecipient); + + /* This implementation is not overly concerned with sending too many + * messages, so support for filters is not yet implemented. + */ + if (filter) + FIXME("Notification filters are not yet implemented! All device notification events will be sent.\n"); + + if (!details || !details->pNotificationCallback) + { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + registration = heap_alloc(sizeof(struct device_notify_registration)); + if (!registration) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + memcpy(®istration->details, details, sizeof(DEVICE_NOTIFICATION_DETAILS)); + + EnterCriticalSection(&service_cs); + list_add_tail(&device_notify_list, ®istration->entry); + + if (!device_notify_thread) + device_notify_thread = CreateThread(NULL, 0, &device_notification_thread, NULL, 0, NULL); + + LeaveCriticalSection(&service_cs); + + return (HDEVNOTIFY) registration; +} + +/****************************************************************************** + * I_ScUnregisterDeviceNotification [SECHOST.@] + */ +BOOL WINAPI I_ScUnregisterDeviceNotification(HDEVNOTIFY notificationHandle) +{ + struct device_notify_registration *item, *registration = NULL; + + TRACE("(%p)\n", notificationHandle); + + EnterCriticalSection(&service_cs); + LIST_FOR_EACH_ENTRY(item, &device_notify_list, struct device_notify_registration, entry) + { + if (item == notificationHandle) + { + registration = item; + break; + } + } + + if (registration) + list_remove(®istration->entry); + LeaveCriticalSection(&service_cs); + + if (!registration) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + heap_free(registration); + return TRUE; +} diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl index c14cd6bb50..0d75cf73c4 100644 --- a/include/wine/svcctl.idl +++ b/include/wine/svcctl.idl @@ -62,6 +62,7 @@ interface svcctl typedef [context_handle] void *SC_RPC_HANDLE; typedef [context_handle] void *SC_RPC_LOCK; typedef [context_handle] void *SC_NOTIFY_RPC_HANDLE; + typedef [context_handle] void *SC_DEV_NOTIFY_RPC_HANDLE;
/* undocumented access rights */ cpp_quote("#define SERVICE_SET_STATUS 0x8000") @@ -805,4 +806,16 @@ typedef [switch_type(DWORD)] union _SC_RPC_SERVICE_CONTROL_OUT_PARAMSW { [in] DWORD info_level, [out] SC_RPC_CONFIG_INFOW *info ); + + /* Not compatible with Windows function 57 */ + DWORD svcctl_OpenDeviceNotificationHandle( + [in, string, unique] SVCCTL_HANDLEW machinename, + [out] SC_DEV_NOTIFY_RPC_HANDLE *handle); + + /* Not compatible with Windows function 58 */ + DWORD svcctl_GetDeviceNotificationResults( + [in] SC_DEV_NOTIFY_RPC_HANDLE handle, + [out] DWORD *event_code, + [out, size_is(,*event_size)] BYTE **event, + [out] DWORD *event_size); } diff --git a/include/winsvc.h b/include/winsvc.h index aa5e9f1ae8..d420535447 100644 --- a/include/winsvc.h +++ b/include/winsvc.h @@ -376,6 +376,18 @@ typedef struct _QUERY_SERVICE_LOCK_STATUSW
DECL_WINELIB_TYPE_AW(QUERY_SERVICE_LOCK_STATUS)
+#ifndef HDEVNOTIFY +typedef PVOID HDEVNOTIFY; +#endif +#include "dbt.h" +typedef DWORD (CALLBACK *REGISTER_DEVICE_NOTIFY_CALLBACK)(HANDLE hRecipient, + DWORD flags, DEV_BROADCAST_HDR *); +typedef struct _DEVICE_NOTIFICATION_DETAILS +{ + REGISTER_DEVICE_NOTIFY_CALLBACK pNotificationCallback; + HANDLE hRecipient; +} DEVICE_NOTIFICATION_DETAILS; + /* Service control handler function prototype */
typedef VOID (WINAPI *LPHANDLER_FUNCTION)(DWORD); @@ -445,6 +457,8 @@ WINADVAPI BOOL WINAPI StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENT WINADVAPI BOOL WINAPI StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW*); #define StartServiceCtrlDispatcher WINELIB_NAME_AW(StartServiceCtrlDispatcher) WINADVAPI BOOL WINAPI UnlockServiceDatabase(SC_LOCK); +WINADVAPI HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification(DEVICE_NOTIFICATION_DETAILS *details, LPVOID filter, DWORD flags); +WINADVAPI BOOL WINAPI I_ScUnregisterDeviceNotification(HDEVNOTIFY notificationHandle);
#ifdef __cplusplus } /* extern "C" */ diff --git a/programs/services/rpc.c b/programs/services/rpc.c index a657492a5f..9bd43267b9 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -59,7 +59,8 @@ typedef enum SC_HTYPE_DONT_CARE = 0, SC_HTYPE_MANAGER, SC_HTYPE_SERVICE, - SC_HTYPE_NOTIFY + SC_HTYPE_NOTIFY, + SC_HTYPE_DEV_NOTIFY } SC_HANDLE_TYPE;
struct sc_handle @@ -83,6 +84,23 @@ struct sc_notify_handle SC_RPC_NOTIFY_PARAMS_LIST *params_list; };
+struct devnotify_event +{ + struct list entry; + DWORD code; + BYTE *data; + DWORD data_size; +}; + +struct sc_dev_notify_handle +{ + struct sc_handle hdr; + struct list entry; + HANDLE event; + CRITICAL_SECTION cs; + struct list event_list; +}; + struct sc_service_handle /* service handle */ { struct sc_handle hdr; @@ -117,6 +135,9 @@ static const WCHAR emptyW[] = {0}; static PTP_CLEANUP_GROUP cleanup_group; HANDLE exit_event;
+static struct list devnotify_listeners = LIST_INIT(devnotify_listeners); +CRITICAL_SECTION device_notifications_cs; + static void CALLBACK group_cancel_callback(void *object, void *userdata) { struct process_entry *process = object; @@ -264,6 +285,15 @@ static DWORD validate_notify_handle(SC_RPC_HANDLE handle, DWORD needed_access, s return err; }
+static DWORD validate_dev_notify_handle(SC_RPC_HANDLE handle, DWORD needed_access, struct sc_dev_notify_handle **notify) +{ + struct sc_handle *hdr; + DWORD err = validate_context_handle(handle, SC_HTYPE_DEV_NOTIFY, needed_access, &hdr); + if (err == ERROR_SUCCESS) + *notify = (struct sc_dev_notify_handle *)hdr; + return err; +} + DWORD __cdecl svcctl_OpenSCManagerW( MACHINE_HANDLEW MachineName, /* Note: this parameter is ignored */ LPCWSTR DatabaseName, @@ -323,6 +353,28 @@ static void SC_RPC_HANDLE_destroy(SC_RPC_HANDLE handle) HeapFree(GetProcessHeap(), 0, service); break; } + case SC_HTYPE_DEV_NOTIFY: + { + struct devnotify_event *event, *next; + struct sc_dev_notify_handle *listener = (struct sc_dev_notify_handle *)hdr; + + /* Destroy this handle and stop sending events to this caller */ + EnterCriticalSection(&device_notifications_cs); + WINE_TRACE("Removing device notification listener from list (%p)\n", listener); + list_remove(&listener->entry); + LeaveCriticalSection(&device_notifications_cs); + + LIST_FOR_EACH_ENTRY_SAFE(event, next, &listener->event_list, struct devnotify_event, entry) + { + list_remove(&event->entry); + MIDL_user_free(event->data); + HeapFree(GetProcessHeap(), 0, event); + } + + CloseHandle(listener->event); + HeapFree(GetProcessHeap(), 0, listener); + break; + } default: WINE_ERR("invalid handle type %d\n", hdr->type); RpcRaiseException(ERROR_INVALID_HANDLE); @@ -2134,12 +2186,78 @@ DWORD __cdecl svcctl_QueryServiceConfig2A( return ERROR_CALL_NOT_IMPLEMENTED; }
+DWORD __cdecl svcctl_OpenDeviceNotificationHandle( + MACHINE_HANDLEW MachineName, /* Note: this parameter is ignored */ + SC_DEV_NOTIFY_RPC_HANDLE *handle) +{ + struct sc_dev_notify_handle *listener; + + if (!(listener = HeapAlloc(GetProcessHeap(), 0, sizeof(*listener)))) + return ERROR_NOT_ENOUGH_SERVER_MEMORY; + + listener->hdr.type = SC_HTYPE_DEV_NOTIFY; + listener->hdr.access = 0; + + InitializeCriticalSection(&listener->cs); + listener->event = CreateEventW(NULL, TRUE, FALSE, NULL); + list_init(&listener->event_list); + + WINE_TRACE("Adding listener to list (%p)\n", listener); + EnterCriticalSection(&device_notifications_cs); + list_add_tail(&devnotify_listeners, &listener->entry); + LeaveCriticalSection(&device_notifications_cs); + + *handle = &listener->hdr; + return ERROR_SUCCESS; +} + +DWORD __cdecl svcctl_GetDeviceNotificationResults( + SC_DEV_NOTIFY_RPC_HANDLE handle, + LPDWORD code, + BYTE **event_dest, + LPDWORD event_dest_size) +{ + struct devnotify_event *event; + struct sc_dev_notify_handle *listener; + DWORD err; + + if ((err = validate_dev_notify_handle(handle, 0, &listener)) != 0) + return err; + + if (!event_dest || !event_dest_size || !code) + return ERROR_INVALID_PARAMETER; + + do + { + /* block until there is a result */ + WaitForSingleObject(listener->event, INFINITE); + + EnterCriticalSection(&listener->cs); + if ((event = LIST_ENTRY(list_head(&listener->event_list), struct devnotify_event, entry))) + list_remove(&event->entry); + else + ResetEvent(listener->event); + LeaveCriticalSection(&listener->cs); + } while (!event); + + WINE_TRACE("Got an event (%p)\n", event); + *code = event->code; + + *event_dest = event->data; + *event_dest_size = event->data_size; + + HeapFree(GetProcessHeap(), 0, event); + return ERROR_SUCCESS; +} + DWORD RPC_Init(void) { WCHAR transport[] = SVCCTL_TRANSPORT; WCHAR endpoint[] = SVCCTL_ENDPOINT; DWORD err;
+ InitializeCriticalSection(&device_notifications_cs); + if (!(cleanup_group = CreateThreadpoolCleanupGroup())) { WINE_ERR("CreateThreadpoolCleanupGroup failed with error %u\n", GetLastError()); @@ -2188,6 +2306,10 @@ void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE handle) { }
+void __RPC_USER SC_DEV_NOTIFY_RPC_HANDLE_rundown(SC_DEV_NOTIFY_RPC_HANDLE handle) +{ +} + void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len) { return HeapAlloc(GetProcessHeap(), 0, len);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=56480
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
Send device notifications via RPC to services.exe
Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- dlls/ntoskrnl.exe/Makefile.in | 4 +- dlls/ntoskrnl.exe/ntoskrnl_private.h | 5 + dlls/ntoskrnl.exe/pnp.c | 1 + dlls/ntoskrnl.exe/rpc.c | 182 +++++++++++++++++++++++++++ dlls/ntoskrnl.exe/svcctl.idl | 3 + include/wine/svcctl.idl | 7 ++ programs/services/rpc.c | 45 +++++++ 7 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 dlls/ntoskrnl.exe/rpc.c create mode 100644 dlls/ntoskrnl.exe/svcctl.idl
diff --git a/dlls/ntoskrnl.exe/Makefile.in b/dlls/ntoskrnl.exe/Makefile.in index a75ca9768d..441238177a 100644 --- a/dlls/ntoskrnl.exe/Makefile.in +++ b/dlls/ntoskrnl.exe/Makefile.in @@ -1,7 +1,7 @@ MODULE = ntoskrnl.exe IMPORTLIB = ntoskrnl IMPORTS = advapi32 hal -DELAYIMPORTS = setupapi user32 +DELAYIMPORTS = setupapi user32 rpcrt4
EXTRADLLFLAGS = -mno-cygwin
@@ -9,6 +9,8 @@ C_SRCS = \ instr.c \ ntoskrnl.c \ pnp.c \ + rpc.c \ sync.c +IDL_SRCS = svcctl.idl
RC_SRCS = ntoskrnl.rc diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h index b5244ef164..ded5c0bec4 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl_private.h +++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h @@ -22,6 +22,8 @@ #define __WINE_NTOSKRNL_PRIVATE_H
#include "wine/asm.h" +#include "winuser.h" +#include "dbt.h"
static inline LPCSTR debugstr_us( const UNICODE_STRING *us ) { @@ -86,4 +88,7 @@ static const WCHAR servicesW[] = {'\','R','e','g','i','s','t','r','y', '\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t', '\','S','e','r','v','i','c','e','s', '\',0}; + +DWORD send_device_notification( DEV_BROADCAST_DEVICEINTERFACE_W *broadcast, BOOL enable ); + #endif diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index 03c4c401f9..645b04fd28 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -605,6 +605,7 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable lstrcpynW( broadcast->dbcc_name, name->Buffer, namelen + 1 ); BroadcastSystemMessageW( BSF_FORCEIFHUNG | BSF_QUERY, NULL, WM_DEVICECHANGE, enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, (LPARAM)broadcast ); + send_device_notification( broadcast, enable );
heap_free( broadcast ); } diff --git a/dlls/ntoskrnl.exe/rpc.c b/dlls/ntoskrnl.exe/rpc.c new file mode 100644 index 0000000000..a4779a168a --- /dev/null +++ b/dlls/ntoskrnl.exe/rpc.c @@ -0,0 +1,182 @@ +/* + * RPC connection with services.exe + * + * Copyright 1995 Sven Verdoolaege + * Copyright 2005 Mike McCormack + * Copyright 2007 Rolf Kalbermatter + * Copyright 2019 Micah N Gorrell for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winsvc.h" +#include "winternl.h" +#include "dbt.h" +#include "svcctl.h" +#include "wine/exception.h" +#include "ddk/ntifs.h" +#include "wine/debug.h" +#include "wine/heap.h" +#include "wine/rbtree.h" + +#include "ntoskrnl_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(plugplay); + +/****************************************************************************** + * RPC connection with services.exe + */ +void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len) +{ + return heap_alloc(len); +} + +void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr) +{ + heap_free(ptr); +} + +static handle_t rpc_wstr_bind(RPC_WSTR str) +{ + WCHAR transport[] = SVCCTL_TRANSPORT; + WCHAR endpoint[] = SVCCTL_ENDPOINT; + RPC_WSTR binding_str; + RPC_STATUS status; + handle_t rpc_handle; + + status = RpcStringBindingComposeW(NULL, transport, str, endpoint, NULL, &binding_str); + if (status != RPC_S_OK) + { + ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status); + return NULL; + } + + status = RpcBindingFromStringBindingW(binding_str, &rpc_handle); + RpcStringFreeW(&binding_str); + + if (status != RPC_S_OK) + { + ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status); + return NULL; + } + + return rpc_handle; +} + +static handle_t rpc_cstr_bind(RPC_CSTR str) +{ + RPC_CSTR transport = (RPC_CSTR)SVCCTL_TRANSPORTA; + RPC_CSTR endpoint = (RPC_CSTR)SVCCTL_ENDPOINTA; + RPC_CSTR binding_str; + RPC_STATUS status; + handle_t rpc_handle; + + status = RpcStringBindingComposeA(NULL, transport, str, endpoint, NULL, &binding_str); + if (status != RPC_S_OK) + { + ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status); + return NULL; + } + + status = RpcBindingFromStringBindingA(binding_str, &rpc_handle); + RpcStringFreeA(&binding_str); + + if (status != RPC_S_OK) + { + ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status); + return NULL; + } + + return rpc_handle; +} + +DECLSPEC_HIDDEN handle_t __RPC_USER MACHINE_HANDLEA_bind(MACHINE_HANDLEA MachineName) +{ + return rpc_cstr_bind((RPC_CSTR)MachineName); +} + +DECLSPEC_HIDDEN void __RPC_USER MACHINE_HANDLEA_unbind(MACHINE_HANDLEA MachineName, handle_t h) +{ + RpcBindingFree(&h); +} + +DECLSPEC_HIDDEN handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName) +{ + return rpc_wstr_bind((RPC_WSTR)MachineName); +} + +DECLSPEC_HIDDEN void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h) +{ + RpcBindingFree(&h); +} + +DECLSPEC_HIDDEN handle_t __RPC_USER SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW MachineName) +{ + return rpc_wstr_bind((RPC_WSTR)MachineName); +} + +DECLSPEC_HIDDEN void __RPC_USER SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW MachineName, handle_t h) +{ + RpcBindingFree(&h); +} + +static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr) +{ + return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode); +} + +static DWORD map_exception_code(DWORD exception_code) +{ + switch (exception_code) + { + case RPC_X_NULL_REF_POINTER: + return ERROR_INVALID_ADDRESS; + case RPC_X_ENUM_VALUE_OUT_OF_RANGE: + case RPC_X_BYTE_COUNT_TOO_SMALL: + return ERROR_INVALID_PARAMETER; + case RPC_S_INVALID_BINDING: + case RPC_X_SS_IN_NULL_CONTEXT: + return ERROR_INVALID_HANDLE; + default: + return exception_code; + } +} + +DWORD send_device_notification(DEV_BROADCAST_DEVICEINTERFACE_W *broadcast, BOOL enable) +{ + DWORD err; + + __TRY + { + err = svcctl_SendDeviceNotification(NULL, + enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, + (const BYTE *) broadcast, broadcast->dbcc_size); + } + __EXCEPT(rpc_filter) + { + err = map_exception_code(GetExceptionCode()); + } + __ENDTRY + + TRACE("send result (%d)\n", err); + return err; +} diff --git a/dlls/ntoskrnl.exe/svcctl.idl b/dlls/ntoskrnl.exe/svcctl.idl new file mode 100644 index 0000000000..b1bc8545d7 --- /dev/null +++ b/dlls/ntoskrnl.exe/svcctl.idl @@ -0,0 +1,3 @@ +#pragma makedep client + +#include "wine/svcctl.idl" diff --git a/include/wine/svcctl.idl b/include/wine/svcctl.idl index 0d75cf73c4..2399f3f5fd 100644 --- a/include/wine/svcctl.idl +++ b/include/wine/svcctl.idl @@ -818,4 +818,11 @@ typedef [switch_type(DWORD)] union _SC_RPC_SERVICE_CONTROL_OUT_PARAMSW { [out] DWORD *event_code, [out, size_is(,*event_size)] BYTE **event, [out] DWORD *event_size); + + /* Not compatible with Windows function 59 */ + DWORD svcctl_SendDeviceNotification( + [in, string, unique] SVCCTL_HANDLEW machinename, + [in] DWORD event_code, + [in, size_is(event_size)] const BYTE *event, + [in] DWORD event_size); } diff --git a/programs/services/rpc.c b/programs/services/rpc.c index 9bd43267b9..d66a575a13 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -2250,6 +2250,51 @@ DWORD __cdecl svcctl_GetDeviceNotificationResults( return ERROR_SUCCESS; }
+DWORD __cdecl svcctl_SendDeviceNotification( + MACHINE_HANDLEW MachineName, /* Note: this parameter is ignored */ + DWORD code, + const BYTE *event_buf, + DWORD event_buf_size) +{ + struct sc_dev_notify_handle *listener; + struct devnotify_event *event; + + if (!event_buf) + return ERROR_INVALID_PARAMETER; + + EnterCriticalSection(&device_notifications_cs); + LIST_FOR_EACH_ENTRY(listener, &devnotify_listeners, struct sc_dev_notify_handle, entry) + { + WINE_TRACE("Triggering listener %p\n", listener); + + event = HeapAlloc(GetProcessHeap(), 0, sizeof(struct devnotify_event)); + if (event) + event->data = MIDL_user_allocate(event_buf_size); + + if (!event || !event->data) + { + HeapFree(GetProcessHeap(), 0, event); + + LeaveCriticalSection(&device_notifications_cs); + return ERROR_NOT_ENOUGH_SERVER_MEMORY; + } + + event->code = code; + memcpy(event->data, event_buf, event_buf_size); + event->data_size = event_buf_size; + + EnterCriticalSection(&listener->cs); + list_add_tail(&listener->event_list, &event->entry); + LeaveCriticalSection(&listener->cs); + + SetEvent(listener->event); + } + WINE_TRACE("Done triggering registrations\n"); + LeaveCriticalSection(&device_notifications_cs); + + return ERROR_SUCCESS; +} + DWORD RPC_Init(void) { WCHAR transport[] = SVCCTL_TRANSPORT;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=56481
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
Implement RegisterDeviceNotification() and UnregisterDeviceNotification() using I_ScRegisterDeviceNotification() and I_ScUnregisterDeviceNotification() in sechost.dll
Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- dlls/user32/Makefile.in | 2 +- dlls/user32/misc.c | 73 +++++++++++++++++++++++++++++++++++------ include/winuser.h | 4 ++- 3 files changed, 67 insertions(+), 12 deletions(-)
diff --git a/dlls/user32/Makefile.in b/dlls/user32/Makefile.in index d420dcb45a..bd3660331e 100644 --- a/dlls/user32/Makefile.in +++ b/dlls/user32/Makefile.in @@ -1,7 +1,7 @@ EXTRADEFS = -D_USER32_ -D_WINABLE_ MODULE = user32.dll IMPORTLIB = user32 -IMPORTS = gdi32 version advapi32 +IMPORTS = gdi32 version advapi32 sechost EXTRAINCL = $(PNG_CFLAGS) DELAYIMPORTS = hid imm32 setupapi usp10
diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c index bed5812a47..17d0b5bcd3 100644 --- a/dlls/user32/misc.c +++ b/dlls/user32/misc.c @@ -4,6 +4,7 @@ * Copyright 1995 Thomas Sandford * Copyright 1997 Marcus Meissner * Copyright 1998 Turchanov Sergey + * Copyright 2019 Micah N Gorrell for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,6 +31,7 @@ #include "wingdi.h" #include "controls.h" #include "user_private.h" +#include "winsvc.h"
#include "wine/unicode.h" #include "wine/debug.h" @@ -288,17 +290,39 @@ DWORD WINAPI RegisterTasklist (DWORD x) return TRUE; }
+static DWORD CALLBACK devnotify_window_callback(HANDLE hRecipient, DWORD flags, DEV_BROADCAST_HDR *dbh) +{ + SendMessageTimeoutW(hRecipient, WM_DEVICECHANGE, flags, + (LPARAM) dbh, SMTO_ABORTIFHUNG, 2000, NULL); + return 0; +} + +static DWORD CALLBACK devnotify_service_callback(HANDLE hRecipient, DWORD flags, DEV_BROADCAST_HDR *dbh) +{ + FIXME("Support for service handles is not yet implemented!\n"); + ControlService(hRecipient, SERVICE_CONTROL_DEVICEEVENT, NULL); + return 0; +} + +static DWORD CALLBACK devnotify_null_callback(HANDLE hRecipient, DWORD flags, DEV_BROADCAST_HDR *dbh) +{ + /* The WM_DEVICECHANGE event is broadcast directly from ntoskrnl.exe so + * nothing needs to be done here. */ + return 0; +}
/*********************************************************************** * RegisterDeviceNotificationA (USER32.@) * * See RegisterDeviceNotificationW. */ -HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE hnd, LPVOID notifyfilter, DWORD flags) +HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE hRecipient, LPVOID pNotificationFilter, DWORD dwFlags) { - FIXME("(hwnd=%p, filter=%p,flags=0x%08x) returns a fake device notification handle!\n", - hnd,notifyfilter,flags ); - return (HDEVNOTIFY) 0xcafecafe; + TRACE("(hwnd=%p, filter=%p,flags=0x%08x)\n", + hRecipient,pNotificationFilter,dwFlags); + if (pNotificationFilter) + FIXME("The notification filter will requires an A->W when filter support is implemented\n"); + return RegisterDeviceNotificationW(hRecipient, pNotificationFilter, dwFlags); }
/*********************************************************************** @@ -326,19 +350,48 @@ HDEVNOTIFY WINAPI RegisterDeviceNotificationA(HANDLE hnd, LPVOID notifyfilter, D */ HDEVNOTIFY WINAPI RegisterDeviceNotificationW(HANDLE hRecipient, LPVOID pNotificationFilter, DWORD dwFlags) { - FIXME("(hwnd=%p, filter=%p,flags=0x%08x) returns a fake device notification handle!\n", - hRecipient,pNotificationFilter,dwFlags ); - return (HDEVNOTIFY) 0xcafeaffe; + DEVICE_NOTIFICATION_DETAILS details; + + TRACE("(hwnd=%p, filter=%p,flags=0x%08x)\n", + hRecipient,pNotificationFilter,dwFlags); + + if (dwFlags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES) + { + dwFlags &= ~DEVICE_NOTIFY_ALL_INTERFACE_CLASSES; + pNotificationFilter = NULL; + } + + details.hRecipient = hRecipient; + + switch (dwFlags) { + case DEVICE_NOTIFY_WINDOW_HANDLE: + details.pNotificationCallback = devnotify_window_callback; + break; + + case DEVICE_NOTIFY_SERVICE_HANDLE: + details.pNotificationCallback = devnotify_service_callback; + break; + + default: + SetLastError(ERROR_INVALID_FLAGS); + return 0; + } + + if (!hRecipient) + details.pNotificationCallback = devnotify_null_callback; + + return I_ScRegisterDeviceNotification(&details, pNotificationFilter, 0); }
/*********************************************************************** * UnregisterDeviceNotification (USER32.@) * */ -BOOL WINAPI UnregisterDeviceNotification(HDEVNOTIFY hnd) +BOOL WINAPI UnregisterDeviceNotification(HDEVNOTIFY hnd) { - FIXME("(handle=%p), STUB!\n", hnd); - return TRUE; + TRACE("(hnd=%p)\n", hnd); + + return I_ScUnregisterDeviceNotification(hnd); }
/*********************************************************************** diff --git a/include/winuser.h b/include/winuser.h index 51c73d25c2..b5dedc0db0 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -3112,7 +3112,9 @@ typedef struct tagTRACKMOUSEEVENT { typedef PVOID HDEVNOTIFY; typedef HDEVNOTIFY *PHDEVNOTIFY;
-#define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000 +#define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000 +#define DEVICE_NOTIFY_SERVICE_HANDLE 0x00000001 +#define DEVICE_NOTIFY_ALL_INTERFACE_CLASSES 0x00000004
/* used for GetWindowInfo() */
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=56482
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
Add test for API usage of RegisterDeviceNotification() and UnregisterDeviceNotification(). Unfortunately an automated way of triggering the actual notifications has not been found, so this test is not complete.
Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- dlls/user32/tests/input.c | 70 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index d0dc4a8bcf..35c5c99730 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -54,6 +54,9 @@ #include "winbase.h" #include "winuser.h" #include "winnls.h" +#include "dbt.h" +#include "initguid.h" +#include "ddk/hidclass.h"
#include "wine/test.h"
@@ -2862,10 +2865,73 @@ static void test_GetPointerType(void) ok(type == PT_MOUSE, " type %d\n", type ); }
+static void test_RegisterDeviceNotification(void) +{ + static const WCHAR mainwindowclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s',0}; + static const WCHAR message_windowW[] = {'m','e','s','s','a','g','e',' ','w','i','n','d','o','w',0}; + + HDEVNOTIFY hnotify1, hnotify2; + DEV_BROADCAST_DEVICEINTERFACE_W dbh; + HWND hwnd; + WNDCLASSEXW cls; + BOOL ret; + + memset(&cls, 0, sizeof(cls)); + cls.cbSize = sizeof(cls); + cls.hInstance = 0; + cls.lpszClassName = mainwindowclassW; + cls.lpfnWndProc = DefWindowProcW; + + RegisterClassExW(&cls); + + hwnd = CreateWindowExW(0, mainwindowclassW, message_windowW, 0, + 0, 0, 0, 0, HWND_MESSAGE, 0, 0, NULL); + ok(hwnd != 0, "CreateWindowExW with parent HWND_MESSAGE failed\n"); + + memset(&dbh, 0, sizeof(dbh)); + + dbh.dbcc_size = sizeof(dbh); + dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + dbh.dbcc_classguid = GUID_DEVINTERFACE_HID; + + /* Test RegisterDeviceNotification behavior */ + + /* Prior to Windows 8 a NULL recipient handle caused a failure, but more + * recent versions of windows allow it. + */ + hnotify1 = RegisterDeviceNotificationW(NULL, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE); + /* ok(hnotify1 != 0, "RegisterDeviceNotificationW failed when called with a NULL recipient window handle\n"); */ + if (hnotify1 != 0) + { + ret = UnregisterDeviceNotification(hnotify1); + ok(ret, "UnregisterDeviceNotification failed with a valid handle\n"); + } + + hnotify1 = RegisterDeviceNotificationW(hwnd, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE); + ok(hnotify1 != 0, "RegisterDeviceNotificationW failed when called with a message only window as recipient\n"); + + hnotify2 = RegisterDeviceNotificationW(hwnd, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE); + ok(hnotify2 != 0, "RegisterDeviceNotificationW failed when called with a window that has already been registered as a recipient\n"); + + ret = UnregisterDeviceNotification(hnotify1); + ok(ret, "UnregisterDeviceNotification failed with a valid handle\n"); + ret = UnregisterDeviceNotification(hnotify2); + ok(ret, "UnregisterDeviceNotification failed with a valid handle\n"); + ret = UnregisterDeviceNotification(hnotify1); + ok(!ret, "UnregisterDeviceNotification succeeded with an already released handle\n"); + ret = UnregisterDeviceNotification(NULL); + ok(!ret, "UnregisterDeviceNotification succeeded with NULL handle\n"); + + hnotify1 = RegisterDeviceNotificationW(hwnd, &dbh, 0xffff); + ok(hnotify1 == 0, "RegisterDeviceNotificationW accepted invalid flags\n"); + + /* FIXME: Find a way to trigger a device notification for testing */ + DestroyWindow(hwnd); +} + START_TEST(input) { POINT pos; - init_function_pointers(); GetCursorPos( &pos );
@@ -2907,4 +2973,6 @@ START_TEST(input) test_GetPointerType(); else win_skip("GetPointerType is not available\n"); + + test_RegisterDeviceNotification(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=56483
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- configure.ac | 1 + dlls/sechost/tests/Makefile.in | 5 ++ dlls/sechost/tests/devnotify.c | 102 +++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 dlls/sechost/tests/Makefile.in create mode 100644 dlls/sechost/tests/devnotify.c
diff --git a/configure.ac b/configure.ac index b4040ccd27..96d9735ebe 100644 --- a/configure.ac +++ b/configure.ac @@ -3645,6 +3645,7 @@ WINE_CONFIG_MAKEFILE(dlls/scrrun) WINE_CONFIG_MAKEFILE(dlls/scrrun/tests) WINE_CONFIG_MAKEFILE(dlls/scsiport.sys) WINE_CONFIG_MAKEFILE(dlls/sechost) +WINE_CONFIG_MAKEFILE(dlls/sechost/tests) WINE_CONFIG_MAKEFILE(dlls/secur32) WINE_CONFIG_MAKEFILE(dlls/secur32/tests) WINE_CONFIG_MAKEFILE(dlls/security) diff --git a/dlls/sechost/tests/Makefile.in b/dlls/sechost/tests/Makefile.in new file mode 100644 index 0000000000..603bc77bb0 --- /dev/null +++ b/dlls/sechost/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = sechost.dll +IMPORTS = sechost + +C_SRCS = \ + devnotify.c diff --git a/dlls/sechost/tests/devnotify.c b/dlls/sechost/tests/devnotify.c new file mode 100644 index 0000000000..7231f86b72 --- /dev/null +++ b/dlls/sechost/tests/devnotify.c @@ -0,0 +1,102 @@ +/* Test device notification registration via sechost + * + * Copyright 2019 Micah N Gorrell for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> +#include <assert.h> + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winnls.h" +#include "dbt.h" +#include "initguid.h" +#include "ddk/hidclass.h" + +#include "wine/test.h" + +typedef DWORD (CALLBACK *REGISTER_DEVICE_NOTIFY_CALLBACK)(HANDLE hRecipient, DWORD flags, + DEV_BROADCAST_HDR *); + +typedef struct +{ + REGISTER_DEVICE_NOTIFY_CALLBACK pNotificationCallback; + HWND hRecipient; +} REGISTER_DEVICE_NOTIFY; + +static HDEVNOTIFY (WINAPI * pI_ScRegisterDeviceNotification)(REGISTER_DEVICE_NOTIFY *data, LPVOID filter, DWORD flags); +static DWORD (WINAPI * pI_ScUnregisterDeviceNotification)(HDEVNOTIFY notify); + +static void init_function_pointers(void) +{ + HMODULE hdll = LoadLibraryA("sechost.dll"); + +#define GET_PROC(func) \ + if (!(p ## func = (void*)GetProcAddress(hdll, #func))) \ + trace("GetProcAddress(%s) failed\n", #func) + + GET_PROC(I_ScRegisterDeviceNotification); + GET_PROC(I_ScUnregisterDeviceNotification); +#undef GET_PROC +} + +static DWORD CALLBACK change_callback(HANDLE hRecipient, DWORD flags, DEV_BROADCAST_HDR *dbh) +{ + return 0; +} + +static void test_RegisterDeviceNotification(void) +{ + HDEVNOTIFY hnotify; + REGISTER_DEVICE_NOTIFY data; + DEV_BROADCAST_DEVICEINTERFACE_W dbh; + BOOL ret; + + memset(&dbh, 0, sizeof(dbh)); + + dbh.dbcc_size = sizeof(dbh); + dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + dbh.dbcc_classguid = GUID_DEVINTERFACE_HID; + + data.pNotificationCallback = change_callback; + data.hRecipient = NULL; + + /* Test I_ScRegisterDeviceNotification behavior */ + /* FIXME: Behavior of other flags hasn't yet been learned */ + hnotify = pI_ScRegisterDeviceNotification(&data, &dbh, 2); + ok(hnotify != 0, "I_ScRegisterDeviceNotification failed\n"); + + ret = pI_ScUnregisterDeviceNotification(hnotify); + ok(ret, "I_ScUnregisterDeviceNotification failed with a valid handle\n"); + ret = pI_ScUnregisterDeviceNotification(hnotify); + ok(!ret, "I_ScUnregisterDeviceNotification succeeded with an already released handle\n"); + ret = pI_ScUnregisterDeviceNotification(NULL); + ok(!ret, "I_ScUnregisterDeviceNotification succeeded with a NULL handle\n"); + + /* FIXME: Find a way to trigger a device notification for testing */ +} + +START_TEST(devnotify) +{ + init_function_pointers(); + + if (pI_ScRegisterDeviceNotification && pI_ScUnregisterDeviceNotification) + test_RegisterDeviceNotification(); + else + win_skip("I_ScRegisterDeviceNotification is not available\n"); +}
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=56484
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/advapi32/service.c:113 Task: Patch failed to apply