https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0a8cd95cad36e7518ddb72...
commit 0a8cd95cad36e7518ddb7256b3af9169789285f7 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Fri Jun 22 23:02:25 2018 +0900 Commit: Hermès BÉLUSCA - MAÏTO hermes.belusca-maito@reactos.org CommitDate: Fri Jun 22 16:02:25 2018 +0200
[USERINIT][EXPLORER] Fix auto startup of Start Menu (#594)
- Remove code for Start-Menu auto-startup items from userinit and put it where it belongs: in explorer.
CORE-10839 --- base/shell/explorer/explorer.cpp | 17 ++-- base/shell/explorer/precomp.h | 5 +- base/shell/explorer/startup.cpp | 191 +++++++++++++++++++++++++++++++++------ base/system/userinit/userinit.c | 49 ---------- 4 files changed, 177 insertions(+), 85 deletions(-)
diff --git a/base/shell/explorer/explorer.cpp b/base/shell/explorer/explorer.cpp index a596da1db7..d696290322 100644 --- a/base/shell/explorer/explorer.cpp +++ b/base/shell/explorer/explorer.cpp @@ -24,6 +24,7 @@ HINSTANCE hExplorerInstance; HANDLE hProcessHeap; HKEY hkExplorer = NULL; +BOOL IsSelfTheShell = FALSE;
class CExplorerModule : public CComModule { @@ -132,10 +133,6 @@ StartWithDesktop(IN HINSTANCE hInstance) InitCommonControls(); OleInitialize(NULL);
-#if !WIN7_DEBUG_MODE - ProcessStartupItems(); -#endif - #if !WIN7_COMPAT_MODE /* Initialize shell dde support */ _ShellDDEInit(TRUE); @@ -164,6 +161,12 @@ StartWithDesktop(IN HINSTANCE hInstance) /* WinXP: Notify msgina to hide the welcome screen */ if (!SetShellReadyEvent(L"msgina: ShellReadyEvent")) SetShellReadyEvent(L"Global\msgina: ShellReadyEvent"); + + if (DoStartStartupItems(Tray)) + { + ProcessStartupItems(); + DoFinishStartupItems(); + } #endif
if (Tray != NULL) @@ -204,14 +207,12 @@ _tWinMain(IN HINSTANCE hInstance, InitRSHELL();
#if !WIN7_COMPAT_MODE - BOOL CreateShellDesktop = FALSE; - TRACE("Explorer starting... Commandline: %S\n", lpCmdLine);
if (GetShellWindow() == NULL) - CreateShellDesktop = TRUE; + IsSelfTheShell = TRUE;
- if (!CreateShellDesktop) + if (!IsSelfTheShell) { return StartWithCommandLine(hInstance); } diff --git a/base/shell/explorer/precomp.h b/base/shell/explorer/precomp.h index 228fc75c5f..9369106728 100644 --- a/base/shell/explorer/precomp.h +++ b/base/shell/explorer/precomp.h @@ -230,8 +230,9 @@ HRESULT ShutdownShellServices(HDPA hdpa); * startup.cpp */
-int -ProcessStartupItems(VOID); +BOOL DoStartStartupItems(ITrayWindow *Tray); +INT ProcessStartupItems(VOID); +BOOL DoFinishStartupItems(VOID);
/* * trayprop.h diff --git a/base/shell/explorer/startup.cpp b/base/shell/explorer/startup.cpp index ab7a478a32..125bc0c39f 100644 --- a/base/shell/explorer/startup.cpp +++ b/base/shell/explorer/startup.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2002 Andreas Mohr * Copyright (C) 2002 Shachar Shemesh * Copyright (C) 2013 Edijs Kolesnikovics + * Copyright (C) 2018 Katayama Hirofumi MZ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -40,6 +41,9 @@
#include "precomp.h"
+// For the auto startup process +static HANDLE s_hStartupMutex = NULL; + #define INVALID_RUNCMD_RETURN -1 /** * This function runs the specified command in the specified dir. @@ -259,17 +263,83 @@ end: return res == ERROR_SUCCESS ? TRUE : FALSE; }
+static BOOL +AutoStartupApplications(INT nCSIDL_Folder) +{ + WCHAR szPath[MAX_PATH] = { 0 }; + HRESULT hResult; + HANDLE hFind; + WIN32_FIND_DATAW FoundData; + size_t cchPathLen; + + TRACE("(%d)\n", nCSIDL_Folder); + + // Get the special folder path + hResult = SHGetFolderPathW(NULL, nCSIDL_Folder, NULL, SHGFP_TYPE_CURRENT, szPath); + cchPathLen = wcslen(szPath); + if (!SUCCEEDED(hResult) || cchPathLen == 0) + { + WARN("SHGetFolderPath() failed with error %lu\n", GetLastError()); + return FALSE; + } + + // Build a path with wildcard + StringCbCatW(szPath, sizeof(szPath), L"\*"); + + // Start enumeration of files + hFind = FindFirstFileW(szPath, &FoundData); + if (hFind == INVALID_HANDLE_VALUE) + { + WARN("FindFirstFile(%s) failed with error %lu\n", debugstr_w(szPath), GetLastError()); + return FALSE; + } + + // Enumerate the files + do + { + // Ignore "." and ".." + if (wcscmp(FoundData.cFileName, L".") == 0 || + wcscmp(FoundData.cFileName, L"..") == 0) + { + continue; + } + + // Don't run hidden files + if (FoundData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) + continue; + + // Build the path + szPath[cchPathLen + 1] = UNICODE_NULL; + StringCbCatW(szPath, sizeof(szPath), FoundData.cFileName); + + TRACE("Executing %s in directory %s\n", debugstr_w(FoundData.cFileName), debugstr_w(szPath)); + + DWORD dwType; + if (GetBinaryTypeW(szPath, &dwType)) + { + runCmd(szPath, NULL, TRUE, FALSE); + } + else + { + SHELLEXECUTEINFOW ExecInfo; + ZeroMemory(&ExecInfo, sizeof(ExecInfo)); + ExecInfo.cbSize = sizeof(ExecInfo); + ExecInfo.lpFile = szPath; + ShellExecuteExW(&ExecInfo); + } + } while (FindNextFileW(hFind, &FoundData)); + + FindClose(hFind); + return TRUE; +}
-int -ProcessStartupItems(VOID) +INT ProcessStartupItems(VOID) { /* TODO: ProcessRunKeys already checks SM_CLEANBOOT -- items prefixed with * should probably run even in safe mode */ BOOL bNormalBoot = GetSystemMetrics(SM_CLEANBOOT) == 0; /* Perform the operations that are performed every boot */ /* First, set the current directory to SystemRoot */ WCHAR gen_path[MAX_PATH]; DWORD res; - HKEY hSessionKey, hKey; - HRESULT hr;
res = GetWindowsDirectoryW(gen_path, _countof(gen_path)); if (res == 0) @@ -286,28 +356,9 @@ ProcessStartupItems(VOID) return 100; }
- hr = SHCreateSessionKey(KEY_WRITE, &hSessionKey); - if (SUCCEEDED(hr)) - { - LONG Error; - DWORD dwDisp; - - Error = RegCreateKeyExW(hSessionKey, L"StartupHasBeenRun", 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp); - RegCloseKey(hSessionKey); - if (Error == ERROR_SUCCESS) - { - RegCloseKey(hKey); - if (dwDisp == REG_OPENED_EXISTING_KEY) - { - /* Startup programs has already been run */ - return 0; - } - } - } - /* Perform the operations by order checking if policy allows it, checking if this is not Safe Mode, * stopping if one fails, skipping if necessary. - */ + */ res = TRUE; /* TODO: RunOnceEx */
@@ -320,9 +371,11 @@ ProcessStartupItems(VOID) if (res && bNormalBoot && (SHRestricted(REST_NOCURRENTUSERRUNONCE) == 0)) res = ProcessRunKeys(HKEY_CURRENT_USER, L"Run", FALSE, FALSE);
- /* TODO: All users Startup folder */ + /* All users Startup folder */ + AutoStartupApplications(CSIDL_COMMON_STARTUP);
- /* TODO: Current user Startup folder */ + /* Current user Startup folder */ + AutoStartupApplications(CSIDL_STARTUP);
/* TODO: HKCU\RunOnce runs even if StartupHasBeenRun exists */ if (res && bNormalBoot && (SHRestricted(REST_NOCURRENTUSERRUNONCE) == 0)) @@ -332,3 +385,89 @@ ProcessStartupItems(VOID)
return res ? 0 : 101; } + +static BOOL IsSelfExplorer(VOID) +{ + WCHAR szPath[MAX_PATH], *pch; + static const WCHAR szExplorer[] = L"explorer.exe"; + + GetModuleFileName(NULL, szPath, _countof(szPath)); + + pch = PathFindFileNameW(szPath); + if (pch) + { + return (StrCmpIW(pch, szExplorer) == 0); + } + return (StrCmpIW(szPath, szExplorer) == 0); +} + +BOOL DoFinishStartupItems(VOID) +{ + if (s_hStartupMutex) + { + ReleaseMutex(s_hStartupMutex); + CloseHandle(s_hStartupMutex); + s_hStartupMutex = NULL; + } + return TRUE; +} + +BOOL DoStartStartupItems(ITrayWindow *Tray) +{ + DWORD dwWait; + + if (!IsSelfExplorer()) + return FALSE; + + if (!s_hStartupMutex) + { + // Accidentally, there is possibility that the system starts multiple Explorers + // before startup of shell. We use a mutex to match the timing of shell initialization. + s_hStartupMutex = CreateMutexW(NULL, FALSE, L"ExplorerIsShellMutex"); + if (s_hStartupMutex == NULL) + return FALSE; + } + + dwWait = WaitForSingleObject(s_hStartupMutex, INFINITE); + TRACE("dwWait: 0x%08lX\n", dwWait); + if (dwWait != WAIT_OBJECT_0) + { + TRACE("LastError: %ld\n", GetLastError()); + + DoFinishStartupItems(); + return FALSE; + } + + const DWORD dwWaitTotal = 3000; // in milliseconds + DWORD dwTick = GetTickCount(); + while (GetShellWindow() == NULL && GetTickCount() - dwTick < dwWaitTotal) + { + TrayProcessMessages(Tray); + } + + if (GetShellWindow() == NULL) + { + DoFinishStartupItems(); + return FALSE; + } + + // Check the volatile "StartupHasBeenRun" key + HKEY hSessionKey, hKey; + HRESULT hr = SHCreateSessionKey(KEY_WRITE, &hSessionKey); + if (SUCCEEDED(hr)) + { + ASSERT(hSessionKey); + + DWORD dwDisp; + LONG Error = RegCreateKeyExW(hSessionKey, L"StartupHasBeenRun", 0, NULL, + REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp); + RegCloseKey(hSessionKey); + RegCloseKey(hKey); + if (Error == ERROR_SUCCESS && dwDisp == REG_OPENED_EXISTING_KEY) + { + return FALSE; // Startup programs has already been run + } + } + + return TRUE; +} diff --git a/base/system/userinit/userinit.c b/base/system/userinit/userinit.c index 4d250afa26..4369a499c2 100644 --- a/base/system/userinit/userinit.c +++ b/base/system/userinit/userinit.c @@ -182,53 +182,6 @@ GetShell( } }
-static VOID -StartAutoApplications( - IN INT clsid) -{ - WCHAR szPath[MAX_PATH] = {0}; - HRESULT hResult; - HANDLE hFind; - WIN32_FIND_DATAW findData; - SHELLEXECUTEINFOW ExecInfo; - size_t len; - - TRACE("(%d)\n", clsid); - - hResult = SHGetFolderPathW(NULL, clsid, NULL, SHGFP_TYPE_CURRENT, szPath); - len = wcslen(szPath); - if (!SUCCEEDED(hResult) || len == 0) - { - WARN("SHGetFolderPath() failed with error %lu\n", GetLastError()); - return; - } - - wcscat(szPath, L"\*"); - hFind = FindFirstFileW(szPath, &findData); - if (hFind == INVALID_HANDLE_VALUE) - { - WARN("FindFirstFile(%s) failed with error %lu\n", debugstr_w(szPath), GetLastError()); - return; - } - - do - { - if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (findData.nFileSizeHigh || findData.nFileSizeLow)) - { - ZeroMemory(&ExecInfo, sizeof(ExecInfo)); - ExecInfo.cbSize = sizeof(ExecInfo); - wcscpy(&szPath[len+1], findData.cFileName); - ExecInfo.lpVerb = L"open"; - ExecInfo.lpFile = szPath; - ExecInfo.lpDirectory = NULL; - TRACE("Executing %s in directory %s\n", - debugstr_w(findData.cFileName), debugstr_w(szPath)); - ShellExecuteExW(&ExecInfo); - } - } while (FindNextFileW(hFind, &findData)); - FindClose(hFind); -} - static BOOL TryToStartShell( IN LPCWSTR Shell) @@ -262,8 +215,6 @@ TryToStartShell( return FALSE; }
- StartAutoApplications(CSIDL_STARTUP); - StartAutoApplications(CSIDL_COMMON_STARTUP); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return TRUE;