https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0a8cd95cad36e7518ddb7…
commit 0a8cd95cad36e7518ddb7256b3af9169789285f7
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Fri Jun 22 23:02:25 2018 +0900
Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)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;