Module: wine Branch: master Commit: 5e28f7ad92e39bdd75cf291e22b7ebae00032e60 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5e28f7ad92e39bdd75cf291e22...
Author: Misha Koshelev mk144210@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;