📄 devsvc.cpp
字号:
}
*pcchBuf = cch; // set the required length in any case
}
else
SetLastError(ERROR_NOT_FOUND);
pDevTree->DecRef();
}
return fRet;
}
/*
* UpnpGetSCPDPathImpl:
*
* - device name must not be null or empty string to retrieve a device record
* - udn and service id must not be null or empty string to retrieve a service record
* - the service control point description count must not be zero to get the path
*
*/
BOOL
UpnpGetSCPDPathImpl(
__in ce::marshal_arg<ce::copy_in, PCWSTR> pszDeviceName, // [in] local device name
__in ce::marshal_arg<ce::copy_in, PCWSTR> pszUDN, // [in] device UDN
__in ce::marshal_arg<ce::copy_in, PCWSTR> pszServiceId, // [in] serviceId (from device description)
__out ce::marshal_arg<ce::copy_out, ce::psl_buffer_wrapper<PWSTR> > SCPDFilePath) // [out] service control point description file path
{
if(!pszDeviceName || !*pszDeviceName)
{
goto Finish;
}
if(!pszUDN || !*pszUDN)
{
goto Finish;
}
if(!pszServiceId || !*pszServiceId)
{
goto Finish;
}
if(!(SCPDFilePath.count()))
{
goto Finish;
}
return UpnpGetSCPDPathImpl((PCWSTR) pszDeviceName, (PCWSTR) pszUDN, (PCWSTR) pszServiceId, static_cast<ce::psl_buffer_wrapper<PWSTR> >(SCPDFilePath));
Finish:
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/*
* UpnpGetSCPDPathImpl:
*
* - get the upnp service control point description path
*
*/
BOOL UpnpGetSCPDPathImpl(__in PCWSTR pszDeviceName, __in PCWSTR pszUDN, __in PCWSTR pszServiceId, __out ce::psl_buffer_wrapper<PWSTR>& SCPDFilePath)
{
BOOL fRet = FALSE;
HostedDeviceTree *pDevTree;
HostedService *pService;
pDevTree = FindDevTreeSafe(pszDeviceName);
if (pDevTree)
{
pService = pDevTree->FindService(pszUDN, pszServiceId);
if (pService)
{
PCWSTR pszPath;
if (pszPath = pService->SCPDPath())
{
DWORD cch;
cch = wcslen(pszPath)+1;
if (*pszPath != '\\')
{
// the path is not absolute. Prepend the upnp resource path.
cch += celems(c_szLocalWebRootDir) - 1;
}
if (SCPDFilePath.count() >= cch)
{
PWSTR pszSCPDFilePath = SCPDFilePath.buffer();
*pszSCPDFilePath = 0;
if (*pszPath != '\\')
wcscpy(pszSCPDFilePath, c_szLocalWebRootDir);
wcscat(pszSCPDFilePath, pszPath);
fRet = TRUE;
}
else
SetLastError(ERROR_INSUFFICIENT_BUFFER);
}
else
SetLastError(ERROR_NOT_FOUND);
}
else
SetLastError(ERROR_NO_MATCH); // error ?
pDevTree->DecRef();
}
return fRet;
}
/*
* SetRawControlResponseImpl:
*
* - ensure that the response string is not null or empty string
*
*/
BOOL SetRawControlResponseImpl(__in DWORD hRequest, __in DWORD dwHttpStatus, __in ce::marshal_arg<ce::copy_in, PCWSTR> pszResp)
{
if(!pszResp || !*pszResp)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return SetRawControlResponseImpl(hRequest, dwHttpStatus, (PCWSTR) pszResp);
}
/*
* SetRawControlResponseImpl:
*
* - called from the device implementation, while processing the UPnP control request
* - locate the owning ControlRequest from the UPNPSERVICECONTROL structure and
* - set the response bytes that are to be returned to the control point
*
*/
BOOL SetRawControlResponseImpl(__in DWORD hRequest, __in DWORD dwHttpStatus, __in PCWSTR pszResp)
{
HostedDeviceTree *pDevTree;
BOOL fRet = FALSE;
pDevTree = FindDevTreeSafe((PCWSTR)hRequest);
if (pDevTree)
{
fRet = pDevTree->SetControlResponse(dwHttpStatus, pszResp);
pDevTree->DecRef();
}
return fRet;
}
/*
* UpnpSubmitPropertyEventImpl:
*
* - device name must be non-null and not empty
* - udn and service id must be non-null and not the empty string
* - the number of UPNPPARAMS must not be zero
*
*/
BOOL
UpnpSubmitPropertyEventImpl(
__in ce::marshal_arg<ce::copy_in, PCWSTR> pszDeviceName,
__in ce::marshal_arg<ce::copy_in, PCWSTR> pszUDN,
__in ce::marshal_arg<ce::copy_in, PCWSTR> pszServiceId,
__in ce::marshal_arg<ce::copy_array_in, ce::psl_buffer_wrapper<UPNPPARAM*> > Args)
{
if(!pszDeviceName || !*pszDeviceName)
{
goto Finish;
}
if(!pszUDN || !*pszUDN)
{
goto Finish;
}
if(!pszServiceId || !*pszServiceId)
{
goto Finish;
}
if(!Args.count())
{
goto Finish;
}
return UpnpSubmitPropertyEventImpl((PCWSTR) pszDeviceName, (PCWSTR) pszUDN, (PCWSTR) pszServiceId, static_cast<ce::psl_buffer_wrapper<UPNPPARAM*> >(Args));
Finish:
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/*
* UpnpSubmitPropertyEventImpl:
*
* - notifies the target service of parameter eventing
*
*/
BOOL UpnpSubmitPropertyEventImpl(__in PCWSTR pszDeviceName, __in PCWSTR pszUDN, __in PCWSTR pszServiceId, __in ce::psl_buffer_wrapper<UPNPPARAM*> Args)
{
BOOL fRet = FALSE;
HostedDeviceTree *pDevTree = NULL;
pDevTree = FindDevTreeSafe(pszDeviceName);
if (pDevTree)
{
fRet = pDevTree->SubmitPropertyEvent(pszUDN,
pszServiceId,
F_MARK_MODIFIED,
Args.count(),
Args.buffer());
pDevTree->DecRef();
}
return fRet;
}
/*
* UpnpUpdateEventedVariablesImpl:
*
* - device name must be non-null and not empty
* - udn and service id must be non-null and not the empty string
* - the number of UPNPPARAMS must not be zero
*
*/
BOOL
UpnpUpdateEventedVariablesImpl(
__in ce::marshal_arg<ce::copy_in, PCWSTR> pszDeviceName,
__in ce::marshal_arg<ce::copy_in, PCWSTR> pszUDN,
__in ce::marshal_arg<ce::copy_in, PCWSTR> pszServiceId,
__in ce::marshal_arg<ce::copy_array_in, ce::psl_buffer_wrapper<UPNPPARAM*> > Args)
{
if(!pszDeviceName || !*pszDeviceName)
{
goto Finish;
}
if(!pszUDN || !*pszUDN)
{
goto Finish;
}
if(!pszServiceId || !*pszServiceId)
{
goto Finish;
}
if(!Args.count())
{
goto Finish;
}
return UpnpUpdateEventedVariablesImpl((PCWSTR) pszDeviceName, (PCWSTR) pszUDN, (PCWSTR) pszServiceId, static_cast<ce::psl_buffer_wrapper<UPNPPARAM*> >(Args));
Finish:
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/*
* UpnpUpdateEventedVariablesImpl:
*
*
*/
BOOL UpnpUpdateEventedVariablesImpl(__in PCWSTR pszDeviceName, __in PCWSTR pszUDN, __in PCWSTR pszServiceId, __in ce::psl_buffer_wrapper<UPNPPARAM*> Args)
{
BOOL fRet = FALSE;
HostedDeviceTree *pDevTree = NULL;
pDevTree = FindDevTreeSafe(pszDeviceName);
if (pDevTree)
{
fRet = pDevTree->SubmitPropertyEvent(pszUDN,
pszServiceId,
0,
Args.count(),
Args.buffer());
pDevTree->DecRef();
}
return fRet;
}
/*
* InitializeReceiveInvokeRequestImpl:
*
* - initializes the environment for the calling user-mode process of the service
* - creates a dispatch gate
* - if the dispatch gate is already in the system then this routine returns false
*
*/
BOOL
InitializeReceiveInvokeRequestImpl()
{
return DispatchGate::AddDispatchGateForProc(GetCallerProcess());
}
/*
* ReceiveInvokeRequestImpl:
*
* - ensure that the invoke request buffer is valid
* - ensure that the invoke request size buffer is valid
*
*/
BOOL
ReceiveInvokeRequestImpl(
__in DWORD retCode,
__out ce::marshal_arg<ce::copy_out, ce::psl_buffer_wrapper<PBYTE> > pReqBuf,
__out ce::marshal_arg<ce::copy_out, PDWORD> pcbReqBuf)
{
if(!pReqBuf.count() || !pcbReqBuf)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return ReceiveInvokeRequestImpl(retCode, static_cast<ce::psl_buffer_wrapper<PBYTE> >(pReqBuf), static_cast<PDWORD>(pcbReqBuf));
}
/**
* ReceiveInvokeRequestImpl:
*
* - blocks waiting to receive a UPNP message for the calling usermode process
* - reuses an existing dispatch gate for the process or creates a new one
* - returns to the caller once a new UPNP message has been received
* - copies the new UPNP message into the users buffer
*
*/
BOOL ReceiveInvokeRequestImpl(__in DWORD retCode, __out ce::psl_buffer_wrapper<PBYTE>& pReqBuf, __out PDWORD pcbReqBuf)
{
HANDLE hCallerProc = GetCallerProcess();
DispatchGate *pCBGate = NULL;
BOOL fRet = TRUE;
DWORD cbReqBuf = pReqBuf.count();
TraceTag(ttidTrace, "%s: Receive Next Invoke Request for Process[%08x]\n", __FUNCTION__, hCallerProc);
// get the dispatch gate for the calling process
pCBGate = DispatchGate::FindDispatchGateForProc(hCallerProc);
if (!pCBGate)
{
// this can occur on shutdown of the request handler thread
TraceTag(ttidError, "%s: Could not find DispatchGate for Process[%08x]\n", __FUNCTION__, hCallerProc);
return FALSE;
}
// if we should notify the invoke request thread
pCBGate->CheckResetMutexRequestor(retCode);
TraceTag(ttidControl, "%s: get UPNP message for Process [%08x]\n", __FUNCTION__, hCallerProc);
pCBGate->SetCallerBuffer(pReqBuf.buffer(), cbReqBuf, pcbReqBuf);
fRet = pCBGate->WaitForRequests(INFINITE);
if (!fRet)
{
// exit if there is an error may be a shutdown request
TraceTag(ttidControl, "%s: failure waiting for incoming request for Process [%08x]\n", __FUNCTION__, hCallerProc);
goto Finish;
}
fRet = pCBGate->DispatchRequest();
if (!fRet)
{
TraceTag(ttidControl, "%s: failure dispatching incoming request for Proc %x\n", __FUNCTION__, hCallerProc);
}
Finish:
TraceTag(ttidControl, "%s: returning received UPNP message for Process[%08x] [%S]\n", __FUNCTION__, hCallerProc, fRet ? L"TRUE" : L"FALSE");
pCBGate->DecRef();
return fRet;
}
/**
* CancelReceiveInvokeRequestImpl:
*
*
*
*/
BOOL
CancelReceiveInvokeRequestImpl()
{
DispatchGate *pCBGate = NULL;
HANDLE hProc = GetCallerProcess();
TraceTag(ttidControl, "%s: entered for Process[%08x]\n", __FUNCTION__, hProc);
pCBGate = DispatchGate::RemoveDispatchGateForProc(hProc);
if (pCBGate)
{
BOOL fRet;
EnterCriticalSection(&g_csUPNP);
fRet = pCBGate->Shutdown(); // mark the thread as shutting down
LeaveCriticalSection(&g_csUPNP);
pCBGate->DecRef(); // release this reference
return fRet;
}
return FALSE;
}
BOOL SubscribeCallback(BOOL fSubscribe, PSTR pszUri)
{
HostedDeviceTree *pDevTree;
LPWSTR pszServiceId;
LPWSTR pszUDN;
BOOL fRet = FALSE;
pDevTree = FindDevTreeAndServiceIdFromUri(pszUri, &pszUDN, &pszServiceId);
if (pDevTree)
{
Assert(pszServiceId);
Assert(pszUDN);
fRet = fSubscribe ? pDevTree->Subscribe(pszUDN, pszServiceId) : pDevTree->Unsubscribe(pszUDN, pszServiceId);
pDevTree->DecRef();
delete [] pszServiceId;
delete [] pszUDN;
}
return fRet;
}
//
// Called when a process is going away.
// There is an assumption that only one handle is opened by a process
// We have to remove all the device trees hosted by the going-away process
//
void
UpnpCleanUpProc(
HANDLE hOwner
)
{
LIST_ENTRY *pLink;
HostedDeviceTree *pDevTree = NULL;
while (1)
{
EnterCriticalSection(&g_csUPNP);
for (pLink = g_DevTreeList.Flink; pLink != &g_DevTreeList; pLink = pLink->Flink)
{
pDevTree = CONTAINING_RECORD(pLink, HostedDeviceTree, m_link);
if (pDevTree->Owner() == hOwner)
{
pDevTree->RemoveFromList();
break;
}
}
LeaveCriticalSection(&g_csUPNP);
if (pLink == &g_DevTreeList)
break; // no more devices hosted in the specified process
pDevTree->Shutdown(HDT_NO_CALLBACKS);
delete pDevTree;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -