From: Pierre Schweitzer Subject: setupapi: Implement SetupOpenLog(), SetupLogErrorA(), SetupLogErrorW(), SetupCloseLog() (try 4) Message-Id: <54D76891.7080909@reactos.org> Date: Sun, 08 Feb 2015 14:45:53 +0100 Dear all, Please find attached a patch that implements the functions SetupOpenLog(), SetupLogErrorA(), SetupLogErrorW() and SetupCloseLog() in setupapi.dll. It comes with a few tests to highlight corners cases (and errors) of the functions. This was designed and tested on Windows 2003 server (even though it's been available starting Windows 2000). It also has been tested on W7, where a little different in behavior happens (as shown in tests). It doesn't accept NULL parameter anymore. Also, there are some behavior I implemented that I failed at designing a test for: (null) on NULL string, written to setupact.log whatever the severity level even if wrong. If anyone has ideas about how to do it properly, just shoot. Here, with such an implementation, the 11 tests are passing. This is the third try, taking into account the comments from wine-devel, and the Marvin fails. With my best regards, -- Pierre Schweitzer System & Network Administrator Senior Kernel Developer ReactOS Deutschland e.V. From 3a734d6134ae398286cb9ce13e0456fcaea00eba Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sat, 7 Feb 2015 21:15:22 +0100 Subject: [PATCH] setupapi: Implement SetupOpenLog(), SetupLogErrorA(), SetupLogErrorW(), SetupCloseLog() --- dlls/setupapi/Makefile.in | 1 + dlls/setupapi/log.c | 183 ++++++++++++++++++++++++++++++++++++++++ dlls/setupapi/setupapi.spec | 2 +- dlls/setupapi/setupcab.c | 2 + dlls/setupapi/stubs.c | 26 ------ dlls/setupapi/tests/Makefile.in | 1 + dlls/setupapi/tests/log.c | 72 ++++++++++++++++ 7 files changed, 260 insertions(+), 27 deletions(-) create mode 100644 dlls/setupapi/log.c create mode 100644 dlls/setupapi/tests/log.c diff --git a/dlls/setupapi/Makefile.in b/dlls/setupapi/Makefile.in index bf157cb..030b2d3 100644 --- a/dlls/setupapi/Makefile.in +++ b/dlls/setupapi/Makefile.in @@ -11,6 +11,7 @@ C_SRCS = \ diskspace.c \ fakedll.c \ install.c \ + log.c \ misc.c \ parser.c \ query.c \ diff --git a/dlls/setupapi/log.c b/dlls/setupapi/log.c new file mode 100644 index 0000000..52d84cf --- /dev/null +++ b/dlls/setupapi/log.c @@ -0,0 +1,183 @@ +/* + * SetupAPI logs functions + * + * Copyright 2015 Pierre Schweitzer + * + * 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 "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "setupapi.h" +#include "winnls.h" + +static HANDLE setupact = INVALID_HANDLE_VALUE; +static HANDLE setuperr = INVALID_HANDLE_VALUE; +static CRITICAL_SECTION setupapi_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &setupapi_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": setupapi_cs") } +}; +static CRITICAL_SECTION setupapi_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + +/*********************************************************************** + * SetupCloseLog(SETUPAPI.@) + */ +void WINAPI SetupCloseLog(void) +{ + EnterCriticalSection(&setupapi_cs); + + CloseHandle(setupact); + setupact = INVALID_HANDLE_VALUE; + + CloseHandle(setuperr); + setuperr = INVALID_HANDLE_VALUE; + + LeaveCriticalSection(&setupapi_cs); +} + +/*********************************************************************** + * SetupLogErrorA(SETUPAPI.@) + */ +BOOL WINAPI SetupLogErrorA(LPCSTR MessageString, LogSeverity Severity) +{ + LPWSTR msg = NULL; + DWORD len; + BOOL ret; + + if (MessageString) + { + len = MultiByteToWideChar(CP_ACP, 0, MessageString, -1, NULL, 0); + msg = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (msg == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + MultiByteToWideChar(CP_ACP, 0, MessageString, -1, msg, len); + } + + ret = SetupLogErrorW(msg, Severity); + + if (msg) + HeapFree(GetProcessHeap(), 0, msg); + + return ret; +} + +/*********************************************************************** + * SetupLogErrorW(SETUPAPI.@) + */ +BOOL WINAPI SetupLogErrorW(LPCWSTR MessageString, LogSeverity Severity) +{ + BOOL ret; + static const WCHAR null[] = {'(','n','u','l','l',')',0}; + DWORD written; + DWORD len; + + EnterCriticalSection(&setupapi_cs); + + if (setupact == INVALID_HANDLE_VALUE || setuperr == INVALID_HANDLE_VALUE) + { + LeaveCriticalSection(&setupapi_cs); + SetLastError(ERROR_FILE_INVALID); + return FALSE; + } + + if (MessageString == NULL) + MessageString = null; + + len = lstrlenW(MessageString) * sizeof(WCHAR); + + ret = WriteFile(setupact, MessageString, len, &written, NULL); + if (!ret) + { + LeaveCriticalSection(&setupapi_cs); + return ret; + } + + if (Severity >= LogSevMaximum) + { + LeaveCriticalSection(&setupapi_cs); + return FALSE; + } + + if (Severity > LogSevInformation) + ret = WriteFile(setuperr, MessageString, len, &written, NULL); + + LeaveCriticalSection(&setupapi_cs); + + return ret; +} + +/*********************************************************************** + * SetupOpenLog(SETUPAPI.@) + */ +BOOL WINAPI SetupOpenLog(BOOL Reserved) +{ + WCHAR path[MAX_PATH]; + WCHAR win[MAX_PATH]; + + static const WCHAR setupactlog[] = {'\\','s','e','t','u','p','a','c','t','.','l','o','g',0}; + static const WCHAR setuperrlog[] = {'\\','s','e','t','u','p','e','r','r','.','l','o','g',0}; + + EnterCriticalSection(&setupapi_cs); + + if (setupact != INVALID_HANDLE_VALUE && setuperr != INVALID_HANDLE_VALUE) + { + LeaveCriticalSection(&setupapi_cs); + SetLastError(ERROR_ALREADY_INITIALIZED); + return TRUE; + } + + GetWindowsDirectoryW(win, MAX_PATH); + lstrcpyW(path, win); + lstrcatW(path, setupactlog); + + setupact = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (setupact == INVALID_HANDLE_VALUE) + { + LeaveCriticalSection(&setupapi_cs); + return FALSE; + } + + SetFilePointer(setupact, 0, NULL, FILE_END); + + lstrcpyW(path, win); + lstrcatW(path, setuperrlog); + + setuperr = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (setuperr == INVALID_HANDLE_VALUE) + { + CloseHandle(setupact); + setupact = INVALID_HANDLE_VALUE; + LeaveCriticalSection(&setupapi_cs); + return FALSE; + } + + SetFilePointer(setuperr, 0, NULL, FILE_END); + + LeaveCriticalSection(&setupapi_cs); + + SetLastError(ERROR_ALREADY_EXISTS); + return TRUE; +} diff --git a/dlls/setupapi/setupapi.spec b/dlls/setupapi/setupapi.spec index 4fcf298..c1dbed5 100644 --- a/dlls/setupapi/setupapi.spec +++ b/dlls/setupapi/setupapi.spec @@ -459,7 +459,7 @@ @ stdcall SetupInstallServicesFromInfSectionW(long wstr long) @ stdcall SetupIterateCabinetA(str long ptr ptr) @ stdcall SetupIterateCabinetW(wstr long ptr ptr) -@ stub SetupLogErrorA +@ stdcall SetupLogErrorA(str long) @ stdcall SetupLogErrorW(wstr long) @ stdcall SetupLogFileA(ptr str str str long str str str long) @ stdcall SetupLogFileW(ptr wstr wstr wstr long wstr wstr wstr long) diff --git a/dlls/setupapi/setupcab.c b/dlls/setupapi/setupcab.c index 21336d7..ed4bb50 100644 --- a/dlls/setupapi/setupcab.c +++ b/dlls/setupapi/setupcab.c @@ -66,6 +66,7 @@ OSVERSIONINFOW OsVersionInfo; static HINSTANCE CABINET_hInstance = 0; HINSTANCE SETUPAPI_hInstance = 0; +extern CRITICAL_SECTION setuplog_critical; static HFDI (__cdecl *sc_FDICreate)(PFNALLOC, PFNFREE, PFNOPEN, PFNREAD, PFNWRITE, PFNCLOSE, PFNSEEK, int, PERF); @@ -694,6 +695,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) break; case DLL_PROCESS_DETACH: if (lpvReserved) break; + SetupCloseLog(); if (CABINET_hInstance) FreeLibrary(CABINET_hInstance); break; } diff --git a/dlls/setupapi/stubs.c b/dlls/setupapi/stubs.c index 673bbbf..a57f5fe 100644 --- a/dlls/setupapi/stubs.c +++ b/dlls/setupapi/stubs.c @@ -189,32 +189,6 @@ BOOL WINAPI RegistryDelnode(DWORD x, DWORD y) } /*********************************************************************** - * SetupCloseLog(SETUPAPI.@) - */ -void WINAPI SetupCloseLog(void) -{ - FIXME("() stub\n"); -} - -/*********************************************************************** - * SetupLogErrorW(SETUPAPI.@) - */ -BOOL WINAPI SetupLogErrorW(LPCWSTR MessageString, LogSeverity Severity) -{ - FIXME("(%s, %d) stub\n", debugstr_w(MessageString), Severity); - return TRUE; -} - -/*********************************************************************** - * SetupOpenLog(SETUPAPI.@) - */ -BOOL WINAPI SetupOpenLog(BOOL Reserved) -{ - FIXME("(%d) stub\n", Reserved); - return TRUE; -} - -/*********************************************************************** * SetupPromptReboot(SETUPAPI.@) */ INT WINAPI SetupPromptReboot( HSPFILEQ file_queue, HWND owner, BOOL scan_only ) diff --git a/dlls/setupapi/tests/Makefile.in b/dlls/setupapi/tests/Makefile.in index 30902e7..32ce41f 100644 --- a/dlls/setupapi/tests/Makefile.in +++ b/dlls/setupapi/tests/Makefile.in @@ -5,6 +5,7 @@ C_SRCS = \ devinst.c \ diskspace.c \ install.c \ + log.c \ misc.c \ parser.c \ query.c \ diff --git a/dlls/setupapi/tests/log.c b/dlls/setupapi/tests/log.c new file mode 100644 index 0000000..f461810 --- /dev/null +++ b/dlls/setupapi/tests/log.c @@ -0,0 +1,72 @@ +/* + * Unit tests for setupapi.dll log functions + * + * Copyright (C) 2015 Pierre Schweitzer + * + * 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 +#include +#include +#include "wine/test.h" + +static void test_SetupLogError(void) +{ + BOOL ret; + DWORD error; + + SetLastError(0xdeadbeef); + ret = SetupLogErrorW((LPCWSTR)L"Test without opening\r\n", LogSevInformation); + error = GetLastError(); + ok(!ret, "SetupLogError succeeded\n"); + ok(error == ERROR_FILE_INVALID, "got wrong error: %d\n", error); + + SetLastError(0xdeadbeef); + ret = SetupOpenLog(FALSE); + error = GetLastError(); + ok(ret, "SetupOpenLog failed\n"); + ok(error == ERROR_ALREADY_EXISTS, "got wrong error: %d\n", error); /* Even if log file didn't exist */ + + SetLastError(0xdeadbeef); + ret = SetupLogErrorW((LPCWSTR)L"Test with wrong log severity\r\n", LogSevMaximum + 1); + error = GetLastError(); + ok(!ret, "SetupLogError succeeded\n"); + ok(error == 0xdeadbeef, "got wrong error: %d\n", error); + SetLastError(0xdeadbeef); + ret = SetupLogErrorW((LPCWSTR)L"Test without EOL", LogSevInformation); + error = GetLastError(); + ok(ret, "SetupLogError failed\n"); + ok(error == 0xdeadbeef, "got wrong error: %d\n", error); + + SetLastError(0xdeadbeef); + ret = SetupLogErrorW(NULL, LogSevInformation); + error = GetLastError(); + if (!ret) ok(error == ERROR_INVALID_PARAMETER, "got wrong error: %d\n", error); /* Win Vista + */ + else ok(ret, "SetupLogError failed\n"); + + SetLastError(0xdeadbeef); + ret = SetupOpenLog(FALSE); + error = GetLastError(); + ok(ret, "SetupOpenLog failed\n"); + ok(error == ERROR_ALREADY_INITIALIZED, "got wrong error: %d\n", error); + + SetupCloseLog(); +} + +START_TEST(log) +{ + test_SetupLogError(); +} -- 1.9.1 0 *H 01 0 +0 *H  040 0  *H 0}1 0 UIL10U  StartCom Ltd.1+0)U "Secure Digital Certificate Signing1)0'U StartCom Certification Authority0 071024210255Z 171024210255Z01 0 UIL10U  StartCom Ltd.1+0)U "Secure Digital Certificate Signing1806U/StartCom Class 2 Primary Intermediate Client CA0"0  *H 0 (E,3* U]"gFSݤ>}m w鞆FA7~ |-ql"/Q?Vp`G&viĜ73 {B'87ds Nfz1%TII|2o/mD \t :08VGqǴ3Rp}JTzF;&X}rD Q 600U00U0UUo1ʹk1㬻0U#0N @[i04hCA0f+Z0X0'+0http://ocsp.startssl.com/ca0-+0!http://www.startssl.com/sfsca.crt0[UT0R0'%#!http://www.startssl.com/sfsca.crl0'%#!http://crl.startssl.com/sfsca.crl0U y0w0u +70f0.+"http://www.startssl.com/policy.pdf04+(http://www.startssl.com/intermediate.pdf0  *H :' ӴiiL\};JBG Ƚ1Fa gR~9P1 Rvg}ȜsWr<];sY/Msߟq'ɽNpʧ`&pPz/ў-Eׁ1KeET5ꥊ@v錈{8@t e=ރt92Ow[%[kd+YO!_uyGYqE\pCbM~ @3xnM+RH?o'V=INjWbᑶYOuZk*9Jz)w󫦒jNnZqwZV=t+΄BMkd"ܧfVSąmzLu8¾ņVcoiQ^7|#Bl@ /D;+@8 ~brA+}TLVŜ 2J(Hn}Rt]fiZ U ]+nŚܓqEF$^fsȕP)*6\q)90a0IY 0  *H  01 0 UIL10U  StartCom Ltd.1+0)U "Secure Digital Certificate Signing1806U/StartCom Class 2 Primary Intermediate Client CA0 141124162727Z 161124202226Z0~1 0 UFR10UHaute-Normandie10U Montivilliers10UPierre Schweitzer1!0 *H  pierre@reactos.org0"0  *H 0 Ik9 Pd `V<%v͗9lyu.=\H~6I~䄅#dZ>4oME\'܎D_eQMUkb/}c T;*z?f aڀ8K,`]:E5˩ "` `=F7wnpZHāڒN[(Tk8b:I7+K00 U00 U0U%0++0UfL,U%Zm0U#0Uo1ʹk1㬻0U0pierre@reactos.org0LU C0?0; +70*0.+"http://www.startssl.com/policy.pdf0+00' StartCom Certification Authority0This certificate was issued according to the Class 2 Validation requirements of the StartCom CA policy, reliance only for the intended purpose in compliance of the relying party obligations.06U/0-0+)'%http://crl.startssl.com/crtu2-crl.crl0+009+0-http://ocsp.startssl.com/sub/class2/client/ca0B+06http://aia.startssl.com/certs/sub.class2.client.ca.crt0#U0http://www.startssl.com/0  *H  &ܚɮI]YugIcG3M\@8JVu=qؖ\ ё, a<]r{JKC'뢀pኡ֗ז'!Ewa2*jH=g_~#WRFjsEgo`\0R_ 2䑌LM1Zz־~r&S`ب+xY(5` Pš[810001 0 UIL10U  StartCom Ltd.1+0)U "Secure Digital Certificate Signing1806U/StartCom Class 2 Primary Intermediate Client CAY 0 +0 *H  1  *H 0 *H  1 150208134553Z0# *H  1\7N|Z/%]U?0l *H  1_0]0  `He*0  `He0 *H 0*H 0 *H @0+0 *H (0  *H 64H,QJlRd)]ܰ-@Joo VЩ-|'jq?f1ph~W?T A5:VR/ˏ9lbV$l2<”TCWR, 6Au5LAհ;E`9g>')'I0(5){]|80xquq_ؤ+$( oc /zCL07RF+"4