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.

786 lines
19 KiB

  1. #include "shellprv.h"
  2. #include "ids.h"
  3. #include "hwcmmn.h"
  4. #include "apdlglog.h"
  5. #include "mtptl.h"
  6. BOOL _AreHandlersDifferent(LPCWSTR pszOriginal, LPCWSTR pszNew)
  7. {
  8. return TRUE;
  9. }
  10. CHandlerDataArray::~CHandlerDataArray()
  11. {
  12. if (IsDPASet())
  13. {
  14. DestroyCallback(_ReleaseHandler, NULL);
  15. }
  16. }
  17. BOOL CHandlerDataArray::_IsDemotedHandler(PCWSTR pszHandler)
  18. {
  19. return ((0 == StrCmpIW(pszHandler, L"MSTakeNoAction"))
  20. || (0 == StrCmpIW(pszHandler, L"MSOpenFolder")));
  21. }
  22. HRESULT CHandlerDataArray::AddHandler(CHandlerData *pdata)
  23. {
  24. // always insert ahead of TakeNoAction and OpenFolder
  25. int iInsert;
  26. if (!_IsDemotedHandler(pdata->_pszHandler))
  27. {
  28. int c = GetPtrCount();
  29. for (iInsert = 0; iInsert < c; iInsert++)
  30. {
  31. if (_IsDemotedHandler(GetPtr(iInsert)->_pszHandler))
  32. {
  33. // insert here
  34. break;
  35. }
  36. }
  37. iInsert = InsertPtr(iInsert, pdata);
  38. }
  39. else
  40. {
  41. iInsert = AppendPtr(pdata);
  42. }
  43. return DPA_ERR != iInsert ? S_OK : E_OUTOFMEMORY;
  44. }
  45. BOOL CHandlerDataArray::IsDuplicateCommand(PCWSTR pszCommand)
  46. {
  47. WCHAR sz[MAX_PATH * 2];
  48. BOOL fRet = FALSE;
  49. int c = GetPtrCount();
  50. for (int i = 0; i < c; i++)
  51. {
  52. CHandlerData *pdata = GetPtr(i);
  53. if (SUCCEEDED(pdata->_GetCommand(sz, ARRAYSIZE(sz))))
  54. {
  55. fRet = (0 == StrCmpIW(pszCommand, sz));
  56. if (fRet)
  57. break;
  58. }
  59. }
  60. return fRet;
  61. }
  62. // We are erring on the side of safety here by giving FALSE positives
  63. // sometimes. This could be optimized to consider if we have diff handler
  64. // just because one is missing.
  65. void CContentTypeData::UpdateDirty()
  66. {
  67. BOOL fDirty = _AreHandlersDifferent(_pszHandlerDefault, _pszHandlerDefaultOriginal) ||
  68. (HANDLERDEFAULT_DEFAULTSAREDIFFERENT & _dwHandlerDefaultFlags);
  69. _SetDirty(fDirty);
  70. }
  71. #define SOFTPREFIX TEXT("[soft]")
  72. HRESULT CContentTypeData::CommitChangesToStorage()
  73. {
  74. HRESULT hr = S_OK;
  75. if (_AreHandlersDifferent(_pszHandlerDefault, _pszHandlerDefaultOriginal) ||
  76. (HANDLERDEFAULT_DEFAULTSAREDIFFERENT & _dwHandlerDefaultFlags))
  77. {
  78. // Yep, changed
  79. IAutoplayHandler* piah;
  80. hr = _GetAutoplayHandler(_szDrive, TEXT("ContentArrival"), _szContentTypeHandler, &piah);
  81. if (SUCCEEDED(hr))
  82. {
  83. if (!_fSoftCommit)
  84. {
  85. hr = piah->SetDefaultHandler(_pszHandlerDefault);
  86. }
  87. else
  88. {
  89. WCHAR szHandler[MAX_HANDLER + ARRAYSIZE(SOFTPREFIX)];
  90. lstrcpyn(szHandler, SOFTPREFIX, ARRAYSIZE(szHandler));
  91. StrCatBuff(szHandler, _pszHandlerDefault, ARRAYSIZE(szHandler));
  92. hr = piah->SetDefaultHandler(szHandler);
  93. }
  94. piah->Release();
  95. }
  96. }
  97. if (SUCCEEDED(hr))
  98. {
  99. _SetHandlerDefault(&_pszHandlerDefaultOriginal, _pszHandlerDefault);
  100. }
  101. return hr;
  102. }
  103. CContentTypeData::~CContentTypeData()
  104. {
  105. if (_pszHandlerDefaultOriginal)
  106. {
  107. CoTaskMemFree(_pszHandlerDefaultOriginal);
  108. }
  109. if (_pszHandlerDefault)
  110. {
  111. CoTaskMemFree(_pszHandlerDefault);
  112. }
  113. }
  114. HRESULT _MakeActionString(LPCWSTR pszAction, LPWSTR* ppszAction2)
  115. {
  116. *ppszAction2 = NULL;
  117. WCHAR szAction[250];
  118. HRESULT hr = SHLoadIndirectString(pszAction, szAction, ARRAYSIZE(szAction), NULL);
  119. if (SUCCEEDED(hr))
  120. {
  121. hr = SHStrDup(szAction, ppszAction2);
  122. }
  123. return hr;
  124. }
  125. HRESULT _MakeProviderString(LPCWSTR pszProvider, LPWSTR* ppszProvider2)
  126. {
  127. WCHAR szProviderNonMUI[250];
  128. HRESULT hr = SHLoadIndirectString(pszProvider, szProviderNonMUI, ARRAYSIZE(szProviderNonMUI), NULL);
  129. if (SUCCEEDED(hr))
  130. {
  131. WCHAR szUsing[50];
  132. if (LoadString(g_hinst, IDS_AP_USING, szUsing, ARRAYSIZE(szUsing)))
  133. {
  134. WCHAR szProvider2[250];
  135. wnsprintf(szProvider2, ARRAYSIZE(szProvider2), szUsing, szProviderNonMUI);
  136. if (SUCCEEDED(SHStrDup(szProvider2, ppszProvider2)))
  137. {
  138. hr = S_OK;
  139. }
  140. else
  141. {
  142. hr = E_OUTOFMEMORY;
  143. }
  144. }
  145. else
  146. {
  147. hr = E_FAIL;
  148. }
  149. }
  150. return hr;
  151. }
  152. inline void _CoTaskMemFree(void* pv)
  153. {
  154. if (pv)
  155. {
  156. CoTaskMemFree(pv);
  157. }
  158. }
  159. HRESULT _CreateHandlerData( PCWSTR pszAction,
  160. PCWSTR pszProvider,
  161. PWSTR *ppszHandler, // IN/OUT
  162. PWSTR *ppszIcon, // IN/OUT
  163. CHandlerData **ppdata)
  164. {
  165. *ppdata = 0;
  166. LPWSTR pszAction2 = NULL;
  167. HRESULT hr = _MakeActionString(pszAction, &pszAction2);
  168. if (SUCCEEDED(hr))
  169. {
  170. LPWSTR pszProvider2 = NULL;
  171. // Special case this guy, we don't want to say:
  172. // "Take no action, using Microsoft Windows"
  173. if (lstrcmp(*ppszHandler, TEXT("MSTakeNoAction")))
  174. {
  175. hr = _MakeProviderString(pszProvider, &pszProvider2);
  176. }
  177. // else this is NULL, and ignored
  178. if (SUCCEEDED(hr))
  179. {
  180. *ppdata = new CHandlerData();
  181. if (*ppdata)
  182. {
  183. // give away ownership of these allocations
  184. (*ppdata)->Init(*ppszHandler, pszAction2,
  185. *ppszIcon, pszProvider2);
  186. *ppszHandler = NULL;
  187. *ppszIcon = NULL;
  188. pszAction2 = NULL;
  189. pszProvider2 = NULL;
  190. }
  191. else
  192. {
  193. hr = E_OUTOFMEMORY;
  194. CoTaskMemFree(pszProvider2);
  195. }
  196. }
  197. CoTaskMemFree(pszAction2);
  198. }
  199. return hr;
  200. }
  201. HRESULT CContentBase::_EnumHandlerHelper(IAutoplayHandler* piah)
  202. {
  203. IEnumAutoplayHandler* penum;
  204. if (S_OK == piah->EnumHandlers(&penum))
  205. {
  206. LPWSTR pszHandler;
  207. LPWSTR pszAction;
  208. LPWSTR pszProvider;
  209. LPWSTR pszIconLocation;
  210. while (S_OK == penum->Next(&pszHandler, &pszAction, &pszProvider,
  211. &pszIconLocation))
  212. {
  213. // Do not free the strings from EnumHandlers
  214. // CHandlerData will free them in its destructor
  215. CHandlerData *pdata;
  216. HRESULT hr = _CreateHandlerData(pszAction, pszProvider, &pszHandler, &pszIconLocation, &pdata);
  217. if (SUCCEEDED(hr))
  218. {
  219. hr = _dpaHandlerData.AddHandler(pdata);
  220. if (FAILED(hr))
  221. {
  222. pdata->Release();
  223. }
  224. }
  225. else
  226. {
  227. CoTaskMemFree(pszHandler);
  228. CoTaskMemFree(pszIconLocation);
  229. }
  230. CoTaskMemFree(pszProvider);
  231. CoTaskMemFree(pszAction);
  232. }
  233. penum->Release();
  234. }
  235. return S_OK;
  236. }
  237. HRESULT _CreateLegacyHandler(IAssociationElement *pae, PCWSTR pszAction, CHandlerData **ppdata)
  238. {
  239. *ppdata = 0;
  240. PWSTR pszIcon;
  241. HRESULT hr = pae->QueryString(AQVS_APPLICATION_PATH, NULL, &pszIcon);
  242. if(SUCCEEDED(hr))
  243. {
  244. PWSTR pszFriendly;
  245. hr = pae->QueryString(AQVS_APPLICATION_FRIENDLYNAME, NULL, &pszFriendly);
  246. if(SUCCEEDED(hr))
  247. {
  248. PWSTR pszHandler;
  249. hr = SHStrDup(TEXT("AutoplayLegacyHandler"), &pszHandler);
  250. if (SUCCEEDED(hr))
  251. {
  252. hr = _CreateHandlerData(pszAction, pszFriendly, &pszHandler, &pszIcon, ppdata);
  253. CoTaskMemFree(pszHandler);
  254. }
  255. CoTaskMemFree(pszFriendly);
  256. }
  257. CoTaskMemFree(pszIcon);
  258. }
  259. return hr;
  260. }
  261. CHandlerData* CContentBase::GetHandlerData(int i)
  262. {
  263. CHandlerData* phandlerdata = _dpaHandlerData.GetPtr(i);
  264. if (phandlerdata)
  265. {
  266. phandlerdata->AddRef();
  267. }
  268. return phandlerdata;
  269. }
  270. HRESULT CContentBase::_AddLegacyHandler(DWORD dwContentType)
  271. {
  272. HRESULT hr = S_FALSE;
  273. if (dwContentType & (CT_CDAUDIO | CT_DVDMOVIE))
  274. {
  275. LPCWSTR pszProgID;
  276. LPCWSTR pszAction;
  277. if (dwContentType & CT_CDAUDIO)
  278. {
  279. pszProgID = TEXT("AudioCD");
  280. pszAction = TEXT("@%SystemRoot%\\system32\\shell32.dll,-17171");
  281. }
  282. else
  283. {
  284. ASSERT(dwContentType & CT_DVDMOVIE);
  285. pszProgID = TEXT("DVD");
  286. pszAction = TEXT("@%SystemRoot%\\system32\\shell32.dll,-17172");
  287. }
  288. IAssociationElement * pae;
  289. hr = AssocElemCreateForClass(&CLSID_AssocProgidElement, pszProgID, &pae);
  290. if (SUCCEEDED(hr))
  291. {
  292. PWSTR pszCommand;
  293. hr = pae->QueryString(AQVS_COMMAND, NULL, &pszCommand);
  294. if (SUCCEEDED(hr))
  295. {
  296. // legacy guys have a command or we dont add them
  297. // we expect new guys to be responsible and add themselves
  298. // to the autoplay handlers key
  299. if (!_dpaHandlerData.IsDuplicateCommand(pszCommand))
  300. {
  301. LPWSTR pszPath;
  302. hr = pae->QueryString(AQVS_APPLICATION_PATH, NULL, &pszPath);
  303. if (SUCCEEDED(hr))
  304. {
  305. DWORD dwAttrib = GetFileAttributes(pszPath);
  306. // We do not want to show legacy handler if their exe
  307. // is hidden
  308. if ((0xFFFFFFFF != dwAttrib) &&
  309. !(FILE_ATTRIBUTE_HIDDEN & dwAttrib))
  310. {
  311. CHandlerData* pdata;
  312. hr = _CreateLegacyHandler(pae, pszAction, &pdata);
  313. if (SUCCEEDED(hr))
  314. {
  315. hr = _dpaHandlerData.AddHandler(pdata);
  316. if (FAILED(hr))
  317. {
  318. pdata->Release();
  319. }
  320. }
  321. }
  322. CoTaskMemFree(pszPath);
  323. }
  324. }
  325. CoTaskMemFree(pszCommand);
  326. }
  327. pae->Release();
  328. }
  329. }
  330. return hr;
  331. }
  332. HRESULT CContentTypeData::Init(LPCWSTR pszDrive, DWORD dwContentType)
  333. {
  334. HRESULT hr;
  335. _dwContentType = dwContentType;
  336. hr = _GetContentTypeHandler(_dwContentType, _szContentTypeHandler,
  337. ARRAYSIZE(_szContentTypeHandler));
  338. if (SUCCEEDED(hr))
  339. {
  340. hr = _GetContentTypeInfo(_dwContentType, _szIconLabel, ARRAYSIZE(_szIconLabel),
  341. _szIconLocation, ARRAYSIZE(_szIconLocation));
  342. lstrcpyn(_szDrive, pszDrive, ARRAYSIZE(_szDrive));
  343. if (SUCCEEDED(hr))
  344. {
  345. IAutoplayHandler* piah;
  346. hr = _GetAutoplayHandler(_szDrive, TEXT("ContentArrival"),
  347. _szContentTypeHandler, &piah);
  348. if (SUCCEEDED(hr))
  349. {
  350. hr = piah->GetDefaultHandler(&_pszHandlerDefaultOriginal);
  351. if (SUCCEEDED(hr))
  352. {
  353. if (S_FALSE != hr)
  354. {
  355. _dwHandlerDefaultFlags = HANDLERDEFAULT_GETFLAGS(hr);
  356. }
  357. // SHStrDup (we want CoTaskMemAlloc)
  358. hr = SHStrDup(_pszHandlerDefaultOriginal, &_pszHandlerDefault);
  359. }
  360. if (SUCCEEDED(hr))
  361. {
  362. if (_dpaHandlerData.Create(4))
  363. {
  364. hr = _EnumHandlerHelper(piah);
  365. if (SUCCEEDED(hr))
  366. {
  367. _AddLegacyHandler(dwContentType);
  368. }
  369. }
  370. }
  371. piah->Release();
  372. }
  373. }
  374. }
  375. return hr;
  376. }
  377. HRESULT CContentTypeLVItem::GetText(LPWSTR pszText, DWORD cchText)
  378. {
  379. HRESULT hr;
  380. CContentTypeData* pdata = GetData();
  381. if (pdata)
  382. {
  383. lstrcpyn(pszText, pdata->_szIconLabel, cchText);
  384. pdata->Release();
  385. hr = S_OK;
  386. }
  387. else
  388. {
  389. *pszText = NULL;
  390. hr = S_FALSE;
  391. }
  392. return hr;
  393. }
  394. HRESULT CContentTypeLVItem::GetIconLocation(LPWSTR pszIconLocation,
  395. DWORD cchIconLocation)
  396. {
  397. HRESULT hr;
  398. CContentTypeData* pdata = GetData();
  399. if (pdata)
  400. {
  401. lstrcpyn(pszIconLocation, pdata->_szIconLocation, cchIconLocation);
  402. pdata->Release();
  403. hr = S_OK;
  404. }
  405. else
  406. {
  407. *pszIconLocation = NULL;
  408. hr = S_FALSE;
  409. }
  410. return hr;
  411. }
  412. HRESULT CContentTypeCBItem::GetText(LPWSTR pszText, DWORD cchText)
  413. {
  414. HRESULT hr;
  415. CContentTypeData* pdata = GetData();
  416. if (pdata)
  417. {
  418. lstrcpyn(pszText, pdata->_szIconLabel, cchText);
  419. pdata->Release();
  420. hr = S_OK;
  421. }
  422. else
  423. {
  424. *pszText = NULL;
  425. hr = S_FALSE;
  426. }
  427. return hr;
  428. }
  429. HRESULT CContentTypeCBItem::GetIconLocation(LPWSTR pszIconLocation, DWORD cchIconLocation)
  430. {
  431. HRESULT hr;
  432. CContentTypeData* pdata = GetData();
  433. if (pdata)
  434. {
  435. lstrcpyn(pszIconLocation, pdata->_szIconLocation, cchIconLocation);
  436. pdata->Release();
  437. hr = S_OK;
  438. }
  439. else
  440. {
  441. *pszIconLocation = NULL;
  442. hr = S_FALSE;
  443. }
  444. return hr;
  445. }
  446. CHandlerData::~CHandlerData()
  447. {
  448. if (_pszHandler)
  449. {
  450. CoTaskMemFree((void*)_pszHandler);
  451. }
  452. if (_pszHandlerFriendlyName)
  453. {
  454. CoTaskMemFree((void*)_pszHandlerFriendlyName);
  455. }
  456. if (_pszIconLocation)
  457. {
  458. CoTaskMemFree((void*)_pszIconLocation);
  459. }
  460. if (_pszTileText)
  461. {
  462. CoTaskMemFree(_pszTileText);
  463. }
  464. }
  465. void CHandlerData::Init(PWSTR pszHandler, PWSTR pszHandlerFriendlyName,
  466. PWSTR pszIconLocation, PWSTR pszTileText)
  467. {
  468. _pszHandler = pszHandler;
  469. _pszHandlerFriendlyName = pszHandlerFriendlyName;
  470. _pszIconLocation = pszIconLocation;
  471. _pszTileText = pszTileText;
  472. // WE CANT FAIL
  473. }
  474. void CHandlerData::UpdateDirty()
  475. {
  476. // nothing to do
  477. }
  478. HRESULT CHandlerCBItem::GetText(LPWSTR pszText, DWORD cchText)
  479. {
  480. HRESULT hr;
  481. CHandlerData* pdata = GetData();
  482. if (pdata)
  483. {
  484. lstrcpyn(pszText, pdata->_pszHandlerFriendlyName, cchText);
  485. pdata->Release();
  486. hr = S_OK;
  487. }
  488. else
  489. {
  490. *pszText = NULL;
  491. hr = S_FALSE;
  492. }
  493. return hr;
  494. }
  495. HRESULT CHandlerLVItem::GetText(LPWSTR pszText, DWORD cchText)
  496. {
  497. HRESULT hr;
  498. CHandlerData* pdata = GetData();
  499. if (pdata)
  500. {
  501. lstrcpyn(pszText, pdata->_pszHandlerFriendlyName, cchText);
  502. pdata->Release();
  503. hr = S_OK;
  504. }
  505. else
  506. {
  507. *pszText = NULL;
  508. hr = S_FALSE;
  509. }
  510. return hr;
  511. }
  512. HRESULT CHandlerLVItem::GetIconLocation(LPWSTR pszIconLocation, DWORD cchIconLocation)
  513. {
  514. HRESULT hr;
  515. CHandlerData* pdata = GetData();
  516. if (pdata)
  517. {
  518. lstrcpyn(pszIconLocation, pdata->_pszIconLocation, cchIconLocation);
  519. pdata->Release();
  520. hr = S_OK;
  521. }
  522. else
  523. {
  524. *pszIconLocation = NULL;
  525. hr = S_FALSE;
  526. }
  527. return hr;
  528. }
  529. HRESULT CHandlerLVItem::GetTileText(int i, LPWSTR pszTileText, DWORD cchTileText)
  530. {
  531. HRESULT hr = S_FALSE;
  532. CHandlerData* pdata = GetData();
  533. *pszTileText = NULL;
  534. hr = S_FALSE;
  535. // we dont support anything but zero
  536. ASSERT(0 == i);
  537. if (pdata)
  538. {
  539. if (pdata->_pszTileText)
  540. {
  541. lstrcpyn(pszTileText, pdata->_pszTileText, cchTileText);
  542. hr = S_OK;
  543. }
  544. pdata->Release();
  545. }
  546. return hr;
  547. }
  548. // We are erring on the side of safety here by giving FALSE positives
  549. // sometimes. This could be optimized to consider if we have diff handler
  550. // just because one is missing.
  551. void CNoContentData::UpdateDirty()
  552. {
  553. BOOL fDirty = _AreHandlersDifferent(_pszHandlerDefault, _pszHandlerDefaultOriginal) ||
  554. (HANDLERDEFAULT_DEFAULTSAREDIFFERENT & _dwHandlerDefaultFlags);
  555. _SetDirty(fDirty);
  556. }
  557. HRESULT CNoContentData::CommitChangesToStorage()
  558. {
  559. HRESULT hr = S_OK;
  560. if (_AreHandlersDifferent(_pszHandlerDefault, _pszHandlerDefaultOriginal) ||
  561. (HANDLERDEFAULT_DEFAULTSAREDIFFERENT & _dwHandlerDefaultFlags))
  562. {
  563. // Yep, changed
  564. IAutoplayHandler* piah;
  565. hr = _GetAutoplayHandlerNoContent(_szDeviceID, TEXT("DeviceArrival"), &piah);
  566. if (SUCCEEDED(hr))
  567. {
  568. if (!_fSoftCommit)
  569. {
  570. hr = piah->SetDefaultHandler(_pszHandlerDefault);
  571. }
  572. else
  573. {
  574. WCHAR szHandler[MAX_HANDLER + ARRAYSIZE(SOFTPREFIX)];
  575. lstrcpyn(szHandler, SOFTPREFIX, ARRAYSIZE(szHandler));
  576. StrCatBuff(szHandler, _pszHandlerDefault, ARRAYSIZE(szHandler));
  577. hr = piah->SetDefaultHandler(szHandler);
  578. }
  579. piah->Release();
  580. }
  581. }
  582. if (SUCCEEDED(hr))
  583. {
  584. _SetHandlerDefault(&_pszHandlerDefaultOriginal, _pszHandlerDefault);
  585. }
  586. return hr;
  587. }
  588. CNoContentData::~CNoContentData()
  589. {
  590. if (_pszHandlerDefaultOriginal)
  591. {
  592. CoTaskMemFree(_pszHandlerDefaultOriginal);
  593. }
  594. if (_pszHandlerDefault)
  595. {
  596. CoTaskMemFree(_pszHandlerDefault);
  597. }
  598. if (_pszIconLabel)
  599. {
  600. CoTaskMemFree((void*)_pszIconLabel);
  601. }
  602. if (_pszIconLocation)
  603. {
  604. CoTaskMemFree((void*)_pszIconLocation);
  605. }
  606. }
  607. HRESULT _MakeDeviceLabel(LPCWSTR pszSource, LPWSTR* ppszDest)
  608. {
  609. WCHAR szDeviceName[250];
  610. HRESULT hr = SHLoadIndirectString(pszSource, szDeviceName, ARRAYSIZE(szDeviceName), NULL);
  611. if (SUCCEEDED(hr))
  612. {
  613. hr = SHStrDup(szDeviceName, ppszDest);
  614. }
  615. return hr;
  616. }
  617. HRESULT CNoContentData::Init(LPCWSTR pszDeviceID)
  618. {
  619. lstrcpyn(_szDeviceID, pszDeviceID, ARRAYSIZE(_szDeviceID));
  620. IAutoplayHandler* piah;
  621. HRESULT hr = _GetAutoplayHandlerNoContent(_szDeviceID, TEXT("DeviceArrival"), &piah);
  622. if (SUCCEEDED(hr))
  623. {
  624. hr = piah->GetDefaultHandler(&_pszHandlerDefaultOriginal);
  625. if (SUCCEEDED(hr))
  626. {
  627. if (S_FALSE != hr)
  628. {
  629. _dwHandlerDefaultFlags = HANDLERDEFAULT_GETFLAGS(hr);
  630. }
  631. // SHStrDup (we want CoTaskMemAlloc)
  632. hr = SHStrDup(_pszHandlerDefaultOriginal, &_pszHandlerDefault);
  633. }
  634. if (SUCCEEDED(hr))
  635. {
  636. if (_dpaHandlerData.Create(4))
  637. {
  638. hr = _EnumHandlerHelper(piah);
  639. }
  640. }
  641. piah->Release();
  642. }
  643. if (SUCCEEDED(hr))
  644. {
  645. IHWDeviceCustomProperties* pihwdevcp;
  646. hr = GetDeviceProperties(_szDeviceID, &pihwdevcp);
  647. if (SUCCEEDED(hr))
  648. {
  649. LPWSTR pszIconLabel;
  650. hr = pihwdevcp->GetStringProperty(TEXT("Label"), &pszIconLabel);
  651. if (SUCCEEDED(hr))
  652. {
  653. hr = _MakeDeviceLabel(pszIconLabel, &_pszIconLabel);
  654. if (SUCCEEDED(hr))
  655. {
  656. WORD_BLOB* pblob;
  657. hr = pihwdevcp->GetMultiStringProperty(TEXT("Icons"), TRUE, &pblob);
  658. if (SUCCEEDED(hr))
  659. {
  660. hr = SHStrDup(pblob->asData, &_pszIconLocation);
  661. CoTaskMemFree(pblob);
  662. }
  663. CoTaskMemFree(pszIconLabel);
  664. }
  665. }
  666. pihwdevcp->Release();
  667. }
  668. }
  669. return hr;
  670. }