From b2aeafcad4885ef74457763f069044364b99bc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Mon, 2 Oct 2006 18:46:39 +0000 Subject: [PATCH] Implement CMP_WaitNoPendingInstallEvents Wait for Pnp manager to finish its job before displaying the 2nd stage setup Thanks Filip for his precious help on the umpnpmgr.exe side (not thread-safe as Single linked list functions are not implemented in ntdll) svn path=/trunk/; revision=24365 --- reactos/base/services/umpnpmgr/umpnpmgr.c | 116 ++++++++++++++++++++-- reactos/dll/win32/setupapi/cfgmgr.c | 19 ++++ reactos/dll/win32/setupapi/setupapi.spec | 2 +- reactos/dll/win32/syssetup/install.c | 8 ++ 4 files changed, 138 insertions(+), 7 deletions(-) diff --git a/reactos/base/services/umpnpmgr/umpnpmgr.c b/reactos/base/services/umpnpmgr/umpnpmgr.c index 55ea0c267e5..d51a8f331aa 100644 --- a/reactos/base/services/umpnpmgr/umpnpmgr.c +++ b/reactos/base/services/umpnpmgr/umpnpmgr.c @@ -26,6 +26,7 @@ */ /* INCLUDES *****************************************************************/ +//#define HAVE_SLIST_ENTRY_IMPLEMENTED #define WIN32_NO_STATUS #include #include @@ -61,7 +62,24 @@ static HKEY hClassKey = NULL; static HANDLE hUserToken = NULL; static HANDLE hInstallEvent = NULL; +static HANDLE hNoPendingInstalls = NULL; +#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED +static SLIST_HEADER DeviceInstallListHead; +#else +static LIST_ENTRY DeviceInstallListHead; +#endif +static HANDLE hDeviceInstallListNotEmpty; + +typedef struct +{ +#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED + SLIST_ENTRY ListEntry; +#else + LIST_ENTRY ListEntry; +#endif + WCHAR DeviceIds[1]; +} DeviceInstallParams; /* FUNCTIONS *****************************************************************/ @@ -1437,6 +1455,51 @@ cleanup: } +/* Loop to install all queued devices installations */ +static DWORD WINAPI +DeviceInstallThread(LPVOID lpParameter) +{ +#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED + PSLIST_ENTRY ListEntry; +#else + PLIST_ENTRY ListEntry; +#endif + DeviceInstallParams* Params; + BOOL setupActive; + + setupActive = SetupIsActive(); + + SetEnvironmentVariable(L"USERPROFILE", L"."); /* FIXME: why is it needed? */ + + while (TRUE) + { +#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED + ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead); +#else + if (IsListEmpty(&DeviceInstallListHead)) + ListEntry = NULL; + else + ListEntry = RemoveHeadList(&DeviceInstallListHead); +#endif + if (ListEntry == NULL) + { + SetEvent(hNoPendingInstalls); + DPRINT1("*** EVENT SETTED\n"); + WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE); + } + else + { + ResetEvent(hNoPendingInstalls); + DPRINT1("*** EVENT RESETTED\n"); + Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry); + InstallDevice(Params->DeviceIds, setupActive); + } + } + + return 0; +} + + static DWORD WINAPI PnpEventThread(LPVOID lpParameter) { @@ -1444,15 +1507,12 @@ PnpEventThread(LPVOID lpParameter) ULONG PnpEventSize; NTSTATUS Status; RPC_STATUS RpcStatus; - BOOL setupActive; PnpEventSize = 0x1000; PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize); if (PnpEvent == NULL) return ERROR_OUTOFMEMORY; - setupActive = SetupIsActive(); - for (;;) { DPRINT("Calling NtGetPlugPlayEvent()\n"); @@ -1476,19 +1536,35 @@ PnpEventThread(LPVOID lpParameter) break; } + /* Process the pnp event */ DPRINT("Received PnP Event\n"); if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus)) { + DeviceInstallParams* Params; + DWORD len; + DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds); - InstallDevice(PnpEvent->TargetDevice.DeviceIds, setupActive); + + /* Queue device install (will be dequeued by DeviceInstallThread */ + len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + + wcslen(PnpEvent->TargetDevice.DeviceIds) * sizeof(WCHAR) + sizeof(UNICODE_NULL); + Params = HeapAlloc(GetProcessHeap(), 0, len); + if (Params) + { + wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds); +#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED + InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry); +#else + InsertTailList(&DeviceInstallListHead, &Params->ListEntry); +#endif + SetEvent(hDeviceInstallListNotEmpty); + } } else { DPRINT1("Unknown event\n"); } - /* FIXME: Process the pnp event */ - /* Dequeue the current pnp event and signal the next one */ NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0); } @@ -1507,6 +1583,11 @@ ServiceMain(DWORD argc, LPTSTR *argv) DPRINT("ServiceMain() called\n"); + hNoPendingInstalls = CreateEventW(NULL, + TRUE, + FALSE, + L"Global\\PnP_No_Pending_Install_Events"); + hThread = CreateThread(NULL, 0, PnpEventThread, @@ -1516,6 +1597,15 @@ ServiceMain(DWORD argc, LPTSTR *argv) if (hThread != NULL) CloseHandle(hThread); + hThread = CreateThread(NULL, + 0, + DeviceInstallThread, + NULL, + 0, + &dwThreadId); + if (hThread != NULL) + CloseHandle(hThread); + hThread = CreateThread(NULL, 0, RpcServerThread, @@ -1544,6 +1634,20 @@ main(int argc, char *argv[]) return dwError; } + hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL); + if (hDeviceInstallListNotEmpty == NULL) + { + dwError = GetLastError(); + DPRINT1("Could not create the Event! (Error %lu)\n", dwError); + return dwError; + } + +#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED + InitializeSListHead(&DeviceInstallListHead); +#else + InitializeListHead(&DeviceInstallListHead); +#endif + dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Enum", 0, diff --git a/reactos/dll/win32/setupapi/cfgmgr.c b/reactos/dll/win32/setupapi/cfgmgr.c index 2a2d4b4fe67..c9d196fa52a 100644 --- a/reactos/dll/win32/setupapi/cfgmgr.c +++ b/reactos/dll/win32/setupapi/cfgmgr.c @@ -76,6 +76,25 @@ static BOOL GuidToString(LPGUID Guid, LPWSTR String) } +/*********************************************************************** + * CMP_WaitNoPendingInstallEvents [SETUPAPI.@] + */ +DWORD WINAPI CMP_WaitNoPendingInstallEvents( + DWORD dwTimeout) +{ + HANDLE hEvent; + DWORD ret; + + hEvent = OpenEventW(SYNCHRONIZE, FALSE, L"Global\\PnP_No_Pending_Install_Events"); + if (hEvent == NULL) + return WAIT_FAILED; + + ret = WaitForSingleObject(hEvent, dwTimeout); + CloseHandle(hEvent); + return ret; +} + + /*********************************************************************** * CMP_Init_Detection [SETUPAPI.@] */ diff --git a/reactos/dll/win32/setupapi/setupapi.spec b/reactos/dll/win32/setupapi/setupapi.spec index 87887db48b0..fcd4708a581 100644 --- a/reactos/dll/win32/setupapi/setupapi.spec +++ b/reactos/dll/win32/setupapi/setupapi.spec @@ -7,7 +7,7 @@ @ stub CMP_RegisterNotification @ stdcall CMP_Report_LogOn(long long) @ stub CMP_UnregisterNotification -@ stub CMP_WaitNoPendingInstallEvents +@ stdcall CMP_WaitNoPendingInstallEvents(long) @ stub CMP_WaitServicesAvailable @ stdcall CM_Add_Empty_Log_Conf(ptr ptr long long) @ stdcall CM_Add_Empty_Log_Conf_Ex(ptr ptr long long ptr) diff --git a/reactos/dll/win32/syssetup/install.c b/reactos/dll/win32/syssetup/install.c index 5a2749d8b6f..0561ac2f195 100644 --- a/reactos/dll/win32/syssetup/install.c +++ b/reactos/dll/win32/syssetup/install.c @@ -49,6 +49,8 @@ #include "globals.h" #include "resource.h" +DWORD WINAPI +CMP_WaitNoPendingInstallEvents(DWORD dwTimeout); /* GLOBALS ******************************************************************/ @@ -656,6 +658,12 @@ InstallReactOS (HINSTANCE hInstance) return 0; } + if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0) + { + DebugPrint("CMP_WaitNoPendingInstallEvents() failed!\n"); + return 0; + } + InstallWizard(); SetupCloseInfFile(hSysSetupInf);