diff --git a/base/services/umpnpmgr/event.c b/base/services/umpnpmgr/event.c index 7f104128f7e..feb430d00cf 100644 --- a/base/services/umpnpmgr/event.c +++ b/base/services/umpnpmgr/event.c @@ -118,6 +118,12 @@ VOID ProcessDeviceClassChangeEvent( _In_ PPLUGPLAY_EVENT_BLOCK PnpEvent) { + RPC_STATUS RpcStatus; + PLIST_ENTRY Current; + PNOTIFY_ENTRY pNotifyData; + PDEV_BROADCAST_DEVICEINTERFACE_W pData; + DWORD dwSize; + DPRINT("ProcessDeviceClassChangeEvent(%p)\n", PnpEvent); DPRINT("SymbolicLink: %S\n", PnpEvent->DeviceClass.SymbolicLinkName); DPRINT("ClassGuid: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n", @@ -125,6 +131,50 @@ ProcessDeviceClassChangeEvent( PnpEvent->DeviceClass.ClassGuid.Data4[0], PnpEvent->DeviceClass.ClassGuid.Data4[1], PnpEvent->DeviceClass.ClassGuid.Data4[2], PnpEvent->DeviceClass.ClassGuid.Data4[3], PnpEvent->DeviceClass.ClassGuid.Data4[4], PnpEvent->DeviceClass.ClassGuid.Data4[5], PnpEvent->DeviceClass.ClassGuid.Data4[6], PnpEvent->DeviceClass.ClassGuid.Data4[7]); + + RtlAcquireResourceShared(&NotificationListLock, TRUE); + + Current = NotificationListHead.Flink; + while (Current != &NotificationListHead) + { + pNotifyData = CONTAINING_RECORD(Current, NOTIFY_ENTRY, ListEntry); + if ((pNotifyData->dwType == CLASS_NOTIFICATION) && + ((pNotifyData->ulFlags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES) || + (UuidEqual(&PnpEvent->DeviceClass.ClassGuid, &pNotifyData->ClassGuid, &RpcStatus)))) + { + if ((pNotifyData->ulFlags & DEVICE_NOTIFY_WINDOW_HANDLE) == DEVICE_NOTIFY_WINDOW_HANDLE) + { + dwSize = sizeof(DEV_BROADCAST_DEVICEINTERFACE_W) + wcslen(PnpEvent->DeviceClass.SymbolicLinkName) * sizeof(WCHAR); + pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); + + pData->dbcc_size = dwSize; + pData->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + CopyMemory(&pData->dbcc_classguid, &PnpEvent->DeviceClass.ClassGuid, sizeof(GUID)); + wcscpy(pData->dbcc_name, PnpEvent->DeviceClass.SymbolicLinkName); + + if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_INTERFACE_ARRIVAL, &RpcStatus)) + { + DPRINT("Interface arrival: %S\n", PnpEvent->DeviceClass.SymbolicLinkName); + SendMessageW((HANDLE)pNotifyData->hRecipient, WM_DEVICECHANGE, DBT_DEVICEARRIVAL, (LPARAM)pData); + } + else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_INTERFACE_ARRIVAL, &RpcStatus)) + { + DPRINT("Interface removal: %S\n", PnpEvent->DeviceClass.SymbolicLinkName); + SendMessageW((HANDLE)pNotifyData->hRecipient, WM_DEVICECHANGE, DBT_DEVICEREMOVECOMPLETE, (LPARAM)pData); + } + + HeapFree(GetProcessHeap(), 0, pData); + } + else + { + DPRINT1("Service notification is not implemented yet!\n"); + } + } + + Current = Current->Flink; + } + + RtlReleaseResource(&NotificationListLock); } diff --git a/base/services/umpnpmgr/precomp.h b/base/services/umpnpmgr/precomp.h index 60f22846938..8c71051c160 100644 --- a/base/services/umpnpmgr/precomp.h +++ b/base/services/umpnpmgr/precomp.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -41,10 +42,21 @@ typedef struct WCHAR DeviceIds[ANYSIZE_ARRAY]; } DeviceInstallParams; +typedef enum +{ + CLASS_NOTIFICATION = 1, + TARGET_NOTIFICATION +} NOTIFICATION_TYPE; + + typedef struct { LIST_ENTRY ListEntry; + NOTIFICATION_TYPE dwType; PWSTR pszName; + DWORD_PTR hRecipient; + DWORD ulFlags; + GUID ClassGuid; } NOTIFY_ENTRY, *PNOTIFY_ENTRY; /* event.c */ @@ -78,6 +90,7 @@ DeviceInstallThread( /* rpcserver.c */ extern LIST_ENTRY NotificationListHead; +extern RTL_RESOURCE NotificationListLock; DWORD WINAPI diff --git a/base/services/umpnpmgr/rpcserver.c b/base/services/umpnpmgr/rpcserver.c index 33ff9da1f55..bf216aeff94 100644 --- a/base/services/umpnpmgr/rpcserver.c +++ b/base/services/umpnpmgr/rpcserver.c @@ -37,8 +37,10 @@ /* GLOBALS ******************************************************************/ static WCHAR szRootDeviceInstanceID[] = L"HTREE\\ROOT\\0"; +LUID LoadDriverPrivilege = {SE_LOAD_DRIVER_PRIVILEGE, 0}; LIST_ENTRY NotificationListHead; +RTL_RESOURCE NotificationListLock; /* FUNCTIONS *****************************************************************/ @@ -53,6 +55,7 @@ RpcServerThread(LPVOID lpParameter) DPRINT("RpcServerThread() called\n"); InitializeListHead(&NotificationListHead); + RtlInitializeResource(&NotificationListLock); #if 0 /* 2k/XP/2k3-compatible protocol sequence/endpoint */ @@ -5051,6 +5054,8 @@ PNP_RegisterNotification( pNotifyData = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFY_ENTRY)); if (pNotifyData == NULL) return CR_OUT_OF_MEMORY; + + pNotifyData->dwType = CLASS_NOTIFICATION; if (pszName != NULL) { @@ -5064,8 +5069,20 @@ PNP_RegisterNotification( } } + pNotifyData->hRecipient = hRecipient; + pNotifyData->ulFlags = ulFlags; + + if ((ulFlags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES) == 0) + { + CopyMemory(&pNotifyData->ClassGuid, + &pBroadcastDeviceInterface->dbcc_classguid, + sizeof(GUID)); + } + /* Add the entry to the notification list */ + RtlAcquireResourceExclusive(&NotificationListLock, TRUE); InsertTailList(&NotificationListHead, &pNotifyData->ListEntry); + RtlReleaseResource(&NotificationListLock); DPRINT("pNotifyData: %p\n", pNotifyData); *pNotifyHandle = (PNP_NOTIFY_HANDLE)pNotifyData; @@ -5108,7 +5125,10 @@ PNP_UnregisterNotification( if (pEntry == NULL) return CR_INVALID_DATA; + RtlAcquireResourceExclusive(&NotificationListLock, TRUE); RemoveEntryList(&pEntry->ListEntry); + RtlReleaseResource(&NotificationListLock); + if (pEntry->pszName) RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry->pszName); RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry);