Index: dll/win32/iernonce/CMakeLists.txt =================================================================== --- dll/win32/iernonce/CMakeLists.txt (revision 71098) +++ dll/win32/iernonce/CMakeLists.txt (working copy) @@ -7,5 +7,6 @@ ${CMAKE_CURRENT_BINARY_DIR}/iernonce.def) set_module_type(iernonce win32dll UNICODE) -add_importlibs(iernonce msvcrt kernel32 ntdll) +target_link_libraries(iernonce wine) +add_importlibs(iernonce msvcrt kernel32 ntdll ole32 advapi32) add_cd_file(TARGET iernonce DESTINATION reactos/system32 FOR all) Index: dll/win32/iernonce/iernonce.c =================================================================== --- dll/win32/iernonce/iernonce.c (revision 71098) +++ dll/win32/iernonce/iernonce.c (working copy) @@ -6,16 +6,323 @@ * PROGRAMMERS: Copyright 2013-2016 Robert Naumann */ +#include "iernonce.h" -#define WIN32_NO_STATUS -#include -#include +HINSTANCE hInstance = 0; -#define NDEBUG -#include +static int runCmd(LPWSTR cmdline, LPCWSTR dir, BOOL wait, BOOL minimized) +{ + STARTUPINFOW si; + PROCESS_INFORMATION info; + DWORD exit_code = 0; + WCHAR szCmdLineExp[MAX_PATH+1] = L"\0"; -HINSTANCE hInstance; + ExpandEnvironmentStringsW(cmdline, szCmdLineExp, sizeof(szCmdLineExp) / sizeof(WCHAR)); + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + if (minimized) + { + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_MINIMIZE; + } + memset(&info, 0, sizeof(info)); + + if (!CreateProcessW(NULL, szCmdLineExp, NULL, NULL, FALSE, 0, NULL, dir, &si, &info)) + { + TRACE("Failed to run command (%lu)\n", GetLastError()); + + return -1; + } + + TRACE("Successfully ran command\n"); + + if (wait) + { /* wait for the process to exit */ + WaitForSingleObject(info.hProcess, INFINITE); + GetExitCodeProcess(info.hProcess, &exit_code); + } + + CloseHandle(info.hThread); + CloseHandle(info.hProcess); + + return exit_code; +} + +static void *LoadProc(WCHAR* strDllW, const char* procName, HMODULE* DllHandle) +{ + void *proc; + + *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 HRESULT RunDllRegisterServer(WCHAR* strDll) +{ + HRESULT (WINAPI *pfRegister)(void) = NULL; + HRESULT hr; + HMODULE DllHandle = NULL; + + pfRegister = LoadProc(strDll, "DllRegisterServer", &DllHandle); + + if (!pfRegister) + return ERROR_INVALID_FUNCTION; + + hr = pfRegister(); + + FreeLibrary(DllHandle); + + return hr; +} + +static HRESULT RunDllInstall(WCHAR *strDll, BOOL install, WCHAR *command_line) +{ + HRESULT (WINAPI *pfInstall)(BOOL, WCHAR*) = NULL; + HRESULT hr; + HMODULE DllHandle = NULL; + + pfInstall = LoadProc(strDll, "DllInstall", &DllHandle); + + if (!pfInstall) + return ERROR_INVALID_FUNCTION; + + hr = pfInstall(install, command_line); + + FreeLibrary(DllHandle); + + return hr; +} + +static BOOL ProcessRunOnceExKey(HKEY hkRunEntry) +{ + DWORD i; + DWORD res = S_OK; + 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); + 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)); + res = RunDllRegisterServer(cmd); + WINE_TRACE("DllRegisterServer returned %d\n", res); + } + HeapFree(GetProcessHeap(), 0, cmd); + } + else if (strncmpW(value, KEY_DLLINSTALL, + strlenW(KEY_DLLINSTALL)) == 0) + { + WCHAR *filename, *arg = NULL; + BOOL install = FALSE; + 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 && (third = strstrW(second, pipe)) != NULL) + { + install = (*(second + strlenW(pipe)) == 'I'); + + argLength = strlenW(third) - strlenW(pipe) - 1; + filename = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * argLength); + lstrcpynW(arg, third + strlenW(pipe) + 2, argLength); + } + + filenameLength = strlenW(szCmdLine) - strlenW(first) + strlenW(pipe); + filename = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * filenameLength); + lstrcpynW(filename, szCmdLine, filenameLength); + + WINE_TRACE("DllInstall (%s, %d, %s)\n", + wine_dbgstr_w(filename), + install, + wine_dbgstr_w(arg)); + res = RunDllInstall(filename, install, arg); + WINE_TRACE("DllInstall returned %d\n", res); + HeapFree( GetProcessHeap(), 0, filename ); + if (arg) + HeapFree( GetProcessHeap(), 0, arg ); + } + } else { + if( (res=runCmd(szCmdLine, NULL, TRUE, FALSE ))== -1 ) + { + 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}; + static const WCHAR FLAGS_NAME[]={'F','l','a','g','s',0}; + HKEY hkRunOnceEx, hkRunEntry; + DWORD i, res, flags; + DWORD dwType = REG_DWORD; + DWORD size = sizeof(DWORD); + + WINE_TRACE("processing L\"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; + + if ( (res=RegQueryValueExW(hkRunOnceEx, FLAGS_NAME, + NULL, &dwType,(LPBYTE)&flags, &size)) != ERROR_SUCCESS) + { + WINE_ERR("Couldn't read in RunOnceEx flags %d\n", res ); + flags = ROEF_DISABLED; + //return TRUE; + } + + WINE_TRACE("Flags: %d\n", flags); + + if (flags & ROEF_SHELLSTATUS) + WINE_WARN("flags: shell verification is not implemented\n"); + if (flags & ~ROEF_NOERRORDIALOGS) + WINE_WARN("flags: error dialog is not implemented\n"); + if (flags & ROEF_ERRORLOG) + WINE_WARN("flags: error log is not implemented\n"); + if (flags & ROEF_EXECUTELOG) + WINE_WARN("flags: execute log is not implemented\n"); + if (flags & ROEF_NOEXCTRAP) + WINE_WARN("flags: exception trap is not implemented\n"); + if (flags & ~ROEF_NOSTATUSDIALOG) + WINE_WARN("flags: status dialog is not implemented\n"); + + if( (res=RegDeleteValueW( hkRunOnceEx, FLAGS_NAME ))!=ERROR_SUCCESS ) + WINE_ERR("Couldn't delete flags key %d\n", res ); + + 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\n", + wine_dbgstr_w( szKeyName ), res); + } + } + + if( hkRunOnceEx!=NULL ) + RegCloseKey( hkRunOnceEx ); + + return res==ERROR_SUCCESS; +} + + + BOOL WINAPI DllMain(HINSTANCE hinstDLL, @@ -22,12 +329,14 @@ DWORD dwReason, LPVOID reserved) { + + hInstance = hinstDLL; switch (dwReason) { + OleInitialize(NULL); case DLL_PROCESS_ATTACH: break; case DLL_PROCESS_DETACH: - hInstance = hinstDLL; break; } @@ -36,5 +345,6 @@ VOID WINAPI RunOnceExProcess(HWND hwnd, HINSTANCE hInst, LPCSTR path, int nShow) { - DPRINT1("RunOnceExProcess() not implemented\n"); + ProcessRunOnceEx( HKEY_LOCAL_MACHINE ); + //DPRINT1("RunOnceExProcess() not implemented\n"); } Index: dll/win32/iernonce/iernonce.h =================================================================== --- dll/win32/iernonce/iernonce.h (nonexistent) +++ dll/win32/iernonce/iernonce.h (working copy) @@ -0,0 +1,40 @@ +/* + * PROJECT: ReactOS system libraries + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll\win32\iernonce\iernonce.h + * PURPOSE: ReactOS Extended RunOnce processing with UI + * PROGRAMMERS: Copyright 2016 Robert Naumann + */ +#ifndef _IERNONCE_H_ +#define _IERNONCE_H_ + +#include +#include +#include +#include +#include +#define WIN32_NO_STATUS + +#include "wine/unicode.h" +#include "wine/debug.h" +WINE_DEFAULT_DEBUG_CHANNEL(iernonce); + +typedef enum { + ROEF_DISABLED = 0x00000000, + ROEF_SHELLSTATUS = 0x00000004, + ROEF_NOERRORDIALOGS = 0x00000008, + ROEF_ERRORLOG = 0x00000010, + ROEF_EXECUTELOG = 0x00000020, + ROEF_NOEXCTRAP = 0x00000040, + ROEF_NOSTATUSDIALOG = 0x00000080 +} RunOnceExFlags; + +static int runCmd(LPWSTR cmdline, LPCWSTR dir, BOOL wait, BOOL minimized); +static void *LoadProc(WCHAR* strDllW, const char* procName, HMODULE* DllHandle); +static HRESULT RunDllRegisterServer(WCHAR* strDll); +static HRESULT RunDllInstall(WCHAR *strDll, BOOL install, WCHAR *command_line); +static BOOL ProcessRunOnceExKey(HKEY hkRunEntry); +static BOOL ProcessRunOnceEx( HKEY hkRoot ); +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID reserved); + +#endif \ No newline at end of file Property changes on: dll/win32/iernonce/iernonce.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property