[USERINIT][EXPLORER] Fix auto startup of Start Menu (#594)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Fri, 22 Jun 2018 14:02:25 +0000 (23:02 +0900)
committerHermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
Fri, 22 Jun 2018 14:02:25 +0000 (16:02 +0200)
- 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
base/shell/explorer/precomp.h
base/shell/explorer/startup.cpp
base/system/userinit/userinit.c

index a596da1..d696290 100644 (file)
@@ -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);
     }
index 228fc75..9369106 100644 (file)
@@ -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
index ab7a478..125bc0c 100644 (file)
@@ -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;
+}
index 4d250af..4369a49 100644 (file)
@@ -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;