/*++ Copyright (c) 1999-2000 Microsoft Corporation File Name: ssdprpc.c Abstract: This file contains code which implements SSDPSRV.exe rpc interfaces. Author: Ting Cai Created: 07/10/1999 --*/ #include #pragma hdrstop #include "ssdperror.h" #include "ssdpsrv.h" #include "status.h" #include "ssdpfunc.h" #include "ssdptypes.h" #include "ssdpnetwork.h" #include "ncbase.h" #include "ncinet.h" #include "event.h" #include #include "announce.h" #include "search.h" #include "cache.h" #include "notify.h" #include "InterfaceList.h" extern LONG bShutdown; extern HANDLE ShutDownEvent; extern HWND hWnd; // Publication INT _RegisterServiceRpc(PCONTEXT_HANDLE_TYPE *pphContext, SSDP_MESSAGE ssdpMsg, DWORD flags) { if (!pphContext) { return ERROR_INVALID_PARAMETER; } if (ssdpMsg.szUSN == NULL || ssdpMsg.szType == NULL) { return ERROR_INVALID_PARAMETER; } if (ssdpMsg.szAltHeaders == NULL && ssdpMsg.szLocHeader == NULL) { return ERROR_INVALID_PARAMETER; } HRESULT hr = S_OK; hr = CSsdpServiceManager::Instance().HrAddService( &ssdpMsg, flags, pphContext); return hr; } INT _DeregisterServiceRpc(PCONTEXT_HANDLE_TYPE *pphContext, BOOL fByebye) { CSsdpService * pService = *reinterpret_cast(pphContext); HRESULT hr = CSsdpServiceManager::Instance().HrRemoveService(pService, fByebye); *pphContext = NULL; return hr; } INT _DeregisterServiceRpcByUSN( /* [string][in] */ LPSTR szUSN, /* [in] */ BOOL fByebye) { HRESULT hr = E_INVALIDARG; CSsdpService * pService = CSsdpServiceManager::Instance().FindServiceByUsn(szUSN); if(pService) { hr = CSsdpServiceManager::Instance().HrRemoveService(pService, fByebye); } return hr; } // Cache VOID _UpdateCacheRpc(PSSDP_REQUEST CandidateRequest) { SSDP_REQUEST SsdpRequest; if (CandidateRequest) { InitializeSsdpRequest(&SsdpRequest); CopySsdpRequest(&SsdpRequest, CandidateRequest); ConvertToAliveNotify(&SsdpRequest); CSsdpCacheEntryManager::Instance().HrUpdateCacheList(&SsdpRequest, TRUE); FreeSsdpRequest(&SsdpRequest); } } /* VOID _LookupCacheRpc( [size_is][length_is][out][in] unsigned char __RPC_FAR pBuffer[ ], [in] LONG lAllocatedSize, [out][in] LONG __RPC_FAR *plUsedSize) { } */ INT _LookupCacheRpc( /* [string][in] */ LPSTR szType, /* [out] */ MessageList __RPC_FAR *__RPC_FAR *svcList) { if (!szType || !*szType || !svcList) { TraceError("Bad parameter to _LookupCacheRpc", E_INVALIDARG); return -1; } return CSsdpCacheEntryManager::Instance().HrSearchListCache(szType, svcList); } VOID _CleanupCacheRpc() { CSsdpCacheEntryManager::Instance().HrShutdown(); } // Notification // Initialize the synchronization handle INT _InitializeSyncHandle(PCONTEXT_HANDLE_TYPE *pphContextSync) { if (!pphContextSync) { return ERROR_INVALID_PARAMETER; } HANDLE Temp = CreateSemaphore(NULL, 0, LONG_MAX, NULL); if (Temp != NULL) { TraceTag(ttidSsdpNotify, "Created semaphore. %x", Temp); *pphContextSync = Temp; return 0; } else { TraceTag(ttidSsdpNotify, "Failed to create sephamore %d", GetLastError()); *pphContextSync = NULL; return ERROR_NOT_ENOUGH_MEMORY; } } VOID _RemoveSyncHandle( PCONTEXT_HANDLE_TYPE *pphContextSync) { if (!pphContextSync) { return; } HANDLE Temp = *pphContextSync; CSsdpNotifyRequestManager::Instance().HrRemoveNotifyRequest(Temp); TraceTag(ttidSsdpNotify, "Closing semaphore %x", Temp); CloseHandle(Temp); *pphContextSync = NULL; } INT _RegisterNotificationRpc( /* [out] */ PCONTEXT_HANDLE_TYPE __RPC_FAR *pphContext, /* [in] */ PSYNC_HANDLE_TYPE phContextSync, /* [in] */ NOTIFY_TYPE nt, /* [string][unique][in] */ LPSTR szType, /* [string][unique][in] */ LPSTR szEventUrl, /* [out] */ SSDP_REGISTER_INFO __RPC_FAR *__RPC_FAR *ppinfo) { HRESULT hr = S_OK; if (!pphContext || !phContextSync || !ppinfo) { return ERROR_INVALID_PARAMETER; } *pphContext = NULL; if (NOTIFY_ALIVE == nt) { hr = CSsdpNotifyRequestManager::Instance().HrCreateAliveNotifyRequest(pphContext, szType, reinterpret_cast(phContextSync)); } else if (NOTIFY_PROP_CHANGE == nt) { hr = CSsdpNotifyRequestManager::Instance().HrCreatePropChangeNotifyRequest(pphContext, szEventUrl, reinterpret_cast(phContextSync), ppinfo); } else { hr = ERROR_INVALID_PARAMETER; } return HRESULT_CODE(hr); } INT _GetNotificationRpc(PCONTEXT_HANDLE_TYPE phContextSync, MessageList **svcList) { if (!phContextSync || !svcList) { return ERROR_INVALID_PARAMETER; } TraceTag(ttidSsdpNotify, "Waiting on notification semaphore %x", phContextSync); HANDLE rgHandles[2]; DWORD dwRet; HRESULT hr = S_OK; rgHandles[0] = phContextSync; rgHandles[1] = ShutDownEvent; dwRet = WaitForMultipleObjects(2, rgHandles, FALSE, INFINITE); TraceTag(ttidSsdpNotify, "Semaphore %x released", phContextSync); if (WAIT_OBJECT_0 == dwRet) { hr = CSsdpNotifyRequestManager::Instance().HrRetreivePendingNotification(reinterpret_cast(phContextSync), svcList); } else { AssertSz(dwRet == WAIT_OBJECT_0 + 1, "Wait on semaphore satisfied for " "some other reason!"); TraceTag(ttidSsdpNotify, "Semaphore released because server is " "shutting down..."); } #if DBG if(svcList && *svcList) { if(0 == (*svcList)->size) { TraceTag(ttidSsdpNotify, "_GetNotificationRpc - HrRetreivePendingNotification returned nothing - must be in shutdown"); } else if(1 == (*svcList)->size) { SSDP_REQUEST * pRequest = (*svcList)->list; if(pRequest->Headers[SSDP_NTS] && !lstrcmpiA(pRequest->Headers[SSDP_NTS], "upnp:propchange")) { TraceTag(ttidSsdpNotify, "_GetNotificationRpc - upnp:propchange - SEQ:%s - SID:%s", pRequest->Headers[GENA_SEQ], pRequest->Headers[GENA_SID]); } else if(pRequest->Headers[SSDP_NTS] && !lstrcmpiA(pRequest->Headers[SSDP_NTS], "ssdp:alive")) { TraceTag(ttidSsdpNotify, "_GetNotificationRpc - ssdp:alive - NT:%s", pRequest->Headers[SSDP_NT]); } } } #endif // DBG return hr; } INT _WakeupGetNotificationRpc(PCONTEXT_HANDLE_TYPE phContextSync) { LONG PreviousCount = 0; if (!phContextSync) { return ERROR_INVALID_PARAMETER; } if (ReleaseSemaphore(phContextSync, 1, &PreviousCount) == TRUE) { TraceTag(ttidSsdpNotify, "Released Semaphore %x by 1, Previous count " "is %d", phContextSync, PreviousCount); return 0; } else { TraceTag(ttidSsdpNotify, "Failed to release semaphore %x, error code " "%d", phContextSync, GetLastError()); return GetLastError(); } } INT _DeregisterNotificationRpc(PCONTEXT_HANDLE_TYPE *pphContext, BOOL fLast) { CSsdpNotifyRequest * pRequest = *reinterpret_cast(pphContext); INT ret = CSsdpNotifyRequestManager::Instance().HrRemoveNotifyRequestByPointer(pRequest); *pphContext = NULL; return ret; } void _EnableDeviceHost() { CUPnPInterfaceList::Instance().HrSetGlobalEnable(); } void _DisableDeviceHost() { CUPnPInterfaceList::Instance().HrClearGlobalEnable(); } void _SetICSInterfaces(/*[in]*/ long nCount, /*[in, size_is(nCount)]*/ GUID * arInterfaces) { CUPnPInterfaceList::Instance().HrSetICSInterfaces(nCount, arInterfaces); } void _SetICSOff() { CUPnPInterfaceList::Instance().HrSetICSOff(); } VOID _Shutdown(VOID) { // Set network and announcemnt state ? TraceTag(ttidSsdpRpcIf, "Shutdown is called."); // T-Cleanup // Sleep(15000); // 15 seconds // T-Clean expires // Temporary testing // WriteListCacheToFile(); InterlockedIncrement(&bShutdown); if (PostMessage(hWnd, WM_QUIT, 0, 0) == FALSE) { TraceTag(ttidSsdpRpcInit, "PostThreadMessage failed with %d", GetLastError()); } else { TraceTag(ttidSsdpRpcInit, "PostThreadMessage was successful", GetLastError()); } TraceTag(ttidSsdpRpcInit, "Setting shut down event"); if (SetEvent(ShutDownEvent) == 0) { TraceTag(ttidSsdpRpcInit, "Failed to set shut down event (%d)", GetLastError()); } // Cleanup will continue in main. } VOID __RPC_USER PCONTEXT_HANDLE_TYPE_rundown( PCONTEXT_HANDLE_TYPE pContext) { if (pContext) { CSsdpRundownSupport::Instance().DoRundown(pContext); } } VOID __RPC_USER PSYNC_HANDLE_TYPE_rundown( PCONTEXT_HANDLE_TYPE pContext) { TraceTag(ttidSsdpRpcIf, "rundown routine is called on sync context %x.",pContext); if (pContext) { _RemoveSyncHandle(&pContext); } }