diff --git a/programs/wineboot/Makefile.in b/programs/wineboot/Makefile.in index cdbab2e..3be7e22 100644 --- a/programs/wineboot/Makefile.in +++ b/programs/wineboot/Makefile.in @@ -4,7 +4,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = wineboot.exe APPMODE = -mconsole -IMPORTS = uuid advapi32 kernel32 ntdll +IMPORTS = uuid advapi32 ole32 kernel32 ntdll DELAYIMPORTS = setupapi shell32 shlwapi version user32 C_SRCS = \ diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c index 717a175..4a91c37 100644 --- a/programs/wineboot/wineboot.c +++ b/programs/wineboot/wineboot.c @@ -86,6 +86,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(wineboot); #define MAX_LINE_LENGTH (2*MAX_PATH+2) +typedef HRESULT (*DLLREGISTER) (void); +typedef HRESULT (*DLLINSTALL) (BOOL,LPCWSTR); + extern BOOL shutdown_close_windows( BOOL force ); extern void kill_processes( BOOL kill_desktop ); @@ -157,6 +160,65 @@ done: return ret; } +static VOID *LoadProc(WCHAR* strDllW, const char* procName, HMODULE* DllHandle) +{ + VOID* (*proc)(void); + + *DllHandle = LoadLibraryExW(strDllW, 0, LOAD_WITH_ALTERED_SEARCH_PATH); + if(!*DllHandle) + { + WINE_TRACE("LoadLibraryEx failed %s\n", + wine_dbgstr_w(strDllW)); + return NULL; + } + proc = (VOID *) GetProcAddress(*DllHandle, procName); + if (!proc) + { + WINE_TRACE("GetProcAddress failed (%s -> %s)\n", + wine_dbgstr_w(strDllW), procName); + FreeLibrary(*DllHandle); + return NULL; + } + return proc; +} + +static int RunDllRegisterServer(WCHAR* strDll) +{ + DLLREGISTER pfRegister = NULL; + HRESULT hr; + HMODULE DllHandle = NULL; + + pfRegister = LoadProc(strDll, "DllRegisterServer", &DllHandle); + + if (!pfRegister) + return -1; + + hr = pfRegister(); + + if(DllHandle) + FreeLibrary(DllHandle); + + return hr; +} + +static HRESULT RunDllInstall(WCHAR *strDll, BOOL install, WCHAR *command_line) +{ + DLLINSTALL pfInstall = NULL; + HRESULT hr; + HMODULE DllHandle = NULL; + + pfInstall = LoadProc(strDll, "DllInstall", &DllHandle); + + if (!pfInstall) + return -1; + + hr = pfInstall(install, command_line); + + if(DllHandle) + FreeLibrary(DllHandle); + return hr; +} + /* Performs the rename operations dictated in %SystemRoot%\Wininit.ini. * Returns FALSE if there was an error, or otherwise if all is ok. */ @@ -526,6 +588,197 @@ end: return res==ERROR_SUCCESS; } +static BOOL ProcessRunOnceExKey(HKEY hkRunEntry) +{ + DWORD i; + DWORD res; + DWORD nMaxCmdLine=0, nMaxValue=0; + WCHAR *szCmdLine=NULL; + WCHAR *szValue=NULL; + static const WCHAR KEY_DLLREGISTERSERVER[]={ + 'D','l','l','R','e','g','i','s','t','e','r','S','e','r','v','e','r',0}; + static const WCHAR KEY_DLLINSTALL[]={ + 'D','l','l','I','n','s','t','a','l','l',0}; + + if( (res=RegQueryInfoKeyW( hkRunEntry, NULL, NULL, NULL, NULL, NULL, NULL, &i, &nMaxValue, + &nMaxCmdLine, NULL, NULL ))!=ERROR_SUCCESS ) + goto end; + + + if( (szCmdLine=HeapAlloc(GetProcessHeap(),0,nMaxCmdLine))==NULL ) + { + WINE_ERR("Couldn't allocate memory for the commands to be executed\n"); + + res=ERROR_NOT_ENOUGH_MEMORY; + goto end; + } + + if( (szValue=HeapAlloc(GetProcessHeap(),0,(++nMaxValue)*sizeof(*szValue)))==NULL ) + { + WINE_ERR("Couldn't allocate memory for the value names\n"); + + res=ERROR_NOT_ENOUGH_MEMORY; + goto end; + } + + while( i>0 ) + { + DWORD nValLength=nMaxValue, nDataLength=nMaxCmdLine; + DWORD type; + WCHAR *first, *second, *third; /* | separated parts of the entry */ + WCHAR pipe[] = {'|',0}; + i--; + + if( (res=RegEnumValueW( hkRunEntry, i, szValue, &nValLength, 0, &type, + (LPBYTE)szCmdLine, &nDataLength ))!=ERROR_SUCCESS ) + { + WINE_ERR("Couldn't read in value %d - %d\n", i, res ); + break; + } + + if (strlenW(szValue) == 0) + { + WINE_TRACE("Processing %s entries\n", wine_dbgstr_w( szCmdLine )); + continue; + } + + if( type!=REG_SZ ) + { + WINE_ERR("Incorrect type of value #%d (%d)\n", i, type ); + continue; + } + + if( (res=RegDeleteValueW( hkRunEntry, szValue ))!=ERROR_SUCCESS ) + { + WINE_ERR("Couldn't delete value - %d, %d. Running command anyways.\n", i, res ); + } + + if ((first = strstrW(szCmdLine, pipe)) != NULL) + { + WCHAR *value = first + strlenW(pipe); + HRESULT retval; + if (strncmpW(value, KEY_DLLREGISTERSERVER, + strlenW(KEY_DLLREGISTERSERVER)) == 0) + { + DWORD len; + WCHAR *cmd; + len = strlenW(szCmdLine) - strlenW(first) + strlenW(pipe); + cmd = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * len); + if (cmd == NULL) + goto end; + + if (lstrcpynW(cmd, szCmdLine, len)) + { + WINE_TRACE("DllRegisterServer %s\n", wine_dbgstr_w(cmd)); + retval = RunDllRegisterServer(cmd); + WINE_TRACE("DllRegisterServer returned %d\n", retval); + } + HeapFree(GetProcessHeap(), 0, cmd); + } + else if (strncmpW(value, KEY_DLLINSTALL, + strlenW(KEY_DLLINSTALL)) == 0) + { + WCHAR *filename, *arg = NULL; + WCHAR install = FALSE; + HRESULT retval; + DWORD filenameLength, argLength; + + /* filename|DllInstall + * filename|DllInstall|i,arg + * filename|DllInstall|I,arg + * FIXME: is i=FALSE,I=TRUE or the reverse? + */ + second = strstrW(first + strlenW(pipe), pipe); + if (second == NULL) + filenameLength = strlenW(szCmdLine) - strlenW(first) + strlenW(pipe); + else if ((third = strstrW(second, pipe)) != NULL) + { + filenameLength = strlenW(szCmdLine) - strlenW(first) + strlenW(pipe); + install = *(second + strlenW(pipe)); + + argLength = strlenW(third) - strlenW(pipe) - 1; + filename = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * argLength); + lstrcpynW(arg, third + strlenW(pipe) + 2, argLength); + } + + filename = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * filenameLength); + lstrcpynW(filename, szCmdLine, filenameLength); + + WINE_TRACE("DllInstall (%s, %d, %s)\n", + wine_dbgstr_w(filename), + install == 'i', + wine_dbgstr_w(arg)); + retval = RunDllInstall(filename, install == 'i', arg); + WINE_TRACE("DllInstall returned %d\n", retval); + HeapFree( GetProcessHeap(), 0, filename ); + if (arg) + HeapFree( GetProcessHeap(), 0, arg ); + } + } else { + if( (res=runCmd(szCmdLine, NULL, TRUE, FALSE ))==INVALID_RUNCMD_RETURN ) + { + WINE_ERR("Error running cmd #%d (%d)\n", i, GetLastError() ); + } + } + } + end: + HeapFree( GetProcessHeap(), 0, szValue ); + HeapFree( GetProcessHeap(), 0, szCmdLine ); + + return res; +} + +static BOOL ProcessRunOnceEx( HKEY hkRoot ) +{ + static const WCHAR WINKEY_NAME[]={'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','E','x',0}; + HKEY hkRunOnceEx, hkRunEntry; + DWORD res; + DWORD i; + + WINE_TRACE("processing RunOnceEx entries under %s\n", hkRoot==HKEY_LOCAL_MACHINE ? "HKLM" : "HKCU"); + + if (RegOpenKeyExW( hkRoot, WINKEY_NAME, 0, KEY_ALL_ACCESS, &hkRunOnceEx ) != ERROR_SUCCESS) + return TRUE; + + i = 0; + while( 1 ) + { + WCHAR szKeyName[2048]; + + res = RegEnumKeyW( hkRunOnceEx, i, szKeyName, 2048); + if ( res==ERROR_NO_MORE_ITEMS ) + break; + else if( res!=ERROR_SUCCESS ) + { + WINE_ERR("Couldn't read in value %d - %d\n", i, res ); + break; + } + i++; + + if (RegOpenKeyExW( hkRunOnceEx, szKeyName, 0, KEY_ALL_ACCESS, &hkRunEntry ) != ERROR_SUCCESS) + return TRUE; + + ProcessRunOnceExKey( hkRunEntry ); + + RegCloseKey( hkRunEntry ); + + if( (res=RegDeleteKeyW( hkRunOnceEx, szKeyName ))!=ERROR_SUCCESS ) + { + WINE_ERR("Couldn't delete key - %s, %d. Running command anyways.\n", + wine_dbgstr_w( szKeyName ), res ); + } + } + if( hkRunOnceEx!=NULL ) + RegCloseKey( hkRunOnceEx ); + + WINE_TRACE("done\n"); + + return res==ERROR_SUCCESS; +} + /* * WFP is Windows File Protection, in NT5 and Windows 2000 it maintains a cache * of known good dlls and scans through and replaces corrupted DLLs with these @@ -824,6 +1077,8 @@ int main( int argc, char *argv[] ) HANDLE event; SECURITY_ATTRIBUTES sa; + OleInitialize(NULL); + GetWindowsDirectoryW( windowsdir, MAX_PATH ); if( !SetCurrentDirectoryW( windowsdir ) ) WINE_ERR("Cannot set the dir to %s (%d)\n", wine_dbgstr_w(windowsdir), GetLastError() ); @@ -875,6 +1130,8 @@ int main( int argc, char *argv[] ) ProcessRunKeys( HKEY_LOCAL_MACHINE, runkeys_names[RUNKEY_RUNONCE], TRUE, TRUE ); + ProcessRunOnceEx( HKEY_LOCAL_MACHINE ); + if (!init && !restart) { ProcessRunKeys( HKEY_LOCAL_MACHINE, runkeys_names[RUNKEY_RUN], FALSE, FALSE );