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.

416 lines
10 KiB

  1. #include "nt.h"
  2. #include "ntrtl.h"
  3. #include "nturtl.h"
  4. #include "objbase.h"
  5. #include "status.h"
  6. #include "ssdpfuncc.h"
  7. #include "ssdpapi.h"
  8. #include "common.h"
  9. #include "ncmem.h"
  10. #include "ncdefine.h"
  11. #include "ncdebug.h"
  12. #include "client_c.c"
  13. #include "timer.h"
  14. #include <rpcasync.h> // I_RpcExceptionFilter
  15. extern HANDLE g_hLaunchEvent;
  16. extern RTL_RESOURCE g_rsrcReg;
  17. LONG cInitialized = 0;
  18. static CRITICAL_SECTION g_csListOpenConn;
  19. int RpcClientStop();
  20. static CONST c_msecMaxServiceStart = 30 * 1000; // 30 seconds
  21. static CONST c_msecPollInterval = 100; // .1 seconds
  22. BOOL FStartSsdpService()
  23. {
  24. SC_HANDLE scm;
  25. BOOL fRet = FALSE;
  26. scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  27. if (scm)
  28. {
  29. SC_HANDLE hsvc;
  30. hsvc = OpenService(scm, "SSDPSRV", SERVICE_QUERY_STATUS | SERVICE_START);
  31. if (hsvc)
  32. {
  33. SERVICE_STATUS status = {0};
  34. DWORD dwTickStart = GetTickCount();
  35. BOOL fDone = FALSE;
  36. do
  37. {
  38. if (QueryServiceStatus(hsvc, &status))
  39. {
  40. switch (status.dwCurrentState)
  41. {
  42. case SERVICE_RUNNING:
  43. TraceTag(ttidSsdpCRpcInit, "SSDP Service has started");
  44. // Success!
  45. fDone = TRUE;
  46. fRet = TRUE;
  47. break;
  48. case SERVICE_STOPPED:
  49. if (!StartService(hsvc, 0, NULL))
  50. {
  51. AssertSz(GetLastError() != ERROR_SERVICE_ALREADY_RUNNING,
  52. "Service cannot be running!");
  53. TraceError("StartSsdpService - could not query"
  54. "start SSDPSRV service!",
  55. HrFromLastWin32Error());
  56. fDone = TRUE;
  57. }
  58. else
  59. {
  60. // reset this again to be more accurate
  61. dwTickStart = GetTickCount();
  62. }
  63. break;
  64. case SERVICE_START_PENDING:
  65. if (GetTickCount() -
  66. dwTickStart >= c_msecMaxServiceStart)
  67. {
  68. // Time ran out
  69. fDone = TRUE;
  70. }
  71. else
  72. {
  73. Sleep(c_msecPollInterval);
  74. }
  75. break;
  76. }
  77. }
  78. else
  79. {
  80. // Error!
  81. TraceError("StartSsdpService - could not query"
  82. "service status for SSDPSRV!",
  83. HrFromLastWin32Error());
  84. fDone = TRUE;
  85. }
  86. } while (!fDone);
  87. CloseServiceHandle(hsvc);
  88. }
  89. else
  90. {
  91. TraceError("StartSsdpService - could not open SSDPSRV service!",
  92. HrFromLastWin32Error());
  93. }
  94. CloseServiceHandle(scm);
  95. }
  96. else
  97. {
  98. TraceError("StartSsdpService - could not open SC Manager!",
  99. HrFromLastWin32Error());
  100. }
  101. return fRet;
  102. }
  103. int RpcClientStart()
  104. {
  105. HRESULT hr = S_OK;
  106. RPC_STATUS status;
  107. unsigned char * pszUuid = NULL;
  108. unsigned char * pszProtocolSequence = (unsigned char *)"ncalrpc";
  109. unsigned char * pszNetworkAddress = NULL;
  110. unsigned char * pszOptions = NULL;
  111. unsigned char * pszStringBinding = NULL;
  112. unsigned long ulCode;
  113. status = 0;
  114. hSSDP = NULL;
  115. #ifdef DBG
  116. InitializeDebugging();
  117. #endif // DBG
  118. TraceTag(ttidSsdpCRpcInit, "RpcClientStart - Enter");
  119. if (!InitializeListNotify())
  120. {
  121. TraceTag(ttidError, "RpcClientStart - InitializeListNotify failed");
  122. goto cleanup;
  123. }
  124. RtlInitializeResource(&g_rsrcReg);
  125. if (!FStartSsdpService())
  126. {
  127. TraceTag(ttidError, "RpcClientStart - Failed to start SSDPSRV service");
  128. goto cleanup;
  129. }
  130. InitializeListSearch();
  131. hr = CTimerQueue::Instance().HrInitialize();
  132. if(FAILED(hr))
  133. {
  134. TraceHr(ttidSsdpCRpcInit, FAL, hr, FALSE, "RpcClientStart - CTimerQueue::Instance().HrInitialize failed");
  135. goto cleanup;
  136. }
  137. // SocketInit() returns 0 on success, and places failure codes in
  138. // GetLastError()
  139. //
  140. if (SocketInit() !=0)
  141. {
  142. TraceTag(ttidError, "RpcClientStart - SocketInit failed");
  143. goto cleanup;
  144. }
  145. Assert(INVALID_HANDLE_VALUE == g_hLaunchEvent);
  146. g_hLaunchEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  147. hr = HrFromLastWin32Error();
  148. TraceTag(ttidSsdpCRpcInit, FAL, hr, FALSE, "RpcClientStart - CreateEvent failed");
  149. if (g_hLaunchEvent == NULL)
  150. {
  151. g_hLaunchEvent = INVALID_HANDLE_VALUE;
  152. return FALSE;
  153. }
  154. Assert(INVALID_HANDLE_VALUE != g_hLaunchEvent);
  155. /* Use a convenience function to concatenate the elements of */
  156. /* the string binding into the proper sequence. */
  157. // To-Do: Security?
  158. status = RpcStringBindingCompose(pszUuid,
  159. pszProtocolSequence,
  160. pszNetworkAddress,
  161. NULL,
  162. pszOptions,
  163. &pszStringBinding);
  164. TraceError("RpcStringBindingCompose returned.", HRESULT_FROM_WIN32(status));
  165. ABORT_ON_FAILURE(status);
  166. /* Set the binding handle that will be used to bind to the server. */
  167. status = RpcBindingFromStringBinding(pszStringBinding, &hSSDP);
  168. TraceError("RpcBindingFromStringBinding returned.",
  169. HRESULT_FROM_WIN32(status));
  170. RpcStringFree(&pszStringBinding);
  171. ABORT_ON_FAILURE(status);
  172. TraceTag(ttidSsdpCRpcInit, "RpcClientStart - Exit");
  173. return TRUE;
  174. cleanup:
  175. TraceTag(ttidError, "RpcClientStart - Exit with failure");
  176. RpcClientStop();
  177. SocketFinish();
  178. #ifdef DBG
  179. UnInitializeDebugging();
  180. #endif // DBG
  181. if (status)
  182. {
  183. // we got here from rpc errors, which leave their result in 'status'
  184. ::SetLastError(status);
  185. }
  186. return FALSE;
  187. }
  188. int RpcClientStop()
  189. {
  190. RPC_STATUS status;
  191. CleanupNotificationThread();
  192. CleanupListSearch();
  193. CTimerQueue::Instance().HrShutdown(INVALID_HANDLE_VALUE);
  194. if (hSSDP != NULL)
  195. {
  196. status = RpcBindingFree(&hSSDP);
  197. hSSDP = NULL;
  198. TraceError("RpcClientStop returned.", HRESULT_FROM_WIN32(status));
  199. }
  200. if (INVALID_HANDLE_VALUE != g_hLaunchEvent)
  201. {
  202. BOOL fResult;
  203. fResult = ::CloseHandle(g_hLaunchEvent);
  204. Assert(fResult);
  205. g_hLaunchEvent = INVALID_HANDLE_VALUE;
  206. }
  207. RtlDeleteResource(&g_rsrcReg);
  208. return 0;
  209. }
  210. //+---------------------------------------------------------------------------
  211. //
  212. // Function: SsdpStartup
  213. //
  214. // Purpose: Initializes global state for the SSDP api functions.
  215. //
  216. // Arguments: <none>
  217. //
  218. // Returns: If the function succeeds, the return value is nonzero.
  219. //
  220. // If the function fails, the return value is zero.
  221. // To get extended error information, call GetLastError.
  222. //
  223. // Notes: This must be called at least once before calling any SSDP
  224. // API functions, or they will fail.with ERROR_NOT_READY.
  225. //
  226. // To deinitialize the ssdp library for a process,
  227. // each successful call to SsdpStartup must be balanced by a
  228. // corresponding call to SsdpCleanup.
  229. //
  230. BOOL WINAPI SsdpStartup()
  231. {
  232. int iRetVal;
  233. EnterCriticalSection(&g_csListOpenConn);
  234. iRetVal = TRUE;
  235. if (!cInitialized)
  236. {
  237. iRetVal = RpcClientStart();
  238. }
  239. if (iRetVal)
  240. {
  241. // if we didn't hit an error, increment the reference count
  242. //
  243. cInitialized++;
  244. }
  245. LeaveCriticalSection(&g_csListOpenConn);
  246. return iRetVal;
  247. }
  248. VOID WINAPI SsdpCleanup()
  249. {
  250. EnterCriticalSection(&g_csListOpenConn);
  251. if (cInitialized > 0)
  252. {
  253. // decrement the reference count, and cleanup when the count
  254. // goes to zero.
  255. //
  256. if (--cInitialized == 0)
  257. {
  258. RpcClientStop();
  259. SocketFinish();
  260. #ifdef DBG
  261. UnInitializeDebugging();
  262. #endif // DBG
  263. }
  264. }
  265. LeaveCriticalSection(&g_csListOpenConn);
  266. }
  267. // Delay load support
  268. //
  269. #include <delayimp.h>
  270. EXTERN_C
  271. FARPROC
  272. WINAPI
  273. DelayLoadFailureHook (
  274. UINT unReason,
  275. PDelayLoadInfo pDelayInfo
  276. );
  277. PfnDliHook __pfnDliFailureHook = DelayLoadFailureHook;
  278. BOOL
  279. DllMain(IN PVOID DllHandle,
  280. IN ULONG Reason,
  281. IN PVOID Context OPTIONAL)
  282. {
  283. switch (Reason)
  284. {
  285. case DLL_PROCESS_ATTACH:
  286. InitializeCriticalSection(&g_csListOpenConn);
  287. // We don't need to receive thread attach and detach
  288. // notifications, so disable them to help application
  289. // performance.
  290. DisableThreadLibraryCalls((HMODULE)DllHandle);
  291. break;
  292. case DLL_THREAD_ATTACH:
  293. break;
  294. case DLL_PROCESS_DETACH:
  295. DeleteCriticalSection(&g_csListOpenConn);
  296. break;
  297. case DLL_THREAD_DETACH:
  298. break;
  299. }
  300. return TRUE;
  301. }
  302. void WINAPI DHEnableDeviceHost()
  303. {
  304. EnableDeviceHost();
  305. }
  306. void WINAPI DHDisableDeviceHost()
  307. {
  308. DisableDeviceHost();
  309. }
  310. void WINAPI DHSetICSInterfaces(long nCount, GUID * arInterfaces)
  311. {
  312. SetICSInterfaces(nCount, arInterfaces);
  313. }
  314. void WINAPI DHSetICSOff()
  315. {
  316. SetICSOff();
  317. }
  318. /*********************************************************************/
  319. /* MIDL allocate and free */
  320. /*********************************************************************/
  321. VOID __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
  322. {
  323. return(malloc(len));
  324. }
  325. VOID __RPC_USER midl_user_free(VOID __RPC_FAR * ptr)
  326. {
  327. free(ptr);
  328. }