Misha Koshelev : winemenubuilder: Wait for parent process to finish instead of creating RunOnce entry that may never run .

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jun 28 08:08:08 CDT 2007


Module: wine
Branch: master
Commit: 5e28f7ad92e39bdd75cf291e22b7ebae00032e60
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5e28f7ad92e39bdd75cf291e22b7ebae00032e60

Author: Misha Koshelev <mk144210 at bcm.edu>
Date:   Wed Jun 27 20:23:33 2007 -0500

winemenubuilder: Wait for parent process to finish instead of creating RunOnce entry that may never run.

---

 dlls/shell32/shelllink.c                   |    7 +-
 programs/winemenubuilder/winemenubuilder.c |  140 ++++++++++++++--------------
 2 files changed, 71 insertions(+), 76 deletions(-)

diff --git a/dlls/shell32/shelllink.c b/dlls/shell32/shelllink.c
index aa21a4a..5f99c9d 100644
--- a/dlls/shell32/shelllink.c
+++ b/dlls/shell32/shelllink.c
@@ -399,7 +399,7 @@ static BOOL StartLinkProcessor( LPCOLESTR szLink )
 {
     static const WCHAR szFormat[] = {
         'w','i','n','e','m','e','n','u','b','u','i','l','d','e','r','.','e','x','e',
-        ' ','-','r',' ','"','%','s','"',0 };
+        ' ','-','w',' ','"','%','s','"',0 };
     LONG len;
     LPWSTR buffer;
     STARTUPINFOW si;
@@ -417,11 +417,6 @@ static BOOL StartLinkProcessor( LPCOLESTR szLink )
     memset(&si, 0, sizeof(si));
     si.cb = sizeof(si);
     if (!CreateProcessW( NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) return FALSE;
-
-    /* wait for a while to throttle the creation of linker processes */
-    if( WAIT_OBJECT_0 != WaitForSingleObject( pi.hProcess, 10000 ) )
-        WARN("Timed out waiting for shell linker\n");
-
     CloseHandle( pi.hProcess );
     CloseHandle( pi.hThread );
 
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index cac3abf..a8ee4b1 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -33,11 +33,11 @@
  * interface, then invoke wineshelllink with the appropriate arguments
  * to create a KDE/Gnome menu entry for the shortcut.
  *
- *  winemenubuilder [ -r ] <shortcut.lnk>
+ *  winemenubuilder [ -w ] <shortcut.lnk>
  *
- *  If the -r parameter is passed, and the shortcut cannot be created,
- * this program will add a RunOnce entry to invoke itself at the next
- * reboot.  This covers the case when a ShortCut is created before the
+ *  If the -w parameter is passed, and the shortcut cannot be created,
+ * this program will wait for the parent process to finish and then try
+ * again. This covers the case when a ShortCut is created before the
  * executable containing its icon.
  *
  * TODO
@@ -72,6 +72,7 @@
 #include <objidl.h>
 #include <shlguid.h>
 #include <appmgmt.h>
+#include <tlhelp32.h>
 
 #include "wine/unicode.h"
 #include "wine/debug.h"
@@ -466,9 +467,8 @@ static unsigned short crc16(const char* string)
 }
 
 /* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */
-static char *extract_icon( LPCWSTR path, int index)
+static char *extract_icon( LPCWSTR path, int index, BOOL bWait )
 {
-    int nodefault = 1;
     unsigned short crc;
     char *iconsdir, *ico_path, *ico_name, *xpm_path;
     char* s;
@@ -520,13 +520,6 @@ static char *extract_icon( LPCWSTR path, int index)
         return NULL;  /* No icon created */
     }
 
-    /* If icon path begins with a '*' then this is a deferred call */
-    if (path[0] == '*')
-    {
-        path++;
-        nodefault = 0;
-    }
-
     /* Determine the icon base name */
     n = WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL);
     ico_path = HeapAlloc(GetProcessHeap(), 0, n);
@@ -558,7 +551,7 @@ static char *extract_icon( LPCWSTR path, int index)
     sprintf(xpm_path,"%s/%04x_%s.xpm",iconsdir,crc,ico_name);
     if (ExtractFromICO( path, xpm_path))
         goto end;
-    if (!nodefault)
+    if (!bWait)
         if (create_default_icon( xpm_path, ico_path ))
             goto end;
 
@@ -571,46 +564,6 @@ static char *extract_icon( LPCWSTR path, int index)
     return xpm_path;
 }
 
-static BOOL DeferToRunOnce(LPWSTR link)
-{
-    HKEY hkey;
-    LONG r, len;
-    static const WCHAR szRunOnce[] = {
-        'S','o','f','t','w','a','r','e','\\',
-        'M','i','c','r','o','s','o','f','t','\\',
-        'W','i','n','d','o','w','s','\\',
-        'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-        'R','u','n','O','n','c','e',0
-    };
-    static const WCHAR szFormat[] = { '%','s',' ','"','%','s','"',0 };
-    LPWSTR buffer;
-    WCHAR szExecutable[MAX_PATH];
-
-    WINE_TRACE( "Deferring icon creation to reboot.\n");
-
-    len = GetModuleFileNameW( 0, szExecutable, MAX_PATH );
-    if (!len || len >= MAX_PATH) return FALSE;
-
-    len = ( lstrlenW( link ) + lstrlenW( szExecutable ) + 4)*sizeof(WCHAR);
-    buffer = HeapAlloc( GetProcessHeap(), 0, len );
-    if( !buffer )
-        return FALSE;
-
-    wsprintfW( buffer, szFormat, szExecutable, link );
-
-    r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szRunOnce, 0,
-              NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, NULL);
-    if ( r == ERROR_SUCCESS )
-    {
-        r = RegSetValueExW(hkey, link, 0, REG_SZ,
-                   (LPBYTE) buffer, (lstrlenW(buffer) + 1)*sizeof(WCHAR));
-        RegCloseKey(hkey);
-    }
-    HeapFree(GetProcessHeap(), 0, buffer);
-
-    return ! r;
-}
-
 /* This escapes \ in filenames */
 static LPSTR escape(LPCWSTR arg)
 {
@@ -897,7 +850,7 @@ static HRESULT get_cmdline( IShellLinkW *sl, LPWSTR szPath, DWORD pathSize,
     return hr;
 }
 
-static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain )
+static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
 {
     static const WCHAR startW[] = {'\\','c','o','m','m','a','n','d',
                                    '\\','s','t','a','r','t','.','e','x','e',0};
@@ -953,14 +906,14 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain )
 
     /* extract the icon */
     if( szIconPath[0] )
-        icon_name = extract_icon( szIconPath , iIconId );
+        icon_name = extract_icon( szIconPath , iIconId, bWait );
     else
-        icon_name = extract_icon( szPath, iIconId );
+        icon_name = extract_icon( szPath, iIconId, bWait );
 
-    /* fail - try once again at reboot time */
+    /* fail - try once again after parent process exit */
     if( !icon_name )
     {
-        if (bAgain)
+        if (bWait)
         {
             WINE_WARN("Unable to extract icon, deferring.\n");
             goto cleanup;
@@ -1049,8 +1002,54 @@ cleanup:
     return TRUE;
 }
 
+static BOOL WaitForParentProcess( void )
+{
+    PROCESSENTRY32 procentry;
+    HANDLE hsnapshot = NULL, hprocess = NULL;
+    DWORD ourpid = GetCurrentProcessId();
+    BOOL ret = FALSE, rc;
+
+    WINE_TRACE("Waiting for parent process\n");
+    if ((hsnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 )) ==
+        INVALID_HANDLE_VALUE)
+    {
+        WINE_ERR("CreateToolhelp32Snapshot failed, error %d\n", GetLastError());
+        goto done;
+    }
+
+    procentry.dwSize = sizeof(PROCESSENTRY32);
+    rc = Process32First( hsnapshot, &procentry );
+    while (rc)
+    {
+        if (procentry.th32ProcessID == ourpid) break;
+        rc = Process32Next( hsnapshot, &procentry );
+    }
+    if (!rc)
+    {
+        WINE_WARN("Unable to find current process id %d when listing processes\n", ourpid);
+        goto done;
+    }
+
+    if ((hprocess = OpenProcess( SYNCHRONIZE, FALSE, procentry.th32ParentProcessID )) ==
+        NULL)
+    {
+        WINE_WARN("OpenProcess failed pid=%d, error %d\n", procentry.th32ParentProcessID,
+                 GetLastError());
+        goto done;
+    }
+
+    if (WaitForSingleObject( hprocess, INFINITE ) == WAIT_OBJECT_0)
+        ret = TRUE;
+    else
+        WINE_ERR("Unable to wait for parent process, error %d\n", GetLastError());
+
+done:
+    if (hprocess) CloseHandle( hprocess );
+    if (hsnapshot) CloseHandle( hsnapshot );
+    return ret;
+}
 
-static BOOL Process_Link( LPCWSTR linkname, BOOL bAgain )
+static BOOL Process_Link( LPCWSTR linkname, BOOL bWait )
 {
     IShellLinkW *sl;
     IPersistFile *pf;
@@ -1058,7 +1057,7 @@ static BOOL Process_Link( LPCWSTR linkname, BOOL bAgain )
     WCHAR fullname[MAX_PATH];
     DWORD len;
 
-    WINE_TRACE("%s, again %d\n", wine_dbgstr_w(linkname), bAgain);
+    WINE_TRACE("%s, wait %d\n", wine_dbgstr_w(linkname), bWait);
 
     if( !linkname[0] )
     {
@@ -1099,12 +1098,13 @@ static BOOL Process_Link( LPCWSTR linkname, BOOL bAgain )
     if( SUCCEEDED( r ) )
     {
         /* If something fails (eg. Couldn't extract icon)
-         * defer this menu entry to reboot via runonce
+         * wait for parent process and try again
          */
-        if( ! InvokeShellLinker( sl, fullname, bAgain ) && bAgain )
-            DeferToRunOnce( fullname );
-        else
-            WINE_TRACE("Success.\n");
+        if( ! InvokeShellLinker( sl, fullname, bWait ) && bWait )
+        {
+            WaitForParentProcess();
+            InvokeShellLinker( sl, fullname, FALSE );
+        }
     }
 
     IPersistFile_Release( pf );
@@ -1159,7 +1159,7 @@ static CHAR *next_token( LPSTR *p )
 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show)
 {
     LPSTR token = NULL, p;
-    BOOL bAgain = FALSE;
+    BOOL bWait = FALSE;
     int ret = 0;
 
     for( p = cmdline; p && *p; )
@@ -1167,8 +1167,8 @@ int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show
         token = next_token( &p );
 	if( !token )
 	    break;
-        if( !lstrcmpA( token, "-r" ) )
-            bAgain = TRUE;
+        if( !lstrcmpA( token, "-w" ) )
+            bWait = TRUE;
 	else if( token[0] == '-' )
 	{
 	    WINE_ERR( "unknown option %s\n",token);
@@ -1178,7 +1178,7 @@ int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show
             WCHAR link[MAX_PATH];
 
             MultiByteToWideChar( CP_ACP, 0, token, -1, link, sizeof(link)/sizeof(WCHAR) );
-            if( !Process_Link( link, bAgain ) )
+            if( !Process_Link( link, bWait ) )
             {
 	        WINE_ERR( "failed to build menu item for %s\n",token);
 	        ret = 1;




More information about the wine-cvs mailing list