OSDN Git Service

Implement setup tool installer "plugin".
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Thu, 25 Jul 2013 20:48:45 +0000 (21:48 +0100)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Thu, 25 Jul 2013 20:48:45 +0000 (21:48 +0100)
ChangeLog
Makefile.in
src/dllhook.cpp
src/setup.cpp
src/setup.h

index 9cfbaa8..f094054 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,35 @@
 2013-07-25  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
+       Implement setup tool installer "plugin".
+
+       * src/setup.h (SETUP_HOOK_RUN_INSTALLER): Define request code.
+
+       * src/dllhook.cpp (run_basic_system_installer): Implement handler...
+       (setup_hook) [SETUP_HOOK_RUN_INSTALLER]: ...and invoke it.
+       (setup_hook) [default]: Collect diagnostics in common message digest.
+       (AppWindowMaker::SetupHookInvoked): Define and initialise it; in this
+       context, which does not conflict with prior definition in guimain.exe,
+       it must always remain true.
+
+       * src/setup.cpp (SetupTool) [constructor]: Invoke...
+       (SetupTool::DispatchSetupHookRequest): ...this, on user's request...
+       (SETUP_HOOK_RUN_INSTALLER): ...with this action code; this replaces...
+       (SetupTool::RunInstalledProgram): ...one reference instance for this
+       external program fork, leaving only one such reference remaining;
+       declare it to be "inline".
+
+       * Makefile.in (GUIMAIN_LIB_OBJECTS): New macro; define it.  It
+       abstracts a subset of the object modules originally enumerated...
+       (GUIMAIN_OBJECTS): ...here, whence use it; also incorporate into...
+       (SETUP_DLL_OBJECTS): ...this.
+       (SETUP_DLL_LIBS): Make it equivalent to...
+       (GUIMAIN_LIBS): ...this.
+       (mingw-get-setup-0.dll): Use...
+       (GUI_LDFLAGS): ...this, to specify linking options, rather than...
+       (LDFLAGS): ...this.
+
+2013-07-25  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
        Add "Basic Setup" as a built-in standard package group.
 
        * src/guimain.h (AppWindowMaker::SetupToolInvoked): New private
index 9abc7af..7717e56 100644 (file)
@@ -173,17 +173,22 @@ CLI_EXE_OBJECTS  =   \
    clistub.$(OBJEXT) version.$(OBJEXT) approot.$(OBJEXT) getopt.$(OBJEXT)
 
 GUIMAIN_OBJECTS  =   \
-   guimain.$(OBJEXT) guiexec.$(OBJEXT) dmhguix.$(OBJEXT) \
-   approot.$(OBJEXT) pkgview.$(OBJEXT) pkgtree.$(OBJEXT) pkglist.$(OBJEXT) \
-   pkgdata.$(OBJEXT) pkgnget.$(OBJEXT) guimain.res.$(OBJEXT)
+   guimain.$(OBJEXT) dmhguix.$(OBJEXT) $(GUIMAIN_LIB_OBJECTS) \
+   approot.$(OBJEXT) guimain.res.$(OBJEXT)
+
+GUIMAIN_LIB_OBJECTS = \
+   guiexec.$(OBJEXT) pkgview.$(OBJEXT) pkgtree.$(OBJEXT) pkglist.$(OBJEXT) \
+   pkgdata.$(OBJEXT) pkgnget.$(OBJEXT)
 
 GUIMAIN_LIBS = -lwtklite -lcomctl32
 
 SETUP_TOOL_OBJECTS = setup.$(OBJEXT) setup.res.$(OBJEXT) apihook.$(OBJEXT)
 SETUP_TOOL_LIBS = -lwtklite -lwininet -lcomctl32 -lole32 -Wl,-Bstatic -llzma
 
-SETUP_DLL_OBJECTS = dllhook.$(OBJEXT)
-SETUP_DLL_LIBS =
+SETUP_DLL_OBJECTS =  \
+   dllhook.$(OBJEXT) $(GUIMAIN_LIB_OBJECTS) guimain.res.$(OBJEXT)
+
+SETUP_DLL_LIBS = $(GUIMAIN_LIBS)
 
 script_srcdir = ${srcdir}/scripts/libexec
 
@@ -225,7 +230,7 @@ mingw-get-0.dll: $(CORE_DLL_OBJECTS)
        $(CXX) -shared -o $@ $(CXXFLAGS) $(LDFLAGS) $+ $(LIBS)
 
 mingw-get-setup-0.dll: $(SETUP_DLL_OBJECTS) mingw-get-0.dll
-       $(CXX) -shared -o $@ $(CXXFLAGS) $(LDFLAGS) $+ $(SETUP_DLL_LIBS)
+       $(CXX) -shared -o $@ $(CXXFLAGS) $(GUI_LDFLAGS) $+ $(SETUP_DLL_LIBS)
 
 # The following recursive invocation hook provides a mechanism for
 # accessing make's facility for reporting what it is doing, even when
index 06394f9..3d117e3 100644 (file)
@@ -48,6 +48,13 @@ static const char *setup_key = "setup";
 #include <sys/stat.h>
 #include <fcntl.h>
 
+/* This file implements the plugin variant of the mingw-get
+ * GUI installer, for use by the setup tool; in this context
+ * this AppWindowMaker static attribute must be initialised
+ * to indicate this mode of use.
+ */
+bool AppWindowMaker::SetupToolInvoked = true;
+
 static const char *internal_error = "internal error";
 #define MSG_INTERNAL_ERROR(MSG) "%s: "MSG_##MSG"\n", internal_error
 
@@ -204,6 +211,59 @@ void update_catalogue( HWND owner )
   free( (void *)(dfile) );
 }
 
+static inline
+int run_basic_system_installer( const wchar_t *dll_name )
+{
+  /* Hook to emulate a subset of the mingw-get GUI installer
+   * capabilities, via an embedded subset of its functions.
+   */
+  try
+  { /* Identify the DLL module, whence we may retrieve resources
+     * similar to those of the free-standing GUI application, and
+     * create a clone of that application's main window.
+     */
+    HINSTANCE instance;
+    AppWindowMaker MainWindow( instance = GetModuleHandleW( dll_name ) );
+    MainWindow.Create( WTK::StringResource( instance, ID_MAIN_WINDOW_CLASS ),
+       WTK::StringResource( instance, ID_MAIN_WINDOW_CAPTION )
+      );
+
+    /* Show this window, and paint its initial content...
+     */
+    MainWindow.Show( SW_SHOW );
+    MainWindow.Update();
+
+    /* ...then invoke its message loop, ultimately returning the
+     * status code which prevails, when the user closes it.
+     */
+    return MainWindow.Invoked();
+  }
+  catch( dmh_exception &e )
+  {
+    /* Here, we handle any fatal exception which has been raised
+     * and identified by the diagnostic message handler...
+     */
+    MessageBox( NULL, e.what(), "WinMain", MB_ICONERROR );
+    return EXIT_FAILURE;
+  }
+  catch( WTK::runtime_error &e )
+  {
+    /* ...while here, we diagnose any other error which was captured
+     * during the creation of the application's window hierarchy, or
+     * processing of its message loop...
+     */
+    MessageBox( NULL, e.what(), "WinMain", MB_ICONERROR );
+    return EXIT_FAILURE;
+  }
+  catch(...)
+  { /* ...and here, we diagnose any other error which we weren't
+     * able to explicitly identify.
+     */
+    MessageBox( NULL, "Unknown exception", "WinMain", MB_ICONERROR );
+    return EXIT_FAILURE;
+  }
+}
+
 EXTERN_C __declspec(dllexport)
 void setup_hook( unsigned int request, va_list argv )
 {
@@ -230,12 +290,21 @@ void setup_hook( unsigned int request, va_list argv )
       update_catalogue( va_arg( argv, HWND ) );
       break;
 
+    case SETUP_HOOK_RUN_INSTALLER:
+      /* This hook invokes the mingw-get GUI, in setup tool mode, to
+       * facilitate installation of a user configured basic system.
+       */
+      run_basic_system_installer( va_arg( argv, const wchar_t * ) );
+      break;
+
     default:
       /* We should never get to here; it's a programming error in
        * the setup tool, if we do.
        */
+      dmh_control( DMH_BEGIN_DIGEST );
       dmh_notify( DMH_ERROR, MSG_INTERNAL_ERROR( INVALID_REQUEST ) );
       dmh_notify( DMH_ERROR, MSG_INTERNAL_ERROR( NOTIFY_MAINTAINER ) );
+      dmh_control( DMH_END_DIGEST );
   }
 }
 
index 4616be8..e9597d9 100644 (file)
@@ -188,7 +188,7 @@ class SetupTool
       ( HWND, unsigned, WPARAM, LPARAM );
 
     static const wchar_t *gui_program;
-    int RunInstalledProgram( const wchar_t * );
+    inline int RunInstalledProgram( const wchar_t * );
 
     inline wchar_t *setup_dll( void )
     { /* Helper function to ensure that the static "approot_path" buffer
@@ -1051,6 +1051,17 @@ base_dll( NULL ), hook_dll( NULL )
        MAKEINTRESOURCE( IDD_SETUP_BEGIN ), NULL, OpeningDialogue
       );
 
+    /* When the user has requested progression to package installation...
+     */
+    if( Status == EXIT_CONTINUE )
+    {
+      /* ...then delegate that to the embedded mingw-get plugin, before
+       * reasserting successful completion status for the setup tool.
+       */
+      DispatchSetupHookRequest( SETUP_HOOK_RUN_INSTALLER, setup_dll() );
+      Status = EXIT_SUCCESS;
+    }
+
     /* If the mingw-get-0.dll and mingw-get-setup-0.dll libraries
      * were successfully loaded, to complete the installation process,
      * then we must now unload them; we also have no further use for
@@ -1062,17 +1073,6 @@ base_dll( NULL ), hook_dll( NULL )
     /* We're done with the COM subsystem; release it.
      */
     CoUninitialize();
-
-    /* When the user has requested progression to advanced installation...
-     */
-    if( Status == EXIT_CONTINUE )
-    {
-      /* ...the delegate that to mingw-get itself, before reasserting
-       * the successful completion status for the setup tool.
-       */
-      RunInstalledProgram( gui_program );
-      Status = EXIT_SUCCESS;
-    }
   }
 }
 
@@ -1285,7 +1285,7 @@ inline HMODULE SetupTool::HaveWorkingInstallation( void )
  */
 const wchar_t *SetupTool::gui_program = L"libexec\\mingw-get\\guimain.exe";
 
-int SetupTool::RunInstalledProgram( const wchar_t *program )
+inline int SetupTool::RunInstalledProgram( const wchar_t *program )
 {
   /* Helper method to spawn an external process, into which a
    * specified program image is loaded; (typically this will be
index 155be28..9463c0c 100644 (file)
@@ -86,7 +86,8 @@ enum
    * serviced by mingw-get-setup-0.dll
    */
   SETUP_HOOK_DMH_BIND = 0,
-  SETUP_HOOK_POST_INSTALL
+  SETUP_HOOK_POST_INSTALL,
+  SETUP_HOOK_RUN_INSTALLER
 };
 
 class pkgSetupAction