advapi32: test and fix ChangeServiceConfig2 when given a zero length or a null description (try4, resend)
Bernhard Übelacker
bernhardu at mailbox.org
Wed Oct 11 08:36:16 CDT 2017
This patch avoids an error 998 while Flatout 2 tries to setup the copy
protection drivers/services.
Happens during the first run of FlatOut2.exe after the patch to v1.2.
The only visible sign in terminal output of the failure is this:
err:rpc:I_RpcReceive we got fault packet with status 0x3e6
This is because the SC_RPC_CONFIG_INFOW parameter has in its
descr->lpDescription a null pointer instead of a valid LPWSTR.
This null pointer is accessed in svcctl_ChangeServiceConfig2W and
causes an exception there, but is hidden by the RPC layer.
Following are the contents of the dialogs shown after the fault:
Protection Driver Installer Fatal Error
Unhandled exception in the Protection Driver Installer.
Try restart the application, if the problem still persist, contact the
customer support service and provide the information following.
Type: class LCommon::System::ServiceControl::Service::Exception
Location: void __thiscall
LCommon::System::ServiceControl::Service::ChangeDescription(class LUnicodeString)
Line: 357
Error Code: 998
Protection Driver Management Fatal Error
Unhandled exception in the Protection Driver
Management subsystem.
Try restart the application, if the problem still persist,
contact the
customer support service and provide the information following.
Type: class
LCommon::System::WindowsErrorException
Location: enum DriverManager::Result __thiscall
DriverManager::InstallDrivers(void)
Line: 677
Error Code: 998
Schutz-System
Fehler
Beim Öffnen der Kopierschutztreiber kam es zu einem unerwarteten Fehler.
Fehlernummer: 998.
Try 1: https://www.winehq.org/pipermail/wine-patches/2015-March/137996.html
Review: https://www.winehq.org/pipermail/wine-devel/2015-March/106999.html
https://www.winehq.org/pipermail/wine-devel/2015-March/107000.html
https://www.winehq.org/pipermail/wine-devel/2015-March/107002.html
https://www.winehq.org/pipermail/wine-devel/2015-March/107014.html
https://www.winehq.org/pipermail/wine-devel/2015-March/107025.html
https://www.winehq.org/pipermail/wine-devel/2015-March/107075.html
https://www.winehq.org/pipermail/wine-devel/2015-March/107086.html
Changes in try 2:
* Move check of descr->lpDescription to server side
* Add some more tests and check the results.
Try 2: https://www.winehq.org/pipermail/wine-patches/2015-June/139762.html
Testbot: https://www.winehq.org/pipermail/wine-devel/2015-June/107788.html
No changes in try 3.
Try 3: https://www.winehq.org/pipermail/wine-patches/2015-July/140923.html
Testbot: https://www.winehq.org/pipermail/wine-devel/2015-July/108455.html
Review: https://www.winehq.org/pipermail/wine-devel/2015-July/108496.html
No changes in try 4.
Signed-off-by: Bernhard Übelacker <bernhardu at mailbox.org>
---
dlls/advapi32/tests/service.c | 66 +++++++++++++++++++++++++++++++++++++++++++
programs/services/rpc.c | 3 ++
2 files changed, 69 insertions(+)
diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c
index ab7ae2e8fe..405cef7662 100644
--- a/dlls/advapi32/tests/service.c
+++ b/dlls/advapi32/tests/service.c
@@ -36,6 +36,7 @@ static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms
static CHAR selfname[MAX_PATH];
static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
+static BOOL (WINAPI *pChangeServiceConfig2W)(SC_HANDLE,DWORD,LPVOID);
static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
DWORD, LPBYTE, DWORD, LPDWORD,
LPDWORD, LPDWORD, LPCSTR);
@@ -57,6 +58,7 @@ static void init_function_pointers(void)
HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A");
+ pChangeServiceConfig2W = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2W");
pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA");
pEnumServicesStatusExW= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExW");
pGetSecurityInfo = (void *)GetProcAddress(hadvapi32, "GetSecurityInfo");
@@ -1954,6 +1956,7 @@ static void test_queryconfig2(void)
DWORD expected, needed;
BYTE buffer[MAX_PATH];
LPSERVICE_DESCRIPTIONA pConfig = (LPSERVICE_DESCRIPTIONA)buffer;
+ LPSERVICE_DESCRIPTIONW pConfigW = (LPSERVICE_DESCRIPTIONW)buffer;
SERVICE_PRESHUTDOWN_INFO preshutdown_info;
static const CHAR servicename [] = "Winetest";
static const CHAR displayname [] = "Winetest dummy service";
@@ -1961,6 +1964,9 @@ static void test_queryconfig2(void)
static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0";
static const CHAR password [] = "";
static const CHAR description [] = "Description";
+ static const CHAR description_empty[] = "";
+ static const WCHAR descriptionW [] = {'D','e','s','c','r','i','p','t','i','o','n','W',0};
+ static const WCHAR descriptionW_empty[] = {0};
if(!pQueryServiceConfig2A)
{
@@ -2121,6 +2127,66 @@ static void test_queryconfig2(void)
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION,buffer, needed,&needed);
ok(ret, "expected QueryServiceConfig2W to succeed\n");
+ pConfig->lpDescription = (LPSTR)description;
+ ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
+ ok(ret, "expected ChangeServiceConfig2A to succeed\n");
+
+ pConfig->lpDescription = NULL;
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
+ ok(ret, "expected QueryServiceConfig2A to succeed\n");
+ ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
+ "expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
+
+ pConfig->lpDescription = NULL;
+ ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
+ ok(ret, "expected ChangeServiceConfig2A to succeed\n");
+
+ pConfig->lpDescription = NULL;
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
+ ok(ret, "expected QueryServiceConfig2A to succeed\n");
+ ok(pConfig->lpDescription && !strcmp(description, pConfig->lpDescription),
+ "expected lpDescription to be %s, got %s\n", description, pConfig->lpDescription);
+
+ pConfig->lpDescription = (LPSTR)description_empty;
+ ret = pChangeServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
+ ok(ret, "expected ChangeServiceConfig2A to succeed\n");
+
+ pConfig->lpDescription = (void*)0xdeadbeef;
+ ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
+ ok(ret, "expected QueryServiceConfig2A to succeed\n");
+ ok(!pConfig->lpDescription,
+ "expected lpDescription to be null, got %s\n", pConfig->lpDescription);
+
+ pConfigW->lpDescription = (LPWSTR)descriptionW;
+ ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
+ ok(ret, "expected ChangeServiceConfig2W to succeed\n");
+
+ pConfigW->lpDescription = NULL;
+ ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
+ ok(ret, "expected QueryServiceConfig2A to succeed\n");
+ ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
+ "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
+
+ pConfigW->lpDescription = NULL;
+ ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
+ ok(ret, "expected ChangeServiceConfig2W to succeed\n");
+
+ pConfigW->lpDescription = NULL;
+ ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
+ ok(ret, "expected QueryServiceConfig2A to succeed\n");
+ ok(pConfigW->lpDescription && !lstrcmpW(descriptionW, pConfigW->lpDescription),
+ "expected lpDescription to be %s, got %s\n", wine_dbgstr_w(descriptionW), wine_dbgstr_w(pConfigW->lpDescription));
+
+ pConfigW->lpDescription = (LPWSTR)descriptionW_empty;
+ ret = pChangeServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, &buffer);
+ ok(ret, "expected ChangeServiceConfig2W to succeed\n");
+
+ pConfigW->lpDescription = (void*)0xdeadbeef;
+ ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_DESCRIPTION, buffer, sizeof(buffer), &needed);
+ ok(ret, "expected QueryServiceConfig2A to succeed\n");
+ ok(!pConfigW->lpDescription,
+ "expected lpDescription to be null, got %s\n", wine_dbgstr_w(pConfigW->lpDescription));
+
SetLastError(0xdeadbeef);
ret = pQueryServiceConfig2W(svc_handle, SERVICE_CONFIG_PRESHUTDOWN_INFO,
(LPBYTE)&preshutdown_info, sizeof(preshutdown_info), &needed);
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 8c95b7eb77..4435af935d 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -826,6 +826,9 @@ DWORD __cdecl svcctl_ChangeServiceConfig2W( SC_RPC_HANDLE hService, SC_RPC_CONFI
{
WCHAR *descr = NULL;
+ if (!config.u.descr->lpDescription)
+ break;
+
if (config.u.descr->lpDescription[0])
{
if (!(descr = strdupW( config.u.descr->lpDescription )))
--
2.11.0
More information about the wine-patches
mailing list