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
This commit is contained in:
Hervé Poussineau 2006-10-02 18:46:39 +00:00
parent 4cfbdb6f63
commit b2aeafcad4
4 changed files with 138 additions and 7 deletions

View file

@ -26,6 +26,7 @@
*/
/* INCLUDES *****************************************************************/
//#define HAVE_SLIST_ENTRY_IMPLEMENTED
#define WIN32_NO_STATUS
#include <windows.h>
#include <cmtypes.h>
@ -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,

View file

@ -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.@]
*/

View file

@ -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)

View file

@ -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);