mirror of
https://github.com/reactos/wine.git
synced 2024-11-29 14:40:56 +00:00
Added support for the RegisterDlls section (partly based on a patch by
Chris Morgan).
This commit is contained in:
parent
67e2d6cb4d
commit
cb283489ad
@ -51,6 +51,14 @@ struct registry_callback_info
|
||||
BOOL delete;
|
||||
};
|
||||
|
||||
/* info passed to callback functions dealing with registering dlls */
|
||||
struct register_dll_info
|
||||
{
|
||||
PSP_FILE_CALLBACK_W callback;
|
||||
PVOID callback_context;
|
||||
BOOL unregister;
|
||||
};
|
||||
|
||||
typedef BOOL (*iterate_fields_func)( HINF hinf, PCWSTR field, void *arg );
|
||||
|
||||
/* Unicode constants */
|
||||
@ -63,6 +71,7 @@ static const WCHAR AddReg[] = {'A','d','d','R','e','g',0};
|
||||
static const WCHAR DelReg[] = {'D','e','l','R','e','g',0};
|
||||
static const WCHAR UpdateInis[] = {'U','p','d','a','t','e','I','n','i','s',0};
|
||||
static const WCHAR UpdateIniFields[] = {'U','p','d','a','t','e','I','n','i','F','i','e','l','d','s',0};
|
||||
static const WCHAR RegisterDlls[] = {'R','e','g','i','s','t','e','r','D','l','l','s',0};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
@ -420,6 +429,153 @@ static BOOL registry_callback( HINF hinf, PCWSTR field, void *arg )
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* do_register_dll
|
||||
*
|
||||
* Register or unregister a dll.
|
||||
*/
|
||||
static BOOL do_register_dll( const struct register_dll_info *info, const WCHAR *path,
|
||||
INT flags, INT timeout, const WCHAR *args )
|
||||
{
|
||||
HMODULE module;
|
||||
HRESULT res;
|
||||
SP_REGISTER_CONTROL_STATUSW status;
|
||||
|
||||
status.cbSize = sizeof(status);
|
||||
status.FileName = path;
|
||||
status.FailureCode = SPREG_SUCCESS;
|
||||
status.Win32Error = ERROR_SUCCESS;
|
||||
|
||||
if (info->callback)
|
||||
{
|
||||
switch(info->callback( info->callback_context, SPFILENOTIFY_STARTREGISTRATION,
|
||||
(UINT_PTR)&status, !info->unregister ))
|
||||
{
|
||||
case FILEOP_ABORT:
|
||||
SetLastError( ERROR_OPERATION_ABORTED );
|
||||
return FALSE;
|
||||
case FILEOP_SKIP:
|
||||
return TRUE;
|
||||
case FILEOP_DOIT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(module = LoadLibraryExW( path, 0, LOAD_WITH_ALTERED_SEARCH_PATH )))
|
||||
{
|
||||
WARN( "could not load %s\n", debugstr_w(path) );
|
||||
status.FailureCode = SPREG_LOADLIBRARY;
|
||||
status.Win32Error = GetLastError();
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (flags & FLG_REGSVR_DLLREGISTER)
|
||||
{
|
||||
const char *entry_point = info->unregister ? "DllUnregisterServer" : "DllRegisterServer";
|
||||
HRESULT (WINAPI *func)(void) = (void *)GetProcAddress( module, entry_point );
|
||||
|
||||
if (!func)
|
||||
{
|
||||
status.FailureCode = SPREG_GETPROCADDR;
|
||||
status.Win32Error = GetLastError();
|
||||
goto done;
|
||||
}
|
||||
|
||||
TRACE( "calling %s in %s\n", entry_point, debugstr_w(path) );
|
||||
res = func();
|
||||
|
||||
if (FAILED(res))
|
||||
{
|
||||
WARN( "calling %s in %s returned error %lx\n", entry_point, debugstr_w(path), res );
|
||||
status.FailureCode = SPREG_REGSVR;
|
||||
status.Win32Error = res;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FLG_REGSVR_DLLINSTALL)
|
||||
{
|
||||
HRESULT (WINAPI *func)(BOOL,LPCWSTR) = (void *)GetProcAddress( module, "DllInstall" );
|
||||
|
||||
if (!func)
|
||||
{
|
||||
status.FailureCode = SPREG_GETPROCADDR;
|
||||
status.Win32Error = GetLastError();
|
||||
goto done;
|
||||
}
|
||||
|
||||
TRACE( "calling DllInstall(%d,%s) in %s\n",
|
||||
!info->unregister, debugstr_w(args), debugstr_w(path) );
|
||||
res = func( !info->unregister, args );
|
||||
|
||||
if (FAILED(res))
|
||||
{
|
||||
WARN( "calling DllInstall in %s returned error %lx\n", debugstr_w(path), res );
|
||||
status.FailureCode = SPREG_REGSVR;
|
||||
status.Win32Error = res;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (module) FreeLibrary( module );
|
||||
if (info->callback) info->callback( info->callback_context, SPFILENOTIFY_ENDREGISTRATION,
|
||||
(UINT_PTR)&status, !info->unregister );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* register_dlls_callback
|
||||
*
|
||||
* Called once for each RegisterDlls entry in a given section.
|
||||
*/
|
||||
static BOOL register_dlls_callback( HINF hinf, PCWSTR field, void *arg )
|
||||
{
|
||||
struct register_dll_info *info = arg;
|
||||
INFCONTEXT context;
|
||||
BOOL ret = TRUE;
|
||||
BOOL ok = SetupFindFirstLineW( hinf, field, NULL, &context );
|
||||
|
||||
for (; ok; ok = SetupFindNextLine( &context, &context ))
|
||||
{
|
||||
WCHAR *path, *args, *p;
|
||||
WCHAR buffer[MAX_INF_STRING_LENGTH];
|
||||
INT flags, timeout;
|
||||
|
||||
/* get directory */
|
||||
if (!(path = PARSER_get_dest_dir( &context ))) continue;
|
||||
|
||||
/* get dll name */
|
||||
if (!SetupGetStringFieldW( &context, 3, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
|
||||
goto done;
|
||||
if (!(p = HeapReAlloc( GetProcessHeap(), 0, path,
|
||||
(strlenW(path) + strlenW(buffer) + 2) * sizeof(WCHAR) ))) goto done;
|
||||
path = p;
|
||||
p += strlenW(p);
|
||||
if (p == path || p[-1] != '\\') *p++ = '\\';
|
||||
strcpyW( p, buffer );
|
||||
|
||||
/* get flags */
|
||||
if (!SetupGetIntField( &context, 4, &flags )) flags = 0;
|
||||
|
||||
/* get timeout */
|
||||
if (!SetupGetIntField( &context, 5, &timeout )) timeout = 60;
|
||||
|
||||
/* get command line */
|
||||
args = NULL;
|
||||
if (SetupGetStringFieldW( &context, 6, buffer, sizeof(buffer)/sizeof(WCHAR), NULL ))
|
||||
args = buffer;
|
||||
|
||||
ret = do_register_dll( info, path, flags, timeout, args );
|
||||
|
||||
done:
|
||||
HeapFree( GetProcessHeap(), 0, path );
|
||||
if (!ret) break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL update_ini_callback( HINF hinf, PCWSTR field, void *arg )
|
||||
{
|
||||
INFCONTEXT context;
|
||||
@ -512,7 +668,8 @@ static BOOL iterate_section_fields( HINF hinf, PCWSTR section, PCWSTR key,
|
||||
goto done;
|
||||
if (!callback( hinf, buffer, arg ))
|
||||
{
|
||||
ERR("callback failed for %s %s\n", debugstr_w(section), debugstr_w(buffer) );
|
||||
WARN("callback failed for %s %s err %ld\n",
|
||||
debugstr_w(section), debugstr_w(buffer), GetLastError() );
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@ -654,6 +811,38 @@ BOOL WINAPI SetupInstallFromInfSectionW( HWND owner, HINF hinf, PCWSTR section,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (flags & SPINST_REGSVR)
|
||||
{
|
||||
struct register_dll_info info;
|
||||
|
||||
info.unregister = FALSE;
|
||||
if (flags & SPINST_REGISTERCALLBACKAWARE)
|
||||
{
|
||||
info.callback = callback;
|
||||
info.callback_context = context;
|
||||
}
|
||||
else info.callback = NULL;
|
||||
|
||||
if (!iterate_section_fields( hinf, section, RegisterDlls, register_dlls_callback, &info ))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (flags & SPINST_UNREGSVR)
|
||||
{
|
||||
struct register_dll_info info;
|
||||
|
||||
info.unregister = TRUE;
|
||||
if (flags & SPINST_REGISTERCALLBACKAWARE)
|
||||
{
|
||||
info.callback = callback;
|
||||
info.callback_context = context;
|
||||
}
|
||||
else info.callback = NULL;
|
||||
|
||||
if (!iterate_section_fields( hinf, section, RegisterDlls, register_dlls_callback, &info ))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (flags & SPINST_REGISTRY)
|
||||
{
|
||||
struct registry_callback_info info;
|
||||
@ -666,7 +855,8 @@ BOOL WINAPI SetupInstallFromInfSectionW( HWND owner, HINF hinf, PCWSTR section,
|
||||
if (!iterate_section_fields( hinf, section, AddReg, registry_callback, &info ))
|
||||
return FALSE;
|
||||
}
|
||||
if (flags & (SPINST_BITREG|SPINST_REGSVR|SPINST_UNREGSVR|SPINST_PROFILEITEMS|SPINST_COPYINF))
|
||||
|
||||
if (flags & (SPINST_BITREG|SPINST_PROFILEITEMS|SPINST_COPYINF))
|
||||
FIXME( "unsupported flags %x\n", flags );
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "winternl.h"
|
||||
#include "winerror.h"
|
||||
#include "setupapi.h"
|
||||
#include "setupapi_private.h"
|
||||
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/debug.h"
|
||||
@ -999,6 +1000,32 @@ const WCHAR *PARSER_get_src_root( HINF hinf )
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PARSER_get_dest_dir
|
||||
*
|
||||
* retrieve a destination dir of the form "dirid,relative_path" in the given entry.
|
||||
* returned buffer must be freed by caller.
|
||||
*/
|
||||
WCHAR *PARSER_get_dest_dir( INFCONTEXT *context )
|
||||
{
|
||||
const WCHAR *dir;
|
||||
WCHAR *ptr, *ret;
|
||||
INT dirid;
|
||||
DWORD len1, len2;
|
||||
|
||||
if (!SetupGetIntField( context, 1, &dirid )) return NULL;
|
||||
if (!(dir = DIRID_get_string( context->Inf, dirid ))) return NULL;
|
||||
len1 = strlenW(dir) + 1;
|
||||
if (!SetupGetStringFieldW( context, 2, NULL, 0, &len2 )) len2 = 0;
|
||||
if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len1+len2) * sizeof(WCHAR) ))) return NULL;
|
||||
strcpyW( ret, dir );
|
||||
ptr = ret + strlenW(ret);
|
||||
if (len2 && ptr > ret && ptr[-1] != '\\') *ptr++ = '\\';
|
||||
if (!SetupGetStringFieldW( context, 2, ptr, len2, NULL )) *ptr = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SetupOpenInfFileA (SETUPAPI.@)
|
||||
*/
|
||||
|
@ -246,6 +246,22 @@ UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
|
||||
MultiByteToWideChar( CP_ACP, 0, buffer, -1, (WCHAR *)old_param2, MAX_PATH );
|
||||
break;
|
||||
|
||||
case SPFILENOTIFY_STARTREGISTRATION:
|
||||
case SPFILENOTIFY_ENDREGISTRATION:
|
||||
{
|
||||
SP_REGISTER_CONTROL_STATUSW *statusW = (SP_REGISTER_CONTROL_STATUSW *)param1;
|
||||
SP_REGISTER_CONTROL_STATUSA statusA;
|
||||
|
||||
statusA.cbSize = sizeof(statusA);
|
||||
statusA.FileName = strdupWtoA( statusW->FileName );
|
||||
statusA.Win32Error = statusW->Win32Error;
|
||||
statusA.FailureCode = statusW->FailureCode;
|
||||
ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification,
|
||||
(UINT_PTR)&statusA, param2 );
|
||||
HeapFree( GetProcessHeap(), 0, (LPSTR)statusA.FileName );
|
||||
}
|
||||
break;
|
||||
|
||||
case SPFILENOTIFY_NEEDMEDIA:
|
||||
case SPFILENOTIFY_QUEUESCAN:
|
||||
FIXME("mapping for %d not implemented\n",notification);
|
||||
@ -257,7 +273,7 @@ UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT notification,
|
||||
ret = callback_ctx->orig_handler( callback_ctx->orig_context, notification, param1, param2 );
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -348,25 +364,11 @@ static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section )
|
||||
{
|
||||
static const WCHAR Dest[] = {'D','e','s','t','i','n','a','t','i','o','n','D','i','r','s',0};
|
||||
static const WCHAR Def[] = {'D','e','f','a','u','l','t','D','e','s','t','D','i','r',0};
|
||||
|
||||
const WCHAR *dir;
|
||||
WCHAR *ptr, *ret;
|
||||
INFCONTEXT context;
|
||||
INT dirid;
|
||||
DWORD len1, len2;
|
||||
|
||||
if (!SetupFindFirstLineW( hinf, Dest, section, &context ) &&
|
||||
!SetupFindFirstLineW( hinf, Dest, Def, &context )) return NULL;
|
||||
if (!SetupGetIntField( &context, 1, &dirid )) return NULL;
|
||||
if (!(dir = DIRID_get_string( hinf, dirid ))) return NULL;
|
||||
len1 = strlenW(dir) + 1;
|
||||
if (!SetupGetStringFieldW( &context, 2, NULL, 0, &len2 )) len2 = 0;
|
||||
if (!(ret = HeapAlloc( GetProcessHeap(), 0, (len1+len2) * sizeof(WCHAR) ))) return NULL;
|
||||
strcpyW( ret, dir );
|
||||
ptr = ret + strlenW(ret);
|
||||
if (len2 && ptr > ret && ptr[-1] != '\\') *ptr++ = '\\';
|
||||
if (!SetupGetStringFieldW( &context, 2, ptr, len2, NULL )) *ptr = 0;
|
||||
return ret;
|
||||
return PARSER_get_dest_dir( &context );
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +38,7 @@ extern unsigned int PARSER_string_substA( struct inf_file *file, const WCHAR *te
|
||||
extern unsigned int PARSER_string_substW( struct inf_file *file, const WCHAR *text,
|
||||
WCHAR *buffer, unsigned int size );
|
||||
extern const WCHAR *PARSER_get_src_root( HINF hinf );
|
||||
extern WCHAR *PARSER_get_dest_dir( INFCONTEXT *context );
|
||||
|
||||
/* support for Ascii queue callback functions */
|
||||
|
||||
|
@ -112,10 +112,37 @@ typedef struct _SP_FILE_COPY_PARAMS_W
|
||||
DECL_WINELIB_SETUPAPI_TYPE_AW(SP_FILE_COPY_PARAMS)
|
||||
DECL_WINELIB_SETUPAPI_TYPE_AW(PSP_FILE_COPY_PARAMS)
|
||||
|
||||
typedef struct _SP_REGISTER_CONTROL_STATUSA
|
||||
{
|
||||
DWORD cbSize;
|
||||
PCSTR FileName;
|
||||
DWORD Win32Error;
|
||||
DWORD FailureCode;
|
||||
} SP_REGISTER_CONTROL_STATUSA, *PSP_REGISTER_CONTROL_STATUSA;
|
||||
|
||||
typedef struct _SP_REGISTER_CONTROL_STATUSW
|
||||
{
|
||||
DWORD cbSize;
|
||||
PCWSTR FileName;
|
||||
DWORD Win32Error;
|
||||
DWORD FailureCode;
|
||||
} SP_REGISTER_CONTROL_STATUSW, *PSP_REGISTER_CONTROL_STATUSW;
|
||||
|
||||
DECL_WINELIB_TYPE_AW(SP_REGISTER_CONTROL_STATUS)
|
||||
DECL_WINELIB_TYPE_AW(PSP_REGISTER_CONTROL_STATUS)
|
||||
|
||||
#define SPREG_SUCCESS 0x00000000
|
||||
#define SPREG_LOADLIBRARY 0x00000001
|
||||
#define SPREG_GETPROCADDR 0x00000002
|
||||
#define SPREG_REGSVR 0x00000003
|
||||
#define SPREG_DLLINSTALL 0x00000004
|
||||
#define SPREG_TIMEOUT 0x00000005
|
||||
#define SPREG_UNKNOWN 0xffffffff
|
||||
|
||||
typedef UINT (CALLBACK *PSP_FILE_CALLBACK_A)( PVOID Context, UINT Notification,
|
||||
UINT Param1, UINT Param2 );
|
||||
UINT_PTR Param1, UINT_PTR Param2 );
|
||||
typedef UINT (CALLBACK *PSP_FILE_CALLBACK_W)( PVOID Context, UINT Notification,
|
||||
UINT Param1, UINT Param2 );
|
||||
UINT_PTR Param1, UINT_PTR Param2 );
|
||||
DECL_WINELIB_SETUPAPI_TYPE_AW(PSP_FILE_CALLBACK)
|
||||
|
||||
#define LINE_LEN 256
|
||||
@ -365,6 +392,9 @@ DECL_WINELIB_SETUPAPI_TYPE_AW(PFILEPATHS)
|
||||
#define FLG_DELREG_OPERATION_MASK (0x000000FE)
|
||||
#define FLG_DELREG_MULTI_SZ_DELSTRING (FLG_DELREG_TYPE_MULTI_SZ | FLG_ADDREG_DELREG_BIT | 0x00000002)
|
||||
|
||||
#define FLG_REGSVR_DLLREGISTER 0x00000001
|
||||
#define FLG_REGSVR_DLLINSTALL 0x00000002
|
||||
|
||||
/* Class installer function codes */
|
||||
#define DIF_SELECTDEVICE 0x01
|
||||
#define DIF_INSTALLDEVICE 0x02
|
||||
|
Loading…
Reference in New Issue
Block a user