|
|
/*++
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 <pch.h>
#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 <limits.h>
#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<CSsdpService**>(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<HANDLE*>(phContextSync)); } else if (NOTIFY_PROP_CHANGE == nt) { hr = CSsdpNotifyRequestManager::Instance().HrCreatePropChangeNotifyRequest(pphContext, szEventUrl, reinterpret_cast<HANDLE*>(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<HANDLE*>(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<CSsdpNotifyRequest**>(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); } }
|