Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

385 lines
9.2 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. File Name:
  4. ssdprpc.c
  5. Abstract:
  6. This file contains code which implements SSDPSRV.exe rpc interfaces.
  7. Author: Ting Cai
  8. Created: 07/10/1999
  9. --*/
  10. #include <pch.h>
  11. #pragma hdrstop
  12. #include "ssdperror.h"
  13. #include "ssdpsrv.h"
  14. #include "status.h"
  15. #include "ssdpfunc.h"
  16. #include "ssdptypes.h"
  17. #include "ssdpnetwork.h"
  18. #include "ncbase.h"
  19. #include "ncinet.h"
  20. #include "event.h"
  21. #include <limits.h>
  22. #include "announce.h"
  23. #include "search.h"
  24. #include "cache.h"
  25. #include "notify.h"
  26. #include "InterfaceList.h"
  27. extern LONG bShutdown;
  28. extern HANDLE ShutDownEvent;
  29. extern HWND hWnd;
  30. // Publication
  31. INT _RegisterServiceRpc(PCONTEXT_HANDLE_TYPE *pphContext,
  32. SSDP_MESSAGE ssdpMsg, DWORD flags)
  33. {
  34. if (!pphContext)
  35. {
  36. return ERROR_INVALID_PARAMETER;
  37. }
  38. if (ssdpMsg.szUSN == NULL || ssdpMsg.szType == NULL)
  39. {
  40. return ERROR_INVALID_PARAMETER;
  41. }
  42. if (ssdpMsg.szAltHeaders == NULL && ssdpMsg.szLocHeader == NULL)
  43. {
  44. return ERROR_INVALID_PARAMETER;
  45. }
  46. HRESULT hr = S_OK;
  47. hr = CSsdpServiceManager::Instance().HrAddService(
  48. &ssdpMsg, flags, pphContext);
  49. return hr;
  50. }
  51. INT _DeregisterServiceRpc(PCONTEXT_HANDLE_TYPE *pphContext, BOOL fByebye)
  52. {
  53. CSsdpService * pService = *reinterpret_cast<CSsdpService**>(pphContext);
  54. HRESULT hr = CSsdpServiceManager::Instance().HrRemoveService(pService, fByebye);
  55. *pphContext = NULL;
  56. return hr;
  57. }
  58. INT _DeregisterServiceRpcByUSN(
  59. /* [string][in] */ LPSTR szUSN,
  60. /* [in] */ BOOL fByebye)
  61. {
  62. HRESULT hr = E_INVALIDARG;
  63. CSsdpService * pService = CSsdpServiceManager::Instance().FindServiceByUsn(szUSN);
  64. if(pService)
  65. {
  66. hr = CSsdpServiceManager::Instance().HrRemoveService(pService, fByebye);
  67. }
  68. return hr;
  69. }
  70. // Cache
  71. VOID _UpdateCacheRpc(PSSDP_REQUEST CandidateRequest)
  72. {
  73. SSDP_REQUEST SsdpRequest;
  74. if (CandidateRequest)
  75. {
  76. InitializeSsdpRequest(&SsdpRequest);
  77. CopySsdpRequest(&SsdpRequest, CandidateRequest);
  78. ConvertToAliveNotify(&SsdpRequest);
  79. CSsdpCacheEntryManager::Instance().HrUpdateCacheList(&SsdpRequest, TRUE);
  80. FreeSsdpRequest(&SsdpRequest);
  81. }
  82. }
  83. /*
  84. VOID _LookupCacheRpc(
  85. [size_is][length_is][out][in] unsigned char __RPC_FAR pBuffer[ ],
  86. [in] LONG lAllocatedSize,
  87. [out][in] LONG __RPC_FAR *plUsedSize)
  88. {
  89. }
  90. */
  91. INT _LookupCacheRpc(
  92. /* [string][in] */ LPSTR szType,
  93. /* [out] */ MessageList __RPC_FAR *__RPC_FAR *svcList)
  94. {
  95. if (!szType || !*szType || !svcList)
  96. {
  97. TraceError("Bad parameter to _LookupCacheRpc", E_INVALIDARG);
  98. return -1;
  99. }
  100. return CSsdpCacheEntryManager::Instance().HrSearchListCache(szType, svcList);
  101. }
  102. VOID _CleanupCacheRpc()
  103. {
  104. CSsdpCacheEntryManager::Instance().HrShutdown();
  105. }
  106. // Notification
  107. // Initialize the synchronization handle
  108. INT _InitializeSyncHandle(PCONTEXT_HANDLE_TYPE *pphContextSync)
  109. {
  110. if (!pphContextSync)
  111. {
  112. return ERROR_INVALID_PARAMETER;
  113. }
  114. HANDLE Temp = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
  115. if (Temp != NULL)
  116. {
  117. TraceTag(ttidSsdpNotify, "Created semaphore. %x", Temp);
  118. *pphContextSync = Temp;
  119. return 0;
  120. }
  121. else
  122. {
  123. TraceTag(ttidSsdpNotify, "Failed to create sephamore %d", GetLastError());
  124. *pphContextSync = NULL;
  125. return ERROR_NOT_ENOUGH_MEMORY;
  126. }
  127. }
  128. VOID _RemoveSyncHandle( PCONTEXT_HANDLE_TYPE *pphContextSync)
  129. {
  130. if (!pphContextSync)
  131. {
  132. return;
  133. }
  134. HANDLE Temp = *pphContextSync;
  135. CSsdpNotifyRequestManager::Instance().HrRemoveNotifyRequest(Temp);
  136. TraceTag(ttidSsdpNotify, "Closing semaphore %x", Temp);
  137. CloseHandle(Temp);
  138. *pphContextSync = NULL;
  139. }
  140. INT _RegisterNotificationRpc(
  141. /* [out] */ PCONTEXT_HANDLE_TYPE __RPC_FAR *pphContext,
  142. /* [in] */ PSYNC_HANDLE_TYPE phContextSync,
  143. /* [in] */ NOTIFY_TYPE nt,
  144. /* [string][unique][in] */ LPSTR szType,
  145. /* [string][unique][in] */ LPSTR szEventUrl,
  146. /* [out] */ SSDP_REGISTER_INFO __RPC_FAR *__RPC_FAR *ppinfo)
  147. {
  148. HRESULT hr = S_OK;
  149. if (!pphContext || !phContextSync || !ppinfo)
  150. {
  151. return ERROR_INVALID_PARAMETER;
  152. }
  153. *pphContext = NULL;
  154. if (NOTIFY_ALIVE == nt)
  155. {
  156. hr = CSsdpNotifyRequestManager::Instance().HrCreateAliveNotifyRequest(pphContext, szType, reinterpret_cast<HANDLE*>(phContextSync));
  157. }
  158. else if (NOTIFY_PROP_CHANGE == nt)
  159. {
  160. hr = CSsdpNotifyRequestManager::Instance().HrCreatePropChangeNotifyRequest(pphContext, szEventUrl, reinterpret_cast<HANDLE*>(phContextSync), ppinfo);
  161. }
  162. else
  163. {
  164. hr = ERROR_INVALID_PARAMETER;
  165. }
  166. return HRESULT_CODE(hr);
  167. }
  168. INT _GetNotificationRpc(PCONTEXT_HANDLE_TYPE phContextSync, MessageList **svcList)
  169. {
  170. if (!phContextSync || !svcList)
  171. {
  172. return ERROR_INVALID_PARAMETER;
  173. }
  174. TraceTag(ttidSsdpNotify, "Waiting on notification semaphore %x", phContextSync);
  175. HANDLE rgHandles[2];
  176. DWORD dwRet;
  177. HRESULT hr = S_OK;
  178. rgHandles[0] = phContextSync;
  179. rgHandles[1] = ShutDownEvent;
  180. dwRet = WaitForMultipleObjects(2, rgHandles, FALSE, INFINITE);
  181. TraceTag(ttidSsdpNotify, "Semaphore %x released", phContextSync);
  182. if (WAIT_OBJECT_0 == dwRet)
  183. {
  184. hr = CSsdpNotifyRequestManager::Instance().HrRetreivePendingNotification(reinterpret_cast<HANDLE*>(phContextSync), svcList);
  185. }
  186. else
  187. {
  188. AssertSz(dwRet == WAIT_OBJECT_0 + 1, "Wait on semaphore satisfied for "
  189. "some other reason!");
  190. TraceTag(ttidSsdpNotify, "Semaphore released because server is "
  191. "shutting down...");
  192. }
  193. #if DBG
  194. if(svcList && *svcList)
  195. {
  196. if(0 == (*svcList)->size)
  197. {
  198. TraceTag(ttidSsdpNotify, "_GetNotificationRpc - HrRetreivePendingNotification returned nothing - must be in shutdown");
  199. }
  200. else if(1 == (*svcList)->size)
  201. {
  202. SSDP_REQUEST * pRequest = (*svcList)->list;
  203. if(pRequest->Headers[SSDP_NTS] && !lstrcmpiA(pRequest->Headers[SSDP_NTS], "upnp:propchange"))
  204. {
  205. TraceTag(ttidSsdpNotify, "_GetNotificationRpc - upnp:propchange - SEQ:%s - SID:%s", pRequest->Headers[GENA_SEQ], pRequest->Headers[GENA_SID]);
  206. }
  207. else if(pRequest->Headers[SSDP_NTS] && !lstrcmpiA(pRequest->Headers[SSDP_NTS], "ssdp:alive"))
  208. {
  209. TraceTag(ttidSsdpNotify, "_GetNotificationRpc - ssdp:alive - NT:%s", pRequest->Headers[SSDP_NT]);
  210. }
  211. }
  212. }
  213. #endif // DBG
  214. return hr;
  215. }
  216. INT _WakeupGetNotificationRpc(PCONTEXT_HANDLE_TYPE phContextSync)
  217. {
  218. LONG PreviousCount = 0;
  219. if (!phContextSync)
  220. {
  221. return ERROR_INVALID_PARAMETER;
  222. }
  223. if (ReleaseSemaphore(phContextSync, 1, &PreviousCount) == TRUE)
  224. {
  225. TraceTag(ttidSsdpNotify, "Released Semaphore %x by 1, Previous count "
  226. "is %d", phContextSync, PreviousCount);
  227. return 0;
  228. }
  229. else
  230. {
  231. TraceTag(ttidSsdpNotify, "Failed to release semaphore %x, error code "
  232. "%d", phContextSync, GetLastError());
  233. return GetLastError();
  234. }
  235. }
  236. INT _DeregisterNotificationRpc(PCONTEXT_HANDLE_TYPE *pphContext, BOOL fLast)
  237. {
  238. CSsdpNotifyRequest * pRequest = *reinterpret_cast<CSsdpNotifyRequest**>(pphContext);
  239. INT ret = CSsdpNotifyRequestManager::Instance().HrRemoveNotifyRequestByPointer(pRequest);
  240. *pphContext = NULL;
  241. return ret;
  242. }
  243. void _EnableDeviceHost()
  244. {
  245. CUPnPInterfaceList::Instance().HrSetGlobalEnable();
  246. }
  247. void _DisableDeviceHost()
  248. {
  249. CUPnPInterfaceList::Instance().HrClearGlobalEnable();
  250. }
  251. void _SetICSInterfaces(/*[in]*/ long nCount, /*[in, size_is(nCount)]*/ GUID * arInterfaces)
  252. {
  253. CUPnPInterfaceList::Instance().HrSetICSInterfaces(nCount, arInterfaces);
  254. }
  255. void _SetICSOff()
  256. {
  257. CUPnPInterfaceList::Instance().HrSetICSOff();
  258. }
  259. VOID _Shutdown(VOID)
  260. {
  261. // Set network and announcemnt state ?
  262. TraceTag(ttidSsdpRpcIf, "Shutdown is called.");
  263. // T-Cleanup
  264. // Sleep(15000); // 15 seconds
  265. // T-Clean expires
  266. // Temporary testing
  267. // WriteListCacheToFile();
  268. InterlockedIncrement(&bShutdown);
  269. if (PostMessage(hWnd, WM_QUIT, 0, 0) == FALSE)
  270. {
  271. TraceTag(ttidSsdpRpcInit, "PostThreadMessage failed with %d", GetLastError());
  272. }
  273. else
  274. {
  275. TraceTag(ttidSsdpRpcInit, "PostThreadMessage was successful", GetLastError());
  276. }
  277. TraceTag(ttidSsdpRpcInit, "Setting shut down event");
  278. if (SetEvent(ShutDownEvent) == 0)
  279. {
  280. TraceTag(ttidSsdpRpcInit, "Failed to set shut down event (%d)", GetLastError());
  281. }
  282. // Cleanup will continue in main.
  283. }
  284. VOID __RPC_USER PCONTEXT_HANDLE_TYPE_rundown( PCONTEXT_HANDLE_TYPE pContext)
  285. {
  286. if (pContext)
  287. {
  288. CSsdpRundownSupport::Instance().DoRundown(pContext);
  289. }
  290. }
  291. VOID __RPC_USER PSYNC_HANDLE_TYPE_rundown( PCONTEXT_HANDLE_TYPE pContext)
  292. {
  293. TraceTag(ttidSsdpRpcIf, "rundown routine is called on sync context %x.",pContext);
  294. if (pContext)
  295. {
  296. _RemoveSyncHandle(&pContext);
  297. }
  298. }