From 8dff62e1f8de3cff46ceddf09ff65f7ffeb246b4 Mon Sep 17 00:00:00 2001 From: The Wine Synchronizer Date: Sat, 2 Sep 2006 06:24:20 +0000 Subject: [PATCH] Autosyncing with Wine HEAD svn path=/trunk/; revision=23882 --- reactos/dll/win32/advpack/advpack.c | 1420 ++++++++++------- reactos/dll/win32/advpack/advpack.def | 37 - reactos/dll/win32/advpack/advpack.h | 254 --- reactos/dll/win32/advpack/advpack.rbuild | 29 +- reactos/dll/win32/advpack/advpack.rc | 7 - reactos/dll/win32/advpack/advpack.spec | 82 + .../advpack/{stubs.c => advpack_private.h} | 28 +- reactos/dll/win32/advpack/files.c | 1073 +++++++++++++ reactos/dll/win32/advpack/install.c | 951 +++++++++++ reactos/dll/win32/advpack/reg.c | 439 +++++ reactos/media/doc/README.WINE | 1 + 11 files changed, 3454 insertions(+), 867 deletions(-) delete mode 100644 reactos/dll/win32/advpack/advpack.def delete mode 100644 reactos/dll/win32/advpack/advpack.h delete mode 100644 reactos/dll/win32/advpack/advpack.rc create mode 100644 reactos/dll/win32/advpack/advpack.spec rename reactos/dll/win32/advpack/{stubs.c => advpack_private.h} (56%) create mode 100644 reactos/dll/win32/advpack/files.c create mode 100644 reactos/dll/win32/advpack/install.c create mode 100644 reactos/dll/win32/advpack/reg.c diff --git a/reactos/dll/win32/advpack/advpack.c b/reactos/dll/win32/advpack/advpack.c index 224cc9c1521..446e8da3b56 100644 --- a/reactos/dll/win32/advpack/advpack.c +++ b/reactos/dll/win32/advpack/advpack.c @@ -1,6 +1,8 @@ /* - * ReactOS Advpack User Library - * Copyright (C) 2004 ReactOS Team + * Advpack main + * + * Copyright 2004 Huw D M Davies + * Copyright 2005 Sami Aario * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -14,626 +16,964 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -/* - * See reference ie6_lib/include/advpub.h from msdn. - * Query "internet explorer headers libraries". - * - * Used wine/debug.h, if someone wanted to, they could port advpack over - * to the Wine project. - */ +#include - -#include -#include "advpack.h" +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "winver.h" +#include "winternl.h" +#include "winnls.h" +#include "setupapi.h" +#include "advpub.h" +#include "wine/unicode.h" #include "wine/debug.h" +#include "advpack_private.h" -/* - * @unimplemented +WINE_DEFAULT_DEBUG_CHANNEL(advpack); + +typedef HRESULT (WINAPI *DLLREGISTER) (void); + +#define MAX_FIELD_LENGTH 512 +#define PREFIX_LEN 5 + +/* registry path of the Installed Components key for per-user stubs */ +static const WCHAR setup_key[] = { + 'S','O','F','T','W','A','R','E','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'A','c','t','i','v','e',' ','S','e','t','u','p','\\', + 'I','n','s','t','a','l','l','e','d',' ', + 'C','o','m','p','o','n','e','n','t','s',0 +}; + +/* parses the destination directory parameters from pszSection + * the parameters are of the form: root,key,value,unknown,fallback + * we first read the reg value root\\key\\value and if that fails, + * use fallback as the destination directory */ -BOOL WINAPI -DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +static void get_dest_dir(HINF hInf, PCWSTR pszSection, PWSTR pszBuffer, DWORD dwSize) { - return TRUE; -} + INFCONTEXT context; + WCHAR key[MAX_PATH], value[MAX_PATH]; + WCHAR prefix[PREFIX_LEN]; + HKEY root, subkey; + DWORD size; -/* - * @unimplemented - */ -HRESULT WINAPI -AddDelBackupEntry( LPCSTR FileList, - LPCSTR BackupDir, - LPCSTR BaseName, - DWORD Flags ) -{ - FIXME("AddDelBackupEntry not implemented\n"); + static const WCHAR hklm[] = {'H','K','L','M',0}; + static const WCHAR hkcu[] = {'H','K','C','U',0}; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + /* load the destination parameters */ + SetupFindFirstLineW(hInf, pszSection, NULL, &context); + SetupGetStringFieldW(&context, 1, prefix, PREFIX_LEN, &size); + SetupGetStringFieldW(&context, 2, key, MAX_PATH, &size); + SetupGetStringFieldW(&context, 3, value, MAX_PATH, &size); - return E_FAIL; -} + if (!lstrcmpW(prefix, hklm)) + root = HKEY_LOCAL_MACHINE; + else if (!lstrcmpW(prefix, hkcu)) + root = HKEY_CURRENT_USER; + else + root = NULL; -/* - * @unimplemented - */ -HRESULT WINAPI -AdvInstallFile( HWND hwnd, - LPCSTR SourceDir, - LPCSTR SourceFile, - LPCSTR DestDir, - LPCSTR DestFile, - DWORD Flags, - DWORD Reserved) -{ - FIXME("AdvInstallFile not implemented\n"); + size = dwSize * sizeof(WCHAR); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - -/* - * @unimplemented - */ -HRESULT WINAPI -CloseINFEngine( HINF hinf ) -{ - FIXME("CloseINFEngine not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - -/* - * @unimplemented - */ -HRESULT WINAPI -DelNode( LPCSTR FileOrDirName, - DWORD Flags ) -{ - FIXME("DelNode not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - -/* - * @unimplemented - */ -HRESULT WINAPI -DelNodeRunDLL32( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ) -{ - FIXME("DelNodeRunDLL32 not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - -/* - * @unimplemented - */ -HRESULT WINAPI -ExecuteCab( HWND hwnd, - PCABINFO Cab, - LPVOID Reserved ) -{ - FIXME("ExecuteCab not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - -/* - * @unimplemented - */ -HRESULT WINAPI -ExtractFiles( LPCSTR CabName, - LPCSTR ExpandDir, - DWORD Flags, - LPCSTR FileList, - LPVOID LReserved, - DWORD Reserved ) -{ - FIXME("ExtractFiles not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - -/* - * @unimplemented - */ -HRESULT WINAPI -FileSaveMarkNotExist( LPSTR FileList, - LPSTR PathDir, - LPSTR BackupBaseName ) -{ - FIXME("FileSaveMarkNotExist not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - - -/* - * @unimplemented - */ -HRESULT WINAPI -FileSaveRestore( HWND hwnd, - LPSTR FileList, - LPSTR PathDir, - LPSTR BackupBaseName, - DWORD Flags ) -{ - FIXME("FileSaveRestore not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - - -/* - * @unimplemented - */ -HRESULT WINAPI -FileSaveRestoreOnINF( HWND hwnd, - PCSTR Title, - PCSTR InfFilename, - PCSTR Section, - HKEY BackupKey, - HKEY NBackupKey, - DWORD Flags ) -{ - FIXME("FileSaveRestoreOnINF not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - - -/* - * @implemented - */ -HRESULT WINAPI -GetVersionFromFile( LPSTR Filename, - LPDWORD MajorVer, - LPDWORD MinorVer, - BOOL Version ) -{ - return (GetVersionFromFileEx(Filename, MajorVer, MinorVer, Version)); -} - -/* - * @implemented - */ -HRESULT WINAPI -GetVersionFromFileEx( LPSTR Filename, - LPDWORD MajorVer, - LPDWORD MinorVer, - BOOL Version ) -{ - DWORD Size, Reserved, Param; - UINT Length; - LPVOID Buffer; - - if (Version) + /* fallback to the default destination dir if reg fails */ + if (RegOpenKeyW(root, key, &subkey) || + RegQueryValueExW(subkey, value, NULL, NULL, (LPBYTE)pszBuffer, &size)) { - Size = GetFileVersionInfoSizeA(Filename, &Reserved); - - Buffer = LocalAlloc ( GMEM_ZEROINIT, Size ); - - GetFileVersionInfoA( Filename, 0, Size, Buffer); - - VerQueryValueA( Buffer, - "\\StringFileInfo\\040904b0\\FileVersion", - (LPVOID) &Param, - &Length ); - - MajorVer = (LPDWORD) (DWORD) HIWORD(Param); - MinorVer = (LPDWORD) (DWORD) LOWORD(Param); - - LocalFree( Buffer ); - } - else - { - /* Language ID */ - MajorVer = (LPDWORD) LANG_ENGLISH; - /* I guess EnumResourceLanguages is used with a call back. - * Return PRIMARYLANGID(wIDLanguage) from the call back. - */ - - /* Codepage ID */ - MinorVer = (LPDWORD) GetACP(); - /* Here again, another guess. */ + SetupGetStringFieldW(&context, 5, pszBuffer, dwSize, NULL); } - return S_OK; + RegCloseKey(subkey); } - -/* - * @implemented - */ -BOOL WINAPI -IsNTAdmin( DWORD Reserved, - PDWORD PReserved ) +/* loads the LDIDs specified in the install section of an INF */ +void set_ldids(HINF hInf, LPCWSTR pszInstallSection, LPCWSTR pszWorkingDir) { - HANDLE Process, Token; - UINT i; - BOOL Good = FALSE; - DWORD Buffer[4096]; - DWORD Size; - PTOKEN_GROUPS TokenGrp = (PTOKEN_GROUPS) Buffer; - SID_IDENTIFIER_AUTHORITY AuthSid = {SECURITY_NT_AUTHORITY}; - PSID psid = NULL; - - Process = GetCurrentProcess(); + WCHAR field[MAX_FIELD_LENGTH]; + WCHAR line[MAX_FIELD_LENGTH]; + WCHAR dest[MAX_PATH]; + INFCONTEXT context; + DWORD size; + int ldid; - if (OpenProcessToken(Process, TOKEN_QUERY, &Token) == FALSE) + static const WCHAR source_dir[] = {'S','o','u','r','c','e','D','i','r',0}; + + static const WCHAR custDestW[] = { + 'C','u','s','t','o','m','D','e','s','t','i','n','a','t','i','o','n',0 + }; + + if (!SetupGetLineTextW(NULL, hInf, pszInstallSection, custDestW, + field, MAX_FIELD_LENGTH, &size)) + return; + + if (!SetupFindFirstLineW(hInf, field, NULL, &context)) + return; + + do { - CloseHandle(Process); - return FALSE; - } - - if ( GetTokenInformation( Token, TokenGroups, Buffer, 4096, &Size) == FALSE) - { - CloseHandle(Process); - CloseHandle(Token); - return FALSE; - } + LPWSTR value, ptr, key, key_copy = NULL; - CloseHandle(Process); - CloseHandle(Token); + SetupGetLineTextW(&context, NULL, NULL, NULL, + line, MAX_FIELD_LENGTH, &size); - if ( AllocateAndInitializeSid( &AuthSid, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &psid) == FALSE) - { - return FALSE; - } + /* SetupGetLineTextW returns the value if there is only one key, but + * returns the whole line if there is more than one key + */ + if (!(value = strchrW(line, '='))) + { + SetupGetStringFieldW(&context, 0, NULL, 0, &size); + key = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); + key_copy = key; + SetupGetStringFieldW(&context, 0, key, size, &size); + value = line; + } + else + { + key = line; + *(value++) = '\0'; + } - for ( i = 0; i < TokenGrp->GroupCount; i++ ) - { - if ( EqualSid( psid , TokenGrp->Groups[i].Sid) != FALSE ) - { - Good = TRUE; - break; - } - } - - FreeSid( psid); - - return(Good); + /* remove leading whitespace from the value */ + while (*value == ' ') + value++; + + /* FIXME: need to check the query option */ + ptr = strchrW(value, ','); + if (ptr) + *ptr = '\0'; + + /* set dest to pszWorkingDir if key is SourceDir */ + if (pszWorkingDir && !lstrcmpiW(value, source_dir)) + lstrcpynW(dest, pszWorkingDir, MAX_PATH); + else + get_dest_dir(hInf, value, dest, MAX_PATH); + + /* set all ldids to dest */ + while ((ptr = get_parameter(&key, ','))) + { + ldid = atolW(ptr); + SetupSetDirectoryIdW(hInf, ldid, dest); + } + HeapFree(GetProcessHeap(), 0, key_copy); + } while (SetupFindNextLine(&context, &context)); } - -/* - * @unimplemented - */ -INT WINAPI -LaunchINFSection( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ) -{ - FIXME("LaunchINFSection not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - - -/* - * @unimplemented - */ -HRESULT WINAPI -LaunchINFSectionEx( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ) -{ - FIXME("LaunchINFSectionEx not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - - -/* - * @unimplemented - */ -BOOL WINAPI -NeedReboot( DWORD RebootCheck ) -{ - FIXME("NeedReboot not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - - -/* - * @unimplemented - */ -DWORD WINAPI -NeedRebootInit( VOID ) -{ - FIXME("NeedRebootInit not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -HRESULT WINAPI -OpenINFEngine( PCSTR InfFilename, - PCSTR InstallSection, - DWORD Flags, - HINF hinf, - PVOID Reserved ) -{ - FIXME("OpenINFEngine not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - - -/* - * @unimplemented - */ -HRESULT WINAPI -RebootCheckOnInstall( HWND hwnd, - PCSTR InfFilename, - PCSTR InfSection, - DWORD Reserved ) -{ - FIXME("RebootCheckOnInstall not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - - -/* - * @unimplemented - */ -HRESULT WINAPI -RegInstall( HMODULE hm, - LPCSTR InfSectionExec, - LPCSTRTABLE TabStringSub ) -{ - FIXME("RegInstall not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; -} - - -/* - * I found this on the net, - * O4 - HKLM\..\RunOnce: [mcagntps.dll] rundll32.exe advpack.dll, - * RegisterOCX c:\PROGRA~1\mcafee.com\agent\mcagntps.dll +/*********************************************************************** + * CloseINFEngine (ADVPACK.@) * - * Not sure if this implementation is correct. I guess it's ActiveX stuff. + * Closes a handle to an INF file opened with OpenINFEngine. + * + * PARAMS + * hInf [I] Handle to the INF file to close. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. */ -/* - * @implemented - */ -HRESULT WINAPI -RegisterOCX(LPCTSTR Filename) +HRESULT WINAPI CloseINFEngine(HINF hInf) { - FARPROC DllEntryPoint; - LPCTSTR DllName = Filename; - HINSTANCE hlib = LoadLibrary(DllName); + TRACE("(%p)\n", hInf); - FIXME("RegisterOCX not implemented\n"); + if (!hInf) + return E_INVALIDARG; - if (hlib < (HINSTANCE)HINSTANCE_ERROR) - return E_FAIL; - DllEntryPoint = GetProcAddress( hlib, "DllRegisterServer"); - if (DllEntryPoint != NULL) + SetupCloseInfFile(hInf); + return S_OK; +} + +/*********************************************************************** + * DllMain (ADVPACK.@) + */ +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + TRACE("(%p, %ld, %p)\n", hinstDLL, fdwReason, lpvReserved); + + if (fdwReason == DLL_PROCESS_ATTACH) + DisableThreadLibraryCalls(hinstDLL); + + return TRUE; +} + +/*********************************************************************** + * IsNTAdmin (ADVPACK.@) + * + * Checks if the user has admin privileges. + * + * PARAMS + * reserved [I] Reserved. Must be 0. + * pReserved [I] Reserved. Must be NULL. + * + * RETURNS + * TRUE if user has admin rights, FALSE otherwise. + */ +BOOL WINAPI IsNTAdmin(DWORD reserved, LPDWORD pReserved) +{ + SID_IDENTIFIER_AUTHORITY SidAuthority = {SECURITY_NT_AUTHORITY}; + PTOKEN_GROUPS pTokenGroups; + BOOL bSidFound = FALSE; + DWORD dwSize, i; + HANDLE hToken; + PSID pSid; + + TRACE("(%ld, %p)\n", reserved, pReserved); + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + return FALSE; + + if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) { - if (FAILED((*DllEntryPoint)())) - { - FreeLibrary(hlib); - return E_FAIL; - } - return S_OK; + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + CloseHandle(hToken); + return FALSE; + } } - else - return E_FAIL; + + pTokenGroups = HeapAlloc(GetProcessHeap(), 0, dwSize); + if (!pTokenGroups) + { + CloseHandle(hToken); + return FALSE; + } + + if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize)) + { + HeapFree(GetProcessHeap(), 0, pTokenGroups); + CloseHandle(hToken); + return FALSE; + } + + CloseHandle(hToken); + + if (!AllocateAndInitializeSid(&SidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid)) + { + HeapFree(GetProcessHeap(), 0, pTokenGroups); + return FALSE; + } + + for (i = 0; i < pTokenGroups->GroupCount; i++) + { + if (EqualSid(pSid, pTokenGroups->Groups[i].Sid)) + { + bSidFound = TRUE; + break; + } + } + + HeapFree(GetProcessHeap(), 0, pTokenGroups); + FreeSid(pSid); + + return bSidFound; } - -/* - * @unimplemented +/*********************************************************************** + * NeedRebootInit (ADVPACK.@) + * + * Sets up conditions for reboot checking. + * + * RETURNS + * Value required by NeedReboot. */ -HRESULT WINAPI -RegRestoreAll( HWND hwnd, - PCSTR TitleString, - HKEY BackupKey ) +DWORD WINAPI NeedRebootInit(VOID) { - FIXME("RegRestoreAll not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; + FIXME("(VOID): stub\n"); + return 0; } - -/* - * @unimplemented +/*********************************************************************** + * NeedReboot (ADVPACK.@) + * + * Determines whether a reboot is required. + * + * PARAMS + * dwRebootCheck [I] Value from NeedRebootInit. + * + * RETURNS + * TRUE if a reboot is needed, FALSE otherwise. + * + * BUGS + * Unimplemented. */ -HRESULT WINAPI -RegSaveRestore( HWND hwnd, - PCSTR TitleString, - HKEY BackupKey, - PCSTR RootKey, - PCSTR SubKey, - PCSTR ValueName, - DWORD Flags ) +BOOL WINAPI NeedReboot(DWORD dwRebootCheck) { - FIXME("RegSaveRestore not implemented\n"); - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; + FIXME("(%ld): stub\n", dwRebootCheck); + return FALSE; } - -/* - * @unimplemented +/*********************************************************************** + * OpenINFEngineA (ADVPACK.@) + * + * See OpenINFEngineW. */ -HRESULT WINAPI -RegSaveRestoreOnINF( HWND hwnd, - PCSTR Title, - PCSTR InfFilename, - PCSTR Section, - HKEY BackupKey, - HKEY NBackupKey, - DWORD Flags ) +HRESULT WINAPI OpenINFEngineA(LPCSTR pszInfFilename, LPCSTR pszInstallSection, + DWORD dwFlags, HINF *phInf, PVOID pvReserved) { - FIXME("RegSaveRestoreOnINF not implemented\n"); + UNICODE_STRING filenameW, installW; + HRESULT res; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_a(pszInfFilename), + debugstr_a(pszInstallSection), dwFlags, phInf, pvReserved); - return E_FAIL; + if (!pszInfFilename || !phInf) + return E_INVALIDARG; + + RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename); + RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection); + + res = OpenINFEngineW(filenameW.Buffer, installW.Buffer, + dwFlags, phInf, pvReserved); + + RtlFreeUnicodeString(&filenameW); + RtlFreeUnicodeString(&installW); + + return res; } - -/* - * @unimplemented +/*********************************************************************** + * OpenINFEngineW (ADVPACK.@) + * + * Opens and returns a handle to an INF file to be used by + * TranslateInfStringEx to continuously translate the INF file. + * + * PARAMS + * pszInfFilename [I] Filename of the INF to open. + * pszInstallSection [I] Name of the Install section in the INF. + * dwFlags [I] See advpub.h. + * phInf [O] Handle to the loaded INF file. + * pvReserved [I] Reserved. Must be NULL. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. */ -HRESULT WINAPI -RunSetupCommand( HWND hwnd, - LPCSTR ExeFilename, - LPCSTR InfSection, - LPCSTR PathExtractedFile, - LPCSTR DialogTitle, - PHANDLE HExeWait, - DWORD Flags, - LPVOID Reserved) +HRESULT WINAPI OpenINFEngineW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection, + DWORD dwFlags, HINF *phInf, PVOID pvReserved) { - FIXME("RunSetupCommand not implemented\n"); + TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_w(pszInfFilename), + debugstr_w(pszInstallSection), dwFlags, phInf, pvReserved); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + if (!pszInfFilename || !phInf) + return E_INVALIDARG; - return E_FAIL; + *phInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL); + if (*phInf == INVALID_HANDLE_VALUE) + return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + + set_ldids(*phInf, pszInstallSection, NULL); + + return S_OK; } - -/* - * @unimplemented +/*********************************************************************** + * RebootCheckOnInstallA (ADVPACK.@) + * + * See RebootCheckOnInstallW. */ -HRESULT WINAPI -SetPerUserSecValues( PPERUSERSECTION PerUser ) +HRESULT WINAPI RebootCheckOnInstallA(HWND hWnd, LPCSTR pszINF, + LPSTR pszSec, DWORD dwReserved) { - FIXME("SetPerUserSecValues not implemented\n"); + UNICODE_STRING infW, secW; + HRESULT res; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + TRACE("(%p, %s, %s, %ld)\n", hWnd, debugstr_a(pszINF), + debugstr_a(pszSec), dwReserved); - return E_FAIL; + if (!pszINF || !pszSec) + return E_INVALIDARG; + + RtlCreateUnicodeStringFromAsciiz(&infW, pszINF); + RtlCreateUnicodeStringFromAsciiz(&secW, pszSec); + + res = RebootCheckOnInstallW(hWnd, infW.Buffer, secW.Buffer, dwReserved); + + RtlFreeUnicodeString(&infW); + RtlFreeUnicodeString(&secW); + + return res; } -/* - * @unimplemented +/*********************************************************************** + * RebootCheckOnInstallW (ADVPACK.@) + * + * Checks if a reboot is required for an installed INF section. + * + * PARAMS + * hWnd [I] Handle to the window used for messages. + * pszINF [I] Filename of the INF file. + * pszSec [I] INF section to check. + * dwReserved [I] Reserved. Must be 0. + * + * RETURNS + * Success: S_OK - Reboot is needed if the INF section is installed. + * S_FALSE - Reboot is not needed. + * Failure: HRESULT of GetLastError(). + * + * NOTES + * if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall + * or DefaultInstall.NT section. + * + * BUGS + * Unimplemented. */ -HRESULT WINAPI -TranslateInfString( PCSTR InfFilename, - PCSTR InstallSection, - PCSTR TranslateSection, - PCSTR TranslateKey, - PSTR BufferToKey, - DWORD BufferSize, - PVOID Reserved ) +HRESULT WINAPI RebootCheckOnInstallW(HWND hWnd, LPCWSTR pszINF, + LPWSTR pszSec, DWORD dwReserved) { - FIXME("TranslateInfString not implemented\n"); + FIXME("(%p, %s, %s, %ld): stub\n", hWnd, debugstr_w(pszINF), + debugstr_w(pszSec), dwReserved); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return E_FAIL; + return E_FAIL; } +/* registers the OCX if do_reg is TRUE, unregisters it otherwise */ +HRESULT do_ocx_reg(HMODULE hocx, BOOL do_reg) +{ + DLLREGISTER reg_func; -/* - * @unimplemented + if (do_reg) + reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllRegisterServer"); + else + reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllUnregisterServer"); + + if (!reg_func) + return E_FAIL; + + reg_func(); + return S_OK; +} + +/*********************************************************************** + * RegisterOCX (ADVPACK.@) + * + * Registers an OCX. + * + * PARAMS + * hWnd [I] Handle to the window used for the display. + * hInst [I] Instance of the process. + * cmdline [I] Contains parameters in the order OCX,flags,param. + * show [I] How the window should be shown. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * NOTES + * OCX - Filename of the OCX to register. + * flags - Controls the operation of RegisterOCX. + * 'I' Call DllRegisterServer and DllInstall. + * 'N' Only call DllInstall. + * param - Command line passed to DllInstall. */ -HRESULT WINAPI -TranslateInfStringEx( HINF hinf, - PCSTR InfFilename, - PCSTR InstallSection, - PCSTR TranslateSection, - PCSTR TranslateKey, - PSTR BufferToKey, - DWORD BufferSize, - PVOID Reserved ) +HRESULT WINAPI RegisterOCX(HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show) { - FIXME("TranslateInfStringEx not implemented\n"); + LPWSTR ocx_filename, str_flags, param; + LPWSTR cmdline_copy, cmdline_ptr; + UNICODE_STRING cmdlineW; + HRESULT hr = E_FAIL; + HMODULE hm = NULL; + DWORD size; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + TRACE("(%s)\n", debugstr_a(cmdline)); - return E_FAIL; + RtlCreateUnicodeStringFromAsciiz(&cmdlineW, cmdline); + + size = (lstrlenW(cmdlineW.Buffer) + 1) * sizeof(WCHAR); + cmdline_copy = HeapAlloc(GetProcessHeap(), 0, size); + cmdline_ptr = cmdline_copy; + lstrcpyW(cmdline_copy, cmdlineW.Buffer); + + ocx_filename = get_parameter(&cmdline_ptr, ','); + if (!ocx_filename || !*ocx_filename) + goto done; + + str_flags = get_parameter(&cmdline_ptr, ','); + param = get_parameter(&cmdline_ptr, ','); + + hm = LoadLibraryExW(ocx_filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!hm) + goto done; + + hr = do_ocx_reg(hm, TRUE); + +done: + FreeLibrary(hm); + HeapFree(GetProcessHeap(), 0, cmdline_copy); + RtlFreeUnicodeString(&cmdlineW); + + return hr; } -/* - * @unimplemented +/*********************************************************************** + * SetPerUserSecValuesA (ADVPACK.@) + * + * See SetPerUserSecValuesW. */ -HRESULT WINAPI -UserInstStubWrapper( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ) +HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser) { - FIXME("UserInstStubWrapper not implemented\n"); + PERUSERSECTIONW perUserW; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + TRACE("(%p)\n", pPerUser); - return E_FAIL; + if (!pPerUser) + return E_INVALIDARG; + + MultiByteToWideChar(CP_ACP, 0, pPerUser->szGUID, -1, perUserW.szGUID, + sizeof(perUserW.szGUID) / sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pPerUser->szDispName, -1, perUserW.szDispName, + sizeof(perUserW.szDispName) / sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pPerUser->szLocale, -1, perUserW.szLocale, + sizeof(perUserW.szLocale) / sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pPerUser->szStub, -1, perUserW.szStub, + sizeof(perUserW.szStub) / sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pPerUser->szVersion, -1, perUserW.szVersion, + sizeof(perUserW.szVersion) / sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pPerUser->szCompID, -1, perUserW.szCompID, + sizeof(perUserW.szCompID) / sizeof(WCHAR)); + perUserW.dwIsInstalled = pPerUser->dwIsInstalled; + perUserW.bRollback = pPerUser->bRollback; + + return SetPerUserSecValuesW(&perUserW); } -/* - * @unimplemented +/*********************************************************************** + * SetPerUserSecValuesW (ADVPACK.@) + * + * Prepares the per-user stub values under IsInstalled\{GUID} that + * control the per-user installation. + * + * PARAMS + * pPerUser [I] Per-user stub values. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. */ -HRESULT WINAPI -UserUnInstStubWrapper( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ) +HRESULT WINAPI SetPerUserSecValuesW(PERUSERSECTIONW* pPerUser) { - FIXME("UserUnInstStubWrapper not implemented\n"); + HKEY setup, guid; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + static const WCHAR stub_path[] = {'S','t','u','b','P','a','t','h',0}; + static const WCHAR version[] = {'V','e','r','s','i','o','n',0}; + static const WCHAR locale[] = {'L','o','c','a','l','e',0}; + static const WCHAR compid[] = {'C','o','m','p','o','n','e','n','t','I','D',0}; + static const WCHAR isinstalled[] = {'I','s','I','n','s','t','a','l','l','e','d',0}; - return E_FAIL; + TRACE("(%p)\n", pPerUser); + + if (!pPerUser || !*pPerUser->szGUID) + return S_OK; + + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, NULL, 0, KEY_WRITE, + NULL, &setup, NULL)) + { + return E_FAIL; + } + + if (RegCreateKeyExW(setup, pPerUser->szGUID, 0, NULL, 0, KEY_ALL_ACCESS, + NULL, &guid, NULL)) + { + RegCloseKey(setup); + return E_FAIL; + } + + if (*pPerUser->szStub) + { + RegSetValueExW(guid, stub_path, 0, REG_SZ, (LPBYTE)pPerUser->szStub, + (lstrlenW(pPerUser->szStub) + 1) * sizeof(WCHAR)); + } + + if (*pPerUser->szVersion) + { + RegSetValueExW(guid, version, 0, REG_SZ, (LPBYTE)pPerUser->szVersion, + (lstrlenW(pPerUser->szVersion) + 1) * sizeof(WCHAR)); + } + + if (*pPerUser->szLocale) + { + RegSetValueExW(guid, locale, 0, REG_SZ, (LPBYTE)pPerUser->szLocale, + (lstrlenW(pPerUser->szLocale) + 1) * sizeof(WCHAR)); + } + + if (*pPerUser->szCompID) + { + RegSetValueExW(guid, compid, 0, REG_SZ, (LPBYTE)pPerUser->szCompID, + (lstrlenW(pPerUser->szCompID) + 1) * sizeof(WCHAR)); + } + + if (*pPerUser->szDispName) + { + RegSetValueExW(guid, NULL, 0, REG_SZ, (LPBYTE)pPerUser->szDispName, + (lstrlenW(pPerUser->szDispName) + 1) * sizeof(WCHAR)); + } + + RegSetValueExW(guid, isinstalled, 0, REG_DWORD, + (LPBYTE)&pPerUser->dwIsInstalled, sizeof(DWORD)); + + RegCloseKey(guid); + RegCloseKey(setup); + + return S_OK; } +/*********************************************************************** + * TranslateInfStringA (ADVPACK.@) + * + * See TranslateInfStringW. + */ +HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection, + LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer, + DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved) +{ + UNICODE_STRING filenameW, installW; + UNICODE_STRING translateW, keyW; + LPWSTR bufferW; + HRESULT res; + DWORD len = 0; -/* EOF */ + TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n", + debugstr_a(pszInfFilename), debugstr_a(pszInstallSection), + debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey), + pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved); + + if (!pszInfFilename || !pszTranslateSection || + !pszTranslateKey || !pdwRequiredSize) + return E_INVALIDARG; + + RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename); + RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection); + RtlCreateUnicodeStringFromAsciiz(&translateW, pszTranslateSection); + RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey); + + res = TranslateInfStringW(filenameW.Buffer, installW.Buffer, + translateW.Buffer, keyW.Buffer, NULL, + dwBufferSize, &len, NULL); + + if (res == S_OK) + { + bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + + res = TranslateInfStringW(filenameW.Buffer, installW.Buffer, + translateW.Buffer, keyW.Buffer, bufferW, + len, &len, NULL); + if (res == S_OK) + { + *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, + NULL, 0, NULL, NULL); + + if (dwBufferSize >= *pdwRequiredSize) + { + WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer, + dwBufferSize, NULL, NULL); + } + else + res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + HeapFree(GetProcessHeap(), 0, bufferW); + } + + RtlFreeUnicodeString(&filenameW); + RtlFreeUnicodeString(&installW); + RtlFreeUnicodeString(&translateW); + RtlFreeUnicodeString(&keyW); + + return res; +} + +/*********************************************************************** + * TranslateInfStringW (ADVPACK.@) + * + * Translates the value of a specified key in an inf file into the + * current locale by expanding string macros. + * + * PARAMS + * pszInfFilename [I] Filename of the inf file. + * pszInstallSection [I] + * pszTranslateSection [I] Inf section where the key exists. + * pszTranslateKey [I] Key to translate. + * pszBuffer [O] Contains the translated string on exit. + * dwBufferSize [I] Size on input of pszBuffer. + * pdwRequiredSize [O] Length of the translated key. + * pvReserved [I] Reserved, must be NULL. + * + * RETURNS + * Success: S_OK. + * Failure: An hresult error code. + */ +HRESULT WINAPI TranslateInfStringW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection, + LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey, LPWSTR pszBuffer, + DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved) +{ + HINF hInf; + + TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n", + debugstr_w(pszInfFilename), debugstr_w(pszInstallSection), + debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey), + pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved); + + if (!pszInfFilename || !pszTranslateSection || + !pszTranslateKey || !pdwRequiredSize) + return E_INVALIDARG; + + hInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL); + if (hInf == INVALID_HANDLE_VALUE) + return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + + set_ldids(hInf, pszInstallSection, NULL); + + if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey, + pszBuffer, dwBufferSize, pdwRequiredSize)) + { + if (dwBufferSize < *pdwRequiredSize) + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + + return SPAPI_E_LINE_NOT_FOUND; + } + + SetupCloseInfFile(hInf); + return S_OK; +} + +/*********************************************************************** + * TranslateInfStringExA (ADVPACK.@) + * + * See TranslateInfStringExW. + */ +HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename, + LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, + LPSTR pszBuffer, DWORD dwBufferSize, + PDWORD pdwRequiredSize, PVOID pvReserved) +{ + UNICODE_STRING filenameW, sectionW, keyW; + LPWSTR bufferW; + HRESULT res; + DWORD len = 0; + + TRACE("(%p, %s, %s, %s, %s, %ld, %p, %p)\n", hInf, debugstr_a(pszInfFilename), + debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey), + debugstr_a(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved); + + if (!pszInfFilename || !pszTranslateSection || + !pszTranslateKey || !pdwRequiredSize) + return E_INVALIDARG; + + RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename); + RtlCreateUnicodeStringFromAsciiz(§ionW, pszTranslateSection); + RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey); + + res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer, + keyW.Buffer, NULL, 0, &len, NULL); + + if (res == S_OK) + { + bufferW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + + res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer, + keyW.Buffer, bufferW, len, &len, NULL); + + if (res == S_OK) + { + *pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, + NULL, 0, NULL, NULL); + + if (dwBufferSize >= *pdwRequiredSize) + { + WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer, + dwBufferSize, NULL, NULL); + } + else + res = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + HeapFree(GetProcessHeap(), 0, bufferW); + } + + RtlFreeUnicodeString(&filenameW); + RtlFreeUnicodeString(§ionW); + RtlFreeUnicodeString(&keyW); + + return res; +} + +/*********************************************************************** + * TranslateInfStringExW (ADVPACK.@) + * + * Using a handle to an INF file opened with OpenINFEngine, translates + * the value of a specified key in an inf file into the current locale + * by expanding string macros. + * + * PARAMS + * hInf [I] Handle to the INF file. + * pszInfFilename [I] Filename of the INF file. + * pszTranslateSection [I] Inf section where the key exists. + * pszTranslateKey [I] Key to translate. + * pszBuffer [O] Contains the translated string on exit. + * dwBufferSize [I] Size on input of pszBuffer. + * pdwRequiredSize [O] Length of the translated key. + * pvReserved [I] Reserved. Must be NULL. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * NOTES + * To use TranslateInfStringEx to translate an INF file continuously, + * open the INF file with OpenINFEngine, call TranslateInfStringEx as + * many times as needed, then release the handle with CloseINFEngine. + * When translating more than one keys, this method is more efficient + * than calling TranslateInfString, because the INF file is only + * opened once. + */ +HRESULT WINAPI TranslateInfStringExW(HINF hInf, LPCWSTR pszInfFilename, + LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey, + LPWSTR pszBuffer, DWORD dwBufferSize, + PDWORD pdwRequiredSize, PVOID pvReserved) +{ + TRACE("(%p, %s, %s, %s, %s, %ld, %p, %p)\n", hInf, debugstr_w(pszInfFilename), + debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey), + debugstr_w(pszBuffer), dwBufferSize, pdwRequiredSize, pvReserved); + + if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey) + return E_INVALIDARG; + + if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey, + pszBuffer, dwBufferSize, pdwRequiredSize)) + { + if (dwBufferSize < *pdwRequiredSize) + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + + return SPAPI_E_LINE_NOT_FOUND; + } + + return S_OK; +} + +/*********************************************************************** + * UserInstStubWrapperA (ADVPACK.@) + * + * See UserInstStubWrapperW. + */ +HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance, + LPSTR pszParms, INT nShow) +{ + UNICODE_STRING parmsW; + HRESULT res; + + TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow); + + if (!pszParms) + return E_INVALIDARG; + + RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms); + + res = UserInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow); + + RtlFreeUnicodeString(&parmsW); + + return res; +} + +/*********************************************************************** + * UserInstStubWrapperW (ADVPACK.@) + * + * Launches the user stub wrapper specified by the RealStubPath + * registry value under Installed Components\szParms. + * + * PARAMS + * hWnd [I] Handle to the window used for the display. + * hInstance [I] Instance of the process. + * szParms [I] The GUID of the installation. + * show [I] How the window should be shown. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * TODO + * If the type of the StubRealPath value is REG_EXPAND_SZ, then + * we should call ExpandEnvironmentStrings on the value and + * launch the result. + */ +HRESULT WINAPI UserInstStubWrapperW(HWND hWnd, HINSTANCE hInstance, + LPWSTR pszParms, INT nShow) +{ + HKEY setup, guid; + WCHAR stub[MAX_PATH]; + DWORD size = MAX_PATH; + HRESULT hr = S_OK; + BOOL res; + + static const WCHAR real_stub_path[] = { + 'R','e','a','l','S','t','u','b','P','a','t','h',0 + }; + + TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_w(pszParms), nShow); + + if (!pszParms || !*pszParms) + return E_INVALIDARG; + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, KEY_READ, &setup)) + { + return E_FAIL; + } + + if (RegOpenKeyExW(setup, pszParms, 0, KEY_READ, &guid)) + { + RegCloseKey(setup); + return E_FAIL; + } + + res = RegQueryValueExW(guid, real_stub_path, NULL, NULL, (LPBYTE)stub, &size); + if (res || !*stub) + goto done; + + /* launch the user stub wrapper */ + hr = launch_exe(stub, NULL, NULL); + +done: + RegCloseKey(setup); + RegCloseKey(guid); + + return hr; +} + +/*********************************************************************** + * UserUnInstStubWrapperA (ADVPACK.@) + * + * See UserUnInstStubWrapperW. + */ +HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance, + LPSTR pszParms, INT nShow) +{ + UNICODE_STRING parmsW; + HRESULT res; + + TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow); + + if (!pszParms) + return E_INVALIDARG; + + RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms); + + res = UserUnInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow); + + RtlFreeUnicodeString(&parmsW); + + return res; +} + +/*********************************************************************** + * UserUnInstStubWrapperW (ADVPACK.@) + */ +HRESULT WINAPI UserUnInstStubWrapperW(HWND hWnd, HINSTANCE hInstance, + LPWSTR pszParms, INT nShow) +{ + FIXME("(%p, %p, %s, %i): stub\n", hWnd, hInstance, debugstr_w(pszParms), nShow); + + return E_FAIL; +} diff --git a/reactos/dll/win32/advpack/advpack.def b/reactos/dll/win32/advpack/advpack.def deleted file mode 100644 index 1d1fe7badda..00000000000 --- a/reactos/dll/win32/advpack/advpack.def +++ /dev/null @@ -1,37 +0,0 @@ -LIBRARY advpack.dll - -EXPORTS -AddDelBackupEntry@16 -AdvInstallFile@28 -CloseINFEngine@4 -DelNode@8 -DelNodeRunDLL32@16 -DllMain@12 -DoInfInstall@4 -ExecuteCab@12 -ExtractFiles@24 -FileSaveMarkNotExist@12 -FileSaveRestore@20 -FileSaveRestoreOnINF@28 -GetVersionFromFile@16 -GetVersionFromFileEx@16 -IsNTAdmin@8 -LaunchINFSection@16 -LaunchINFSectionEx@16 -NeedReboot@4 -NeedRebootInit@0 -OpenINFEngine@20 -RebootCheckOnInstall@16 -RegInstall@12 -RegRestoreAll@12 -RegSaveRestore@28 -RegSaveRestoreOnINF@28 -RegisterOCX@4 -RunSetupCommand@32 -SetPerUserSecValues@4 -TranslateInfString@28 -TranslateInfStringEx@32 -UserInstStubWrapper@16 -UserUnInstStubWrapper@16 - -; EOF diff --git a/reactos/dll/win32/advpack/advpack.h b/reactos/dll/win32/advpack/advpack.h deleted file mode 100644 index 547e1c3e171..00000000000 --- a/reactos/dll/win32/advpack/advpack.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - ADVPACK.H - */ - -#ifndef _ADVPACK_H -#define _ADVPACK_H -#if __GNUC__ >=3 -#pragma GCC system_header -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct _StrEntry { - LPSTR Name; - LPSTR Value; -} STRENTRY, *LPSTRENTRY; - -typedef const STRENTRY CSTRENTRY; -typedef CSTRENTRY *LPCSTRENTRY; - -typedef struct _StrTable { - DWORD Entries; - LPSTRENTRY Array; -} STRTABLE, *LPSTRTABLE; - -typedef const STRTABLE CSTRTABLE; -typedef CSTRTABLE *LPCSTRTABLE; - -typedef struct _CabInfo { - PSTR Cab; - PSTR Inf; - PSTR Section; - char Path[MAX_PATH]; - DWORD Flags; -} CABINFO, *PCABINFO; - -typedef PVOID HINF; - -typedef struct _PERUSERSECTION { - char GUID[59]; - char DisplayName[128]; - char Locale[10]; - char Stub[MAX_PATH*4]; - char Version[32]; - char CompId[128]; - DWORD IsInstalled; - BOOL RollBack; -} PERUSERSECTION, *PPERUSERSECTION; - - -HRESULT WINAPI -AddDelBackupEntry( LPCSTR FileList, - LPCSTR BackupDir, - LPCSTR BaseName, - DWORD Flags ); - -HRESULT WINAPI -AdvInstallFile( HWND hwnd, - LPCSTR SourceDir, - LPCSTR SourceFile, - LPCSTR DestDir, - LPCSTR DestFile, - DWORD Flags, - DWORD Reserved); - -HRESULT WINAPI -CloseINFEngine( HINF hinf ); - -HRESULT WINAPI -DelNode( LPCSTR FileOrDirName, - DWORD Flags ); - -HRESULT WINAPI -DelNodeRunDLL32( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ); - - -HRESULT WINAPI -ExecuteCab( HWND hwnd, - PCABINFO Cab, - LPVOID Reserved ); - -HRESULT WINAPI -ExtractFiles( LPCSTR CabName, - LPCSTR ExpandDir, - DWORD Flags, - LPCSTR FileList, - LPVOID LReserved, - DWORD Reserved ); - -HRESULT WINAPI -FileSaveMarkNotExist( LPSTR FileList, - LPSTR PathDir, - LPSTR BackupBaseName ); - -HRESULT WINAPI -FileSaveRestore( HWND hwnd, - LPSTR FileList, - LPSTR PathDir, - LPSTR BackupBaseName, - DWORD Flags ); - - -HRESULT WINAPI -FileSaveRestoreOnINF( HWND hwnd, - PCSTR Title, - PCSTR InfFilename, - PCSTR Section, - HKEY BackupKey, - HKEY NBackupKey, - DWORD Flags ); - - -HRESULT WINAPI -GetVersionFromFile( LPSTR Filename, - LPDWORD MajorVer, - LPDWORD MinorVer, - BOOL Version ); - -HRESULT WINAPI -GetVersionFromFileEx( LPSTR Filename, - LPDWORD MajorVer, - LPDWORD MinorVer, - BOOL Version ); - -BOOL WINAPI -IsNTAdmin( DWORD Reserved, - PDWORD PReserved ); - -INT WINAPI -LaunchINFSection( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ); - -HRESULT WINAPI -LaunchINFSectionEx( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ); - -BOOL WINAPI -NeedReboot( DWORD RebootCheck ); - -DWORD WINAPI -NeedRebootInit( VOID ); - -HRESULT WINAPI -OpenINFEngine( PCSTR InfFilename, - PCSTR InstallSection, - DWORD Flags, - HINF hinf, - PVOID Reserved ); - -HRESULT WINAPI -RebootCheckOnInstall( HWND hwnd, - PCSTR InfFilename, - PCSTR InfSection, - DWORD Reserved ); - -HRESULT WINAPI -RegInstall( HMODULE hm, - LPCSTR InfSectionExec, - LPCSTRTABLE TabStringSub ); - -HRESULT WINAPI -RegRestoreAll( HWND hwnd, - PCSTR TitleString, - HKEY BackupKey ); - -HRESULT WINAPI -RegSaveRestore( HWND hwnd, - PCSTR TitleString, - HKEY BackupKey, - PCSTR RootKey, - PCSTR SubKey, - PCSTR ValueName, - DWORD Flags ); - -HRESULT WINAPI -RegSaveRestoreOnINF( HWND hwnd, - PCSTR Title, - PCSTR InfFilename, - PCSTR Section, - HKEY BackupKey, - HKEY NBackupKey, - DWORD Flags ); - - -HRESULT WINAPI -RunSetupCommand( HWND hwnd, - LPCSTR ExeFilename, - LPCSTR InfSection, - LPCSTR PathExtractedFile, - LPCSTR DialogTitle, - PHANDLE HExeWait, - DWORD Flags, - LPVOID Reserved); - - -HRESULT WINAPI -TranslateInfString( PCSTR InfFilename, - PCSTR InstallSection, - PCSTR TranslateSection, - PCSTR TranslateKey, - PSTR BufferToKey, - DWORD BufferSize, - PVOID Reserved ); - -HRESULT WINAPI -TranslateInfStringEx( HINF hinf, - PCSTR InfFilename, - PCSTR InstallSection, - PCSTR TranslateSection, - PCSTR TranslateKey, - PSTR BufferToKey, - DWORD BufferSize, - PVOID Reserved ); - -HRESULT WINAPI -SetPerUserSecValues( PPERUSERSECTION PerUser ); - -HRESULT WINAPI -UserInstStubWrapper( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ); - -HRESULT WINAPI -UserUnInstStubWrapper( HWND hwnd, - HINSTANCE Inst, - PSTR Params, - INT Index ); - -/* - * - * - */ -HRESULT WINAPI -DoInfInstall( DWORD Unknown); - -HRESULT WINAPI -RegisterOCX( LPCTSTR Filename ); - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/reactos/dll/win32/advpack/advpack.rbuild b/reactos/dll/win32/advpack/advpack.rbuild index 521b889b606..c1c44e25d0a 100644 --- a/reactos/dll/win32/advpack/advpack.rbuild +++ b/reactos/dll/win32/advpack/advpack.rbuild @@ -1,20 +1,23 @@ - - + + . - - + include/reactos/wine + - 0x0600 + 0x600 0x501 - ntdll - kernel32 - user32 - gdi32 - advapi32 - ole32 + 0x501 + wine + setupapi version + user32 + advapi32 + kernel32 + ntdll advpack.c - stubs.c - advpack.rc + files.c + install.c + reg.c + advpack.spec diff --git a/reactos/dll/win32/advpack/advpack.rc b/reactos/dll/win32/advpack/advpack.rc deleted file mode 100644 index eda74338e7c..00000000000 --- a/reactos/dll/win32/advpack/advpack.rc +++ /dev/null @@ -1,7 +0,0 @@ -#include - -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Advpack User Library\0" -#define REACTOS_STR_INTERNAL_NAME "advpack\0" -#define REACTOS_STR_ORIGINAL_FILENAME "advpack.dll\0" -#include diff --git a/reactos/dll/win32/advpack/advpack.spec b/reactos/dll/win32/advpack/advpack.spec new file mode 100644 index 00000000000..2ba1057332f --- /dev/null +++ b/reactos/dll/win32/advpack/advpack.spec @@ -0,0 +1,82 @@ +@ stdcall AddDelBackupEntryA(str str str long) +@ stdcall AddDelBackupEntryW(wstr wstr wstr long) +@ stdcall AddDelBackupEntry(str str str long) AddDelBackupEntryA +@ stdcall AdvInstallFileA(long str str str str long long) +@ stdcall AdvInstallFileW(long wstr wstr wstr wstr long long) +@ stdcall AdvInstallFile(long str str str str long long) AdvInstallFileA +@ stdcall CloseINFEngine(long) +@ stdcall DelNodeA(str long) +@ stdcall DelNodeW(wstr long) +@ stdcall DelNode(str long) DelNodeA +@ stdcall DelNodeRunDLL32A(ptr ptr str long) +@ stdcall DelNodeRunDLL32W(ptr ptr wstr long) +@ stdcall DelNodeRunDLL32(ptr ptr str long) DelNodeRunDLL32A +@ stdcall -private DllMain(long long ptr) +@ stdcall DoInfInstall(ptr) +@ stdcall ExecuteCabA(ptr ptr ptr) +@ stdcall ExecuteCabW(ptr ptr ptr) +@ stdcall ExecuteCab(ptr ptr ptr) ExecuteCabA +@ stdcall ExtractFilesA(str str long ptr ptr long) +# stdcall ExtractFilesW(wstr wstr long ptr ptr long) +@ stdcall ExtractFiles(str str long ptr ptr long) ExtractFilesA +@ stdcall FileSaveMarkNotExistA(str str str) +@ stdcall FileSaveMarkNotExistW(wstr wstr wstr) +@ stdcall FileSaveMarkNotExist(str str str) FileSaveMarkNotExistA +@ stdcall FileSaveRestoreA(ptr str str str long) +@ stdcall FileSaveRestoreW(ptr wstr wstr wstr long) +@ stdcall FileSaveRestore(ptr str str str long) FileSaveRestoreA +@ stdcall FileSaveRestoreOnINFA(ptr str str str str str long) +@ stdcall FileSaveRestoreOnINFW(ptr wstr wstr wstr wstr wstr long) +@ stdcall FileSaveRestoreOnINF(ptr str str str str str long) FileSaveRestoreOnINFA +@ stdcall GetVersionFromFileA(str ptr ptr long) +@ stdcall GetVersionFromFileW(wstr ptr ptr long) +@ stdcall GetVersionFromFile(str ptr ptr long) GetVersionFromFileA +@ stdcall GetVersionFromFileExA(str ptr ptr long) +@ stdcall GetVersionFromFileExW(wstr ptr ptr long) +@ stdcall GetVersionFromFileEx(str ptr ptr long) GetVersionFromFileExA +@ stdcall IsNTAdmin(long ptr) +@ stdcall LaunchINFSectionA(ptr ptr str long) +@ stdcall LaunchINFSectionW(ptr ptr wstr long) +@ stdcall LaunchINFSection(ptr ptr str long) LaunchINFSectionA +@ stdcall LaunchINFSectionExA(ptr ptr str long) +@ stdcall LaunchINFSectionExW(ptr ptr wstr long) +@ stdcall LaunchINFSectionEx(ptr ptr str long) LaunchINFSectionExA +@ stdcall NeedReboot(long) +@ stdcall NeedRebootInit() +@ stdcall OpenINFEngineA(str str long ptr ptr) +@ stdcall OpenINFEngineW(wstr wstr long ptr ptr) +@ stdcall OpenINFEngine(str str long ptr ptr) OpenINFEngineA +@ stdcall RebootCheckOnInstallA(long str str long) +@ stdcall RebootCheckOnInstallW(long wstr wstr long) +@ stdcall RebootCheckOnInstall(long str str long) RebootCheckOnInstallA +@ stdcall RegInstallA(ptr str ptr) +@ stdcall RegInstallW(ptr wstr ptr) +@ stdcall RegInstall(ptr str ptr) RegInstallA +@ stdcall RegRestoreAllA(ptr str long) +@ stdcall RegRestoreAllW(ptr wstr long) +@ stdcall RegRestoreAll(ptr str long) RegRestoreAllA +@ stdcall RegSaveRestoreA(ptr str long str str str long) +@ stdcall RegSaveRestoreW(ptr wstr long wstr wstr wstr long) +@ stdcall RegSaveRestore(ptr str long str str str long) RegSaveRestoreA +@ stdcall RegSaveRestoreOnINFA(ptr str str str long long long) +@ stdcall RegSaveRestoreOnINFW(ptr wstr wstr wstr long long long) +@ stdcall RegSaveRestoreOnINF(ptr str str str long long long) RegSaveRestoreOnINFA +@ stdcall RegisterOCX(ptr ptr str long) +@ stdcall RunSetupCommandA(long str str str str ptr long ptr) +@ stdcall RunSetupCommandW(long wstr wstr wstr wstr ptr long ptr) +@ stdcall RunSetupCommand(long str str str str ptr long ptr) RunSetupCommandA +@ stdcall SetPerUserSecValuesA(ptr) +@ stdcall SetPerUserSecValuesW(ptr) +@ stdcall SetPerUserSecValues(ptr) SetPerUserSecValuesA +@ stdcall TranslateInfStringA(str str str str ptr long ptr ptr) +@ stdcall TranslateInfStringW(wstr wstr wstr wstr ptr long ptr ptr) +@ stdcall TranslateInfString(str str str str ptr long ptr ptr) TranslateInfStringA +@ stdcall TranslateInfStringExA(long str str str str long ptr ptr) +@ stdcall TranslateInfStringExW(long wstr wstr wstr wstr long ptr ptr) +@ stdcall TranslateInfStringEx(long str str str str long ptr ptr) TranslateInfStringExA +@ stdcall UserInstStubWrapperA(long long str long) +@ stdcall UserInstStubWrapperW(long long wstr long) +@ stdcall UserInstStubWrapper(long long str long) UserInstStubWrapperA +@ stdcall UserUnInstStubWrapperA(long long str long) +@ stdcall UserUnInstStubWrapperW(long long wstr long) +@ stdcall UserUnInstStubWrapper(long long str long) UserUnInstStubWrapperA diff --git a/reactos/dll/win32/advpack/stubs.c b/reactos/dll/win32/advpack/advpack_private.h similarity index 56% rename from reactos/dll/win32/advpack/stubs.c rename to reactos/dll/win32/advpack/advpack_private.h index 8420d313ad2..323bd2997d2 100644 --- a/reactos/dll/win32/advpack/stubs.c +++ b/reactos/dll/win32/advpack/advpack_private.h @@ -1,6 +1,7 @@ /* - * ReactOS Advpack Stub Library - * Copyright (C) 2004 ReactOS Team + * Advpack private header + * + * Copyright 2006 James Hawkins * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -14,22 +15,17 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include -#include "advpack.h" -#include "wine/debug.h" +#ifndef __ADVPACK_PRIVATE_H +#define __ADVPACK_PRIVATE_H -HRESULT WINAPI -DoInfInstall(DWORD Unknown) -{ - FIXME("DoInfInstall not implemented\n"); +HRESULT do_ocx_reg(HMODULE hocx, BOOL do_reg); +LPWSTR get_parameter(LPWSTR *params, WCHAR separator); +void set_ldids(HINF hInf, LPCWSTR pszInstallSection, LPCWSTR pszWorkingDir); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); +HRESULT launch_exe(LPCWSTR cmd, LPCWSTR dir, HANDLE *phEXE); +HRESULT do_ocx_reg(HMODULE hocx, BOOL do_reg); - return E_FAIL; -} - - -/* EOF */ +#endif /* __ADVPACK_PRIVATE_H */ diff --git a/reactos/dll/win32/advpack/files.c b/reactos/dll/win32/advpack/files.c new file mode 100644 index 00000000000..86cf70f6809 --- /dev/null +++ b/reactos/dll/win32/advpack/files.c @@ -0,0 +1,1073 @@ +/* + * Advpack file functions + * + * Copyright 2006 James Hawkins + * + * 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 "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "winver.h" +#include "winternl.h" +#include "setupapi.h" +#include "advpub.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "advpack_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(advpack); + +/* converts an ansi double null-terminated list to a unicode list */ +static LPWSTR ansi_to_unicode_list(LPCSTR ansi_list) +{ + DWORD len, wlen = 0; + LPWSTR list; + LPCSTR ptr = ansi_list; + + while (*ptr) ptr += lstrlenA(ptr) + 1; + len = ptr + 1 - ansi_list; + wlen = MultiByteToWideChar(CP_ACP, 0, ansi_list, len, NULL, 0); + list = HeapAlloc(GetProcessHeap(), 0, wlen * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, ansi_list, len, list, wlen); + return list; +} + +/*********************************************************************** + * AddDelBackupEntryA (ADVPACK.@) + * + * See AddDelBackupEntryW. + */ +HRESULT WINAPI AddDelBackupEntryA(LPCSTR lpcszFileList, LPCSTR lpcszBackupDir, + LPCSTR lpcszBaseName, DWORD dwFlags) +{ + UNICODE_STRING backupdir, basename; + LPWSTR filelist, backup; + HRESULT res; + + TRACE("(%s, %s, %s, %ld)\n", debugstr_a(lpcszFileList), + debugstr_a(lpcszBackupDir), debugstr_a(lpcszBaseName), dwFlags); + + if (lpcszFileList) + filelist = ansi_to_unicode_list(lpcszFileList); + else + filelist = NULL; + + RtlCreateUnicodeStringFromAsciiz(&backupdir, lpcszBackupDir); + RtlCreateUnicodeStringFromAsciiz(&basename, lpcszBaseName); + + if (lpcszBackupDir) + backup = backupdir.Buffer; + else + backup = NULL; + + res = AddDelBackupEntryW(filelist, backup, basename.Buffer, dwFlags); + + HeapFree(GetProcessHeap(), 0, filelist); + + RtlFreeUnicodeString(&backupdir); + RtlFreeUnicodeString(&basename); + + return res; +} + +/*********************************************************************** + * AddDelBackupEntryW (ADVPACK.@) + * + * Either appends the files in the file list to the backup section of + * the specified INI, or deletes the entries from the INI file. + * + * PARAMS + * lpcszFileList [I] NULL-separated list of filenames. + * lpcszBackupDir [I] Path of the backup directory. + * lpcszBaseName [I] Basename of the INI file. + * dwFlags [I] AADBE_ADD_ENTRY adds the entries in the file list + * to the INI file, while AADBE_DEL_ENTRY removes + * the entries from the INI file. + * + * RETURNS + * S_OK in all cases. + * + * NOTES + * If the INI file does not exist before adding entries to it, the file + * will be created. + * + * If lpcszBackupDir is NULL, the INI file is assumed to exist in + * c:\windows or created there if it does not exist. + */ +HRESULT WINAPI AddDelBackupEntryW(LPCWSTR lpcszFileList, LPCWSTR lpcszBackupDir, + LPCWSTR lpcszBaseName, DWORD dwFlags) +{ + WCHAR szIniPath[MAX_PATH]; + LPWSTR szString = NULL; + + static const WCHAR szBackupEntry[] = { + '-','1',',','0',',','0',',','0',',','0',',','0',',','-','1',0 + }; + + static const WCHAR backslash[] = {'\\',0}; + static const WCHAR ini[] = {'.','i','n','i',0}; + static const WCHAR backup[] = {'b','a','c','k','u','p',0}; + + TRACE("(%s, %s, %s, %ld)\n", debugstr_w(lpcszFileList), + debugstr_w(lpcszBackupDir), debugstr_w(lpcszBaseName), dwFlags); + + if (!lpcszFileList || !*lpcszFileList) + return S_OK; + + if (lpcszBackupDir) + lstrcpyW(szIniPath, lpcszBackupDir); + else + GetWindowsDirectoryW(szIniPath, MAX_PATH); + + lstrcatW(szIniPath, backslash); + lstrcatW(szIniPath, lpcszBaseName); + lstrcatW(szIniPath, ini); + + SetFileAttributesW(szIniPath, FILE_ATTRIBUTE_NORMAL); + + if (dwFlags & AADBE_ADD_ENTRY) + szString = (LPWSTR)szBackupEntry; + else if (dwFlags & AADBE_DEL_ENTRY) + szString = NULL; + + /* add or delete the INI entries */ + while (*lpcszFileList) + { + WritePrivateProfileStringW(backup, lpcszFileList, szString, szIniPath); + lpcszFileList += lstrlenW(lpcszFileList) + 1; + } + + /* hide the INI file */ + SetFileAttributesW(szIniPath, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN); + + return S_OK; +} + +/* FIXME: this is only for the local case, X:\ */ +#define ROOT_LENGTH 3 + +UINT CALLBACK pQuietQueueCallback(PVOID Context, UINT Notification, + UINT_PTR Param1, UINT_PTR Param2) +{ + return 1; +} + +UINT CALLBACK pQueueCallback(PVOID Context, UINT Notification, + UINT_PTR Param1, UINT_PTR Param2) +{ + /* only be verbose for error notifications */ + if (!Notification || + Notification == SPFILENOTIFY_RENAMEERROR || + Notification == SPFILENOTIFY_DELETEERROR || + Notification == SPFILENOTIFY_COPYERROR) + { + return SetupDefaultQueueCallbackW(Context, Notification, + Param1, Param2); + } + + return 1; +} + +/*********************************************************************** + * AdvInstallFileA (ADVPACK.@) + * + * See AdvInstallFileW. + */ +HRESULT WINAPI AdvInstallFileA(HWND hwnd, LPCSTR lpszSourceDir, LPCSTR lpszSourceFile, + LPCSTR lpszDestDir, LPCSTR lpszDestFile, + DWORD dwFlags, DWORD dwReserved) +{ + UNICODE_STRING sourcedir, sourcefile; + UNICODE_STRING destdir, destfile; + HRESULT res; + + TRACE("(%p, %s, %s, %s, %s, %ld, %ld)\n", hwnd, debugstr_a(lpszSourceDir), + debugstr_a(lpszSourceFile), debugstr_a(lpszDestDir), + debugstr_a(lpszDestFile), dwFlags, dwReserved); + + if (!lpszSourceDir || !lpszSourceFile || !lpszDestDir) + return E_INVALIDARG; + + RtlCreateUnicodeStringFromAsciiz(&sourcedir, lpszSourceDir); + RtlCreateUnicodeStringFromAsciiz(&sourcefile, lpszSourceFile); + RtlCreateUnicodeStringFromAsciiz(&destdir, lpszDestDir); + RtlCreateUnicodeStringFromAsciiz(&destfile, lpszDestFile); + + res = AdvInstallFileW(hwnd, sourcedir.Buffer, sourcefile.Buffer, + destdir.Buffer, destfile.Buffer, dwFlags, dwReserved); + + RtlFreeUnicodeString(&sourcedir); + RtlFreeUnicodeString(&sourcefile); + RtlFreeUnicodeString(&destdir); + RtlFreeUnicodeString(&destfile); + + return res; +} + +/*********************************************************************** + * AdvInstallFileW (ADVPACK.@) + * + * Copies a file from the source to a destination. + * + * PARAMS + * hwnd [I] Handle to the window used for messages. + * lpszSourceDir [I] Source directory. + * lpszSourceFile [I] Source filename. + * lpszDestDir [I] Destination directory. + * lpszDestFile [I] Optional destination filename. + * dwFlags [I] See advpub.h. + * dwReserved [I] Reserved. Must be 0. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * NOTES + * If lpszDestFile is NULL, the destination filename is the same as + * lpszSourceFIle. + */ +HRESULT WINAPI AdvInstallFileW(HWND hwnd, LPCWSTR lpszSourceDir, LPCWSTR lpszSourceFile, + LPCWSTR lpszDestDir, LPCWSTR lpszDestFile, + DWORD dwFlags, DWORD dwReserved) +{ + PSP_FILE_CALLBACK_W pFileCallback; + LPWSTR szPath, szDestFilename; + WCHAR szRootPath[ROOT_LENGTH]; + DWORD dwLen, dwLastError; + HSPFILEQ fileQueue; + PVOID pContext; + + TRACE("(%p, %s, %s, %s, %s, %ld, %ld)\n", hwnd, debugstr_w(lpszSourceDir), + debugstr_w(lpszSourceFile), debugstr_w(lpszDestDir), + debugstr_w(lpszDestFile), dwFlags, dwReserved); + + if (!lpszSourceDir || !lpszSourceFile || !lpszDestDir) + return E_INVALIDARG; + + fileQueue = SetupOpenFileQueue(); + if (fileQueue == INVALID_HANDLE_VALUE) + return HRESULT_FROM_WIN32(GetLastError()); + + pContext = NULL; + dwLastError = ERROR_SUCCESS; + + lstrcpynW(szRootPath, lpszSourceDir, ROOT_LENGTH); + szPath = (LPWSTR)lpszSourceDir + ROOT_LENGTH; + + /* use lpszSourceFile as destination filename if lpszDestFile is NULL */ + if (lpszDestFile) + { + dwLen = lstrlenW(lpszDestFile); + szDestFilename = HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR)); + lstrcpyW(szDestFilename, lpszDestFile); + } + else + { + dwLen = lstrlenW(lpszSourceFile); + szDestFilename = HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR)); + lstrcpyW(szDestFilename, lpszSourceFile); + } + + /* add the file copy operation to the setup queue */ + if (!SetupQueueCopyW(fileQueue, szRootPath, szPath, lpszSourceFile, NULL, + NULL, lpszDestDir, szDestFilename, dwFlags)) + { + dwLastError = GetLastError(); + goto done; + } + + pContext = SetupInitDefaultQueueCallbackEx(hwnd, INVALID_HANDLE_VALUE, + 0, 0, NULL); + if (!pContext) + { + dwLastError = GetLastError(); + goto done; + } + + /* don't output anything for AIF_QUIET */ + if (dwFlags & AIF_QUIET) + pFileCallback = pQuietQueueCallback; + else + pFileCallback = pQueueCallback; + + /* perform the file copy */ + if (!SetupCommitFileQueueW(hwnd, fileQueue, pFileCallback, pContext)) + { + dwLastError = GetLastError(); + goto done; + } + +done: + SetupTermDefaultQueueCallback(pContext); + SetupCloseFileQueue(fileQueue); + + HeapFree(GetProcessHeap(), 0, szDestFilename); + + return HRESULT_FROM_WIN32(dwLastError); +} + +static HRESULT DELNODE_recurse_dirtree(LPWSTR fname, DWORD flags) +{ + DWORD fattrs = GetFileAttributesW(fname); + HRESULT ret = E_FAIL; + + static const WCHAR backslash[] = {'\\',0}; + static const WCHAR asterisk[] = {'*',0}; + static const WCHAR dot[] = {'.',0}; + static const WCHAR dotdot[] = {'.','.',0}; + + if (fattrs & FILE_ATTRIBUTE_DIRECTORY) + { + HANDLE hFindFile; + WIN32_FIND_DATAW w32fd; + BOOL done = TRUE; + int fname_len = lstrlenW(fname); + + /* Generate a path with wildcard suitable for iterating */ + if (lstrcmpW(CharPrevW(fname, fname + fname_len), backslash)) + { + lstrcpyW(fname + fname_len, backslash); + ++fname_len; + } + lstrcpyW(fname + fname_len, asterisk); + + if ((hFindFile = FindFirstFileW(fname, &w32fd)) != INVALID_HANDLE_VALUE) + { + /* Iterate through the files in the directory */ + for (done = FALSE; !done; done = !FindNextFileW(hFindFile, &w32fd)) + { + TRACE("%s\n", debugstr_w(w32fd.cFileName)); + if (lstrcmpW(dot, w32fd.cFileName) != 0 && + lstrcmpW(dotdot, w32fd.cFileName) != 0) + { + lstrcpyW(fname + fname_len, w32fd.cFileName); + if (DELNODE_recurse_dirtree(fname, flags) != S_OK) + { + break; /* Failure */ + } + } + } + FindClose(hFindFile); + } + + /* We're done with this directory, so restore the old path without wildcard */ + *(fname + fname_len) = '\0'; + + if (done) + { + TRACE("%s: directory\n", debugstr_w(fname)); + if (SetFileAttributesW(fname, FILE_ATTRIBUTE_NORMAL) && RemoveDirectoryW(fname)) + { + ret = S_OK; + } + } + } + else + { + TRACE("%s: file\n", debugstr_w(fname)); + if (SetFileAttributesW(fname, FILE_ATTRIBUTE_NORMAL) && DeleteFileW(fname)) + { + ret = S_OK; + } + } + + return ret; +} + +/*********************************************************************** + * DelNodeA (ADVPACK.@) + * + * See DelNodeW. + */ +HRESULT WINAPI DelNodeA(LPCSTR pszFileOrDirName, DWORD dwFlags) +{ + UNICODE_STRING fileordirname; + HRESULT res; + + TRACE("(%s, %ld)\n", debugstr_a(pszFileOrDirName), dwFlags); + + RtlCreateUnicodeStringFromAsciiz(&fileordirname, pszFileOrDirName); + + res = DelNodeW(fileordirname.Buffer, dwFlags); + + RtlFreeUnicodeString(&fileordirname); + + return res; +} + +/*********************************************************************** + * DelNodeW (ADVPACK.@) + * + * Deletes a file or directory + * + * PARAMS + * pszFileOrDirName [I] Name of file or directory to delete + * dwFlags [I] Flags; see include/advpub.h + * + * RETURNS + * Success: S_OK + * Failure: E_FAIL + * + * BUGS + * - Ignores flags + * - Native version apparently does a lot of checking to make sure + * we're not trying to delete a system directory etc. + */ +HRESULT WINAPI DelNodeW(LPCWSTR pszFileOrDirName, DWORD dwFlags) +{ + WCHAR fname[MAX_PATH]; + HRESULT ret = E_FAIL; + + TRACE("(%s, %ld)\n", debugstr_w(pszFileOrDirName), dwFlags); + + if (dwFlags) + FIXME("Flags ignored!\n"); + + if (pszFileOrDirName && *pszFileOrDirName) + { + lstrcpyW(fname, pszFileOrDirName); + + /* TODO: Should check for system directory deletion etc. here */ + + ret = DELNODE_recurse_dirtree(fname, dwFlags); + } + + return ret; +} + +/*********************************************************************** + * DelNodeRunDLL32A (ADVPACK.@) + * + * See DelNodeRunDLL32W. + */ +HRESULT WINAPI DelNodeRunDLL32A(HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show) +{ + UNICODE_STRING params; + HRESULT hr; + + TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_a(cmdline), show); + + RtlCreateUnicodeStringFromAsciiz(¶ms, cmdline); + + hr = DelNodeRunDLL32W(hWnd, hInst, params.Buffer, show); + + RtlFreeUnicodeString(¶ms); + + return hr; +} + +/*********************************************************************** + * DelNodeRunDLL32W (ADVPACK.@) + * + * Deletes a file or directory, WinMain style. + * + * PARAMS + * hWnd [I] Handle to the window used for the display. + * hInst [I] Instance of the process. + * cmdline [I] Contains parameters in the order FileOrDirName,Flags. + * show [I] How the window should be shown. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + */ +HRESULT WINAPI DelNodeRunDLL32W(HWND hWnd, HINSTANCE hInst, LPWSTR cmdline, INT show) +{ + LPWSTR szFilename, szFlags; + LPWSTR cmdline_copy, cmdline_ptr; + DWORD dwFlags = 0; + HRESULT res; + + TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_w(cmdline), show); + + cmdline_copy = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR)); + cmdline_ptr = cmdline_copy; + lstrcpyW(cmdline_copy, cmdline); + + /* get the parameters at indexes 0 and 1 respectively */ + szFilename = get_parameter(&cmdline_ptr, ','); + szFlags = get_parameter(&cmdline_ptr, ','); + + if (szFlags) + dwFlags = atolW(szFlags); + + res = DelNodeW(szFilename, dwFlags); + + HeapFree(GetProcessHeap(), 0, cmdline_copy); + + return res; +} + +/* The following defintions were copied from dlls/cabinet/cabinet.h */ + +/* EXTRACTdest flags */ +#define EXTRACT_FILLFILELIST 0x00000001 +#define EXTRACT_EXTRACTFILES 0x00000002 + +struct ExtractFileList { + LPSTR filename; + struct ExtractFileList *next; + BOOL unknown; /* always 1L */ +} ; + +/* the first parameter of the function Extract */ +typedef struct { + long result1; /* 0x000 */ + long unknown1[3]; /* 0x004 */ + struct ExtractFileList *filelist; /* 0x010 */ + long filecount; /* 0x014 */ + DWORD flags; /* 0x018 */ + char directory[0x104]; /* 0x01c */ + char lastfile[0x20c]; /* 0x120 */ +} EXTRACTdest; + +static HRESULT (WINAPI *pExtract)(EXTRACTdest*, LPCSTR); + +/* removes legal characters before and after file list, and + * converts the file list to a NULL-separated list + */ +static LPSTR convert_file_list(LPCSTR FileList, DWORD *dwNumFiles) +{ + DWORD dwLen; + char *first = (char *)FileList; + char *last = (char *)FileList + strlen(FileList) - 1; + LPSTR szConvertedList, temp; + + /* any number of these chars before the list is OK */ + while (first < last && (*first == ' ' || *first == '\t' || *first == ':')) + first++; + + /* any number of these chars after the list is OK */ + while (last > first && (*last == ' ' || *last == '\t' || *last == ':')) + last--; + + if (first == last) + return NULL; + + dwLen = last - first + 3; /* room for double-null termination */ + szConvertedList = HeapAlloc(GetProcessHeap(), 0, dwLen); + lstrcpynA(szConvertedList, first, dwLen - 1); + + szConvertedList[dwLen - 1] = '\0'; + szConvertedList[dwLen] = '\0'; + + /* empty list */ + if (!lstrlenA(szConvertedList)) + return NULL; + + *dwNumFiles = 1; + + /* convert the colons to double-null termination */ + temp = szConvertedList; + while (*temp) + { + if (*temp == ':') + { + *temp = '\0'; + (*dwNumFiles)++; + } + + temp++; + } + + return szConvertedList; +} + +static void free_file_node(struct ExtractFileList *pNode) +{ + HeapFree(GetProcessHeap(), 0, pNode->filename); + HeapFree(GetProcessHeap(), 0, pNode); +} + +/* determines whether szFile is in the NULL-separated szFileList */ +static BOOL file_in_list(LPSTR szFile, LPSTR szFileList) +{ + DWORD dwLen = lstrlenA(szFile); + DWORD dwTestLen; + + while (*szFileList) + { + dwTestLen = lstrlenA(szFileList); + + if (dwTestLen == dwLen) + { + if (!lstrcmpiA(szFile, szFileList)) + return TRUE; + } + + szFileList += dwTestLen + 1; + } + + return FALSE; +} + +/* removes nodes from the linked list that aren't specified in szFileList + * returns the number of files that are in both the linked list and szFileList + */ +static DWORD fill_file_list(EXTRACTdest *extractDest, LPCSTR szCabName, LPSTR szFileList) +{ + DWORD dwNumFound = 0; + struct ExtractFileList *pNode; + struct ExtractFileList *prev = NULL; + + extractDest->flags |= EXTRACT_FILLFILELIST; + if (pExtract(extractDest, szCabName)) + { + extractDest->flags &= ~EXTRACT_FILLFILELIST; + return -1; + } + + pNode = extractDest->filelist; + while (pNode) + { + if (file_in_list(pNode->filename, szFileList)) + { + prev = pNode; + pNode = pNode->next; + dwNumFound++; + } + else if (prev) + { + prev->next = pNode->next; + free_file_node(pNode); + pNode = prev->next; + } + else + { + extractDest->filelist = pNode->next; + free_file_node(pNode); + pNode = extractDest->filelist; + } + } + + extractDest->flags &= ~EXTRACT_FILLFILELIST; + return dwNumFound; +} + +/*********************************************************************** + * ExtractFilesA (ADVPACK.@) + * + * Extracts the specified files from a cab archive into + * a destination directory. + * + * PARAMS + * CabName [I] Filename of the cab archive. + * ExpandDir [I] Destination directory for the extracted files. + * Flags [I] Reserved. + * FileList [I] Optional list of files to extract. See NOTES. + * LReserved [I] Reserved. Must be NULL. + * Reserved [I] Reserved. Must be 0. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * NOTES + * FileList is a colon-separated list of filenames. If FileList is + * non-NULL, only the files in the list will be extracted from the + * cab file, otherwise all files will be extracted. Any number of + * spaces, tabs, or colons can be before or after the list, but + * the list itself must only be separated by colons. + */ +HRESULT WINAPI ExtractFilesA(LPCSTR CabName, LPCSTR ExpandDir, DWORD Flags, + LPCSTR FileList, LPVOID LReserved, DWORD Reserved) +{ + EXTRACTdest extractDest; + HMODULE hCabinet; + HRESULT res = S_OK; + DWORD dwFileCount = 0; + DWORD dwFilesFound = 0; + LPSTR szConvertedList = NULL; + + TRACE("(%s, %s, %ld, %s, %p, %ld)\n", debugstr_a(CabName), debugstr_a(ExpandDir), + Flags, debugstr_a(FileList), LReserved, Reserved); + + if (!CabName || !ExpandDir) + return E_INVALIDARG; + + if (GetFileAttributesA(ExpandDir) == INVALID_FILE_ATTRIBUTES) + return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); + + hCabinet = LoadLibraryA("cabinet.dll"); + if (!hCabinet) + return E_FAIL; + + pExtract = (void *)GetProcAddress(hCabinet, "Extract"); + if (!pExtract) + { + res = E_FAIL; + goto done; + } + + ZeroMemory(&extractDest, sizeof(EXTRACTdest)); + lstrcpyA(extractDest.directory, ExpandDir); + + if (FileList) + { + szConvertedList = convert_file_list(FileList, &dwFileCount); + if (!szConvertedList || dwFileCount == -1) + { + res = E_FAIL; + goto done; + } + + dwFilesFound = fill_file_list(&extractDest, CabName, szConvertedList); + if (dwFilesFound != dwFileCount) + { + res = E_FAIL; + goto done; + } + } + else + extractDest.flags |= EXTRACT_FILLFILELIST; + + extractDest.flags |= EXTRACT_EXTRACTFILES; + res = pExtract(&extractDest, CabName); + +done: + FreeLibrary(hCabinet); + HeapFree(GetProcessHeap(), 0, szConvertedList); + + return res; +} + +/*********************************************************************** + * FileSaveMarkNotExistA (ADVPACK.@) + * + * See FileSaveMarkNotExistW. + */ +HRESULT WINAPI FileSaveMarkNotExistA(LPSTR pszFileList, LPSTR pszDir, LPSTR pszBaseName) +{ + TRACE("(%s, %s, %s)\n", debugstr_a(pszFileList), + debugstr_a(pszDir), debugstr_a(pszBaseName)); + + return AddDelBackupEntryA(pszFileList, pszDir, pszBaseName, AADBE_DEL_ENTRY); +} + +/*********************************************************************** + * FileSaveMarkNotExistW (ADVPACK.@) + * + * Marks the files in the file list as not existing so they won't be + * backed up during a save. + * + * PARAMS + * pszFileList [I] NULL-separated list of filenames. + * pszDir [I] Path of the backup directory. + * pszBaseName [I] Basename of the INI file. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + */ +HRESULT WINAPI FileSaveMarkNotExistW(LPWSTR pszFileList, LPWSTR pszDir, LPWSTR pszBaseName) +{ + TRACE("(%s, %s, %s)\n", debugstr_w(pszFileList), + debugstr_w(pszDir), debugstr_w(pszBaseName)); + + return AddDelBackupEntryW(pszFileList, pszDir, pszBaseName, AADBE_DEL_ENTRY); +} + +/*********************************************************************** + * FileSaveRestoreA (ADVPACK.@) + * + * See FileSaveRestoreW. + */ +HRESULT WINAPI FileSaveRestoreA(HWND hDlg, LPSTR pszFileList, LPSTR pszDir, + LPSTR pszBaseName, DWORD dwFlags) +{ + UNICODE_STRING filelist, dir, basename; + HRESULT hr; + + TRACE("(%p, %s, %s, %s, %ld)\n", hDlg, debugstr_a(pszFileList), + debugstr_a(pszDir), debugstr_a(pszBaseName), dwFlags); + + RtlCreateUnicodeStringFromAsciiz(&filelist, pszFileList); + RtlCreateUnicodeStringFromAsciiz(&dir, pszDir); + RtlCreateUnicodeStringFromAsciiz(&basename, pszBaseName); + + hr = FileSaveRestoreW(hDlg, filelist.Buffer, dir.Buffer, + basename.Buffer, dwFlags); + + RtlFreeUnicodeString(&filelist); + RtlFreeUnicodeString(&dir); + RtlFreeUnicodeString(&basename); + + return hr; +} + +/*********************************************************************** + * FileSaveRestoreW (ADVPACK.@) + * + * Saves or restores the files in the specified file list. + * + * PARAMS + * hDlg [I] Handle to the dialog used for the display. + * pszFileList [I] NULL-separated list of filenames. + * pszDir [I] Path of the backup directory. + * pszBaseName [I] Basename of the backup files. + * dwFlags [I] See advpub.h. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * NOTES + * If pszFileList is NULL on restore, all files will be restored. + * + * BUGS + * Unimplemented. + */ +HRESULT WINAPI FileSaveRestoreW(HWND hDlg, LPWSTR pszFileList, LPWSTR pszDir, + LPWSTR pszBaseName, DWORD dwFlags) +{ + FIXME("(%p, %s, %s, %s, %ld) stub\n", hDlg, debugstr_w(pszFileList), + debugstr_w(pszDir), debugstr_w(pszBaseName), dwFlags); + + return E_FAIL; +} + +/*********************************************************************** + * FileSaveRestoreOnINFA (ADVPACK.@) + * + * See FileSaveRestoreOnINFW. + */ +HRESULT WINAPI FileSaveRestoreOnINFA(HWND hWnd, LPCSTR pszTitle, LPCSTR pszINF, + LPCSTR pszSection, LPCSTR pszBackupDir, + LPCSTR pszBaseBackupFile, DWORD dwFlags) +{ + UNICODE_STRING title, inf, section; + UNICODE_STRING backupdir, backupfile; + HRESULT hr; + + TRACE("(%p, %s, %s, %s, %s, %s, %ld)\n", hWnd, debugstr_a(pszTitle), + debugstr_a(pszINF), debugstr_a(pszSection), debugstr_a(pszBackupDir), + debugstr_a(pszBaseBackupFile), dwFlags); + + RtlCreateUnicodeStringFromAsciiz(&title, pszTitle); + RtlCreateUnicodeStringFromAsciiz(&inf, pszINF); + RtlCreateUnicodeStringFromAsciiz(§ion, pszSection); + RtlCreateUnicodeStringFromAsciiz(&backupdir, pszBackupDir); + RtlCreateUnicodeStringFromAsciiz(&backupfile, pszBaseBackupFile); + + hr = FileSaveRestoreOnINFW(hWnd, title.Buffer, inf.Buffer, section.Buffer, + backupdir.Buffer, backupfile.Buffer, dwFlags); + + RtlFreeUnicodeString(&title); + RtlFreeUnicodeString(&inf); + RtlFreeUnicodeString(§ion); + RtlFreeUnicodeString(&backupdir); + RtlFreeUnicodeString(&backupfile); + + return hr; +} + +/*********************************************************************** + * FileSaveRestoreOnINFW (ADVPACK.@) + * + * + * PARAMS + * hWnd [I] Handle to the window used for the display. + * pszTitle [I] Title of the window. + * pszINF [I] Fully-qualified INF filename. + * pszSection [I] GenInstall INF section name. + * pszBackupDir [I] Directory to store the backup file. + * pszBaseBackupFile [I] Basename of the backup files. + * dwFlags [I] See advpub.h + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * NOTES + * If pszSection is NULL, the default section will be used. + * + * BUGS + * Unimplemented. + */ +HRESULT WINAPI FileSaveRestoreOnINFW(HWND hWnd, LPCWSTR pszTitle, LPCWSTR pszINF, + LPCWSTR pszSection, LPCWSTR pszBackupDir, + LPCWSTR pszBaseBackupFile, DWORD dwFlags) +{ + FIXME("(%p, %s, %s, %s, %s, %s, %ld): stub\n", hWnd, debugstr_w(pszTitle), + debugstr_w(pszINF), debugstr_w(pszSection), debugstr_w(pszBackupDir), + debugstr_w(pszBaseBackupFile), dwFlags); + + return E_FAIL; +} + +/*********************************************************************** + * GetVersionFromFileA (ADVPACK.@) + * + * See GetVersionFromFileExW. + */ +HRESULT WINAPI GetVersionFromFileA(LPCSTR Filename, LPDWORD MajorVer, + LPDWORD MinorVer, BOOL Version ) +{ + TRACE("(%s, %p, %p, %d)\n", debugstr_a(Filename), MajorVer, MinorVer, Version); + return GetVersionFromFileExA(Filename, MajorVer, MinorVer, Version); +} + +/*********************************************************************** + * GetVersionFromFileW (ADVPACK.@) + * + * See GetVersionFromFileExW. + */ +HRESULT WINAPI GetVersionFromFileW(LPCWSTR Filename, LPDWORD MajorVer, + LPDWORD MinorVer, BOOL Version ) +{ + TRACE("(%s, %p, %p, %d)\n", debugstr_w(Filename), MajorVer, MinorVer, Version); + return GetVersionFromFileExW(Filename, MajorVer, MinorVer, Version); +} + +/* data for GetVersionFromFileEx */ +typedef struct tagLANGANDCODEPAGE +{ + WORD wLanguage; + WORD wCodePage; +} LANGANDCODEPAGE; + +/*********************************************************************** + * GetVersionFromFileExA (ADVPACK.@) + * + * See GetVersionFromFileExW. + */ +HRESULT WINAPI GetVersionFromFileExA(LPCSTR lpszFilename, LPDWORD pdwMSVer, + LPDWORD pdwLSVer, BOOL bVersion ) +{ + UNICODE_STRING filename; + HRESULT res; + + TRACE("(%s, %p, %p, %d)\n", debugstr_a(lpszFilename), + pdwMSVer, pdwLSVer, bVersion); + + RtlCreateUnicodeStringFromAsciiz(&filename, lpszFilename); + + res = GetVersionFromFileExW(filename.Buffer, pdwMSVer, pdwLSVer, bVersion); + + RtlFreeUnicodeString(&filename); + + return res; +} + +/*********************************************************************** + * GetVersionFromFileExW (ADVPACK.@) + * + * Gets the files version or language information. + * + * PARAMS + * lpszFilename [I] The file to get the info from. + * pdwMSVer [O] Major version. + * pdwLSVer [O] Minor version. + * bVersion [I] Whether to retrieve version or language info. + * + * RETURNS + * Always returns S_OK. + * + * NOTES + * If bVersion is TRUE, version information is retrieved, else + * pdwMSVer gets the language ID and pdwLSVer gets the codepage ID. + */ +HRESULT WINAPI GetVersionFromFileExW(LPCWSTR lpszFilename, LPDWORD pdwMSVer, + LPDWORD pdwLSVer, BOOL bVersion ) +{ + VS_FIXEDFILEINFO *pFixedVersionInfo; + LANGANDCODEPAGE *pLangAndCodePage; + DWORD dwHandle, dwInfoSize; + WCHAR szWinDir[MAX_PATH]; + WCHAR szFile[MAX_PATH]; + LPVOID pVersionInfo = NULL; + BOOL bFileCopied = FALSE; + UINT uValueLen; + + static WCHAR backslash[] = {'\\',0}; + static WCHAR translation[] = { + '\\','V','a','r','F','i','l','e','I','n','f','o', + '\\','T','r','a','n','s','l','a','t','i','o','n',0 + }; + + TRACE("(%s, %p, %p, %d)\n", debugstr_w(lpszFilename), + pdwMSVer, pdwLSVer, bVersion); + + *pdwLSVer = 0; + *pdwMSVer = 0; + + lstrcpynW(szFile, lpszFilename, MAX_PATH); + + dwInfoSize = GetFileVersionInfoSizeW(szFile, &dwHandle); + if (!dwInfoSize) + { + /* check that the file exists */ + if (GetFileAttributesW(szFile) == INVALID_FILE_ATTRIBUTES) + return S_OK; + + /* file exists, but won't be found by GetFileVersionInfoSize, + * so copy it to the temp dir where it will be found. + */ + GetWindowsDirectoryW(szWinDir, MAX_PATH); + GetTempFileNameW(szWinDir, NULL, 0, szFile); + CopyFileW(lpszFilename, szFile, FALSE); + bFileCopied = TRUE; + + dwInfoSize = GetFileVersionInfoSizeW(szFile, &dwHandle); + if (!dwInfoSize) + goto done; + } + + pVersionInfo = HeapAlloc(GetProcessHeap(), 0, dwInfoSize); + if (!pVersionInfo) + goto done; + + if (!GetFileVersionInfoW(szFile, dwHandle, dwInfoSize, pVersionInfo)) + goto done; + + if (bVersion) + { + if (!VerQueryValueW(pVersionInfo, backslash, + (LPVOID *)&pFixedVersionInfo, &uValueLen)) + goto done; + + if (!uValueLen) + goto done; + + *pdwMSVer = pFixedVersionInfo->dwFileVersionMS; + *pdwLSVer = pFixedVersionInfo->dwFileVersionLS; + } + else + { + if (!VerQueryValueW(pVersionInfo, translation, + (LPVOID *)&pLangAndCodePage, &uValueLen)) + goto done; + + if (!uValueLen) + goto done; + + *pdwMSVer = pLangAndCodePage->wLanguage; + *pdwLSVer = pLangAndCodePage->wCodePage; + } + +done: + HeapFree(GetProcessHeap(), 0, pVersionInfo); + + if (bFileCopied) + DeleteFileW(szFile); + + return S_OK; +} diff --git a/reactos/dll/win32/advpack/install.c b/reactos/dll/win32/advpack/install.c new file mode 100644 index 00000000000..2398b7587cb --- /dev/null +++ b/reactos/dll/win32/advpack/install.c @@ -0,0 +1,951 @@ +/* + * Advpack install functions + * + * Copyright 2006 James Hawkins + * + * 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 "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "winver.h" +#include "winternl.h" +#include "winnls.h" +#include "setupapi.h" +#include "advpub.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "advpack_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(advpack); + +#define SPAPI_ERROR 0xE0000000L +#define SPAPI_PREFIX 0x800F0000L +#define SPAPI_MASK 0xFFFFL +#define HRESULT_FROM_SPAPI(x) ((x & SPAPI_MASK) | SPAPI_PREFIX) + +#define ADV_HRESULT(x) ((x & SPAPI_ERROR) ? HRESULT_FROM_SPAPI(x) : HRESULT_FROM_WIN32(x)) + +#define ADV_SUCCESS 0 +#define ADV_FAILURE 1 + +/* contains information about a specific install instance */ +typedef struct _ADVInfo +{ + HINF hinf; + LPWSTR inf_filename; + LPWSTR install_sec; + LPWSTR working_dir; + DWORD flags; + BOOL need_reboot; +} ADVInfo; + +typedef HRESULT (*iterate_fields_func)(HINF hinf, PCWSTR field, void *arg); + +/* Advanced INF commands */ +static const WCHAR CheckAdminRights[] = { + 'C','h','e','c','k','A','d','m','i','n','R','i','g','h','t','s',0 +}; +static const WCHAR DelDirs[] = {'D','e','l','D','i','r','s',0}; +static const WCHAR PerUserInstall[] = {'P','e','r','U','s','e','r','I','n','s','t','a','l','l',0}; +static const WCHAR RegisterOCXs[] = {'R','e','g','i','s','t','e','r','O','C','X','s',0}; +static const WCHAR RunPreSetupCommands[] = { + 'R','u','n','P','r','e','S','e','t','u','p','C','o','m','m','a','n','d','s',0 +}; +static const WCHAR RunPostSetupCommands[] = { + 'R','u','n','P','o','s','t','S','e','t','u','p','C','o','m','m','a','n','d','s',0 +}; + +/* Advanced INF callbacks */ +static HRESULT del_dirs_callback(HINF hinf, PCWSTR field, void *arg) +{ + INFCONTEXT context; + HRESULT hr = S_OK; + DWORD size; + + BOOL ok = SetupFindFirstLineW(hinf, field, NULL, &context); + + for (; ok; ok = SetupFindNextLine(&context, &context)) + { + WCHAR directory[MAX_INF_STRING_LENGTH]; + + if (!SetupGetLineTextW(&context, NULL, NULL, NULL, directory, + MAX_INF_STRING_LENGTH, &size)) + continue; + + if (DelNodeW(directory, ADN_DEL_IF_EMPTY)) + hr = E_FAIL; + } + + return hr; +} + +static HRESULT per_user_install_callback(HINF hinf, PCWSTR field, void *arg) +{ + PERUSERSECTIONW per_user; + INFCONTEXT context; + DWORD size; + + static const WCHAR disp_name[] = {'D','i','s','p','l','a','y','N','a','m','e',0}; + static const WCHAR version[] = {'V','e','r','s','i','o','n',0}; + static const WCHAR is_installed[] = {'I','s','I','n','s','t','a','l','l','e','d',0}; + static const WCHAR comp_id[] = {'C','o','m','p','o','n','e','n','t','I','D',0}; + static const WCHAR guid[] = {'G','U','I','D',0}; + static const WCHAR locale[] = {'L','o','c','a','l','e',0}; + static const WCHAR stub_path[] = {'S','t','u','b','P','a','t','h',0}; + + per_user.bRollback = FALSE; + per_user.dwIsInstalled = 0; + + SetupGetLineTextW(NULL, hinf, field, disp_name, per_user.szDispName, + sizeof(per_user.szDispName) / sizeof(WCHAR), &size); + + SetupGetLineTextW(NULL, hinf, field, version, per_user.szVersion, + sizeof(per_user.szVersion) / sizeof(WCHAR), &size); + + if (SetupFindFirstLineW(hinf, field, is_installed, &context)) + { + SetupGetIntField(&context, 1, (PINT)&per_user.dwIsInstalled); + } + + SetupGetLineTextW(NULL, hinf, field, comp_id, per_user.szCompID, + sizeof(per_user.szCompID) / sizeof(WCHAR), &size); + + SetupGetLineTextW(NULL, hinf, field, guid, per_user.szGUID, + sizeof(per_user.szGUID) / sizeof(WCHAR), &size); + + SetupGetLineTextW(NULL, hinf, field, locale, per_user.szLocale, + sizeof(per_user.szLocale) / sizeof(WCHAR), &size); + + SetupGetLineTextW(NULL, hinf, field, stub_path, per_user.szStub, + sizeof(per_user.szStub) / sizeof(WCHAR), &size); + + return SetPerUserSecValuesW(&per_user); +} + +static HRESULT register_ocxs_callback(HINF hinf, PCWSTR field, void *arg) +{ + HMODULE hm; + INFCONTEXT context; + HRESULT hr = S_OK; + + BOOL ok = SetupFindFirstLineW(hinf, field, NULL, &context); + + for (; ok; ok = SetupFindNextLine(&context, &context)) + { + WCHAR buffer[MAX_INF_STRING_LENGTH]; + + /* get OCX filename */ + if (!SetupGetStringFieldW(&context, 1, buffer, + sizeof(buffer) / sizeof(WCHAR), NULL)) + continue; + + hm = LoadLibraryExW(buffer, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!hm) + continue; + + if (do_ocx_reg(hm, TRUE)) + hr = E_FAIL; + + FreeLibrary(hm); + } + + return hr; +} + +static HRESULT run_setup_commands_callback(HINF hinf, PCWSTR field, void *arg) +{ + ADVInfo *info = (ADVInfo *)arg; + INFCONTEXT context; + HRESULT hr = S_OK; + DWORD size; + + BOOL ok = SetupFindFirstLineW(hinf, field, NULL, &context); + + for (; ok; ok = SetupFindNextLine(&context, &context)) + { + WCHAR buffer[MAX_INF_STRING_LENGTH]; + + if (!SetupGetLineTextW(&context, NULL, NULL, NULL, buffer, + MAX_INF_STRING_LENGTH, &size)) + continue; + + if (launch_exe(buffer, info->working_dir, NULL)) + hr = E_FAIL; + } + + return hr; +} + +/* sequentially returns pointers to parameters in a parameter list + * returns NULL if the parameter is empty, e.g. one,,three */ +LPWSTR get_parameter(LPWSTR *params, WCHAR separator) +{ + LPWSTR token = *params; + + if (!*params) + return NULL; + + *params = strchrW(*params, separator); + if (*params) + *(*params)++ = '\0'; + + if (!*token) + return NULL; + + return token; +} + +static BOOL is_full_path(LPWSTR path) +{ + const int MIN_PATH_LEN = 3; + + if (!path || lstrlenW(path) < MIN_PATH_LEN) + return FALSE; + + if (path[1] == ':' || (path[0] == '\\' && path[1] == '\\')) + return TRUE; + + return FALSE; +} + +/* retrieves the contents of a field, dynamically growing the buffer if necessary */ +static WCHAR *get_field_string(INFCONTEXT *context, DWORD index, WCHAR *buffer, + WCHAR *static_buffer, DWORD *size) +{ + DWORD required; + + if (SetupGetStringFieldW(context, index, buffer, *size, &required)) return buffer; + + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + /* now grow the buffer */ + if (buffer != static_buffer) HeapFree(GetProcessHeap(), 0, buffer); + if (!(buffer = HeapAlloc(GetProcessHeap(), 0, required*sizeof(WCHAR)))) return NULL; + *size = required; + if (SetupGetStringFieldW(context, index, buffer, *size, &required)) return buffer; + } + + if (buffer != static_buffer) HeapFree(GetProcessHeap(), 0, buffer); + return NULL; +} + +/* iterates over all fields of a certain key of a certain section */ +static HRESULT iterate_section_fields(HINF hinf, PCWSTR section, PCWSTR key, + iterate_fields_func callback, void *arg) +{ + WCHAR static_buffer[200]; + WCHAR *buffer = static_buffer; + DWORD size = sizeof(static_buffer) / sizeof(WCHAR); + INFCONTEXT context; + HRESULT hr = E_FAIL; + + BOOL ok = SetupFindFirstLineW(hinf, section, key, &context); + while (ok) + { + UINT i, count = SetupGetFieldCount(&context); + + for (i = 1; i <= count; i++) + { + if (!(buffer = get_field_string(&context, i, buffer, static_buffer, &size))) + goto done; + + if ((hr = callback(hinf, buffer, arg)) != S_OK) + goto done; + } + + ok = SetupFindNextMatchLineW(&context, key, &context); + } + + hr = S_OK; + + done: + if (buffer != static_buffer) HeapFree(GetProcessHeap(), 0, buffer); + return hr; +} + +static HRESULT check_admin_rights(ADVInfo *info) +{ + INT check; + INFCONTEXT context; + HRESULT hr = S_OK; + + if (!SetupFindFirstLineW(info->hinf, info->install_sec, + CheckAdminRights, &context)) + return S_OK; + + if (!SetupGetIntField(&context, 1, &check)) + return S_OK; + + if (check == 1) + hr = IsNTAdmin(0, NULL) ? S_OK : E_FAIL; + + return hr; +} + +/* performs a setupapi-level install of the INF file */ +static HRESULT spapi_install(ADVInfo *info) +{ + BOOL ret; + HRESULT res; + PVOID context; + + context = SetupInitDefaultQueueCallbackEx(NULL, INVALID_HANDLE_VALUE, 0, 0, NULL); + if (!context) + return ADV_HRESULT(GetLastError()); + + ret = SetupInstallFromInfSectionW(NULL, info->hinf, info->install_sec, + SPINST_FILES, NULL, info->working_dir, + SP_COPY_NEWER, SetupDefaultQueueCallbackW, + context, NULL, NULL); + if (!ret) + { + res = ADV_HRESULT(GetLastError()); + SetupTermDefaultQueueCallback(context); + + return res; + } + + SetupTermDefaultQueueCallback(context); + + ret = SetupInstallFromInfSectionW(NULL, info->hinf, info->install_sec, + SPINST_INIFILES | SPINST_REGISTRY, + HKEY_LOCAL_MACHINE, NULL, 0, + NULL, NULL, NULL, NULL); + if (!ret) + return ADV_HRESULT(GetLastError()); + + return S_OK; +} + +/* processes the Advanced INF commands */ +static HRESULT adv_install(ADVInfo *info) +{ + HRESULT hr; + + hr = check_admin_rights(info); + if (hr != S_OK) + return hr; + + hr = iterate_section_fields(info->hinf, info->install_sec, RunPreSetupCommands, + run_setup_commands_callback, info); + if (hr != S_OK) + return hr; + + hr = iterate_section_fields(info->hinf, info->install_sec, + RegisterOCXs, register_ocxs_callback, NULL); + if (hr != S_OK) + return hr; + + hr = iterate_section_fields(info->hinf, info->install_sec, + PerUserInstall, per_user_install_callback, info); + if (hr != S_OK) + return hr; + + hr = iterate_section_fields(info->hinf, info->install_sec, RunPostSetupCommands, + run_setup_commands_callback, info); + if (hr != S_OK) + return hr; + + hr = iterate_section_fields(info->hinf, info->install_sec, + DelDirs, del_dirs_callback, info); + if (hr != S_OK) + return hr; + + return hr; +} + +/* loads the INF file and performs checks on it */ +HRESULT install_init(LPCWSTR inf_filename, LPCWSTR install_sec, + LPCWSTR working_dir, DWORD flags, ADVInfo *info) +{ + DWORD len; + LPCWSTR ptr; + + static const WCHAR default_install[] = { + 'D','e','f','a','u','l','t','I','n','s','t','a','l','l',0 + }; + + len = lstrlenW(inf_filename); + + info->inf_filename = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + if (!info->inf_filename) + return E_OUTOFMEMORY; + + lstrcpyW(info->inf_filename, inf_filename); + + /* FIXME: determine the proper platform to install (NTx86, etc) */ + if (!install_sec || !*install_sec) + { + len = sizeof(default_install) - 1; + ptr = default_install; + } + else + { + len = lstrlenW(install_sec); + ptr = install_sec; + } + + info->install_sec = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + if (!info->install_sec) + return E_OUTOFMEMORY; + + lstrcpyW(info->install_sec, ptr); + + /* FIXME: need to get the real working directory */ + if (!working_dir || !*working_dir) + { + ptr = strrchrW(info->inf_filename, '\\'); + len = ptr - info->inf_filename + 1; + ptr = info->inf_filename; + } + else + { + len = lstrlenW(working_dir) + 1; + ptr = working_dir; + } + + info->working_dir = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!info->working_dir) + return E_OUTOFMEMORY; + + lstrcpynW(info->working_dir, ptr, len); + + info->hinf = SetupOpenInfFileW(info->inf_filename, NULL, INF_STYLE_WIN4, NULL); + if (info->hinf == INVALID_HANDLE_VALUE) + return ADV_HRESULT(GetLastError()); + + set_ldids(info->hinf, info->install_sec, info->working_dir); + + /* FIXME: check that the INF is advanced */ + + info->flags = flags; + info->need_reboot = FALSE; + + return S_OK; +} + +/* release the install instance information */ +void install_release(ADVInfo *info) +{ + if (info->hinf && info->hinf != INVALID_HANDLE_VALUE) + SetupCloseInfFile(info->hinf); + + HeapFree(GetProcessHeap(), 0, info->inf_filename); + HeapFree(GetProcessHeap(), 0, info->install_sec); + HeapFree(GetProcessHeap(), 0, info->working_dir); +} + +/* this structure very closely resembles parameters of RunSetupCommand() */ +typedef struct +{ + HWND hwnd; + LPCSTR title; + LPCSTR inf_name; + LPCSTR dir; + LPCSTR section_name; +} SETUPCOMMAND_PARAMS; + +typedef struct +{ + HWND hwnd; + LPCWSTR title; + LPCWSTR inf_name; + LPCWSTR dir; + LPCWSTR section_name; +} SETUPCOMMAND_PARAMSW; + +/* internal: see DoInfInstall */ +static HRESULT DoInfInstallW(const SETUPCOMMAND_PARAMSW *setup) +{ + ADVInfo info; + HRESULT hr; + + TRACE("(%p)\n", setup); + + ZeroMemory(&info, sizeof(ADVInfo)); + + hr = install_init(setup->inf_name, setup->section_name, setup->dir, 0, &info); + if (hr != S_OK) + goto done; + + hr = spapi_install(&info); + if (hr != S_OK) + goto done; + + hr = adv_install(&info); + +done: + install_release(&info); + + return S_OK; +} + +/*********************************************************************** + * DoInfInstall (ADVPACK.@) + * + * Install an INF section. + * + * PARAMS + * setup [I] Structure containing install information. + * + * RETURNS + * S_OK Everything OK + * HRESULT_FROM_WIN32(GetLastError()) Some other error + */ +HRESULT WINAPI DoInfInstall(const SETUPCOMMAND_PARAMS *setup) +{ + UNICODE_STRING title, inf, section, dir; + SETUPCOMMAND_PARAMSW params; + HRESULT hr; + + if (!setup) + return E_INVALIDARG; + + RtlCreateUnicodeStringFromAsciiz(&title, setup->title); + RtlCreateUnicodeStringFromAsciiz(&inf, setup->inf_name); + RtlCreateUnicodeStringFromAsciiz(§ion, setup->section_name); + RtlCreateUnicodeStringFromAsciiz(&dir, setup->dir); + + params.title = title.Buffer; + params.inf_name = inf.Buffer; + params.section_name = section.Buffer; + params.dir = dir.Buffer; + params.hwnd = setup->hwnd; + + hr = DoInfInstallW(¶ms); + + RtlFreeUnicodeString(&title); + RtlFreeUnicodeString(&inf); + RtlFreeUnicodeString(§ion); + RtlFreeUnicodeString(&dir); + + return hr; +} + +/*********************************************************************** + * ExecuteCabA (ADVPACK.@) + * + * See ExecuteCabW. + */ +HRESULT WINAPI ExecuteCabA(HWND hwnd, CABINFOA* pCab, LPVOID pReserved) +{ + UNICODE_STRING cab, inf, section; + CABINFOW cabinfo; + HRESULT hr; + + TRACE("(%p, %p, %p)\n", hwnd, pCab, pReserved); + + if (!pCab) + return E_INVALIDARG; + + if (pCab->pszCab) + { + RtlCreateUnicodeStringFromAsciiz(&cab, pCab->pszCab); + cabinfo.pszCab = cab.Buffer; + } + else + cabinfo.pszCab = NULL; + + RtlCreateUnicodeStringFromAsciiz(&inf, pCab->pszInf); + RtlCreateUnicodeStringFromAsciiz(§ion, pCab->pszSection); + + MultiByteToWideChar(CP_ACP, 0, pCab->szSrcPath, -1, cabinfo.szSrcPath, + sizeof(cabinfo.szSrcPath) / sizeof(WCHAR)); + + cabinfo.pszInf = inf.Buffer; + cabinfo.pszSection = section.Buffer; + cabinfo.dwFlags = pCab->dwFlags; + + hr = ExecuteCabW(hwnd, &cabinfo, pReserved); + + if (pCab->pszCab) + RtlFreeUnicodeString(&cab); + + RtlFreeUnicodeString(&inf); + RtlFreeUnicodeString(§ion); + + return hr; +} + +/*********************************************************************** + * ExecuteCabW (ADVPACK.@) + * + * Installs the INF file extracted from a specified cabinet file. + * + * PARAMS + * hwnd [I] Handle to the window used for the display. + * pCab [I] Information about the cabinet file. + * pReserved [I] Reserved. Must be NULL. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + */ +HRESULT WINAPI ExecuteCabW(HWND hwnd, CABINFOW* pCab, LPVOID pReserved) +{ + ADVInfo info; + HRESULT hr; + + TRACE("(%p, %p, %p)\n", hwnd, pCab, pReserved); + + ZeroMemory(&info, sizeof(ADVInfo)); + + if (pCab->pszCab && *pCab->pszCab) + FIXME("Cab archive not extracted!\n"); + + hr = install_init(pCab->pszInf, pCab->pszSection, pCab->szSrcPath, pCab->dwFlags, &info); + if (hr != S_OK) + goto done; + + hr = spapi_install(&info); + if (hr != S_OK) + goto done; + + hr = adv_install(&info); + +done: + install_release(&info); + + return hr; +} + +/*********************************************************************** + * LaunchINFSectionA (ADVPACK.@) + * + * See LaunchINFSectionW. + */ +INT WINAPI LaunchINFSectionA(HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show) +{ + UNICODE_STRING cmd; + HRESULT hr; + + TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_a(cmdline), show); + + if (!cmdline) + return ADV_FAILURE; + + RtlCreateUnicodeStringFromAsciiz(&cmd, cmdline); + + hr = LaunchINFSectionW(hWnd, hInst, cmd.Buffer, show); + + RtlFreeUnicodeString(&cmd); + + return hr; +} + +/*********************************************************************** + * LaunchINFSectionW (ADVPACK.@) + * + * Installs an INF section without BACKUP/ROLLBACK capabilities. + * + * PARAMS + * hWnd [I] Handle to parent window, NULL for desktop. + * hInst [I] Instance of the process. + * cmdline [I] Contains parameters in the order INF,section,flags,reboot. + * show [I] How the window should be shown. + * + * RETURNS + * Success: ADV_SUCCESS. + * Failure: ADV_FAILURE. + * + * NOTES + * INF - Filename of the INF to launch. + * section - INF section to install. + * flags - see advpub.h. + * reboot - smart reboot behavior + * 'A' Always reboot. + * 'I' Reboot if needed (default). + * 'N' No reboot. + */ +INT WINAPI LaunchINFSectionW(HWND hWnd, HINSTANCE hInst, LPWSTR cmdline, INT show) +{ + ADVInfo info; + LPWSTR cmdline_copy, cmdline_ptr; + LPWSTR inf_filename, install_sec; + LPWSTR str_flags; + DWORD flags = 0; + HRESULT hr = S_OK; + + TRACE("(%p, %p, %s, %d)\n", hWnd, hInst, debugstr_w(cmdline), show); + + if (!cmdline) + return ADV_FAILURE; + + cmdline_copy = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR)); + cmdline_ptr = cmdline_copy; + lstrcpyW(cmdline_copy, cmdline); + + inf_filename = get_parameter(&cmdline_ptr, ','); + install_sec = get_parameter(&cmdline_ptr, ','); + + str_flags = get_parameter(&cmdline_ptr, ','); + if (str_flags) + flags = atolW(str_flags); + + ZeroMemory(&info, sizeof(ADVInfo)); + + hr = install_init(inf_filename, install_sec, NULL, flags, &info); + if (hr != S_OK) + goto done; + + hr = spapi_install(&info); + if (hr != S_OK) + goto done; + + hr = adv_install(&info); + +done: + install_release(&info); + HeapFree(GetProcessHeap(), 0, cmdline_copy); + + return SUCCEEDED(hr) ? ADV_SUCCESS : ADV_FAILURE; +} + +/*********************************************************************** + * LaunchINFSectionExA (ADVPACK.@) + * + * See LaunchINFSectionExW. + */ +HRESULT WINAPI LaunchINFSectionExA(HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show) +{ + UNICODE_STRING cmd; + HRESULT hr; + + TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_a(cmdline), show); + + if (!cmdline) + return ADV_FAILURE; + + RtlCreateUnicodeStringFromAsciiz(&cmd, cmdline); + + hr = LaunchINFSectionExW(hWnd, hInst, cmd.Buffer, show); + + RtlFreeUnicodeString(&cmd); + + return hr; +} + +/*********************************************************************** + * LaunchINFSectionExW (ADVPACK.@) + * + * Installs an INF section with BACKUP/ROLLBACK capabilities. + * + * PARAMS + * hWnd [I] Handle to parent window, NULL for desktop. + * hInst [I] Instance of the process. + * cmdline [I] Contains parameters in the order INF,section,CAB,flags,reboot. + * show [I] How the window should be shown. + * + * RETURNS + * Success: ADV_SUCCESS. + * Failure: ADV_FAILURE. + * + * NOTES + * INF - Filename of the INF to launch. + * section - INF section to install. + * flags - see advpub.h. + * reboot - smart reboot behavior + * 'A' Always reboot. + * 'I' Reboot if needed (default). + * 'N' No reboot. + * + * BUGS + * Doesn't handle the reboot flag. + */ +HRESULT WINAPI LaunchINFSectionExW(HWND hWnd, HINSTANCE hInst, LPWSTR cmdline, INT show) +{ + LPWSTR cmdline_copy, cmdline_ptr; + LPWSTR flags, ptr; + CABINFOW cabinfo; + HRESULT hr = S_OK; + + TRACE("(%p, %p, %s, %d)\n", hWnd, hInst, debugstr_w(cmdline), show); + + if (!cmdline) + return ADV_FAILURE; + + cmdline_copy = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR)); + cmdline_ptr = cmdline_copy; + lstrcpyW(cmdline_copy, cmdline); + + cabinfo.pszInf = get_parameter(&cmdline_ptr, ','); + cabinfo.pszSection = get_parameter(&cmdline_ptr, ','); + cabinfo.pszCab = get_parameter(&cmdline_ptr, ','); + *cabinfo.szSrcPath = '\0'; + + flags = get_parameter(&cmdline_ptr, ','); + if (flags) + cabinfo.dwFlags = atolW(flags); + + /* get the source path from the cab filename */ + if (cabinfo.pszCab && *cabinfo.pszCab) + { + if (!is_full_path(cabinfo.pszCab)) + goto done; + + lstrcpyW(cabinfo.szSrcPath, cabinfo.pszCab); + ptr = strrchrW(cabinfo.szSrcPath, '\\'); + *(++ptr) = '\0'; + } + + hr = ExecuteCabW(hWnd, &cabinfo, NULL); + +done: + HeapFree(GetProcessHeap(), 0, cmdline_copy); + + return SUCCEEDED(hr) ? ADV_SUCCESS : ADV_FAILURE; +} + +HRESULT launch_exe(LPCWSTR cmd, LPCWSTR dir, HANDLE *phEXE) +{ + STARTUPINFOW si; + PROCESS_INFORMATION pi; + + if (phEXE) *phEXE = NULL; + + ZeroMemory(&pi, sizeof(pi)); + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + + if (!CreateProcessW(NULL, (LPWSTR)cmd, NULL, NULL, FALSE, + CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_PROCESS_GROUP, + NULL, dir, &si, &pi)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + + CloseHandle(pi.hThread); + + if (phEXE) + { + *phEXE = pi.hProcess; + return S_ASYNCHRONOUS; + } + + /* wait for the child process to finish */ + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + + return S_OK; +} + +/*********************************************************************** + * RunSetupCommandA (ADVPACK.@) + * + * See RunSetupCommandW. + */ +HRESULT WINAPI RunSetupCommandA(HWND hWnd, LPCSTR szCmdName, + LPCSTR szInfSection, LPCSTR szDir, + LPCSTR lpszTitle, HANDLE *phEXE, + DWORD dwFlags, LPVOID pvReserved) +{ + UNICODE_STRING cmdname, infsec; + UNICODE_STRING dir, title; + HRESULT hr; + + TRACE("(%p, %s, %s, %s, %s, %p, %ld, %p)\n", + hWnd, debugstr_a(szCmdName), debugstr_a(szInfSection), + debugstr_a(szDir), debugstr_a(lpszTitle), + phEXE, dwFlags, pvReserved); + + if (!szCmdName || !szDir) + return E_INVALIDARG; + + RtlCreateUnicodeStringFromAsciiz(&cmdname, szCmdName); + RtlCreateUnicodeStringFromAsciiz(&infsec, szInfSection); + RtlCreateUnicodeStringFromAsciiz(&dir, szDir); + RtlCreateUnicodeStringFromAsciiz(&title, lpszTitle); + + hr = RunSetupCommandW(hWnd, cmdname.Buffer, infsec.Buffer, dir.Buffer, + title.Buffer, phEXE, dwFlags, pvReserved); + + RtlFreeUnicodeString(&cmdname); + RtlFreeUnicodeString(&infsec); + RtlFreeUnicodeString(&dir); + RtlFreeUnicodeString(&title); + + return hr; +} + +/*********************************************************************** + * RunSetupCommandW (ADVPACK.@) + * + * Executes an install section in an INF file or a program. + * + * PARAMS + * hWnd [I] Handle to parent window, NULL for quiet mode + * szCmdName [I] Inf or EXE filename to execute + * szInfSection [I] Inf section to install, NULL for DefaultInstall + * szDir [I] Path to extracted files + * szTitle [I] Title of all dialogs + * phEXE [O] Handle of EXE to wait for + * dwFlags [I] Flags; see include/advpub.h + * pvReserved [I] Reserved + * + * RETURNS + * S_OK Everything OK + * S_ASYNCHRONOUS OK, required to wait on phEXE + * ERROR_SUCCESS_REBOOT_REQUIRED Reboot required + * E_INVALIDARG Invalid argument given + * HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION) + * Not supported on this Windows version + * E_UNEXPECTED Unexpected error + * HRESULT_FROM_WIN32(GetLastError()) Some other error + */ +HRESULT WINAPI RunSetupCommandW(HWND hWnd, LPCWSTR szCmdName, + LPCWSTR szInfSection, LPCWSTR szDir, + LPCWSTR lpszTitle, HANDLE *phEXE, + DWORD dwFlags, LPVOID pvReserved) +{ + ADVInfo info; + HRESULT hr; + + TRACE("(%p, %s, %s, %s, %s, %p, %ld, %p)\n", + hWnd, debugstr_w(szCmdName), debugstr_w(szInfSection), + debugstr_w(szDir), debugstr_w(lpszTitle), + phEXE, dwFlags, pvReserved); + + if (dwFlags & RSC_FLAG_UPDHLPDLLS) + FIXME("Unhandled flag: RSC_FLAG_UPDHLPDLLS\n"); + + if (!szCmdName || !szDir) + return E_INVALIDARG; + + if (!(dwFlags & RSC_FLAG_INF)) + return launch_exe(szCmdName, szDir, phEXE); + + ZeroMemory(&info, sizeof(ADVInfo)); + + hr = install_init(szCmdName, szInfSection, szDir, dwFlags, &info); + if (hr != S_OK) + goto done; + + hr = spapi_install(&info); + if (hr != S_OK) + goto done; + + hr = adv_install(&info); + +done: + install_release(&info); + + return hr; +} diff --git a/reactos/dll/win32/advpack/reg.c b/reactos/dll/win32/advpack/reg.c new file mode 100644 index 00000000000..64e3ca65e32 --- /dev/null +++ b/reactos/dll/win32/advpack/reg.c @@ -0,0 +1,439 @@ +/* + * Advpack registry functions + * + * Copyright 2004 Huw D M Davies + * + * 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 "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winerror.h" +#include "winuser.h" +#include "winternl.h" +#include "setupapi.h" +#include "advpub.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(advpack); + +static const WCHAR REGINST[] = {'R','E','G','I','N','S','T',0}; +static const WCHAR Strings[] = {'S','t','r','i','n','g','s',0}; +static const WCHAR MOD_PATH[] = {'_','M','O','D','_','P','A','T','H',0}; +static const WCHAR SYS_MOD_PATH[] = {'_','S','Y','S','_','M','O','D','_','P','A','T','H',0}; +static const WCHAR SystemRoot[] = {'S','y','s','t','e','m','R','o','o','t',0}; +static const WCHAR escaped_SystemRoot[] = {'%','S','y','s','t','e','m','R','o','o','t','%',0}; +static const WCHAR quote[] = {'\"',0}; + +static BOOL get_temp_ini_path(LPWSTR name) +{ + WCHAR tmp_dir[MAX_PATH]; + WCHAR prefix[] = {'a','v','p',0}; + + if(!GetTempPathW(sizeof(tmp_dir)/sizeof(WCHAR), tmp_dir)) + return FALSE; + + if(!GetTempFileNameW(tmp_dir, prefix, 0, name)) + return FALSE; + return TRUE; +} + +static BOOL create_tmp_ini_file(HMODULE hm, WCHAR *ini_file) +{ + HRSRC hrsrc; + HGLOBAL hmem = NULL; + DWORD rsrc_size, bytes_written; + VOID *rsrc_data; + HANDLE hf = INVALID_HANDLE_VALUE; + + if(!get_temp_ini_path(ini_file)) { + ERR("Can't get temp ini file path\n"); + goto error; + } + + if(!(hrsrc = FindResourceW(hm, REGINST, REGINST))) { + ERR("Can't find REGINST resource\n"); + goto error; + } + + rsrc_size = SizeofResource(hm, hrsrc); + hmem = LoadResource(hm, hrsrc); + rsrc_data = LockResource(hmem); + + if(!rsrc_data || !rsrc_size) { + ERR("Can't load REGINST resource\n"); + goto error; + } + + if((hf = CreateFileW(ini_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { + ERR("Unable to create temp ini file\n"); + goto error; + } + if(!WriteFile(hf, rsrc_data, rsrc_size, &bytes_written, NULL) || rsrc_size != bytes_written) { + ERR("Write failed\n"); + goto error; + } + FreeResource(hmem); + CloseHandle(hf); + return TRUE; +error: + if(hmem) FreeResource(hmem); + if(hf != INVALID_HANDLE_VALUE) CloseHandle(hf); + return FALSE; +} + +static void strentry_atow(STRENTRYA *aentry, STRENTRYW *wentry) +{ + DWORD name_len, val_len; + + name_len = MultiByteToWideChar(CP_ACP, 0, aentry->pszName, -1, NULL, 0); + val_len = MultiByteToWideChar(CP_ACP, 0, aentry->pszValue, -1, NULL, 0); + + wentry->pszName = HeapAlloc(GetProcessHeap(), 0, name_len * sizeof(WCHAR)); + wentry->pszValue = HeapAlloc(GetProcessHeap(), 0, val_len * sizeof(WCHAR)); + + MultiByteToWideChar(CP_ACP, 0, aentry->pszName, -1, wentry->pszName, name_len); + MultiByteToWideChar(CP_ACP, 0, aentry->pszValue, -1, wentry->pszValue, val_len); +} + +static STRTABLEW *strtable_atow(const STRTABLEA *atable) +{ + STRTABLEW *wtable; + DWORD j; + + wtable = HeapAlloc(GetProcessHeap(), 0, sizeof(STRTABLEW)); + wtable->pse = HeapAlloc(GetProcessHeap(), 0, atable->cEntries * sizeof(STRENTRYW)); + wtable->cEntries = atable->cEntries; + + for (j = 0; j < wtable->cEntries; j++) + strentry_atow(&atable->pse[j], &wtable->pse[j]); + + return wtable; +} + +static void free_strtable(STRTABLEW *wtable) +{ + DWORD j; + + for (j = 0; j < wtable->cEntries; j++) + { + HeapFree(GetProcessHeap(), 0, wtable->pse[j].pszName); + HeapFree(GetProcessHeap(), 0, wtable->pse[j].pszValue); + } + + HeapFree(GetProcessHeap(), 0, wtable->pse); + HeapFree(GetProcessHeap(), 0, wtable); +} + +/*********************************************************************** + * RegInstallA (advpack.@) + * + * See RegInstallW. + */ +HRESULT WINAPI RegInstallA(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable) +{ + UNICODE_STRING section; + STRTABLEW *wtable; + HRESULT hr; + + TRACE("(%p, %s, %p)\n", hm, debugstr_a(pszSection), pstTable); + + if (pstTable) + wtable = strtable_atow(pstTable); + else + wtable = NULL; + + RtlCreateUnicodeStringFromAsciiz(§ion, pszSection); + + hr = RegInstallW(hm, section.Buffer, wtable); + + if (pstTable) + free_strtable(wtable); + + RtlFreeUnicodeString(§ion); + + return hr; +} + +static HRESULT write_predefined_strings(HMODULE hm, LPWSTR ini_path) +{ + WCHAR mod_path[MAX_PATH + 2]; + WCHAR sys_mod_path[MAX_PATH + 2]; + WCHAR sys_root[MAX_PATH]; + + *mod_path = '\"'; + if (!GetModuleFileNameW(hm, mod_path + 1, sizeof(mod_path) / sizeof(WCHAR) - 2)) + return E_FAIL; + + lstrcatW(mod_path, quote); + WritePrivateProfileStringW(Strings, MOD_PATH, mod_path, ini_path); + + *sys_root = '\0'; + GetEnvironmentVariableW(SystemRoot, sys_root, sizeof(sys_root) / sizeof(WCHAR)); + + if(!strncmpiW(sys_root, mod_path + 1, strlenW(sys_root))) + { + *sys_mod_path = '\"'; + strcpyW(sys_mod_path + 1, escaped_SystemRoot); + strcatW(sys_mod_path, mod_path + 1 + strlenW(sys_root)); + } + else + { + FIXME("SYS_MOD_PATH needs more work\n"); + strcpyW(sys_mod_path, mod_path); + } + + WritePrivateProfileStringW(Strings, SYS_MOD_PATH, sys_mod_path, ini_path); + + return S_OK; +} + +/*********************************************************************** + * RegInstallW (advpack.@) + * + * Loads an INF from a string resource, adds entries to the string + * substitution table, and executes the INF. + * + * PARAMS + * hm [I] Module that contains the REGINST resouce. + * pszSection [I] The INF section to execute. + * pstTable [I] Table of string substitutions. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + */ +HRESULT WINAPI RegInstallW(HMODULE hm, LPCWSTR pszSection, const STRTABLEW* pstTable) +{ + int i; + CABINFOW cabinfo; + WCHAR tmp_ini_path[MAX_PATH]; + HRESULT hr = E_FAIL; + + TRACE("(%p, %s, %p)\n", hm, debugstr_w(pszSection), pstTable); + + if(!create_tmp_ini_file(hm, tmp_ini_path)) + return E_FAIL; + + if (write_predefined_strings(hm, tmp_ini_path)) + goto done; + + /* Write the additional string table */ + if (pstTable) + { + for(i = 0; i < pstTable->cEntries; i++) + { + WCHAR tmp_value[MAX_PATH + 2]; + + tmp_value[0] = '\"'; + lstrcpyW(tmp_value + 1, pstTable->pse[i].pszValue); + lstrcatW(tmp_value, quote); + + WritePrivateProfileStringW(Strings, pstTable->pse[i].pszName, tmp_value, tmp_ini_path); + } + } + + /* flush cache */ + WritePrivateProfileStringW(NULL, NULL, NULL, tmp_ini_path); + + /* FIXME: read AdvOptions val for dwFlags */ + ZeroMemory(&cabinfo, sizeof(CABINFOW)); + cabinfo.pszInf = tmp_ini_path; + cabinfo.pszSection = (LPWSTR)pszSection; + cabinfo.dwFlags = 0; + + hr = ExecuteCabW(NULL, &cabinfo, NULL); + +done: + + DeleteFileW(tmp_ini_path); + + return hr; +} + +/*********************************************************************** + * RegRestoreAllA (advpack.@) + * + * See RegRestoreAllW. + */ +HRESULT WINAPI RegRestoreAllA(HWND hWnd, LPSTR pszTitleString, HKEY hkBackupKey) +{ + UNICODE_STRING title; + HRESULT hr; + + TRACE("(%p, %s, %p)\n", hWnd, debugstr_a(pszTitleString), hkBackupKey); + + RtlCreateUnicodeStringFromAsciiz(&title, pszTitleString); + + hr = RegRestoreAllW(hWnd, title.Buffer, hkBackupKey); + + RtlFreeUnicodeString(&title); + + return hr; +} + +/*********************************************************************** + * RegRestoreAllW (advpack.@) + * + * Restores all saved registry entries. + * + * PARAMS + * hWnd [I] Handle to the window used for the display. + * pszTitleString [I] Title of the window. + * hkBackupKey [I] Handle to the backup key. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * BUGS + * Unimplemented. + */ +HRESULT WINAPI RegRestoreAllW(HWND hWnd, LPWSTR pszTitleString, HKEY hkBackupKey) +{ + FIXME("(%p, %s, %p) stub\n", hWnd, debugstr_w(pszTitleString), hkBackupKey); + + return E_FAIL; +} + +/*********************************************************************** + * RegSaveRestoreA (advpack.@) + * + * See RegSaveRestoreW. + */ +HRESULT WINAPI RegSaveRestoreA(HWND hWnd, LPCSTR pszTitleString, HKEY hkBackupKey, + LPCSTR pcszRootKey, LPCSTR pcszSubKey, + LPCSTR pcszValueName, DWORD dwFlags) +{ + UNICODE_STRING title, root, subkey, value; + HRESULT hr; + + TRACE("(%p, %s, %p, %s, %s, %s, %ld)\n", hWnd, debugstr_a(pszTitleString), + hkBackupKey, debugstr_a(pcszRootKey), debugstr_a(pcszSubKey), + debugstr_a(pcszValueName), dwFlags); + + RtlCreateUnicodeStringFromAsciiz(&title, pszTitleString); + RtlCreateUnicodeStringFromAsciiz(&root, pcszRootKey); + RtlCreateUnicodeStringFromAsciiz(&subkey, pcszSubKey); + RtlCreateUnicodeStringFromAsciiz(&value, pcszValueName); + + hr = RegSaveRestoreW(hWnd, title.Buffer, hkBackupKey, root.Buffer, + subkey.Buffer, value.Buffer, dwFlags); + + RtlFreeUnicodeString(&title); + RtlFreeUnicodeString(&root); + RtlFreeUnicodeString(&subkey); + RtlFreeUnicodeString(&value); + + return hr; +} + +/*********************************************************************** + * RegSaveRestoreW (advpack.@) + * + * Saves or restores the specified registry value. + * + * PARAMS + * hWnd [I] Handle to the window used for the display. + * pszTitleString [I] Title of the window. + * hkBackupKey [I] Key used to store the backup data. + * pcszRootKey [I] Root key of the registry value + * pcszSubKey [I] Sub key of the registry value. + * pcszValueName [I] Value to save or restore. + * dwFlags [I] See advpub.h. + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * BUGS + * Unimplemented. + */ +HRESULT WINAPI RegSaveRestoreW(HWND hWnd, LPCWSTR pszTitleString, HKEY hkBackupKey, + LPCWSTR pcszRootKey, LPCWSTR pcszSubKey, + LPCWSTR pcszValueName, DWORD dwFlags) +{ + FIXME("(%p, %s, %p, %s, %s, %s, %ld): stub\n", hWnd, debugstr_w(pszTitleString), + hkBackupKey, debugstr_w(pcszRootKey), debugstr_w(pcszSubKey), + debugstr_w(pcszValueName), dwFlags); + + return E_FAIL; +} + +/*********************************************************************** + * RegSaveRestoreOnINFA (advpack.@) + * + * See RegSaveRestoreOnINFW. + */ +HRESULT WINAPI RegSaveRestoreOnINFA(HWND hWnd, LPCSTR pszTitle, LPCSTR pszINF, + LPCSTR pszSection, HKEY hHKLMBackKey, + HKEY hHKCUBackKey, DWORD dwFlags) +{ + UNICODE_STRING title, inf, section; + HRESULT hr; + + TRACE("(%p, %s, %s, %s, %p, %p, %ld)\n", hWnd, debugstr_a(pszTitle), + debugstr_a(pszINF), debugstr_a(pszSection), + hHKLMBackKey, hHKCUBackKey, dwFlags); + + RtlCreateUnicodeStringFromAsciiz(&title, pszTitle); + RtlCreateUnicodeStringFromAsciiz(&inf, pszINF); + RtlCreateUnicodeStringFromAsciiz(§ion, pszSection); + + hr = RegSaveRestoreOnINFW(hWnd, title.Buffer, inf.Buffer, section.Buffer, + hHKLMBackKey, hHKCUBackKey, dwFlags); + + RtlFreeUnicodeString(&title); + RtlFreeUnicodeString(&inf); + RtlFreeUnicodeString(§ion); + + return hr; +} + +/*********************************************************************** + * RegSaveRestoreOnINFW (advpack.@) + * + * Saves or restores the specified INF Reg section. + * + * PARAMS + * hWnd [I] Handle to the window used for the display. + * pszTitle [I] Title of the window. + * pszINF [I] Filename of the INF. + * pszSection [I] Section to save or restore. + * hHKLMBackKey [I] Opened key in HKLM to store data. + * hHKCUBackKey [I] Opened key in HKCU to store data. + * dwFlags [I] See advpub.h + * + * RETURNS + * Success: S_OK. + * Failure: E_FAIL. + * + * BUGS + * Unimplemented. + */ +HRESULT WINAPI RegSaveRestoreOnINFW(HWND hWnd, LPCWSTR pszTitle, LPCWSTR pszINF, + LPCWSTR pszSection, HKEY hHKLMBackKey, + HKEY hHKCUBackKey, DWORD dwFlags) +{ + FIXME("(%p, %s, %s, %s, %p, %p, %ld): stub\n", hWnd, debugstr_w(pszTitle), + debugstr_w(pszINF), debugstr_w(pszSection), + hHKLMBackKey, hHKCUBackKey, dwFlags); + + return E_FAIL; +} diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 3aecccaec90..9a8c89e2087 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -37,6 +37,7 @@ reactos/tools/widl # Synced to Wine-20060729 The following libraries are shared with Wine. +reactos/dll/win32/advpack # Autosync reactos/dll/win32/avifil32 # Autosync reactos/dll/win32/cabinet # Autosync reactos/dll/win32/comctl32 # Autosync