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.

775 lines
21 KiB

  1. #include <pch.h>
  2. #pragma hdrstop
  3. #include <limits.h>
  4. #include "ssdpfunc.h"
  5. #include "ssdpnetwork.h"
  6. #include "ncbase.h"
  7. #include "cache.h"
  8. #include "upthread.h"
  9. #include "notify.h"
  10. #define BUF_SIZE 100
  11. #define CACHE_RESULT_SIZE 2
  12. static const int g_cMaxCacheDefault = 1000; // default max size of SSDP cache
  13. static const int g_cMaxCacheMin = 10; // min allowed max size of SSDP cache
  14. static const int g_cMaxCacheMax = 30000; // max allowed max size of SSDP cache
  15. CSsdpCacheEntry::CSsdpCacheEntry() : m_timer(*this), m_bTimerFired(FALSE)
  16. {
  17. ZeroMemory(&m_ssdpRequest, sizeof(m_ssdpRequest));
  18. }
  19. CSsdpCacheEntry::~CSsdpCacheEntry()
  20. {
  21. FreeSsdpRequest(&m_ssdpRequest);
  22. }
  23. class CSsdpCacheEntryByebye : public CWorkItem
  24. {
  25. public:
  26. static HRESULT HrCreate(CSsdpCacheEntry * pEntry);
  27. private:
  28. CSsdpCacheEntryByebye(CSsdpCacheEntry * pEntry);
  29. ~CSsdpCacheEntryByebye();
  30. CSsdpCacheEntryByebye(const CSsdpCacheEntryByebye &);
  31. CSsdpCacheEntryByebye & operator=(const CSsdpCacheEntryByebye &);
  32. DWORD DwRun();
  33. CSsdpCacheEntry * m_pEntry;
  34. };
  35. CSsdpCacheEntryByebye::CSsdpCacheEntryByebye(CSsdpCacheEntry * pEntry)
  36. : m_pEntry(pEntry)
  37. {
  38. }
  39. CSsdpCacheEntryByebye::~CSsdpCacheEntryByebye()
  40. {
  41. }
  42. HRESULT CSsdpCacheEntryByebye::HrCreate(CSsdpCacheEntry * pEntry)
  43. {
  44. HRESULT hr = S_OK;
  45. CSsdpCacheEntryByebye * pByebye = new CSsdpCacheEntryByebye(pEntry);
  46. if(!pByebye)
  47. {
  48. hr = E_OUTOFMEMORY;
  49. }
  50. if(SUCCEEDED(hr))
  51. {
  52. hr = pByebye->HrStart(TRUE);
  53. if(FAILED(hr))
  54. {
  55. delete pByebye;
  56. }
  57. }
  58. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntryByebye::HrCreate");
  59. return hr;
  60. }
  61. DWORD CSsdpCacheEntryByebye::DwRun()
  62. {
  63. HRESULT hr = S_OK;
  64. hr = CSsdpCacheEntryManager::Instance().HrRemoveEntry(m_pEntry);
  65. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntryByebye::DwRun");
  66. return 0;
  67. }
  68. void CSsdpCacheEntry::TimerFired()
  69. {
  70. HRESULT hr = S_OK;
  71. if(!ConvertToByebyeNotify(&m_ssdpRequest))
  72. {
  73. hr = E_FAIL;
  74. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::TimerFired - ConvertToByebyeNotify failed!");
  75. }
  76. // Mark that the timer has fired in case a renew comes in
  77. m_bTimerFired = TRUE;
  78. if(SUCCEEDED(hr))
  79. {
  80. // Queue the delete to happen later
  81. hr = CSsdpCacheEntryByebye::HrCreate(this);
  82. }
  83. }
  84. BOOL CSsdpCacheEntry::TimerTryToLock()
  85. {
  86. return m_critSec.FTryEnter();
  87. }
  88. void CSsdpCacheEntry::TimerUnlock()
  89. {
  90. m_critSec.Leave();
  91. }
  92. HRESULT CSsdpCacheEntry::HrInitialize(const SSDP_REQUEST * pRequest)
  93. {
  94. HRESULT hr = S_OK;
  95. if(!CopySsdpRequest(&m_ssdpRequest, pRequest))
  96. {
  97. hr = E_FAIL;
  98. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::HrInitialize - CopySsdpRequest failed!");
  99. }
  100. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::HrInitialize");
  101. return hr;
  102. }
  103. HRESULT CSsdpCacheEntry::HrStartTimer(const SSDP_REQUEST * pRequest)
  104. {
  105. HRESULT hr = S_OK;
  106. hr = HrUpdateExpireTime(pRequest);
  107. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::HrStartTimer");
  108. return hr;
  109. }
  110. BOOL CSsdpCacheEntry::FTimerFired()
  111. {
  112. CLock lock(m_critSec);
  113. return m_bTimerFired;
  114. }
  115. HRESULT CSsdpCacheEntry::HrShutdown(BOOL bExpired)
  116. {
  117. HRESULT hr = S_OK;
  118. CLock lock(m_critSec);
  119. Assert(FImplies(bExpired, m_bTimerFired));
  120. hr = m_timer.HrDelete(INVALID_HANDLE_VALUE);
  121. if(bExpired)
  122. {
  123. hr = CSsdpNotifyRequestManager::Instance().HrCheckListNotifyForAliveOrByebye(&m_ssdpRequest);
  124. }
  125. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::HrShutdown");
  126. return hr;
  127. }
  128. HRESULT CSsdpCacheEntry::HrUpdateExpireTime(const SSDP_REQUEST * pRequest)
  129. {
  130. HRESULT hr = S_OK;
  131. CLock lock(m_critSec);
  132. if(!pRequest->Headers[SSDP_CACHECONTROL])
  133. {
  134. hr = E_INVALIDARG;
  135. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::HrUpdateExpireTime - No cache-control header");
  136. }
  137. if(SUCCEEDED(hr))
  138. {
  139. DWORD dwTimeout = GetMaxAgeFromCacheControl(pRequest->Headers[SSDP_CACHECONTROL]);
  140. hr = m_timer.HrResetTimer(dwTimeout * 1000);
  141. m_bTimerFired = FALSE;
  142. }
  143. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::HrUpdateExpireTime");
  144. return hr;
  145. }
  146. HRESULT CSsdpCacheEntry::HrUpdateEntry(const SSDP_REQUEST * pRequest, BOOL * pbCheckListNotify)
  147. {
  148. HRESULT hr = S_OK;
  149. CLock lock(m_critSec);
  150. hr = HrUpdateExpireTime(pRequest);
  151. if(S_OK == hr)
  152. {
  153. if(!CompareSsdpRequest(&m_ssdpRequest, pRequest))
  154. {
  155. *pbCheckListNotify = TRUE;
  156. // Requests don't match. Check location headers. If different,
  157. // then we need to fake a byebye then allow the new alive to be
  158. // notified
  159. if (lstrcmpi(m_ssdpRequest.Headers[SSDP_LOCATION],
  160. pRequest->Headers[SSDP_LOCATION]))
  161. {
  162. if(!ConvertToByebyeNotify(&m_ssdpRequest))
  163. {
  164. hr = E_FAIL;
  165. TraceHr(ttidSsdpCache, FAL, hr, FALSE,
  166. "CSsdpCacheEntry::HrUpdateEntry - "
  167. "ConvertToByebyeNotify failed!");
  168. }
  169. else
  170. {
  171. hr = CSsdpNotifyRequestManager::Instance().HrCheckListNotifyForAliveOrByebye(&m_ssdpRequest);
  172. }
  173. }
  174. }
  175. FreeSsdpRequest(&m_ssdpRequest);
  176. if(!CopySsdpRequest(&m_ssdpRequest, pRequest))
  177. {
  178. hr = E_OUTOFMEMORY;
  179. }
  180. }
  181. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::HrUpdateEntry");
  182. return hr;
  183. }
  184. BOOL CSsdpCacheEntry::FIsMatchUSN(const char * szUSN)
  185. {
  186. CLock lock(m_critSec);
  187. return 0 == lstrcmpA(m_ssdpRequest.Headers[SSDP_USN], szUSN);
  188. }
  189. BOOL CSsdpCacheEntry::FIsSearchMatch(const char * szType)
  190. {
  191. CLock lock(m_critSec);
  192. if(0 == lstrcmpiA(szType, "ssdp:all"))
  193. {
  194. return TRUE;
  195. }
  196. if(m_ssdpRequest.Headers[SSDP_NT] &&
  197. 0 == lstrcmpiA(m_ssdpRequest.Headers[SSDP_NT], szType))
  198. {
  199. return TRUE;
  200. }
  201. if(m_ssdpRequest.Headers[SSDP_ST] &&
  202. 0 == lstrcmpiA(m_ssdpRequest.Headers[SSDP_ST], szType))
  203. {
  204. return TRUE;
  205. }
  206. return FALSE;
  207. }
  208. HRESULT CSsdpCacheEntry::HrGetRequest(SSDP_REQUEST * pRequest)
  209. {
  210. HRESULT hr = S_OK;
  211. CLock lock(m_critSec);
  212. if(!CopySsdpRequest(pRequest, &m_ssdpRequest))
  213. {
  214. hr = E_OUTOFMEMORY;
  215. }
  216. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::HrCacheEntryExpired");
  217. return hr;
  218. }
  219. void CSsdpCacheEntry::PrintItem()
  220. {
  221. TraceTag(ttidSsdpCache, " %s - %s - %s",
  222. m_ssdpRequest.Headers[SSDP_USN],
  223. m_ssdpRequest.Headers[SSDP_NT],
  224. m_ssdpRequest.Headers[SSDP_LOCATION]);
  225. }
  226. BOOL CSsdpCacheEntry::FCheckForDirtyInterfaceGuids(long nCount, GUID * arGuidInterfaces)
  227. {
  228. BOOL bDirty = FALSE;
  229. HRESULT hr = S_OK;
  230. CLock lock(m_critSec);
  231. for(long n = 0; n < nCount; ++n)
  232. {
  233. if(arGuidInterfaces[n] == m_ssdpRequest.guidInterface)
  234. {
  235. bDirty = TRUE;
  236. if(ConvertToByebyeNotify(&m_ssdpRequest))
  237. {
  238. hr = CSsdpNotifyRequestManager::Instance().HrCheckListNotifyForAliveOrByebye(&m_ssdpRequest);
  239. }
  240. else
  241. {
  242. TraceTag(ttidError, "CSsdpCacheEntry::FCheckForDirtyInterfaceGuids - ConvertToByebyeNotify failed");
  243. }
  244. break;
  245. }
  246. }
  247. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntry::FCheckForDirtyInterfaceGuids");
  248. return bDirty;
  249. }
  250. CSsdpCacheEntryManager CSsdpCacheEntryManager::s_instance;
  251. CSsdpCacheEntryManager::CSsdpCacheEntryManager():m_cCacheEntries(0), m_cMaxCacheEntries(1000)
  252. {
  253. }
  254. CSsdpCacheEntryManager::~CSsdpCacheEntryManager()
  255. {
  256. }
  257. HRESULT CSsdpCacheEntryManager::HrInitialize()
  258. {
  259. HRESULT hr = S_OK;
  260. HKEY hkey;
  261. DWORD dwMaxCache = g_cMaxCacheDefault;
  262. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  263. "SYSTEM\\CurrentControlSet\\Services"
  264. "\\SSDPSRV\\Parameters", 0,
  265. KEY_READ, &hkey))
  266. {
  267. DWORD cbSize = sizeof(DWORD);
  268. // ignore failure. In that case, we'll use default
  269. (VOID) RegQueryValueEx(hkey, "MaxCache", NULL, NULL, (BYTE *)&dwMaxCache, &cbSize);
  270. RegCloseKey(hkey);
  271. }
  272. dwMaxCache = max(dwMaxCache, g_cMaxCacheMin);
  273. dwMaxCache = min(dwMaxCache, g_cMaxCacheMax);
  274. m_cMaxCacheEntries = dwMaxCache;
  275. m_cCacheEntries = 0;
  276. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrInitialize - Max Cache %d",m_cMaxCacheEntries);
  277. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntryManager::HrInitialize");
  278. return hr;
  279. }
  280. CSsdpCacheEntryManager & CSsdpCacheEntryManager::Instance()
  281. {
  282. return s_instance;
  283. }
  284. BOOL CSsdpCacheEntryManager::IsCacheListNotFull()
  285. {
  286. CLock lock(m_critSec);
  287. if (m_cCacheEntries < m_cMaxCacheEntries)
  288. return TRUE;
  289. else
  290. return FALSE;
  291. }
  292. HRESULT CSsdpCacheEntryManager::HrShutdown()
  293. {
  294. HRESULT hr = S_OK;
  295. CLock lock(m_critSec);
  296. CacheEntryList::Iterator iter;
  297. if(S_OK == m_cacheEntryList.GetIterator(iter))
  298. {
  299. CSsdpCacheEntry * pEntryIter = NULL;
  300. while(S_OK == iter.HrGetItem(&pEntryIter))
  301. {
  302. hr = pEntryIter->HrShutdown(FALSE);
  303. if(S_OK != iter.HrErase())
  304. {
  305. break;
  306. }
  307. }
  308. }
  309. m_cCacheEntries = 0;
  310. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntryManager::HrShutdown");
  311. return hr;
  312. }
  313. HRESULT CSsdpCacheEntryManager::HrRemoveEntry(CSsdpCacheEntry * pEntry)
  314. {
  315. HRESULT hr = S_OK;
  316. CacheEntryList cacheEntryListRemove;
  317. {
  318. CLock lock(m_critSec);
  319. CacheEntryList::Iterator iter;
  320. if(S_OK == m_cacheEntryList.GetIterator(iter))
  321. {
  322. CSsdpCacheEntry * pEntryIter = NULL;
  323. while(S_OK == iter.HrGetItem(&pEntryIter))
  324. {
  325. if(pEntryIter == pEntry)
  326. {
  327. if(pEntry->FTimerFired())
  328. {
  329. iter.HrMoveToList(cacheEntryListRemove);
  330. m_cCacheEntries--;
  331. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrRemoveEntry - Cache Entries %d", m_cCacheEntries);
  332. }
  333. break;
  334. }
  335. if(S_OK != iter.HrNext())
  336. {
  337. break;
  338. }
  339. }
  340. }
  341. }
  342. // Remove outside of lock
  343. CacheEntryList::Iterator iter;
  344. if(S_OK == cacheEntryListRemove.GetIterator(iter))
  345. {
  346. CSsdpCacheEntry * pEntryIter = NULL;
  347. while(S_OK == iter.HrGetItem(&pEntryIter))
  348. {
  349. hr = pEntryIter->HrShutdown(TRUE);
  350. if(S_OK != iter.HrNext())
  351. {
  352. break;
  353. }
  354. }
  355. }
  356. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntryManager::HrRemoveEntry");
  357. return hr;
  358. }
  359. #ifdef DBG
  360. #define CACHECONTENTTRACE DBG
  361. #endif // DBG
  362. HRESULT CSsdpCacheEntryManager::HrUpdateCacheList(const SSDP_REQUEST * pRequest, BOOL bIsSubscribed)
  363. {
  364. HRESULT hr = S_OK;
  365. BOOL bIsByebye = FALSE;
  366. BOOL bFound = FALSE;
  367. // Debugging only
  368. #if CACHECONTENTTRACE
  369. BOOL bAdded = FALSE;
  370. BOOL bRemoved = FALSE;
  371. #endif //CACHECONTENTTRACE
  372. BOOL bCheckListNotify = FALSE;
  373. CacheEntryList cacheEntryListRemove;
  374. if(pRequest->Headers[SSDP_NTS] &&
  375. 0 == lstrcmpA(pRequest->Headers[SSDP_NTS], "ssdp:byebye"))
  376. {
  377. bIsByebye = TRUE;
  378. }
  379. if(!bIsByebye && !pRequest->Headers[SSDP_CACHECONTROL])
  380. {
  381. // Not cacheable
  382. hr = S_FALSE;
  383. if(S_OK == hr)
  384. {
  385. if(!bIsByebye && !pRequest->Headers[SSDP_SERVER])
  386. {
  387. // No server header
  388. hr = S_FALSE;
  389. }
  390. }
  391. }
  392. {
  393. CLock lock(m_critSec);
  394. if(S_OK == hr)
  395. {
  396. CacheEntryList::Iterator iter;
  397. if(S_OK == m_cacheEntryList.GetIterator(iter))
  398. {
  399. CSsdpCacheEntry * pEntryIter = NULL;
  400. while(S_OK == iter.HrGetItem(&pEntryIter))
  401. {
  402. if(pEntryIter->FIsMatchUSN(pRequest->Headers[SSDP_USN]))
  403. {
  404. bFound = TRUE;
  405. if(bIsByebye)
  406. {
  407. bCheckListNotify = TRUE;
  408. iter.HrMoveToList(cacheEntryListRemove);
  409. m_cCacheEntries--;
  410. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrUpdateCacheList - Bye Bye - Cache Entries %d", m_cCacheEntries);
  411. #if CACHECONTENTTRACE
  412. bRemoved = TRUE;
  413. #endif //CACHECONTENTTRACE
  414. }
  415. else
  416. {
  417. hr = pEntryIter->HrUpdateEntry(pRequest, &bCheckListNotify);
  418. }
  419. break;
  420. }
  421. if(S_OK != iter.HrNext())
  422. {
  423. break;
  424. }
  425. }
  426. }
  427. }
  428. if(S_OK == hr && !bFound && ! bIsByebye && bIsSubscribed)
  429. {
  430. if(IsCacheListNotFull())
  431. {
  432. CacheEntryList cacheEntryList;
  433. hr = cacheEntryList.HrPushFrontDefault();
  434. if(SUCCEEDED(hr))
  435. {
  436. hr = cacheEntryList.Front().HrInitialize(pRequest);
  437. if(SUCCEEDED(hr))
  438. {
  439. bCheckListNotify = TRUE;
  440. hr = cacheEntryList.Front().HrStartTimer(pRequest);
  441. if(SUCCEEDED(hr))
  442. {
  443. m_cacheEntryList.Prepend(cacheEntryList);
  444. m_cCacheEntries++;
  445. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrUpdateCacheList - Cache Entries %d", m_cCacheEntries);
  446. #if CACHECONTENTTRACE
  447. bAdded = TRUE;
  448. #endif //CACHECONTENTTRACE
  449. }
  450. }
  451. }
  452. }
  453. else
  454. {
  455. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrUpdateCacheList - Cache Entries Reached MAX");
  456. }
  457. }
  458. #if CACHECONTENTTRACE
  459. if(bAdded || bRemoved)
  460. {
  461. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrUpdateCacheList - Cache Contents");
  462. long nCount = 0;
  463. CacheEntryList::Iterator iter;
  464. if(S_OK == m_cacheEntryList.GetIterator(iter))
  465. {
  466. CSsdpCacheEntry * pEntryIter = NULL;
  467. while(S_OK == iter.HrGetItem(&pEntryIter))
  468. {
  469. pEntryIter->PrintItem();
  470. ++nCount;
  471. if(S_OK != iter.HrNext())
  472. {
  473. break;
  474. }
  475. }
  476. }
  477. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrUpdateCacheList - Cache Content Count: %d", nCount);
  478. if(bAdded)
  479. {
  480. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrUpdateCacheList - Added: %s", pRequest->Headers[SSDP_USN]);
  481. }
  482. if(bRemoved)
  483. {
  484. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrUpdateCacheList - Removed: %s", pRequest->Headers[SSDP_USN]);
  485. }
  486. }
  487. #endif // CACHECONTENTTRACE
  488. }
  489. if(bCheckListNotify)
  490. {
  491. CSsdpNotifyRequestManager::Instance().HrCheckListNotifyForAliveOrByebye(pRequest);
  492. }
  493. // Remove outside of lock
  494. CacheEntryList::Iterator iter;
  495. if(S_OK == cacheEntryListRemove.GetIterator(iter))
  496. {
  497. CSsdpCacheEntry * pEntryIter = NULL;
  498. while(S_OK == iter.HrGetItem(&pEntryIter))
  499. {
  500. hr = pEntryIter->HrShutdown(FALSE);
  501. if(S_OK != iter.HrNext())
  502. {
  503. break;
  504. }
  505. }
  506. }
  507. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntryManager::HrUpdateCacheList");
  508. return hr;
  509. }
  510. HRESULT CSsdpCacheEntryManager::HrSearchListCache(char * szType, MessageList ** ppSvcList)
  511. {
  512. HRESULT hr = S_OK;
  513. CLock lock(m_critSec);
  514. *ppSvcList = NULL;
  515. typedef CUList<SSDP_REQUEST> RequestList;
  516. RequestList requestList;
  517. SSDP_REQUEST ssdpRequest;
  518. long nItems = 0;
  519. CacheEntryList::Iterator iter;
  520. if(S_OK == m_cacheEntryList.GetIterator(iter))
  521. {
  522. CSsdpCacheEntry * pEntryIter = NULL;
  523. while(S_OK == iter.HrGetItem(&pEntryIter))
  524. {
  525. if(pEntryIter->FIsSearchMatch(szType))
  526. {
  527. hr = pEntryIter->HrGetRequest(&ssdpRequest);
  528. if(SUCCEEDED(hr))
  529. {
  530. hr = requestList.HrPushFront(ssdpRequest);
  531. if(SUCCEEDED(hr))
  532. {
  533. ++nItems;
  534. }
  535. if(FAILED(hr))
  536. {
  537. FreeSsdpRequest(&ssdpRequest);
  538. }
  539. }
  540. if(FAILED(hr))
  541. {
  542. break;
  543. }
  544. }
  545. if(S_OK != iter.HrNext())
  546. {
  547. break;
  548. }
  549. }
  550. }
  551. if(SUCCEEDED(hr))
  552. {
  553. MessageList * pSvcList = new MessageList;
  554. if(!pSvcList)
  555. {
  556. hr = E_OUTOFMEMORY;
  557. }
  558. if(SUCCEEDED(hr))
  559. {
  560. if(nItems)
  561. {
  562. pSvcList->list = new SSDP_REQUEST[nItems];
  563. if(!pSvcList->list)
  564. {
  565. hr = E_OUTOFMEMORY;
  566. }
  567. else
  568. {
  569. ZeroMemory(pSvcList->list, sizeof(SSDP_REQUEST) * nItems);
  570. }
  571. }
  572. else
  573. {
  574. pSvcList->list = NULL;
  575. }
  576. pSvcList->size = nItems;
  577. if(SUCCEEDED(hr))
  578. {
  579. RequestList::Iterator iter;
  580. if(S_OK == requestList.GetIterator(iter))
  581. {
  582. SSDP_REQUEST * pRequestDst = pSvcList->list;
  583. SSDP_REQUEST * pRequest = NULL;
  584. while(S_OK == iter.HrGetItem(&pRequest))
  585. {
  586. CopyMemory(pRequestDst, pRequest, sizeof(SSDP_REQUEST));
  587. ++pRequestDst;
  588. if(S_OK != iter.HrNext())
  589. {
  590. break;
  591. }
  592. }
  593. }
  594. *ppSvcList = pSvcList;
  595. }
  596. }
  597. }
  598. if(FAILED(hr))
  599. {
  600. RequestList::Iterator iter;
  601. if(S_OK == requestList.GetIterator(iter))
  602. {
  603. SSDP_REQUEST * pRequest = NULL;
  604. while(S_OK == iter.HrGetItem(&pRequest))
  605. {
  606. FreeSsdpRequest(pRequest);
  607. if(S_OK != iter.HrNext())
  608. {
  609. break;
  610. }
  611. }
  612. }
  613. }
  614. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntryManager::HrSearchListCache");
  615. return hr;
  616. }
  617. HRESULT CSsdpCacheEntryManager::HrClearDirtyInterfaceGuids(long nCount, GUID * arGuidInterfaces)
  618. {
  619. HRESULT hr = S_OK;
  620. CacheEntryList cacheEntryListRemove;
  621. {
  622. CLock lock(m_critSec);
  623. CacheEntryList::Iterator iter;
  624. if(S_OK == m_cacheEntryList.GetIterator(iter))
  625. {
  626. CSsdpCacheEntry * pEntryIter = NULL;
  627. while(S_OK == iter.HrGetItem(&pEntryIter))
  628. {
  629. if(pEntryIter->FCheckForDirtyInterfaceGuids(nCount, arGuidInterfaces))
  630. {
  631. m_cCacheEntries--;
  632. TraceTag(ttidSsdpCache, "CSsdpCacheEntryManager::HrClearDirtyInterfaceGuids - Cache Entries %d", m_cCacheEntries);
  633. if(S_OK != iter.HrMoveToList(cacheEntryListRemove))
  634. {
  635. break;
  636. }
  637. }
  638. if(S_OK != iter.HrNext())
  639. {
  640. break;
  641. }
  642. }
  643. }
  644. }
  645. // Remove outside of lock
  646. CacheEntryList::Iterator iter;
  647. if(S_OK == cacheEntryListRemove.GetIterator(iter))
  648. {
  649. CSsdpCacheEntry * pEntryIter = NULL;
  650. while(S_OK == iter.HrGetItem(&pEntryIter))
  651. {
  652. hr = pEntryIter->HrShutdown(FALSE);
  653. if(S_OK != iter.HrNext())
  654. {
  655. break;
  656. }
  657. }
  658. }
  659. TraceHr(ttidSsdpCache, FAL, hr, FALSE, "CSsdpCacheEntryManager::HrClearDirtyInterfaceGuids");
  660. return hr;
  661. }