advpack: Implement LaunchINFSection on top of DoInfInstall

Markus Amsler markus.amsler at oribi.org
Fri Jan 13 05:24:58 CST 2006


James Hawkins wrote:

>On 1/12/06, Markus Amsler <markus.amsler at oribi.org> wrote:
>  
>
>>ChangeLog:
>>Implement LaunchINFSection on top of DoInfInstall
>>
>>    
>>
>
>I'm afraid this implementation isn't correct.  DoInfInstall calls
>SetupInstallFromInfSection which only concerns the Install section of
>an INF file.  SetupInstallFromInfSection and consequently DoInfInstall
>cannot provide enough functionality for LaunchINFSection/Ex. 
>LaunchINFSection/Ex also takes into acount reg and file saves (see
>Reg/FileSaveRestore), per user sections (see SetPerUserSecValues),
>registering ocx's, extracting cabinets, and a whole mush of other
>intricacies.  LaunchINFSection/Ex basically combines all the other
>functions of advpack into a monstrosity of functionality.  I'm working
>my way towards fully implementing LaunchINFSection/Ex, but I've got to
>finish the lower levels first, so if you'd like to help in this
>direction, take a look at the stubs I've mentioned in advpack.  I
>appreciate your effort in this implementation, but it will do more
>harm than good because we'll have to take it out when it comes time to
>fully implement LaunchINFSection.
>
>--
>James Hawkins
>  
>
I'm aware of that. We just have different approaches. Mine is from 
higher level functions to lower level, yours the other way round. Our 
approaches are not exclusive, we can simply meet in the middle (I know i 
took the easier way :-)). Is that OK for you? I think there's no problem 
if this patches get applied. The next patch will implement an advanced 
inf section infrastructure, based on setupapi install.c (See atachement, 
still needs some work).

>The same comments for LaunchINFSection apply here as well.  If these
>three APIs just call DoInfInstall, then what's the point in having
>them?
>
Don't ask me, ask Microsoft.
My tests/understanding show all four of them do basically the same work. 
I tested Run(Post|Pre)SetupCommands. All four functions execute this 
advanced inf section (so i guess this is also true for the others).

Microsofts idea was probably to use them from different places:
- DoInfInstall: Internal function that does the real work, with 
backup,sync/async (undocumented, parameters packed)
- RunSetupCommand: Programming API function used from C/C++/.., with 
backup, sync/async (partially documented, nice function parameters)
- LaunchINFSection: useable from commandline, rundll32 without backup, 
synchronus (documented, arguments packed in a string)
- LaunchINFSectionEx: useable from commandline, rundll32 with backup, 
synchronus (documented, arguments packed in a string)
But now every function gets called from programs.

Markus Amsler


-------------- next part --------------
c3ccdde665347bf136a251586eaf31a86b43bc21
diff --git a/dlls/advpack/install.c b/dlls/advpack/install.c
index 72d8f3c..fbce5f4 100644
--- a/dlls/advpack/install.c
+++ b/dlls/advpack/install.c
@@ -3,6 +3,7 @@
  *
  * Copyright 2004 Huw D M Davies
  * Copyright 2005 Sami Aario
+ * Copyright 2005 Markus Amsler
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,7 @@
 #include "winbase.h"
 #include "winuser.h"
 #include "winreg.h"
+#include "winternl.h"
 #include "winver.h"
 #include "winnls.h"
 #include "setupapi.h"
@@ -34,6 +36,177 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(advpack);
 
+typedef BOOL (*iterate_fields_func)( HINF hinf, PCWSTR field, void *arg );
+
+/* Unicode constants */
+static const WCHAR RegisterOCXs[]   = {'R','e','g','i','s','t','e','r','O','C','X','s',0};
+static const WCHAR UnRegisterOCXs[] = {'U','n','R','e','g','i','s','t','e','r','O','C','X','s',0};
+static const WCHAR BeginPrompt[]    = {'B','e','g','i','n','P','r','o','m','p','t',0};
+static const WCHAR EndPrompt[]      = {'E','n','d','P','r','o','m','p','t',0};
+static const WCHAR DelDirs[]        = {'D','e','l','D','i','r','s',0};
+static const WCHAR BackupReg[]      = {'B','a','c','k','u','p','R','e','g',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};
+
+/***********************************************************************
+ *            get_field_string
+ *
+ * Retrieve 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;
+}
+
+static BOOL registerocxs_callback( HINF hinf, PCWSTR field, void *arg )
+{
+    FIXME( "should do registerocxs %s\n", debugstr_w(field) );
+    return TRUE;
+}
+
+static BOOL unregisterocxs_callback( HINF hinf, PCWSTR field, void *arg )
+{
+    FIXME( "should do unregisterocxs %s\n", debugstr_w(field) );
+    return TRUE;
+}
+
+static BOOL beginprompt_callback( HINF hinf, PCWSTR field, void *arg )
+{
+    FIXME( "should do beginprompt %s\n", debugstr_w(field) );
+    return TRUE;
+}
+
+static BOOL endprompt_callback( HINF hinf, PCWSTR field, void *arg )
+{
+    FIXME( "should do endprompt %s\n", debugstr_w(field) );
+    return TRUE;
+}
+
+static BOOL deldirs_callback( HINF hinf, PCWSTR field, void *arg )
+{
+    FIXME( "should do deldirs %s\n", debugstr_w(field) );
+    return TRUE;
+}
+
+static BOOL backupreg_callback( HINF hinf, PCWSTR field, void *arg )
+{
+    FIXME( "should do backupreg %s\n", debugstr_w(field) );
+    return TRUE;
+}
+
+static BOOL runpresetupcommands_callback( HINF hinf, PCWSTR field, void *arg )
+{
+    FIXME( "should do runpresetupcommands %s\n", debugstr_w(field) );
+    return TRUE;
+}
+
+static BOOL runpostsetupcommands_callback( HINF hinf, PCWSTR field, void *arg )
+{
+    FIXME( "should do runpostupcommands %s\n", debugstr_w(field) );
+    return TRUE;
+}
+
+/***********************************************************************
+ *            iterate_section_fields
+ *
+ * Iterate over all fields of a certain key of a certain section
+ */
+static BOOL 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;
+    BOOL ret = FALSE;
+
+    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 (!callback( hinf, buffer, arg ))
+            {
+                WARN("callback failed for %s %s err %ld\n",
+                     debugstr_w(section), debugstr_w(buffer), GetLastError() );
+                goto done;
+            }
+        }
+        ok = SetupFindNextMatchLineW( &context, key, &context );
+    }
+    ret = TRUE;
+ done:
+    if (buffer && buffer != static_buffer) HeapFree( GetProcessHeap(), 0, buffer );
+    return ret;
+}
+
+/***********************************************************************
+ *            do_before_install
+ *
+ * Performs advanced inf actions before normal setup.
+ *
+ * TODO:
+ *  implement PreRollback
+ */
+static BOOL do_before_install( HINF hinf, PCWSTR section )
+{
+    if (!iterate_section_fields( hinf, section, BeginPrompt, beginprompt_callback, NULL ))
+        return FALSE;
+    
+    if (!iterate_section_fields( hinf, section, BackupReg, backupreg_callback, NULL ))
+        return FALSE;
+    
+    if (!iterate_section_fields( hinf, section, RegisterOCXs, registerocxs_callback, NULL ))
+        return FALSE;
+
+    if (!iterate_section_fields( hinf, section, RunPreSetupCommands,
+                                 runpresetupcommands_callback, NULL ))
+        return FALSE;
+
+    if (!iterate_section_fields( hinf, section, DelDirs, deldirs_callback, NULL ))
+        return FALSE;
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *            do_after_install
+ *
+ * Performs advanced inf actions after normal setup.
+ */
+static BOOL do_after_install( HINF hinf, PCWSTR section )
+{
+    if (!iterate_section_fields( hinf, section, UnRegisterOCXs, unregisterocxs_callback, NULL ))
+        return FALSE;
+    
+    if (!iterate_section_fields( hinf, section, RunPostSetupCommands,
+                                 runpostsetupcommands_callback, NULL ))
+        return FALSE;
+    
+    if (!iterate_section_fields( hinf, section, EndPrompt, endprompt_callback, NULL ))
+        return FALSE;
+
+    return TRUE;
+}
+
 /***********************************************************************
  *		DoInfInstall  (ADVPACK.@)
  *
@@ -48,16 +221,25 @@ WINE_DEFAULT_DEBUG_CHANNEL(advpack);
  */
 HRESULT WINAPI DoInfInstall(LPCINFINSTALLPARAMS setup)
 {
-    BOOL ret;
+    BOOL ret = FALSE;
     HINF hinf;
     void *callback_context;
+    UNICODE_STRING sectionW;
 
     TRACE("%p %s %s %s %s\n", setup->hwnd, debugstr_a(setup->title),
           debugstr_a(setup->inf_name), debugstr_a(setup->dir),
           debugstr_a(setup->section_name));
-
+    
     hinf = SetupOpenInfFileA(setup->inf_name, NULL, INF_STYLE_WIN4, NULL);
-    if (hinf == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError());
+    if (hinf == INVALID_HANDLE_VALUE)
+        goto done;
+
+    if (!RtlCreateUnicodeStringFromAsciiz( &sectionW, setup->section_name ))
+        goto done;
+
+    ret = do_before_install(hinf, sectionW.Buffer);
+    if (!ret)
+        goto done_free;
 
     callback_context = SetupInitDefaultQueueCallback(setup->hwnd);
 
@@ -65,8 +247,16 @@ HRESULT WINAPI DoInfInstall(LPCINFINSTAL
                                       NULL, NULL, 0, SetupDefaultQueueCallbackA,
                                       callback_context, NULL, NULL);
     SetupTermDefaultQueueCallback(callback_context);
+    if (!ret)
+        goto done_close;
+    
+    ret = do_after_install(hinf, sectionW.Buffer);
+ 
+ done_close:
     SetupCloseInfFile(hinf);
-
+ done_free:
+    RtlFreeUnicodeString( &sectionW );
+ done:
     return ret ? S_OK : HRESULT_FROM_WIN32(GetLastError());
 }
 


More information about the wine-devel mailing list