regsvr32: Re-exec as 32-bit or 64-bit if necessary.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47075 Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
de9406bccd
commit
e90cca8e7a
|
@ -83,6 +83,97 @@ static void WINAPIV output_write(UINT id, ...)
|
|||
LocalFree(str);
|
||||
}
|
||||
|
||||
static LPCWSTR find_arg_start(LPCWSTR cmdline)
|
||||
{
|
||||
LPCWSTR s;
|
||||
BOOL in_quotes;
|
||||
int bcount;
|
||||
|
||||
bcount=0;
|
||||
in_quotes=FALSE;
|
||||
s=cmdline;
|
||||
while (1) {
|
||||
if (*s==0 || ((*s=='\t' || *s==' ') && !in_quotes)) {
|
||||
/* end of this command line argument */
|
||||
break;
|
||||
} else if (*s=='\\') {
|
||||
/* '\', count them */
|
||||
bcount++;
|
||||
} else if ((*s=='"') && ((bcount & 1)==0)) {
|
||||
/* unescaped '"' */
|
||||
in_quotes=!in_quotes;
|
||||
bcount=0;
|
||||
} else {
|
||||
/* a regular character */
|
||||
bcount=0;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void reexec_self(void)
|
||||
{
|
||||
/* restart current process as 32-bit or 64-bit with same command line */
|
||||
static const WCHAR exe_name[] = {'\\','r','e','g','s','v','r','3','2','.','e','x','e',0};
|
||||
#ifndef _WIN64
|
||||
static const WCHAR sysnative[] = {'\\','S','y','s','N','a','t','i','v','e',0};
|
||||
BOOL wow64;
|
||||
#endif
|
||||
WCHAR systemdir[MAX_PATH];
|
||||
LPCWSTR args;
|
||||
WCHAR *cmdline;
|
||||
STARTUPINFOW si = {0};
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
#ifdef _WIN64
|
||||
TRACE("restarting as 32-bit\n");
|
||||
GetSystemWow64DirectoryW(systemdir, MAX_PATH);
|
||||
#else
|
||||
TRACE("restarting as 64-bit\n");
|
||||
|
||||
if (!IsWow64Process(GetCurrentProcess(), &wow64) || !wow64)
|
||||
{
|
||||
TRACE("not running in wow64, can't restart as 64-bit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
GetWindowsDirectoryW(systemdir, MAX_PATH);
|
||||
wcscat(systemdir, sysnative);
|
||||
#endif
|
||||
|
||||
args = find_arg_start(GetCommandLineW());
|
||||
|
||||
cmdline = HeapAlloc(GetProcessHeap(), 0,
|
||||
(wcslen(systemdir)+wcslen(exe_name)+wcslen(args)+1)*sizeof(WCHAR));
|
||||
|
||||
wcscpy(cmdline, systemdir);
|
||||
wcscat(cmdline, exe_name);
|
||||
wcscat(cmdline, args);
|
||||
|
||||
si.cb = sizeof(si);
|
||||
|
||||
if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
|
||||
{
|
||||
DWORD exit_code;
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
GetExitCodeProcess(pi.hProcess, &exit_code);
|
||||
ExitProcess(exit_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
WINE_TRACE("failed to restart, err=%d\n", GetLastError());
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, cmdline);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
# define ALT_BINARY_TYPE SCS_32BIT_BINARY
|
||||
#else
|
||||
# define ALT_BINARY_TYPE SCS_64BIT_BINARY
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Loads procedure.
|
||||
*
|
||||
|
@ -90,14 +181,22 @@ static void WINAPIV output_write(UINT id, ...)
|
|||
* strDll - name of the dll.
|
||||
* procName - name of the procedure to load from the dll.
|
||||
* DllHandle - a variable that receives the handle of the loaded dll.
|
||||
* firstDll - true if this is the first dll in the command line.
|
||||
*/
|
||||
static VOID *LoadProc(const WCHAR* strDll, const char* procName, HMODULE* DllHandle)
|
||||
static VOID *LoadProc(const WCHAR* strDll, const char* procName, HMODULE* DllHandle, BOOL firstDll)
|
||||
{
|
||||
VOID* (*proc)(void);
|
||||
|
||||
*DllHandle = LoadLibraryExW(strDll, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
if(!*DllHandle)
|
||||
{
|
||||
DWORD binary_type;
|
||||
if (firstDll && GetLastError() == ERROR_BAD_EXE_FORMAT &&
|
||||
GetBinaryTypeW(strDll, &binary_type) &&
|
||||
binary_type == ALT_BINARY_TYPE)
|
||||
{
|
||||
reexec_self();
|
||||
}
|
||||
output_write(STRING_DLL_LOAD_FAILED, strDll);
|
||||
ExitProcess(LOADLIBRARY_FAILED);
|
||||
}
|
||||
|
@ -111,13 +210,13 @@ static VOID *LoadProc(const WCHAR* strDll, const char* procName, HMODULE* DllHan
|
|||
return proc;
|
||||
}
|
||||
|
||||
static int RegisterDll(const WCHAR* strDll)
|
||||
static int RegisterDll(const WCHAR* strDll, BOOL firstDll)
|
||||
{
|
||||
HRESULT hr;
|
||||
DLLREGISTER pfRegister;
|
||||
HMODULE DllHandle = NULL;
|
||||
|
||||
pfRegister = LoadProc(strDll, "DllRegisterServer", &DllHandle);
|
||||
pfRegister = LoadProc(strDll, "DllRegisterServer", &DllHandle, firstDll);
|
||||
if (!pfRegister)
|
||||
return GETPROCADDRESS_FAILED;
|
||||
|
||||
|
@ -134,13 +233,13 @@ static int RegisterDll(const WCHAR* strDll)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int UnregisterDll(const WCHAR* strDll)
|
||||
static int UnregisterDll(const WCHAR* strDll, BOOL firstDll)
|
||||
{
|
||||
HRESULT hr;
|
||||
DLLUNREGISTER pfUnregister;
|
||||
HMODULE DllHandle = NULL;
|
||||
|
||||
pfUnregister = LoadProc(strDll, "DllUnregisterServer", &DllHandle);
|
||||
pfUnregister = LoadProc(strDll, "DllUnregisterServer", &DllHandle, firstDll);
|
||||
if (!pfUnregister)
|
||||
return GETPROCADDRESS_FAILED;
|
||||
|
||||
|
@ -157,13 +256,13 @@ static int UnregisterDll(const WCHAR* strDll)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int InstallDll(BOOL install, const WCHAR *strDll, const WCHAR *command_line)
|
||||
static int InstallDll(BOOL install, const WCHAR *strDll, const WCHAR *command_line, BOOL firstDll)
|
||||
{
|
||||
HRESULT hr;
|
||||
DLLINSTALL pfInstall;
|
||||
HMODULE DllHandle = NULL;
|
||||
|
||||
pfInstall = LoadProc(strDll, "DllInstall", &DllHandle);
|
||||
pfInstall = LoadProc(strDll, "DllInstall", &DllHandle, firstDll);
|
||||
if (!pfInstall)
|
||||
return GETPROCADDRESS_FAILED;
|
||||
|
||||
|
@ -278,11 +377,12 @@ int __cdecl wmain(int argc, WCHAR* argv[])
|
|||
if (argv[i])
|
||||
{
|
||||
WCHAR *DllName = argv[i];
|
||||
BOOL firstDll = !DllFound;
|
||||
res = 0;
|
||||
|
||||
DllFound = TRUE;
|
||||
if (CallInstall && Unregister)
|
||||
res = InstallDll(!Unregister, DllName, wsCommandLine);
|
||||
res = InstallDll(!Unregister, DllName, wsCommandLine, firstDll);
|
||||
|
||||
/* The Windows version stops processing the current file on the first error. */
|
||||
if (res)
|
||||
|
@ -294,9 +394,9 @@ int __cdecl wmain(int argc, WCHAR* argv[])
|
|||
if (!CallInstall || CallRegister)
|
||||
{
|
||||
if(Unregister)
|
||||
res = UnregisterDll(DllName);
|
||||
res = UnregisterDll(DllName, firstDll);
|
||||
else
|
||||
res = RegisterDll(DllName);
|
||||
res = RegisterDll(DllName, firstDll);
|
||||
}
|
||||
|
||||
if (res)
|
||||
|
@ -306,7 +406,7 @@ int __cdecl wmain(int argc, WCHAR* argv[])
|
|||
}
|
||||
|
||||
if (CallInstall && !Unregister)
|
||||
res = InstallDll(!Unregister, DllName, wsCommandLine);
|
||||
res = InstallDll(!Unregister, DllName, wsCommandLine, firstDll);
|
||||
|
||||
if (res)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue