windows-nt/Source/XPSP1/NT/net/upnp/ssdp/common/ssdpsrv/ssdprpc.cpp
2020-09-26 16:20:57 +08:00

386 lines
9.2 KiB
C++

/*++
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);
}
}