[PATCH 2/2] wineboot: Split prefix updating into two parts.

David Hedberg dhedberg at codeweavers.com
Thu Jun 16 03:27:01 CDT 2011


On initial prefix creation, services.exe is started before the
environment is properly set up. This leads to calls to
ExpandEnvironmentStrings failing, in turn breaking at least one
installer. This splits the creation/update process into two parts, and
sets up the environment before starting services.
---
 programs/wineboot/wineboot.c |   44 +++++++++++++++++++++++++++++++++--------
 tools/wine.inf.in            |   27 ++++++++++++++++++++-----
 2 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 47a9bf1..1902393 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -918,13 +918,15 @@ static HWND show_wait_window(void)
     return hwnd;
 }
 
-static HANDLE start_rundll32( const char *inf_path, BOOL wow64 )
+static HANDLE start_rundll32( const char *inf_path, BOOL wow64, BOOL service_install )
 {
     static const WCHAR rundll[] = {'\\','r','u','n','d','l','l','3','2','.','e','x','e',0};
     static const WCHAR setupapi[] = {' ','s','e','t','u','p','a','p','i',',',
                                      'I','n','s','t','a','l','l','H','i','n','f','S','e','c','t','i','o','n',0};
     static const WCHAR definstall[] = {' ','D','e','f','a','u','l','t','I','n','s','t','a','l','l',0};
+    static const WCHAR svcinstall[] = {' ','S','e','r','v','i','c','e','I','n','s','t','a','l','l',0};
     static const WCHAR wowinstall[] = {' ','W','o','w','6','4','I','n','s','t','a','l','l',0};
+    static const WCHAR wowsvcinstall[] = {' ','W','o','w','6','4','S','e','r','v','i','c','e','I','n','s','t','a','l','l',0};
     static const WCHAR inf[] = {' ','1','2','8',' ','\\','\\','?','\\','u','n','i','x',0 };
 
     WCHAR app[MAX_PATH + sizeof(rundll)/sizeof(WCHAR)];
@@ -951,7 +953,8 @@ static HANDLE start_rundll32( const char *inf_path, BOOL wow64 )
 
     strcpyW( buffer, app );
     strcatW( buffer, setupapi );
-    strcatW( buffer, wow64 ? wowinstall : definstall );
+    if (service_install)  strcatW( buffer, wow64 ? wowsvcinstall : svcinstall );
+    else                  strcatW( buffer, wow64 ? wowinstall : definstall );
     strcatW( buffer, inf );
     MultiByteToWideChar( CP_UNIXCP, 0, inf_path, -1, buffer + strlenW(buffer), inf_len );
 
@@ -965,17 +968,18 @@ static HANDLE start_rundll32( const char *inf_path, BOOL wow64 )
 }
 
 /* execute rundll32 on the wine.inf file if necessary */
-static void update_wineprefix( int force )
+static BOOL update_wineprefix( int force, BOOL service_install )
 {
     const char *config_dir = wine_get_config_dir();
     char *inf_path = get_wine_inf_path();
     int fd;
     struct stat st;
+    BOOL ret = FALSE;
 
     if (!inf_path)
     {
         WINE_MESSAGE( "wine: failed to update %s, wine.inf not found\n", config_dir );
-        return;
+        return FALSE;
     }
     if ((fd = open( inf_path, O_RDONLY )) == -1)
     {
@@ -991,7 +995,7 @@ static void update_wineprefix( int force )
         HANDLE process;
         DWORD count = 0;
 
-        if ((process = start_rundll32( inf_path, FALSE )))
+        if ((process = start_rundll32( inf_path, FALSE, service_install )))
         {
             HWND hwnd = show_wait_window();
             for (;;)
@@ -1001,17 +1005,33 @@ static void update_wineprefix( int force )
                 if (res == WAIT_OBJECT_0)
                 {
                     CloseHandle( process );
-                    if (count++ || !(process = start_rundll32( inf_path, TRUE ))) break;
+                    if (count++ || !(process = start_rundll32( inf_path, TRUE, service_install ))) break;
                 }
                 else while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageW( &msg );
             }
             DestroyWindow( hwnd );
         }
-        WINE_MESSAGE( "wine: configuration in '%s' has been updated.\n", config_dir );
+        if (service_install)
+            WINE_MESSAGE( "wine: service configuration in '%s' has been updated.\n", config_dir);
+        else
+            WINE_MESSAGE( "wine: configuration in '%s' has been updated.\n", config_dir );
+        ret = TRUE;
     }
 
 done:
     HeapFree( GetProcessHeap(), 0, inf_path );
+    return ret;
+}
+
+static void update_environment(void)
+{
+    HINSTANCE kernel32 = GetModuleHandleA("kernel32");
+    void (CDECL *update_environment)();
+
+    if ( (update_environment = GetProcAddress(kernel32, "__wine_update_environment")) )
+        update_environment();
+    else
+        WINE_ERR("Failed to get __wine_update_environment from kernel32.\n");
 }
 
 /* Process items in the StartUp group of the user's Programs under the Start Menu. Some installers put
@@ -1139,7 +1159,7 @@ int main( int argc, char *argv[] )
     int end_session = 0, force = 0, init = 0, kill = 0, restart = 0, shutdown = 0, update = 0;
     HANDLE event;
     SECURITY_ATTRIBUTES sa;
-    BOOL is_wow64;
+    BOOL is_wow64, is_updating = FALSE;
 
     GetWindowsDirectoryW( windowsdir, MAX_PATH );
     if( !SetCurrentDirectoryW( windowsdir ) )
@@ -1211,6 +1231,12 @@ int main( int argc, char *argv[] )
     wininit();
     pendingRename();
 
+    if (init || update)
+    {
+        if ( (is_updating = update_wineprefix( update, FALSE )) )
+            update_environment();
+    }
+
     ProcessWindowsFileProtection();
     ProcessRunKeys( HKEY_LOCAL_MACHINE, runkeys_names[RUNKEY_RUNSERVICESONCE], TRUE, FALSE );
 
@@ -1219,7 +1245,7 @@ int main( int argc, char *argv[] )
         ProcessRunKeys( HKEY_LOCAL_MACHINE, runkeys_names[RUNKEY_RUNSERVICES], FALSE, FALSE );
         start_services_process();
     }
-    if (init || update) update_wineprefix( update );
+    if (is_updating) update_wineprefix( TRUE, TRUE );
 
     create_volatile_environment_registry_key();
 
diff --git a/tools/wine.inf.in b/tools/wine.inf.in
index 8e8eba8..5f62219 100644
--- a/tools/wine.inf.in
+++ b/tools/wine.inf.in
@@ -108,6 +108,15 @@ AddReg=\
     VersionInfo,\
     Wow64
 
+[ServiceInstall]
+RegisterDlls=ServiceDllsSection
+
+[ServiceInstall.NT]
+RegisterDlls=ServiceDllsSection
+
+[ServiceInstall.ntamd64]
+RegisterDlls=ServiceDllsSection
+
 [Wow64Install]
 RegisterDlls=RegisterDllsSection
 WineFakeDlls=FakeDllsWin32,FakeDllsWow64
@@ -123,19 +132,22 @@ AddReg=\
     Tapi,\
     VersionInfo
 
-[DefaultInstall.Services]
+[Wow64ServiceInstall]
+RegisterDlls=ServiceDllsSection
+
+[ServiceInstall.Services]
 AddService=MountMgr,0x800,MountMgrService
 AddService=Spooler,0,SpoolerService
 AddService=TermService,0,TerminalServices
 AddService=PlugPlay,0,PlugPlayService
 
-[DefaultInstall.NT.Services]
+[ServiceInstall.NT.Services]
 AddService=MountMgr,0x800,MountMgrService
 AddService=Spooler,0,SpoolerService
 AddService=TermService,0,TerminalServices
 AddService=PlugPlay,0,PlugPlayService
 
-[DefaultInstall.ntamd64.Services]
+[ServiceInstall.ntamd64.Services]
 AddService=MountMgr,0x800,MountMgrService
 AddService=Spooler,0,SpoolerService
 AddService=TermService,0,TerminalServices
@@ -2538,7 +2550,6 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G"
 11,,msdaps.dll,1
 11,,mshtml.dll,1
 11,,msi.dll,1
-11,,msiexec.exe,1
 11,,msimtf.dll,1
 11,,msisip.dll,1
 11,,mstask.dll,1
@@ -2551,7 +2562,6 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G"
 11,,oledb32.dll,1
 11,,qcap.dll,1
 11,,qedit.dll,1
-11,,qmgr.dll,1
 11,,qmgrprxy.dll,1
 11,,quartz.dll,1
 11,,rsaenh.dll,1
@@ -2559,7 +2569,6 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G"
 11,,sti.dll,1
 11,,urlmon.dll,1
 11,,wbemprox.dll,1
-11,,wiaservc.dll,1
 11,,windowscodecs.dll,1
 11,,winegstreamer.dll,1
 11,,wineqtdecoder.dll,1
@@ -2568,6 +2577,12 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G"
 11,,wuapi.dll,1
 11,,iexplore.exe,1
 
+; Requires a running instance of services
+[ServiceDllsSection]
+11,,msiexec.exe,1
+11,,qmgr.dll,1
+11,,wiaservc.dll,1
+
 ; 32bit-only fake dlls
 [FakeDllsWin32]
 10,,rundll.exe,rundll.exe16
-- 
1.7.5.3




More information about the wine-patches mailing list