386 lines
9.2 KiB
C++
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);
|
||
|
}
|
||
|
}
|