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.

1105 lines
33 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: R E G I S T R A R . C P P
  7. //
  8. // Contents: Top level device host object
  9. //
  10. // Notes:
  11. //
  12. // Author: mbend 12 Sep 2000
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "uhbase.h"
  18. #include "hostp.h"
  19. #include "Registrar.h"
  20. #include "upsync.h"
  21. #include "ComUtility.h"
  22. #include "uhutil.h"
  23. #include "ssdpapi.h"
  24. #include "evtapi.h"
  25. #include "InterfaceList.h"
  26. #include "uhcommon.h"
  27. static const int c_minLifeTime = 900;
  28. static const int c_defLifeTime = 1800;
  29. // Helper functions
  30. HRESULT HrSetErrorInfo(
  31. const wchar_t * szErrorString,
  32. REFIID riid)
  33. {
  34. HRESULT hr = S_OK;
  35. IErrorInfo * pErrorInfo = NULL;
  36. ICreateErrorInfo * pCreateErrorInfo = NULL;
  37. hr = CreateErrorInfo(&pCreateErrorInfo);
  38. if(SUCCEEDED(hr))
  39. {
  40. hr = pCreateErrorInfo->SetDescription(const_cast<wchar_t*>(szErrorString));
  41. if(SUCCEEDED(hr))
  42. {
  43. hr = pCreateErrorInfo->SetGUID(riid);
  44. if(SUCCEEDED(hr))
  45. {
  46. hr = pCreateErrorInfo->QueryInterface(&pErrorInfo);
  47. if(SUCCEEDED(hr))
  48. {
  49. hr = SetErrorInfo(0, pErrorInfo);
  50. }
  51. }
  52. }
  53. }
  54. ReleaseObj(pErrorInfo);
  55. ReleaseObj(pCreateErrorInfo);
  56. TraceHr(ttidRegistrar, FAL, hr, FALSE, "HrSetErrorInfo(%S)", szErrorString);
  57. return hr;
  58. }
  59. //
  60. // Verify that the given resource path starts with X:\ where X is a drive
  61. // letter
  62. //
  63. HRESULT HrValidateResourcePath(BSTR bstrPath)
  64. {
  65. HRESULT hr = E_INVALIDARG;
  66. if (!bstrPath)
  67. {
  68. hr = E_POINTER;
  69. }
  70. else
  71. {
  72. if (!FFileExists(bstrPath, TRUE))
  73. {
  74. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  75. }
  76. else
  77. {
  78. if (isalpha(bstrPath[0]))
  79. {
  80. if (bstrPath[1] == L':')
  81. {
  82. if (bstrPath[2] == L'\\')
  83. {
  84. hr = S_OK;
  85. }
  86. }
  87. }
  88. }
  89. }
  90. TraceHr(ttidRegistrar, FAL, hr, FALSE, "HrValidateResourcePath");
  91. return hr;
  92. }
  93. // Constructors and destructors
  94. CRegistrar::CRegistrar() : m_bSetAutoStart(FALSE)
  95. {
  96. }
  97. CRegistrar::~CRegistrar()
  98. {
  99. }
  100. // ISupportErrorInfo methods
  101. STDMETHODIMP CRegistrar::InterfaceSupportsErrorInfo(REFIID riid)
  102. {
  103. HRESULT hr = S_FALSE;
  104. if(riid == IID_IUPnPRegistrar || riid == IID_IUPnPReregistrar)
  105. {
  106. hr = S_OK;
  107. }
  108. return hr;
  109. }
  110. // IUPnPRegistrarLookup methods
  111. STDMETHODIMP CRegistrar::GetEventingManager(
  112. /*[in, string]*/ const wchar_t * szUDN,
  113. /*[in, string]*/ const wchar_t * szServiceId,
  114. /*[out]*/ IUPnPEventingManager ** ppEventingManager)
  115. {
  116. TraceTag(ttidRegistrar, "CRegistrar::GetEventingManager");
  117. HRESULT hr = S_OK;
  118. CALock lock(*this);
  119. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC );
  120. if ( SUCCEEDED( hr ) )
  121. {
  122. CServiceInfo * pServiceInfo = NULL;
  123. hr = m_deviceManager.HrGetService(szUDN, szServiceId, &pServiceInfo);
  124. if(SUCCEEDED(hr))
  125. {
  126. hr = pServiceInfo->HrGetEventingManager(ppEventingManager);
  127. }
  128. }
  129. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetEventingManager");
  130. return hr;
  131. }
  132. STDMETHODIMP CRegistrar::GetAutomationProxy(
  133. /*[in, string]*/ const wchar_t * szUDN,
  134. /*[in, string]*/ const wchar_t * szServiceId,
  135. /*[out]*/ IUPnPAutomationProxy ** ppAutomationProxy)
  136. {
  137. TraceTag(ttidRegistrar, "CRegistrar::GetAutomationProxy");
  138. HRESULT hr = S_OK;
  139. CALock lock(*this);
  140. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  141. if ( SUCCEEDED( hr ) )
  142. {
  143. CServiceInfo * pServiceInfo = NULL;
  144. hr = m_deviceManager.HrGetService(szUDN, szServiceId, &pServiceInfo);
  145. if(SUCCEEDED(hr))
  146. {
  147. hr = pServiceInfo->HrGetAutomationProxy(ppAutomationProxy);
  148. }
  149. }
  150. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetAutomationProxy");
  151. return hr;
  152. }
  153. // IUPnPRegistrarPrivate methods
  154. STDMETHODIMP CRegistrar::Initialize()
  155. {
  156. TraceTag(ttidRegistrar,"CRegistrar::Initialize");
  157. HRESULT hr = S_OK;
  158. CALock lock(*this);
  159. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  160. if ( SUCCEEDED( hr ) )
  161. {
  162. hr = CUPnPInterfaceList::Instance().HrInitialize();
  163. }
  164. if(SUCCEEDED(hr))
  165. {
  166. hr = HrInitEventApi();
  167. }
  168. if (SUCCEEDED(hr))
  169. {
  170. SsdpStartup();
  171. hr = m_pDescriptionManager.HrCreateInstanceInproc(CLSID_UPnPDescriptionManager);
  172. if(SUCCEEDED(hr))
  173. {
  174. hr = m_pDevicePersistenceManager.HrCreateInstanceInproc(CLSID_UPnPDevicePersistenceManager);
  175. if(SUCCEEDED(hr))
  176. {
  177. IUPnPDynamicContentSourcePtr pDynamicContentSource;
  178. hr = pDynamicContentSource.HrCreateInstanceInproc(CLSID_UPnPDynamicContentSource);
  179. if(SUCCEEDED(hr))
  180. {
  181. IUPnPDynamicContentProviderPtr pDynamicContentProvider;
  182. hr = pDynamicContentProvider.HrAttach(m_pDescriptionManager);
  183. if(SUCCEEDED(hr))
  184. {
  185. hr = pDynamicContentSource->RegisterProvider(pDynamicContentProvider);
  186. if(SUCCEEDED(hr))
  187. {
  188. hr = m_pValidationManager.HrCreateInstanceInproc(CLSID_UPnPValidationManager);
  189. }
  190. }
  191. }
  192. }
  193. }
  194. }
  195. if (SUCCEEDED(hr))
  196. {
  197. hr = m_pContainerManager.HrCreateInstanceInproc(CLSID_UPnPContainerManager);
  198. if (SUCCEEDED(hr))
  199. {
  200. hr = m_pDynamicContentSource.HrCreateInstanceInproc(CLSID_UPnPDynamicContentSource);
  201. }
  202. }
  203. // Get the PDIs
  204. if(SUCCEEDED(hr))
  205. {
  206. long nDevices = 0;
  207. GUID * arPdi;
  208. hr = m_pDevicePersistenceManager->GetPhysicalDevices(&nDevices, &arPdi);
  209. if(SUCCEEDED(hr))
  210. {
  211. // Bring each persistent device to life
  212. for(long n = 0; n < nDevices; ++n)
  213. {
  214. // Use a temporary HRESULT because we don't want one thing to cause everything to fail
  215. HRESULT hrTemp = S_OK;
  216. wchar_t * szProgIdDeviceControlClass = NULL;
  217. wchar_t * szInitString = NULL;
  218. wchar_t * szContainerId = NULL;
  219. wchar_t * szResourcePath = NULL;
  220. long nLifetime = 0;
  221. hrTemp = m_pDevicePersistenceManager->LookupPhysicalDevice(
  222. arPdi[n], &szProgIdDeviceControlClass, &szInitString, &szContainerId, &szResourcePath, &nLifetime);
  223. if(SUCCEEDED(hrTemp))
  224. {
  225. // Load the description document
  226. hrTemp = m_pDescriptionManager->LoadDescription(arPdi[n]);
  227. if(SUCCEEDED(hrTemp))
  228. {
  229. // Get the UDNs
  230. wchar_t ** arszUDNs = NULL;
  231. long nUDNCount = 0;
  232. hrTemp = m_pDescriptionManager->GetUDNs(arPdi[n], &nUDNCount, &arszUDNs);
  233. if(SUCCEEDED(hrTemp))
  234. {
  235. // Add device
  236. hrTemp = m_deviceManager.HrAddDevice(arPdi[n], szProgIdDeviceControlClass, szInitString,
  237. szContainerId, nUDNCount, arszUDNs);
  238. if(SUCCEEDED(hrTemp))
  239. {
  240. // Publish the device
  241. hrTemp = m_pDescriptionManager->PublishDescription(arPdi[n], nLifetime);
  242. }
  243. // Free UDNs
  244. for(long n = 0; n < nUDNCount; ++n)
  245. {
  246. CoTaskMemFree(arszUDNs[n]);
  247. }
  248. CoTaskMemFree(arszUDNs);
  249. }
  250. }
  251. TraceHr(ttidError, FAL, hr, FALSE, "CRegistrar::Initialize - Failed to init device (ProgId=%S)",
  252. szProgIdDeviceControlClass);
  253. CoTaskMemFree(szProgIdDeviceControlClass);
  254. CoTaskMemFree(szInitString);
  255. CoTaskMemFree(szContainerId);
  256. CoTaskMemFree(szResourcePath);
  257. }
  258. }
  259. CoTaskMemFree(arPdi);
  260. }
  261. }
  262. // Do the providers
  263. if(SUCCEEDED(hr))
  264. {
  265. long nProviders = 0;
  266. wchar_t ** arszProviderNames = NULL;
  267. hr = m_pDevicePersistenceManager->GetDeviceProviders(&nProviders, &arszProviderNames);
  268. if(SUCCEEDED(hr))
  269. {
  270. // Load each provider
  271. long n;
  272. for(n = 0; n < nProviders; ++n)
  273. {
  274. HRESULT hrTemp = S_OK;
  275. wchar_t * szProgIdProviderClass = NULL;
  276. wchar_t * szInitString = NULL;
  277. wchar_t * szContainerId = NULL;
  278. hrTemp = m_pDevicePersistenceManager->LookupDeviceProvider(
  279. arszProviderNames[n], &szProgIdProviderClass, &szInitString, &szContainerId);
  280. if(SUCCEEDED(hrTemp))
  281. {
  282. hrTemp = m_providerManager.HrRegisterProvider(
  283. arszProviderNames[n], szProgIdProviderClass, szInitString, szContainerId);
  284. TraceHr(ttidError, FAL, hr, FALSE, "CRegistrar::Initialize - Failed to load provider (%S)", arszProviderNames[n]);
  285. CoTaskMemFree(szProgIdProviderClass);
  286. CoTaskMemFree(szInitString);
  287. CoTaskMemFree(szContainerId);
  288. }
  289. }
  290. for(n = 0; n < nProviders; ++n)
  291. {
  292. CoTaskMemFree(arszProviderNames[n]);
  293. }
  294. CoTaskMemFree(arszProviderNames);
  295. }
  296. }
  297. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::Initialize");
  298. return hr;
  299. }
  300. STDMETHODIMP CRegistrar::Shutdown()
  301. {
  302. TraceTag(ttidRegistrar, "CRegistrar::Shutdown");
  303. HRESULT hr = S_OK;
  304. CALock lock(*this);
  305. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  306. if ( SUCCEEDED( hr ) )
  307. {
  308. if (m_pDynamicContentSource)
  309. {
  310. IUPnPDynamicContentProviderPtr pDynamicContentProvider;
  311. hr = pDynamicContentProvider.HrAttach(m_pDescriptionManager);
  312. if(SUCCEEDED(hr))
  313. {
  314. hr = m_pDynamicContentSource->UnregisterProvider(pDynamicContentProvider);
  315. }
  316. m_pDynamicContentSource.Release();
  317. }
  318. m_pDescriptionManager.Release();
  319. m_pDevicePersistenceManager.Release();
  320. m_pValidationManager.Release();
  321. m_providerManager.HrShutdown();
  322. m_deviceManager.HrShutdown();
  323. if (m_pContainerManager)
  324. {
  325. m_pContainerManager->Shutdown();
  326. }
  327. m_pContainerManager.Release();
  328. SsdpCleanup();
  329. DeInitEventApi();
  330. CUPnPInterfaceList::Instance().HrShutdown();
  331. }
  332. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::Shutdown");
  333. return hr;
  334. }
  335. STDMETHODIMP CRegistrar::GetSCPDText(
  336. /*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
  337. /*[in, string]*/ const wchar_t * szUDN,
  338. /*[in, string]*/ const wchar_t * szServiceId,
  339. /*[out, string]*/ wchar_t ** pszSCPDText,
  340. /*[out, string]*/ wchar_t ** pszServiceType)
  341. {
  342. TraceTag(ttidRegistrar, "CRegistrar::GetSCPDText(UDN=%S, ServiceId=%S)", szUDN, szServiceId);
  343. HRESULT hr = S_OK;
  344. CALock lock(*this);
  345. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  346. if ( SUCCEEDED( hr ) )
  347. {
  348. hr = m_pDescriptionManager->GetSCPDText(guidPhysicalDeviceIdentifier, szUDN,
  349. szServiceId, pszSCPDText, pszServiceType);
  350. }
  351. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetSCPDText");
  352. return hr;
  353. }
  354. STDMETHODIMP CRegistrar::GetDescriptionText(
  355. /*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
  356. /*[out]*/ BSTR * pbstrDescriptionDocument)
  357. {
  358. TraceTag(ttidRegistrar, "CRegistrar::GetDescriptionText");
  359. HRESULT hr = S_OK;
  360. CALock lock(*this);
  361. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  362. if ( SUCCEEDED( hr ) )
  363. {
  364. hr = m_pDescriptionManager->GetDescriptionText(guidPhysicalDeviceIdentifier,
  365. pbstrDescriptionDocument);
  366. }
  367. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetDescriptionText");
  368. return hr;
  369. }
  370. // IUPnPRegistrar methods
  371. STDMETHODIMP CRegistrar::RegisterDevice(
  372. /*[in]*/ BSTR bstrXMLDesc,
  373. /*[in]*/ BSTR bstrProgIDDeviceControlClass,
  374. /*[in]*/ BSTR bstrInitString,
  375. /*[in]*/ BSTR bstrContainerId,
  376. /*[in]*/ BSTR bstrResourcePath,
  377. /*[in]*/ long nLifeTime,
  378. /*[out, retval]*/ BSTR * pbstrDeviceIdentifier)
  379. {
  380. TraceTag(ttidRegistrar,"CRegistrar::RegisterDevice");
  381. HRESULT hr = S_OK;
  382. BOOL fAllowed = FALSE;
  383. CALock lock(*this);
  384. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
  385. if(SUCCEEDED(hr))
  386. {
  387. hr = HrValidateResourcePath(bstrResourcePath);
  388. }
  389. if (SUCCEEDED(hr))
  390. {
  391. // Do validation
  392. wchar_t * szErrorString = NULL;
  393. hr = m_pValidationManager->ValidateDescriptionDocumentAndReferences(
  394. bstrXMLDesc, bstrResourcePath, &szErrorString);
  395. if(FAILED(hr))
  396. {
  397. HrSetErrorInfo(szErrorString, IID_IUPnPRegistrar);
  398. return hr;
  399. }
  400. if(szErrorString)
  401. {
  402. CoTaskMemFree(szErrorString);
  403. szErrorString = NULL;
  404. }
  405. if (!nLifeTime)
  406. {
  407. nLifeTime = c_defLifeTime;
  408. }
  409. else if (nLifeTime < c_minLifeTime)
  410. {
  411. hr = E_INVALIDARG;
  412. }
  413. }
  414. if(SUCCEEDED(hr))
  415. {
  416. hr = HrSetAutoStart();
  417. }
  418. if (SUCCEEDED(hr))
  419. {
  420. // Process the description document
  421. PhysicalDeviceIdentifier pdi;
  422. hr = m_pDescriptionManager->ProcessDescriptionTemplate(
  423. bstrXMLDesc, bstrResourcePath, &pdi, TRUE, FALSE);
  424. if(SUCCEEDED(hr))
  425. {
  426. // Get the UDNs
  427. wchar_t ** arszUDNs = NULL;
  428. long nUDNCount = 0;
  429. hr = m_pDescriptionManager->GetUDNs(pdi, &nUDNCount, &arszUDNs);
  430. if(SUCCEEDED(hr))
  431. {
  432. // Add device
  433. hr = m_deviceManager.HrAddDevice(pdi, bstrProgIDDeviceControlClass, bstrInitString,
  434. bstrContainerId, nUDNCount, arszUDNs);
  435. if(SUCCEEDED(hr))
  436. {
  437. // Save the device
  438. hr = m_pDevicePersistenceManager->SavePhyisicalDevice(
  439. pdi, bstrProgIDDeviceControlClass, bstrInitString, bstrContainerId, bstrResourcePath, nLifeTime);
  440. if(SUCCEEDED(hr))
  441. {
  442. // Publish the device
  443. hr = m_pDescriptionManager->PublishDescription(pdi, nLifeTime);
  444. if(SUCCEEDED(hr))
  445. {
  446. CUString strPdi;
  447. hr = HrPhysicalDeviceIdentifierToString(pdi, strPdi);
  448. if(SUCCEEDED(hr))
  449. {
  450. hr = strPdi.HrGetBSTR(pbstrDeviceIdentifier);
  451. }
  452. }
  453. }
  454. }
  455. // Free UDNs
  456. for(long n = 0; n < nUDNCount; ++n)
  457. {
  458. CoTaskMemFree(arszUDNs[n]);
  459. }
  460. CoTaskMemFree(arszUDNs);
  461. }
  462. if (FAILED(hr))
  463. {
  464. HrUnregisterDeviceByPDI(pdi, TRUE);
  465. }
  466. }
  467. }
  468. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::RegisterDevice");
  469. return hr;
  470. }
  471. STDMETHODIMP CRegistrar::RegisterRunningDevice(
  472. /*[in]*/ BSTR bstrXMLDesc,
  473. /*[in]*/ IUnknown * punkDeviceControl,
  474. /*[in]*/ BSTR bstrInitString,
  475. /*[in]*/ BSTR bstrResourcePath,
  476. /*[in]*/ long nLifeTime,
  477. /*[out, retval]*/ BSTR * pbstrDeviceIdentifier)
  478. {
  479. TraceTag(ttidRegistrar, "CRegistrar::RegisterRunningDevice");
  480. HRESULT hr = S_OK;
  481. CALock lock(*this);
  482. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
  483. if(SUCCEEDED(hr))
  484. {
  485. hr = HrValidateResourcePath(bstrResourcePath);
  486. }
  487. if (SUCCEEDED(hr))
  488. {
  489. // Do validation
  490. wchar_t * szErrorString = NULL;
  491. hr = m_pValidationManager->ValidateDescriptionDocumentAndReferences(
  492. bstrXMLDesc, bstrResourcePath, &szErrorString);
  493. if(FAILED(hr))
  494. {
  495. HrSetErrorInfo(szErrorString, IID_IUPnPRegistrar);
  496. return hr;
  497. }
  498. if(szErrorString)
  499. {
  500. CoTaskMemFree(szErrorString);
  501. szErrorString = NULL;
  502. }
  503. if (!nLifeTime)
  504. {
  505. nLifeTime = c_defLifeTime;
  506. }
  507. else if (nLifeTime < c_minLifeTime)
  508. {
  509. hr = E_INVALIDARG;
  510. }
  511. }
  512. if(SUCCEEDED(hr))
  513. {
  514. hr = CoImpersonateClient();
  515. }
  516. if (SUCCEEDED(hr))
  517. {
  518. // Process the description document
  519. PhysicalDeviceIdentifier pdi;
  520. hr = m_pDescriptionManager->ProcessDescriptionTemplate(
  521. bstrXMLDesc, bstrResourcePath, &pdi, FALSE, FALSE);
  522. if(SUCCEEDED(hr))
  523. {
  524. // Get the UDNs
  525. wchar_t ** arszUDNs = NULL;
  526. long nUDNCount = 0;
  527. hr = m_pDescriptionManager->GetUDNs(pdi, &nUDNCount, &arszUDNs);
  528. if(SUCCEEDED(hr))
  529. {
  530. // Add device
  531. hr = m_deviceManager.HrAddRunningDevice(
  532. pdi, punkDeviceControl, bstrInitString, nUDNCount, arszUDNs);
  533. if(SUCCEEDED(hr))
  534. {
  535. // Publish the device
  536. hr = m_pDescriptionManager->PublishDescription(pdi, nLifeTime);
  537. if(SUCCEEDED(hr))
  538. {
  539. CUString strPdi;
  540. hr = HrPhysicalDeviceIdentifierToString(pdi, strPdi);
  541. if(SUCCEEDED(hr))
  542. {
  543. hr = strPdi.HrGetBSTR(pbstrDeviceIdentifier);
  544. }
  545. }
  546. }
  547. // Free UDNs
  548. for(long n = 0; n < nUDNCount; ++n)
  549. {
  550. CoTaskMemFree(arszUDNs[n]);
  551. }
  552. CoTaskMemFree(arszUDNs);
  553. }
  554. if (FAILED(hr))
  555. {
  556. HrUnregisterDeviceByPDI(pdi, TRUE);
  557. }
  558. }
  559. }
  560. CoRevertToSelf();
  561. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::RegisterRunningDevice");
  562. return hr;
  563. }
  564. STDMETHODIMP CRegistrar::RegisterDeviceProvider(
  565. /*[in]*/ BSTR bstrProviderName,
  566. /*[in]*/ BSTR bstrProgIDProviderClass,
  567. /*[in]*/ BSTR bstrInitString,
  568. /*[in]*/ BSTR bstrContainerId)
  569. {
  570. TraceTag(ttidRegistrar, "CRegistrar::RegisterDeviceProvider");
  571. HRESULT hr = S_OK;
  572. CALock lock(*this);
  573. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
  574. if(SUCCEEDED(hr))
  575. {
  576. hr = m_providerManager.HrRegisterProvider(
  577. bstrProviderName, bstrProgIDProviderClass, bstrInitString, bstrContainerId);
  578. }
  579. if(SUCCEEDED(hr))
  580. {
  581. hr = m_pDevicePersistenceManager->SaveDeviceProvider(
  582. bstrProviderName, bstrProgIDProviderClass, bstrInitString, bstrContainerId);
  583. if(SUCCEEDED(hr))
  584. {
  585. hr = HrSetAutoStart();
  586. }
  587. }
  588. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::RegisterDeviceProvider");
  589. return hr;
  590. }
  591. STDMETHODIMP CRegistrar::GetUniqueDeviceName(
  592. /*[in]*/ BSTR bstrDeviceIdentifier,
  593. /*[in]*/ BSTR bstrTemplateUDN,
  594. /*[out, retval]*/ BSTR * pbstrUDN)
  595. {
  596. TraceTag(ttidRegistrar, "CRegistrar::GetUniqueDeviceName");
  597. HRESULT hr = S_OK;
  598. // No locking here to allow for reentrant calls
  599. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
  600. if(SUCCEEDED(hr))
  601. {
  602. if (!bstrDeviceIdentifier || !pbstrUDN)
  603. {
  604. hr = E_POINTER;
  605. }
  606. else
  607. {
  608. PhysicalDeviceIdentifier pdi;
  609. hr = HrStringToPhysicalDeviceIdentifier(bstrDeviceIdentifier, pdi);
  610. if(SUCCEEDED(hr))
  611. {
  612. wchar_t * szUDN = NULL;
  613. hr = m_pDescriptionManager->GetUniqueDeviceName(pdi, bstrTemplateUDN, &szUDN);
  614. if(SUCCEEDED(hr))
  615. {
  616. hr = HrSysAllocString(szUDN, pbstrUDN);
  617. CoTaskMemFree(szUDN);
  618. }
  619. }
  620. else if (CO_E_CLASSSTRING == hr)
  621. {
  622. // remap this error to invalid argument error
  623. hr = E_INVALIDARG;
  624. }
  625. }
  626. }
  627. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetUniqueDeviceName");
  628. return hr;
  629. }
  630. HRESULT CRegistrar::HrUnregisterDeviceByPDI(PhysicalDeviceIdentifier & pdi, BOOL fPermanent)
  631. {
  632. CALock lock(*this);
  633. HRESULT hr = S_OK;
  634. hr = m_pDescriptionManager->RemoveDescription(pdi, fPermanent);
  635. TraceHr(ttidError, FAL, hr, FALSE, "CRegistrar::UnregisterDeviceByPDI "
  636. "RemoveDescription failed!");
  637. if(SUCCEEDED(hr))
  638. {
  639. hr = m_pDevicePersistenceManager->RemovePhysicalDevice(pdi);
  640. if(FAILED(hr))
  641. {
  642. TraceTag(ttidRegistrar, "CRegistrar::UnregisterDeviceByPDI - "
  643. "RemovePhysicalDevice failed. This is expected "
  644. "for running devices.");
  645. }
  646. hr = m_deviceManager.HrRemoveDevice(pdi);
  647. }
  648. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::UnregisterDeviceByPDI");
  649. return hr;
  650. }
  651. STDMETHODIMP CRegistrar::UnregisterDevice(
  652. /*[in]*/ BSTR bstrDeviceIdentifier,
  653. /*[in]*/ BOOL fPermanent)
  654. {
  655. TraceTag(ttidRegistrar, "CRegistrar::UnregisterDevice");
  656. HRESULT hr = S_OK;
  657. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
  658. if(SUCCEEDED(hr))
  659. {
  660. if (!bstrDeviceIdentifier)
  661. {
  662. hr = E_POINTER;
  663. }
  664. else
  665. {
  666. CALock lock(*this);
  667. PhysicalDeviceIdentifier pdi;
  668. hr = HrStringToPhysicalDeviceIdentifier(bstrDeviceIdentifier, pdi);
  669. if(SUCCEEDED(hr))
  670. {
  671. hr = HrUnregisterDeviceByPDI(pdi, fPermanent);
  672. }
  673. else if (CO_E_CLASSSTRING == hr)
  674. {
  675. // remap this error to invalid argument error
  676. hr = E_INVALIDARG;
  677. }
  678. }
  679. }
  680. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::UnregisterDevice");
  681. return hr;
  682. }
  683. STDMETHODIMP CRegistrar::UnregisterDeviceProvider(
  684. /*[in]*/ BSTR bstrProviderName)
  685. {
  686. TraceTag(ttidRegistrar, "CRegistrar::UnegisterDeviceProvider");
  687. HRESULT hr = S_OK;
  688. CALock lock(*this);
  689. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
  690. if(SUCCEEDED(hr))
  691. {
  692. hr = m_providerManager.UnegisterProvider(bstrProviderName);
  693. }
  694. if(SUCCEEDED(hr))
  695. {
  696. hr = m_pDevicePersistenceManager->RemoveDeviceProvider(bstrProviderName);
  697. }
  698. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::UnegisterDeviceProvider");
  699. return hr;
  700. }
  701. // IUPnPReregistrar methods
  702. STDMETHODIMP CRegistrar::ReregisterDevice(
  703. /*[in]*/ BSTR bstrDeviceIdentifier,
  704. /*[in]*/ BSTR bstrXMLDesc,
  705. /*[in]*/ BSTR bstrProgIDDeviceControlClass,
  706. /*[in]*/ BSTR bstrInitString,
  707. /*[in]*/ BSTR bstrContainerId,
  708. /*[in]*/ BSTR bstrResourcePath,
  709. /*[in]*/ long nLifeTime)
  710. {
  711. TraceTag(ttidRegistrar, "CRegistrar::ReregisterDevice");
  712. HRESULT hr = S_OK;
  713. CALock lock(*this);
  714. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
  715. if(SUCCEEDED(hr))
  716. {
  717. hr = HrValidateResourcePath(bstrResourcePath);
  718. }
  719. if (SUCCEEDED(hr))
  720. {
  721. // Do validation
  722. wchar_t * szErrorString = NULL;
  723. hr = m_pValidationManager->ValidateDescriptionDocumentAndReferences(
  724. bstrXMLDesc, bstrResourcePath, &szErrorString);
  725. if(FAILED(hr))
  726. {
  727. HrSetErrorInfo(szErrorString, IID_IUPnPReregistrar);
  728. return hr;
  729. }
  730. if(szErrorString)
  731. {
  732. CoTaskMemFree(szErrorString);
  733. szErrorString = NULL;
  734. }
  735. if (!nLifeTime)
  736. {
  737. nLifeTime = c_defLifeTime;
  738. }
  739. else if (nLifeTime < c_minLifeTime)
  740. {
  741. hr = E_INVALIDARG;
  742. }
  743. if (!bstrDeviceIdentifier)
  744. {
  745. hr = E_POINTER;
  746. }
  747. }
  748. if(SUCCEEDED(hr))
  749. {
  750. hr = HrSetAutoStart();
  751. }
  752. if (SUCCEEDED(hr))
  753. {
  754. // Process the description document
  755. PhysicalDeviceIdentifier pdi;
  756. hr = HrStringToPhysicalDeviceIdentifier(bstrDeviceIdentifier, pdi);
  757. if(SUCCEEDED(hr))
  758. {
  759. if (m_deviceManager.FHasDevice(pdi))
  760. {
  761. hr = UPNP_E_DEVICE_RUNNING;
  762. }
  763. if (SUCCEEDED(hr))
  764. {
  765. hr = m_pDescriptionManager->ProcessDescriptionTemplate(
  766. bstrXMLDesc, bstrResourcePath, &pdi, TRUE, TRUE);
  767. }
  768. if(SUCCEEDED(hr))
  769. {
  770. // Get the UDNs
  771. wchar_t ** arszUDNs = NULL;
  772. long nUDNCount = 0;
  773. hr = m_pDescriptionManager->GetUDNs(pdi, &nUDNCount, &arszUDNs);
  774. if(SUCCEEDED(hr))
  775. {
  776. // Add device
  777. hr = m_deviceManager.HrAddDevice(pdi, bstrProgIDDeviceControlClass, bstrInitString,
  778. bstrContainerId, nUDNCount, arszUDNs);
  779. if(SUCCEEDED(hr))
  780. {
  781. // Save the device
  782. hr = m_pDevicePersistenceManager->SavePhyisicalDevice(
  783. pdi, bstrProgIDDeviceControlClass, bstrInitString, bstrContainerId, bstrResourcePath, nLifeTime);
  784. if(SUCCEEDED(hr))
  785. {
  786. // Publish the device
  787. hr = m_pDescriptionManager->PublishDescription(pdi, nLifeTime);
  788. }
  789. }
  790. // Free UDNs
  791. for(long n = 0; n < nUDNCount; ++n)
  792. {
  793. CoTaskMemFree(arszUDNs[n]);
  794. }
  795. CoTaskMemFree(arszUDNs);
  796. }
  797. if (FAILED(hr) && hr != UPNP_E_DEVICE_RUNNING)
  798. {
  799. HrUnregisterDeviceByPDI(pdi, FALSE);
  800. }
  801. }
  802. }
  803. else if (CO_E_CLASSSTRING == hr)
  804. {
  805. // remap this error to invalid argument error
  806. hr = E_INVALIDARG;
  807. }
  808. }
  809. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::ReregisterDevice");
  810. return hr;
  811. }
  812. STDMETHODIMP CRegistrar::ReregisterRunningDevice(
  813. /*[in]*/ BSTR bstrDeviceIdentifier,
  814. /*[in]*/ BSTR bstrXMLDesc,
  815. /*[in]*/ IUnknown * punkDeviceControl,
  816. /*[in]*/ BSTR bstrInitString,
  817. /*[in]*/ BSTR bstrResourcePath,
  818. /*[in]*/ long nLifeTime)
  819. {
  820. TraceTag(ttidRegistrar, "CRegistrar::ReregisterRunningDevice");
  821. HRESULT hr = S_OK;
  822. CALock lock(*this);
  823. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
  824. if(SUCCEEDED(hr))
  825. {
  826. hr = HrValidateResourcePath(bstrResourcePath);
  827. }
  828. if (SUCCEEDED(hr))
  829. {
  830. // Do validation
  831. wchar_t * szErrorString = NULL;
  832. hr = m_pValidationManager->ValidateDescriptionDocumentAndReferences(
  833. bstrXMLDesc, bstrResourcePath, &szErrorString);
  834. if(FAILED(hr))
  835. {
  836. HrSetErrorInfo(szErrorString, IID_IUPnPReregistrar);
  837. return hr;
  838. }
  839. if(szErrorString)
  840. {
  841. CoTaskMemFree(szErrorString);
  842. szErrorString = NULL;
  843. }
  844. if (!nLifeTime)
  845. {
  846. nLifeTime = c_defLifeTime;
  847. }
  848. else if (nLifeTime < c_minLifeTime)
  849. {
  850. hr = E_INVALIDARG;
  851. }
  852. if (!bstrDeviceIdentifier)
  853. {
  854. hr = E_POINTER;
  855. }
  856. }
  857. if(SUCCEEDED(hr))
  858. {
  859. hr = CoImpersonateClient();
  860. }
  861. if (SUCCEEDED(hr))
  862. {
  863. // Process the description document
  864. PhysicalDeviceIdentifier pdi;
  865. hr = HrStringToPhysicalDeviceIdentifier(bstrDeviceIdentifier, pdi);
  866. if(SUCCEEDED(hr))
  867. {
  868. if (m_deviceManager.FHasDevice(pdi))
  869. {
  870. hr = UPNP_E_DEVICE_RUNNING;
  871. }
  872. // Process the description document
  873. if (SUCCEEDED(hr))
  874. {
  875. hr = m_pDescriptionManager->ProcessDescriptionTemplate(
  876. bstrXMLDesc, bstrResourcePath, &pdi, FALSE, TRUE);
  877. }
  878. if(SUCCEEDED(hr))
  879. {
  880. // Get the UDNs
  881. wchar_t ** arszUDNs = NULL;
  882. long nUDNCount = 0;
  883. hr = m_pDescriptionManager->GetUDNs(pdi, &nUDNCount, &arszUDNs);
  884. if(SUCCEEDED(hr))
  885. {
  886. // Add device
  887. hr = m_deviceManager.HrAddRunningDevice(
  888. pdi, punkDeviceControl, bstrInitString, nUDNCount, arszUDNs);
  889. if(SUCCEEDED(hr))
  890. {
  891. // Publish the device
  892. hr = m_pDescriptionManager->PublishDescription(pdi, nLifeTime);
  893. }
  894. // Free UDNs
  895. for(long n = 0; n < nUDNCount; ++n)
  896. {
  897. CoTaskMemFree(arszUDNs[n]);
  898. }
  899. CoTaskMemFree(arszUDNs);
  900. }
  901. if (FAILED(hr) && hr != UPNP_E_DEVICE_RUNNING)
  902. {
  903. HrUnregisterDeviceByPDI(pdi, FALSE);
  904. }
  905. }
  906. }
  907. else if (CO_E_CLASSSTRING == hr)
  908. {
  909. // remap this error to invalid argument error
  910. hr = E_INVALIDARG;
  911. }
  912. }
  913. CoRevertToSelf();
  914. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::ReregisterRunningDevice");
  915. return hr;
  916. }
  917. STDMETHODIMP CRegistrar::SetICSInterfaces(/*[in]*/ long nCount, /*[in, size_is(nCount)]*/ GUID * arPrivateInterfaceGuids)
  918. {
  919. HRESULT hr = S_OK;
  920. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_INPROC | CALL_LOCALITY_LOCAL ));
  921. if ( SUCCEEDED( hr ) )
  922. {
  923. hr = CUPnPInterfaceList::Instance().HrSetICSInterfaces(nCount, arPrivateInterfaceGuids);
  924. }
  925. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::SetICSInterfaces");
  926. return hr;
  927. }
  928. STDMETHODIMP CRegistrar::SetICSOff()
  929. {
  930. HRESULT hr = S_OK;
  931. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
  932. if ( SUCCEEDED( hr ) )
  933. {
  934. hr = CUPnPInterfaceList::Instance().HrSetICSOff();
  935. }
  936. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::SetICSOff");
  937. return hr;
  938. }
  939. HRESULT CRegistrar::HrSetAutoStart()
  940. {
  941. HRESULT hr = S_OK;
  942. CALock lock(*this);
  943. if(!m_bSetAutoStart)
  944. {
  945. SC_HANDLE scm = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
  946. if(!scm)
  947. {
  948. hr = HrFromLastWin32Error();
  949. }
  950. if(SUCCEEDED(hr))
  951. {
  952. SC_HANDLE scUpnphost = OpenService(scm, L"upnphost", SERVICE_CHANGE_CONFIG);
  953. if(!scUpnphost)
  954. {
  955. hr = HrFromLastWin32Error();
  956. }
  957. if(SUCCEEDED(hr))
  958. {
  959. if(!ChangeServiceConfig(scUpnphost, SERVICE_NO_CHANGE, SERVICE_AUTO_START,
  960. SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL,
  961. NULL, NULL, NULL))
  962. {
  963. hr = HrFromLastWin32Error();
  964. }
  965. CloseServiceHandle(scUpnphost);
  966. }
  967. CloseServiceHandle(scm);
  968. }
  969. }
  970. TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::HrSetAutoStart");
  971. return hr;
  972. }