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.

1591 lines
44 KiB

  1. #include "shellprv.h"
  2. #include "filetype.h"
  3. #include "ftascstr.h" //for now, until CoCreateInstance
  4. #include "ftassoc.h"
  5. #include "fassoc.h"
  6. HIMAGELIST CFTAssocInfo::_himlSysSmall = NULL;
  7. HIMAGELIST CFTAssocInfo::_himlSysLarge = NULL;
  8. CFTAssocInfo::CFTAssocInfo() : _cRef(1)
  9. {
  10. }
  11. HRESULT CFTAssocInfo::Init(AIINIT aiinitFlags, LPTSTR pszStr)
  12. {
  13. HRESULT hres = E_INVALIDARG;
  14. _aiinitFlags1 = aiinitFlags;
  15. *_szInitStr2 = 0;
  16. _aiinitFlags2 = AIINIT_NONE;
  17. if (!pszStr && (AIINIT_PROGID == aiinitFlags))
  18. {
  19. // This happens when we create a new ProgID
  20. hres = S_OK;
  21. }
  22. else
  23. {
  24. if (pszStr && *pszStr && (AIINIT_NONE != aiinitFlags))
  25. {
  26. if ((AIINIT_EXT == aiinitFlags) && (TEXT('.') != *pszStr))
  27. {
  28. *_szInitStr1 = TEXT('.');
  29. StrCpyN(_szInitStr1 + 1, pszStr, ARRAYSIZE(_szInitStr1) - 1);
  30. }
  31. else
  32. StrCpyN(_szInitStr1, pszStr, ARRAYSIZE(_szInitStr1));
  33. hres = S_OK;
  34. }
  35. }
  36. // set the info for the registry support
  37. RSInitRoot(HKEY_CLASSES_ROOT, _szInitStr1, NULL, REG_OPTION_NON_VOLATILE,
  38. REG_OPTION_NON_VOLATILE);
  39. return hres;
  40. }
  41. HRESULT CFTAssocInfo::InitComplex(AIINIT aiinitFlags1, LPTSTR pszStr1,
  42. AIINIT aiinitFlags2, LPTSTR pszStr2)
  43. {
  44. HRESULT hres = E_INVALIDARG;
  45. if ((pszStr1 && *pszStr1 && (AIINIT_NONE != aiinitFlags1)) &&
  46. (pszStr2 && *pszStr2&& (AIINIT_NONE != aiinitFlags2)))
  47. {
  48. TCHAR szSubKey[MAX_PROGID + 7 + MAX_ACTION];
  49. StrCpyN(_szInitStr1, pszStr1, ARRAYSIZE(_szInitStr1));
  50. _aiinitFlags1 = aiinitFlags1;
  51. StrCpyN(_szInitStr2, pszStr2, ARRAYSIZE(_szInitStr2));
  52. _aiinitFlags2 = aiinitFlags2;
  53. // set the info for the registry support
  54. StrCpyN(szSubKey, _szInitStr1, MAX_PROGID);
  55. lstrcat(szSubKey, TEXT("\\shell"));
  56. RSInitRoot(HKEY_CLASSES_ROOT, szSubKey, _szInitStr2, REG_OPTION_NON_VOLATILE,
  57. REG_OPTION_NON_VOLATILE);
  58. hres = S_OK;
  59. }
  60. return hres;
  61. }
  62. HRESULT CFTAssocInfo::GetString(AISTR aistrFlags, LPTSTR pszStr, DWORD* pcchStr)
  63. {
  64. HRESULT hres = E_FAIL;
  65. switch(_aiinitFlags1)
  66. {
  67. case AIINIT_EXT:
  68. {
  69. switch(aistrFlags)
  70. {
  71. case AISTR_APPFRIENDLY:
  72. hres = _GetOpenWithInfo(pszStr, pcchStr);
  73. break;
  74. case AISTR_EXT:
  75. StrCpyN(pszStr, _szInitStr1 + 1, *pcchStr);
  76. hres = S_OK;
  77. break;
  78. case AISTR_DOTEXT:
  79. StrCpyN(pszStr, _szInitStr1, *pcchStr);
  80. hres = S_OK;
  81. break;
  82. case AISTR_PROGID:
  83. hres = (RSGetTextValue(NULL, NULL, pszStr, pcchStr) ? S_OK : E_FAIL);
  84. break;
  85. // We fall back to using the progid for the AISTR_XXX's below
  86. case AISTR_ICONLOCATION:
  87. case AISTR_PROGIDDESCR:
  88. {
  89. TCHAR szProgID[MAX_PROGID];
  90. DWORD cchProgID = ARRAYSIZE(szProgID);
  91. IAssocInfo* pAI = NULL;
  92. CFTAssocStore* pAssocStore = new CFTAssocStore();
  93. if ( !pAssocStore )
  94. {
  95. hres = E_OUTOFMEMORY;
  96. break;
  97. }
  98. hres = pAssocStore->GetAssocInfo(_szInitStr1, AIINIT_EXT, &pAI);
  99. if (SUCCEEDED(hres))
  100. {
  101. hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID);
  102. pAI->Release();
  103. if (SUCCEEDED(hres))
  104. {
  105. hres = pAssocStore->GetAssocInfo(szProgID, AIINIT_PROGID, &pAI);
  106. if (SUCCEEDED(hres))
  107. {
  108. hres = pAI->GetString(aistrFlags, pszStr, pcchStr);
  109. pAI->Release();
  110. }
  111. }
  112. }
  113. delete pAssocStore;
  114. break;
  115. }
  116. default:
  117. hres = E_INVALIDARG;
  118. break;
  119. }
  120. break;
  121. }
  122. case AIINIT_PROGID:
  123. {
  124. if (AIINIT_NONE == _aiinitFlags2)
  125. {
  126. switch(aistrFlags)
  127. {
  128. case AISTR_PROGIDDEFAULTACTION:
  129. hres = _GetProgIDDefaultAction(pszStr, pcchStr);
  130. break;
  131. case AISTR_ICONLOCATION:
  132. hres = _GetIconLocation(pszStr, pcchStr);
  133. break;
  134. case AISTR_PROGID:
  135. StrCpyN(pszStr, _szInitStr1, *pcchStr);
  136. hres = S_OK;
  137. break;
  138. case AISTR_PROGIDDESCR:
  139. hres = _GetProgIDDescr(pszStr, pcchStr);
  140. break;
  141. default:
  142. hres = E_INVALIDARG;
  143. break;
  144. }
  145. }
  146. else
  147. {
  148. if (AIINIT_ACTION == _aiinitFlags2)
  149. {
  150. switch (aistrFlags)
  151. {
  152. case AISTR_ACTION:
  153. {
  154. StrCpyN(pszStr, _szInitStr2, *pcchStr);
  155. hres = S_OK;
  156. break;
  157. }
  158. case AISTR_ACTIONFRIENDLY:
  159. {
  160. if (RSGetTextValue(NULL, NULL, pszStr, pcchStr))
  161. {
  162. if (*pszStr)
  163. {
  164. hres = S_OK;
  165. }
  166. else
  167. {
  168. hres = S_FALSE;
  169. }
  170. }
  171. else
  172. {
  173. hres = S_FALSE;
  174. }
  175. break;
  176. }
  177. }
  178. }
  179. else
  180. hres = E_INVALIDARG;
  181. }
  182. break;
  183. }
  184. default:
  185. hres = E_INVALIDARG;
  186. break;
  187. }
  188. return hres;
  189. }
  190. HRESULT CFTAssocInfo::GetDWORD(AIDWORD aidwordFlags, DWORD* pdwData)
  191. {
  192. HRESULT hres = E_FAIL;
  193. switch(_aiinitFlags1)
  194. {
  195. case AIINIT_EXT:
  196. {
  197. switch(aidwordFlags)
  198. {
  199. case AIDWORD_DOCSMALLICON:
  200. case AIDWORD_DOCLARGEICON:
  201. {
  202. hres = _GetExtDocIcon(_szInitStr1,
  203. (AIDWORD_DOCSMALLICON == aidwordFlags), (int*)pdwData);
  204. if (FAILED(hres))
  205. {
  206. TCHAR szProgID[MAX_PROGID];
  207. DWORD cchProgID = ARRAYSIZE(szProgID);
  208. IAssocInfo* pAI = NULL;
  209. CFTAssocStore* pAssocStore = new CFTAssocStore();
  210. if (pAssocStore)
  211. {
  212. hres = pAssocStore->GetAssocInfo(_szInitStr1, AIINIT_EXT, &pAI);
  213. if (SUCCEEDED(hres))
  214. {
  215. hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID);
  216. pAI->Release();
  217. if (SUCCEEDED(hres))
  218. {
  219. hres = pAssocStore->GetAssocInfo(szProgID, AIINIT_PROGID, &pAI);
  220. if (SUCCEEDED(hres))
  221. {
  222. hres = pAI->GetDWORD(aidwordFlags, pdwData);
  223. pAI->Release();
  224. }
  225. }
  226. }
  227. delete pAssocStore;
  228. }
  229. }
  230. break;
  231. }
  232. case AIDWORD_DOCSMALLICON | AIALL_PERUSER:
  233. case AIDWORD_APPSMALLICON:
  234. hres = _GetAppIcon(TRUE, (int*)pdwData);
  235. break;
  236. default:
  237. hres = E_INVALIDARG;
  238. break;
  239. }
  240. break;
  241. }
  242. case AIINIT_PROGID:
  243. {
  244. if (AIINIT_NONE == _aiinitFlags2)
  245. {
  246. switch(aidwordFlags)
  247. {
  248. case AIDWORD_PROGIDEDITFLAGS:
  249. hres = _GetProgIDEditFlags(pdwData);
  250. break;
  251. case AIDWORD_DOCSMALLICON:
  252. case AIDWORD_DOCLARGEICON:
  253. hres = _GetProgIDDocIcon((AIDWORD_DOCSMALLICON == aidwordFlags),
  254. (int*)pdwData);
  255. break;
  256. default:
  257. hres = E_INVALIDARG;
  258. break;
  259. }
  260. }
  261. else
  262. {
  263. hres = E_INVALIDARG;
  264. if (AIINIT_ACTION == _aiinitFlags2)
  265. if (AIDWORD_ACTIONATTRIBUTES == aidwordFlags)
  266. hres = _GetProgIDActionAttributes(pdwData);
  267. }
  268. break;
  269. }
  270. default:
  271. hres = E_INVALIDARG;
  272. break;
  273. }
  274. return hres;
  275. }
  276. HRESULT CFTAssocInfo::GetData(AIDWORD aidataFlags, PBYTE pbData, DWORD* pcbData)
  277. {
  278. HRESULT hres = E_INVALIDARG;
  279. if ((AIINIT_PROGID == _aiinitFlags1) && (AIINIT_ACTION == _aiinitFlags2) &&
  280. (AIDATA_PROGIDACTION == aidataFlags))
  281. {
  282. LPTSTR pszProgID = _szInitStr1;
  283. PROGIDACTION* pPIDA = (PROGIDACTION*)pbData;
  284. LPTSTR pszActionReg = _szInitStr2;
  285. DWORD cchStr = 0;
  286. pPIDA->fUseDDE = FALSE;
  287. StrCpyN(pPIDA->szActionReg, pszActionReg, ARRAYSIZE(pPIDA->szActionReg));
  288. StrCpyN(pPIDA->szOldActionReg, pszActionReg, ARRAYSIZE(pPIDA->szOldActionReg));
  289. cchStr = ARRAYSIZE(pPIDA->szAction);
  290. if (!RSGetTextValue(NULL, NULL, pPIDA->szAction, &cchStr))
  291. {
  292. // By default the friendly name will be the same as the reg key name
  293. StrCpyN(pPIDA->szAction, pszActionReg, ARRAYSIZE(pPIDA->szAction));
  294. }
  295. StrCpyN(pPIDA->szOldAction, pPIDA->szAction, ARRAYSIZE(pPIDA->szOldAction));
  296. cchStr = ARRAYSIZE(pPIDA->szCmdLine);
  297. hres = AssocQueryString(0, ASSOCSTR_COMMAND, pszProgID, pszActionReg,
  298. pPIDA->szCmdLine, &cchStr);
  299. if (SUCCEEDED(hres))
  300. {
  301. HRESULT hresTmp = E_FAIL;
  302. cchStr = ARRAYSIZE(pPIDA->szDDEMsg);
  303. hresTmp = AssocQueryString(0, ASSOCSTR_DDECOMMAND, pszProgID, pszActionReg,
  304. pPIDA->szDDEMsg, &cchStr);
  305. if (SUCCEEDED(hresTmp))
  306. pPIDA->fUseDDE = TRUE;
  307. cchStr = ARRAYSIZE(pPIDA->szDDEApplication);
  308. hresTmp = AssocQueryString(0, ASSOCSTR_DDEAPPLICATION, pszProgID, pszActionReg,
  309. pPIDA->szDDEApplication, &cchStr);
  310. if (SUCCEEDED(hresTmp))
  311. pPIDA->fUseDDE = TRUE;
  312. cchStr = ARRAYSIZE(pPIDA->szDDEAppNotRunning);
  313. hresTmp = AssocQueryString(0, ASSOCSTR_DDEIFEXEC, pszProgID, pszActionReg,
  314. pPIDA->szDDEAppNotRunning, &cchStr);
  315. if (SUCCEEDED(hresTmp))
  316. pPIDA->fUseDDE = TRUE;
  317. cchStr = ARRAYSIZE(pPIDA->szDDETopic);
  318. hresTmp = AssocQueryString(0, ASSOCSTR_DDETOPIC, pszProgID, pszActionReg,
  319. pPIDA->szDDETopic, &cchStr);
  320. if (SUCCEEDED(hresTmp))
  321. pPIDA->fUseDDE = TRUE;
  322. }
  323. }
  324. return hres;
  325. }
  326. HRESULT CFTAssocInfo::SetData(AIDWORD aidataFlags, PBYTE pbData, DWORD cbData)
  327. {
  328. HRESULT hres = E_INVALIDARG;
  329. if ((AIINIT_PROGID == _aiinitFlags1) && (AIINIT_ACTION == _aiinitFlags2) &&
  330. (AIDATA_PROGIDACTION == aidataFlags))
  331. {
  332. HKEY hProgIDKey = NULL;
  333. LONG lRes = RegOpenKeyEx(HKEY_CLASSES_ROOT, _szInitStr1, 0, KEY_WRITE, &hProgIDKey);
  334. hres = E_FAIL;
  335. // <ProgID>
  336. // |_ shell
  337. // |_ <action>
  338. // | (Default): Fr&iendly name (value) (optional) (no UI to set it)
  339. // | "EditFlags": 0x000.... (value) (optional) (no UI to set it)
  340. // |_ Command
  341. // | (Default): e.g. c:\winnt\system32\notepad.exe "%1"
  342. // |_ ddeexec
  343. // | (Default): DDE msg
  344. // |_ Application
  345. // | (Default): Application
  346. // |_ IfExec
  347. // | (Default): ifexec
  348. // |_ Topic
  349. // (Default): topic
  350. if (ERROR_SUCCESS == lRes)
  351. {
  352. HKEY hShellKey = NULL;
  353. HKEY hActionKey = NULL;
  354. HKEY hCommandKey = NULL;
  355. HKEY hDDEKey = NULL;
  356. DWORD dwKey = 0;
  357. PROGIDACTION* pPIDA = (PROGIDACTION*)pbData;
  358. lRes = RegCreateKeyEx(hProgIDKey, TEXT("shell"), 0, NULL,
  359. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hShellKey, &dwKey);
  360. RegCloseKey(hProgIDKey);
  361. if (ERROR_SUCCESS == lRes)
  362. {
  363. lRes = RegCreateKeyEx(hShellKey, _szInitStr2, 0, NULL,
  364. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hActionKey, &dwKey);
  365. RegCloseKey(hShellKey);
  366. }
  367. if (ERROR_SUCCESS == lRes)
  368. {
  369. // Set the friendly name, if different
  370. if (lstrcmp(pPIDA->szAction, pPIDA->szActionReg))
  371. {
  372. lRes = RegSetValueEx(hActionKey, NULL, NULL, REG_SZ, (PBYTE)pPIDA->szAction,
  373. lstrlen(pPIDA->szAction) * sizeof(TCHAR));
  374. }
  375. if (ERROR_SUCCESS == lRes)
  376. {
  377. lRes = RegCreateKeyEx(hActionKey, TEXT("command"), 0, NULL,
  378. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hCommandKey, &dwKey);
  379. }
  380. }
  381. if (ERROR_SUCCESS == lRes)
  382. {
  383. int iLen = lstrlen(pPIDA->szCmdLine);
  384. lRes = RegSetValueEx(hCommandKey, NULL, 0, REG_SZ, (PBYTE)(pPIDA->szCmdLine),
  385. iLen * sizeof(TCHAR));
  386. }
  387. if (ERROR_SUCCESS == lRes)
  388. {
  389. if (pPIDA->fUseDDE)
  390. {
  391. lRes = RegCreateKeyEx(hActionKey, TEXT("ddeexec"), 0, NULL,
  392. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hDDEKey, &dwKey);
  393. if (ERROR_SUCCESS == lRes)
  394. {
  395. HKEY hTmpKey = NULL;
  396. int iLen = 0;
  397. hres = S_OK;
  398. if (*(pPIDA->szDDEMsg))
  399. {
  400. iLen = lstrlen(pPIDA->szDDEMsg);
  401. lRes = RegSetValueEx(hDDEKey, NULL, 0, REG_SZ, (PBYTE)(pPIDA->szDDEMsg),
  402. iLen * sizeof(TCHAR));
  403. if (ERROR_SUCCESS != lRes)
  404. hres = E_FAIL;
  405. }
  406. if (*(pPIDA->szDDEApplication))
  407. {
  408. lRes = RegCreateKeyEx(hDDEKey, TEXT("Application"), 0, NULL,
  409. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hTmpKey, &dwKey);
  410. if (ERROR_SUCCESS == lRes)
  411. {
  412. iLen = lstrlen(pPIDA->szDDEApplication);
  413. lRes = RegSetValueEx(hTmpKey, NULL, 0, REG_SZ,
  414. (PBYTE)(pPIDA->szDDEApplication), iLen * sizeof(TCHAR));
  415. if (ERROR_SUCCESS != lRes)
  416. hres = E_FAIL;
  417. RegCloseKey(hTmpKey);
  418. }
  419. }
  420. if (*(pPIDA->szDDEAppNotRunning))
  421. {
  422. lRes = RegCreateKeyEx(hDDEKey, TEXT("IfExec"), 0, NULL,
  423. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hTmpKey, &dwKey);
  424. if (ERROR_SUCCESS == lRes)
  425. {
  426. iLen = lstrlen(pPIDA->szDDEAppNotRunning);
  427. lRes = RegSetValueEx(hTmpKey, NULL, 0, REG_SZ,
  428. (PBYTE)(pPIDA->szDDEAppNotRunning), iLen * sizeof(TCHAR));
  429. if (ERROR_SUCCESS != lRes)
  430. hres = E_FAIL;
  431. RegCloseKey(hTmpKey);
  432. }
  433. }
  434. if (*(pPIDA->szDDETopic))
  435. {
  436. lRes = RegCreateKeyEx(hDDEKey, TEXT("Topic"), 0, NULL,
  437. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hTmpKey, &dwKey);
  438. if (ERROR_SUCCESS == lRes)
  439. {
  440. iLen = lstrlen(pPIDA->szDDETopic);
  441. lRes = RegSetValueEx(hTmpKey, NULL, 0, REG_SZ,
  442. (PBYTE)(pPIDA->szDDETopic), iLen * sizeof(TCHAR));
  443. if (ERROR_SUCCESS != lRes)
  444. hres = E_FAIL;
  445. RegCloseKey(hTmpKey);
  446. }
  447. }
  448. }
  449. }
  450. }
  451. if (hActionKey)
  452. RegCloseKey(hActionKey);
  453. if (hCommandKey)
  454. RegCloseKey(hCommandKey);
  455. if (hDDEKey)
  456. RegCloseKey(hDDEKey);
  457. }
  458. }
  459. return hres;
  460. }
  461. HRESULT CFTAssocInfo::SetDWORD(AIDWORD aidwordFlags, DWORD dwData)
  462. {
  463. return E_NOTIMPL;
  464. }
  465. HRESULT CFTAssocInfo::SetString(AISTR aistrFlags, LPTSTR pszStr)
  466. {
  467. HRESULT hres = E_FAIL;
  468. switch(_aiinitFlags1)
  469. {
  470. case AIINIT_PROGID:
  471. {
  472. if (AIINIT_NONE == _aiinitFlags2)
  473. {
  474. switch(aistrFlags)
  475. {
  476. case AISTR_PROGIDDEFAULTACTION:
  477. hres = _SetProgIDDefaultAction(pszStr);
  478. break;
  479. case AISTR_PROGIDDESCR:
  480. hres = (RSSetTextValue(NULL, NULL, pszStr) ? S_OK : E_FAIL);
  481. break;
  482. case AISTR_ICONLOCATION:
  483. hres = _SetIconLocation(pszStr);
  484. break;
  485. default:
  486. hres = E_INVALIDARG;
  487. break;
  488. }
  489. }
  490. else
  491. {
  492. hres = E_INVALIDARG;
  493. }
  494. break;
  495. }
  496. case AIINIT_EXT:
  497. {
  498. switch(aistrFlags)
  499. {
  500. case AISTR_PROGID:
  501. hres = (RSSetTextValue(NULL, NULL,pszStr) ? S_OK : E_FAIL);
  502. break;
  503. default:
  504. hres = E_INVALIDARG;
  505. break;
  506. }
  507. break;
  508. }
  509. default:
  510. hres = E_INVALIDARG;
  511. break;
  512. }
  513. return hres;
  514. }
  515. HRESULT CFTAssocInfo::GetBOOL(AIBOOL aiboolFlags, BOOL* pfBool)
  516. {
  517. HRESULT hres = E_FAIL;
  518. switch(_aiinitFlags1)
  519. {
  520. case AIINIT_EXT:
  521. {
  522. switch(aiboolFlags)
  523. {
  524. case AIBOOL_EXTEXIST:
  525. {
  526. HKEY hKey = NULL;
  527. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, _szInitStr1,
  528. 0, KEY_READ, &hKey))
  529. {
  530. *pfBool = TRUE;
  531. RegCloseKey(hKey);
  532. }
  533. else
  534. *pfBool = FALSE;
  535. hres = S_OK;
  536. break;
  537. }
  538. case AIBOOL_EXTASSOCIATED:
  539. hres = _ExtIsAssociated(pfBool);
  540. break;
  541. case AIBOOL_PERUSERINFOAVAILABLE:
  542. {
  543. IQueryAssociations *pQA;
  544. WCHAR szwExt[MAX_EXT];
  545. SHTCharToUnicode(_szInitStr1, szwExt, ARRAYSIZE(szwExt));
  546. // This need to return FALSE on failure
  547. *pfBool = FALSE;
  548. if (SUCCEEDED(AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations, (void**)&pQA)))
  549. {
  550. pQA->Init(0, szwExt, NULL, NULL);
  551. if (pQA->GetData(0, ASSOCDATA_HASPERUSERASSOC, NULL, NULL, NULL) == S_OK)
  552. *pfBool = TRUE;
  553. pQA->Release();
  554. hres = S_OK;
  555. }
  556. break;
  557. }
  558. case AIBOOL_EXCLUDE:
  559. {
  560. CFTAssocStore* pAssocStore = new CFTAssocStore();
  561. if (pAssocStore)
  562. {
  563. IAssocInfo* pAI = NULL;
  564. hres = pAssocStore->GetAssocInfo(_szInitStr1, AIINIT_EXT, &pAI);
  565. if (SUCCEEDED(hres))
  566. {
  567. TCHAR szProgID[MAX_PROGID];
  568. DWORD cchProgID = ARRAYSIZE(szProgID);
  569. hres = pAI->GetString(AISTR_PROGID, szProgID, &cchProgID);
  570. pAI->Release();
  571. if (SUCCEEDED(hres))
  572. {
  573. hres = pAssocStore->GetAssocInfo(szProgID, AIINIT_PROGID, &pAI);
  574. if (SUCCEEDED(hres))
  575. {
  576. hres = pAI->GetBOOL(aiboolFlags, pfBool);
  577. pAI->Release();
  578. }
  579. }
  580. }
  581. delete pAssocStore;
  582. }
  583. break;
  584. }
  585. default:
  586. hres = E_INVALIDARG;
  587. break;
  588. }
  589. break;
  590. }
  591. case AIINIT_PROGID:
  592. {
  593. switch(aiboolFlags)
  594. {
  595. case AIBOOL_CONFIRMOPEN:
  596. case AIBOOL_EDITDESCR:
  597. case AIBOOL_EDITDOCICON:
  598. case AIBOOL_EDIT:
  599. case AIBOOL_EDITREMOVE:
  600. case AIBOOL_EXCLUDE:
  601. case AIBOOL_SHOW:
  602. case AIBOOL_PROGIDHASNOEXT:
  603. {
  604. hres = _IsEditFlagSet(aiboolFlags, pfBool);
  605. break;
  606. }
  607. case AIBOOL_BROWSEINPLACE:
  608. {
  609. hres = _IsBrowseInPlace(pfBool);
  610. break;
  611. }
  612. case AIBOOL_BROWSEINPLACEENABLED:
  613. {
  614. hres = _IsBrowseInPlaceEnabled(pfBool);
  615. break;
  616. }
  617. case AIBOOL_ALWAYSSHOWEXT:
  618. {
  619. *pfBool = RSValueExist(NULL, TEXT("AlwaysShowExt"));
  620. hres = S_OK;
  621. break;
  622. }
  623. default:
  624. hres = E_INVALIDARG;
  625. break;
  626. }
  627. break;
  628. }
  629. default:
  630. hres = E_INVALIDARG;
  631. break;
  632. }
  633. return hres;
  634. }
  635. HRESULT CFTAssocInfo::SetBOOL(AIBOOL aiboolFlags, BOOL fBool)
  636. {
  637. HRESULT hres = E_FAIL;
  638. switch(_aiinitFlags1)
  639. {
  640. case AIINIT_PROGID:
  641. {
  642. switch(aiboolFlags)
  643. {
  644. case AIBOOL_CONFIRMOPEN:
  645. {
  646. hres = _SetEditFlagSet(aiboolFlags, fBool);
  647. break;
  648. }
  649. case AIBOOL_BROWSEINPLACE:
  650. {
  651. hres = _SetBrowseInPlace(fBool);
  652. break;
  653. }
  654. case AIBOOL_ALWAYSSHOWEXT:
  655. {
  656. if (fBool)
  657. {
  658. RSDeleteValue(NULL, TEXT("NeverShowExt"));
  659. hres = (RSSetTextValue(NULL, TEXT("AlwaysShowExt"), TEXT("")) ? S_OK : E_FAIL);
  660. }
  661. else
  662. hres = (RSDeleteValue(NULL, TEXT("AlwaysShowExt")) ? S_OK : E_FAIL);
  663. break;
  664. }
  665. default:
  666. hres = E_INVALIDARG;
  667. break;
  668. }
  669. break;
  670. }
  671. default:
  672. hres = E_INVALIDARG;
  673. break;
  674. }
  675. return hres;
  676. }
  677. HRESULT CFTAssocInfo::Create()
  678. {
  679. HRESULT hres = E_FAIL;
  680. switch(_aiinitFlags1)
  681. {
  682. case AIINIT_EXT:
  683. {
  684. HKEY hKey = NULL;
  685. DWORD dwKey = 0;
  686. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CLASSES_ROOT, _szInitStr1,
  687. 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hKey, &dwKey))
  688. {
  689. RegCloseKey(hKey);
  690. hres = S_OK;
  691. }
  692. break;
  693. }
  694. case AIINIT_PROGID:
  695. {
  696. hres = _CreateProgID();
  697. break;
  698. }
  699. default:
  700. hres = E_INVALIDARG;
  701. break;
  702. }
  703. return hres;
  704. }
  705. HRESULT CFTAssocInfo::DelString(AISTR aistrFlags)
  706. {
  707. HRESULT hres = E_FAIL;
  708. switch(_aiinitFlags1)
  709. {
  710. case AIINIT_EXT:
  711. {
  712. switch(aistrFlags)
  713. {
  714. case AISTR_PROGID:
  715. {
  716. hres = (RSDeleteValue(NULL, NULL) ? S_OK : E_FAIL);
  717. break;
  718. }
  719. default:
  720. hres = E_INVALIDARG;
  721. break;
  722. }
  723. break;
  724. }
  725. default:
  726. hres = E_INVALIDARG;
  727. break;
  728. }
  729. return hres;
  730. }
  731. HRESULT CFTAssocInfo::Delete(AIALL aiallFlags)
  732. {
  733. HRESULT hres = E_INVALIDARG;
  734. switch (aiallFlags)
  735. {
  736. case AIALL_NONE:
  737. {
  738. LONG lRes = -1;
  739. if ((AIINIT_PROGID == _aiinitFlags1) && (AIINIT_ACTION == _aiinitFlags2))
  740. {
  741. TCHAR szProgIDShell[MAX_PROGID + 1 + 5 + 1];
  742. HKEY hProgIDKey = NULL;
  743. StrCpyN(szProgIDShell, _szInitStr1, ARRAYSIZE(szProgIDShell));
  744. lstrcat(szProgIDShell, TEXT("\\shell"));
  745. lRes = RegOpenKeyEx(HKEY_CLASSES_ROOT, szProgIDShell, 0, KEY_ALL_ACCESS,
  746. &hProgIDKey);
  747. if (ERROR_SUCCESS == lRes)
  748. {
  749. lRes = SHDeleteKey(hProgIDKey, _szInitStr2);
  750. RegCloseKey(hProgIDKey);
  751. }
  752. }
  753. else
  754. {
  755. if (AIINIT_EXT == _aiinitFlags1)
  756. lRes = SHDeleteKey(HKEY_CLASSES_ROOT, _szInitStr1);
  757. }
  758. hres = (ERROR_SUCCESS == lRes) ? S_OK : E_FAIL;
  759. break;
  760. }
  761. case AIALL_PERUSER:
  762. {
  763. if (AIINIT_EXT == _aiinitFlags1)
  764. {
  765. UserAssocSet(UASET_CLEAR, _szInitStr1, NULL);
  766. hres = S_OK;
  767. }
  768. else
  769. {
  770. hres = E_NOTIMPL;
  771. }
  772. break;
  773. }
  774. }
  775. return hres;
  776. }
  777. HRESULT CFTAssocInfo::_CreateProgID()
  778. {
  779. HRESULT hres = E_FAIL;
  780. LRESULT lRes = -1;
  781. DWORD dwKey = REG_OPENED_EXISTING_KEY;
  782. int i = 1;
  783. do
  784. {
  785. HKEY hKey = NULL;
  786. wnsprintf(_szInitStr1, ARRAYSIZE(_szInitStr1), TEXT("ft%06d"), i);
  787. lRes = RegCreateKeyEx(HKEY_CLASSES_ROOT, _szInitStr1,
  788. 0, NULL, REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hKey, &dwKey);
  789. if (ERROR_SUCCESS == lRes)
  790. RegCloseKey(hKey);
  791. ++i;
  792. }
  793. while((ERROR_SUCCESS == lRes) && (REG_OPENED_EXISTING_KEY == dwKey));
  794. if (REG_OPENED_EXISTING_KEY != dwKey)
  795. hres = S_OK;
  796. return hres;
  797. }
  798. HRESULT CFTAssocInfo::_SetIconLocation(LPTSTR pszStr)
  799. {
  800. HKEY hProgIDKey = NULL;
  801. LONG lRes = RegOpenKeyEx(HKEY_CLASSES_ROOT, _szInitStr1, 0, KEY_WRITE, &hProgIDKey);
  802. // ProgID
  803. // |_ DefaultIcon
  804. // |_ (Default) "path\filename.ext, index"
  805. //
  806. if (ERROR_SUCCESS == lRes)
  807. {
  808. HKEY hDefaultIconKey = NULL;
  809. DWORD dwKey = NULL;
  810. lRes = RegCreateKeyEx(hProgIDKey, TEXT("DefaultIcon"), 0, NULL,
  811. REG_OPTION_NON_VOLATILE, MAXIMUM_ALLOWED, NULL, &hDefaultIconKey, &dwKey);
  812. if (ERROR_SUCCESS == lRes)
  813. {
  814. lRes = RegSetValueEx(hDefaultIconKey, NULL, 0, REG_SZ, (PBYTE)pszStr,
  815. lstrlen(pszStr) * sizeof(TCHAR));
  816. RegCloseKey(hDefaultIconKey);
  817. }
  818. RegCloseKey(hProgIDKey);
  819. }
  820. return ((ERROR_SUCCESS == lRes) ? S_OK : E_FAIL);
  821. }
  822. HRESULT CFTAssocInfo::_GetProgIDDefaultAction(LPTSTR pszStr, DWORD* pcchStr)
  823. {
  824. return (RSGetTextValue(TEXT("shell"), NULL, pszStr, pcchStr) ? S_OK : E_FAIL);
  825. }
  826. HRESULT CFTAssocInfo::_SetProgIDDefaultAction(LPTSTR pszStr)
  827. {
  828. return (RSSetTextValue(TEXT("shell"), NULL, pszStr) ? S_OK : E_FAIL);
  829. }
  830. HRESULT CFTAssocInfo::_IsBrowseInPlaceEnabled(BOOL* pfBool)
  831. {
  832. HRESULT hres = (RSSubKeyExist(TEXT("DocObject")) ? S_OK : E_FAIL);
  833. if (SUCCEEDED(hres))
  834. *pfBool = TRUE;
  835. else
  836. *pfBool = FALSE;
  837. if (FAILED(hres))
  838. hres = S_FALSE;
  839. return hres;
  840. }
  841. HRESULT CFTAssocInfo::_IsBrowseInPlace(BOOL* pfBool)
  842. {
  843. HRESULT hres = E_FAIL;
  844. LPTSTR pszProgID = _szInitStr1;
  845. ASSERT(_aiinitFlags1 == AIINIT_PROGID);
  846. *pfBool = FALSE;
  847. if (RSSubKeyExist(TEXT("DocObject")))
  848. {
  849. DWORD dwValue;
  850. hres = (RSGetDWORDValue(NULL, TEXT("BrowserFlags"), &dwValue) ? S_OK : E_FAIL);
  851. if (SUCCEEDED(hres))
  852. {
  853. *pfBool = IsFlagClear(dwValue, BROWSEHACK_DONTINPLACENAVIGATE);
  854. }
  855. else
  856. {
  857. *pfBool = TRUE;
  858. }
  859. }
  860. if (FAILED(hres))
  861. hres = S_FALSE;
  862. return hres;
  863. }
  864. HRESULT CFTAssocInfo::_SetBrowseInPlace(BOOL fBool)
  865. {
  866. DWORD dwValue;
  867. DWORD cbSize = sizeof(dwValue);
  868. LPTSTR pszProgID = _szInitStr1;
  869. if (RSGetDWORDValue(NULL, TEXT("BrowserFlags"), &dwValue))
  870. {
  871. // Watch out: Inverse of fBool
  872. if (fBool)
  873. ClearFlag(dwValue, BROWSEHACK_DONTINPLACENAVIGATE);
  874. else
  875. SetFlag(dwValue, BROWSEHACK_DONTINPLACENAVIGATE);
  876. }
  877. else
  878. {
  879. dwValue = fBool ? 0 : BROWSEHACK_DONTINPLACENAVIGATE;
  880. }
  881. if (dwValue)
  882. {
  883. RSSetDWORDValue(NULL, TEXT("BrowserFlags"), dwValue);
  884. }
  885. else
  886. {
  887. RSDeleteValue(NULL, TEXT("BrowserFlags"));
  888. }
  889. return S_OK;
  890. }
  891. HRESULT CFTAssocInfo::_IsEditFlagSet(DWORD dwMask, BOOL* pfBool)
  892. {
  893. DWORD dwEditFlags = 0;
  894. LPTSTR pszProgID = _szInitStr1;
  895. HRESULT hres = _GetProgIDEditFlags(&dwEditFlags);
  896. if (FAILED(hres))
  897. {
  898. hres = S_FALSE;
  899. // let's put a default value
  900. dwEditFlags = 0;
  901. }
  902. switch(dwMask)
  903. {
  904. case AIBOOL_CONFIRMOPEN:
  905. *pfBool = IsFlagSet(dwEditFlags, FTA_OpenIsSafe);
  906. break;
  907. case AIBOOL_EDITDESCR:
  908. *pfBool = !(IsFlagSet(dwEditFlags, FTA_NoEditDesc));
  909. break;
  910. case AIBOOL_EDITDOCICON:
  911. *pfBool = !(IsFlagSet(dwEditFlags, FTA_NoEditIcon));
  912. break;
  913. case AIBOOL_EDIT:
  914. *pfBool = !(IsFlagSet(dwEditFlags, FTA_NoEdit));
  915. break;
  916. case AIBOOL_EDITREMOVE:
  917. *pfBool = !(IsFlagSet(dwEditFlags, FTA_NoRemove));
  918. break;
  919. case AIBOOL_EXCLUDE:
  920. *pfBool = IsFlagSet(dwEditFlags, FTA_Exclude);
  921. break;
  922. case AIBOOL_SHOW:
  923. *pfBool = IsFlagSet(dwEditFlags, FTA_Show);
  924. break;
  925. case AIBOOL_PROGIDHASNOEXT:
  926. *pfBool = !IsFlagSet(dwEditFlags, FTA_HasExtension);
  927. break;
  928. }
  929. return hres;
  930. }
  931. HRESULT CFTAssocInfo::_SetEditFlagSet(DWORD dwMask, BOOL fBool)
  932. {
  933. DWORD dwEditFlags = 0;
  934. DWORD dwToSet = 0;
  935. HRESULT hres = _GetProgIDEditFlags(&dwEditFlags);
  936. if (FAILED(hres))
  937. dwEditFlags = 0;
  938. switch(dwMask)
  939. {
  940. case AIBOOL_CONFIRMOPEN:
  941. dwToSet = FTA_OpenIsSafe;
  942. hres = S_OK;
  943. break;
  944. default:
  945. hres = E_FAIL;
  946. break;
  947. }
  948. if (SUCCEEDED(hres))
  949. {
  950. if (fBool)
  951. SetFlag(dwEditFlags, dwToSet);
  952. else
  953. ClearFlag(dwEditFlags, dwToSet);
  954. if (!RSSetDWORDValue(NULL, TEXT("EditFlags"), dwEditFlags))
  955. {
  956. hres = E_FAIL;
  957. }
  958. }
  959. return hres;
  960. }
  961. HRESULT CFTAssocInfo::_GetProgIDActionAttributes(DWORD* pdwAttributes)
  962. {
  963. DWORD dwSize = sizeof(*pdwAttributes);
  964. HRESULT hres = E_FAIL;
  965. // Was there an EditFlags key?
  966. if (RSGetDWORDValue(NULL, TEXT("EditFlags"), pdwAttributes))
  967. {
  968. // Yes
  969. hres = S_OK;
  970. }
  971. else
  972. {
  973. // No default to attributes = 0
  974. *pdwAttributes = 0;
  975. hres = S_FALSE;
  976. }
  977. return hres;
  978. }
  979. HRESULT CFTAssocInfo::_GetProgIDEditFlags(DWORD* pdwEditFlags)
  980. {
  981. DWORD dwSize = sizeof(*pdwEditFlags);
  982. LPTSTR pszProgID = _szInitStr1;
  983. return (RSGetDWORDValue(NULL, TEXT("EditFlags"), pdwEditFlags) ? S_OK : E_FAIL);
  984. }
  985. HRESULT CFTAssocInfo::_GetIconLocation(LPTSTR pszStr, DWORD* pcchStr)
  986. {
  987. return (RSGetTextValue(TEXT("DefaultIcon"), NULL, pszStr, pcchStr) ? S_OK : E_FAIL);
  988. }
  989. HRESULT CFTAssocInfo::_GetOpenWithInfo(LPTSTR pszStr, DWORD* pcchStr)
  990. {
  991. int iRet = -1;
  992. LPTSTR pszExt = _szInitStr1;
  993. IQueryAssociations* pQA = NULL;
  994. HRESULT hres = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations,
  995. (LPVOID*)&pQA);
  996. if (SUCCEEDED(hres))
  997. {
  998. WCHAR szwExt[MAX_EXT];
  999. SHTCharToUnicode(pszExt, szwExt, ARRAYSIZE(szwExt));
  1000. hres = pQA->Init(0, szwExt, NULL, NULL);
  1001. if (SUCCEEDED(hres))
  1002. {
  1003. WCHAR szwAppFriendlyName[MAX_APPFRIENDLYNAME];
  1004. DWORD cchAFName = ARRAYSIZE(szwAppFriendlyName);
  1005. TCHAR szAppl[MAX_PATH];
  1006. HRESULT hresFriendlyName = pQA->GetString(ASSOCF_VERIFY | ASSOCF_OPEN_BYEXENAME,
  1007. ASSOCSTR_FRIENDLYAPPNAME, NULL, szwAppFriendlyName, &cchAFName);
  1008. // Did we get a friendly name?
  1009. if (SUCCEEDED(hresFriendlyName))
  1010. {
  1011. // Yes, use it
  1012. SHUnicodeToTChar(szwAppFriendlyName, pszStr, *pcchStr);
  1013. }
  1014. // Reuse szwAppFriendlyName
  1015. hres = pQA->GetString(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, NULL,
  1016. szwAppFriendlyName, &cchAFName);
  1017. if (SUCCEEDED(hres))
  1018. {
  1019. SHUnicodeToTChar(szwAppFriendlyName, szAppl, ARRAYSIZE(szAppl));
  1020. if (FAILED(hresFriendlyName))
  1021. {
  1022. // We failed to get a friendly name, use the EXE name
  1023. StrCpyN(pszStr, szAppl, *pcchStr);
  1024. }
  1025. }
  1026. }
  1027. pQA->Release();
  1028. }
  1029. if (FAILED(hres))
  1030. *(pszStr) = 0;
  1031. return hres;
  1032. }
  1033. HRESULT CFTAssocInfo::_GetAppIcon(BOOL fSmall, int* piIcon)
  1034. {
  1035. LPTSTR pszExt = _szInitStr1;
  1036. IQueryAssociations* pQA = NULL;
  1037. HRESULT hres = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations,
  1038. (LPVOID*)&pQA);
  1039. if (SUCCEEDED(hres))
  1040. {
  1041. WCHAR szwExt[MAX_EXT];
  1042. SHTCharToUnicode(pszExt, szwExt, ARRAYSIZE(szwExt));
  1043. hres = pQA->Init(0, szwExt, NULL, NULL);
  1044. if (SUCCEEDED(hres))
  1045. {
  1046. WCHAR szwExecutable[MAX_PATH];
  1047. DWORD cchExecutable = ARRAYSIZE(szwExecutable);
  1048. hres = pQA->GetString(ASSOCF_VERIFY,
  1049. ASSOCSTR_EXECUTABLE, NULL, szwExecutable, &cchExecutable);
  1050. if (SUCCEEDED(hres))
  1051. {
  1052. HIMAGELIST himl = fSmall ? _himlSysSmall : _himlSysLarge;
  1053. int iImage = -1;
  1054. TCHAR szExe[MAX_PATH];
  1055. SHUnicodeToTChar(szwExecutable, szExe, ARRAYSIZE(szExe));
  1056. SHFILEINFO sfi = {0};
  1057. UINT uFlags = SHGFI_USEFILEATTRIBUTES;
  1058. uFlags |= (fSmall ? (SHGFI_SMALLICON|SHGFI_ICON) : SHGFI_ICON);
  1059. if (SHGetFileInfo(szExe, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), uFlags))
  1060. {
  1061. *piIcon = sfi.iIcon;
  1062. DestroyIcon(sfi.hIcon);
  1063. hres = S_OK;
  1064. }
  1065. }
  1066. }
  1067. pQA->Release();
  1068. }
  1069. return hres;
  1070. }
  1071. HRESULT CFTAssocInfo::_ExtIsAssociated(BOOL* pfIsAssociated)
  1072. {
  1073. TCHAR szProgID[MAX_PROGID];
  1074. DWORD cchProgID = ARRAYSIZE(szProgID);
  1075. LPTSTR pszExt = _szInitStr1;
  1076. if (RSGetTextValue(NULL, NULL, szProgID, &cchProgID) && szProgID[0])
  1077. {
  1078. *pfIsAssociated = TRUE;
  1079. }
  1080. else
  1081. {
  1082. *pfIsAssociated = FALSE;
  1083. }
  1084. return S_OK;
  1085. }
  1086. HRESULT CFTAssocInfo::_GetExtDocIcon(LPTSTR pszExt, BOOL fSmall, int* piIcon)
  1087. {
  1088. HRESULT hres = E_FAIL;
  1089. SHFILEINFO sfi = {0};
  1090. ASSERT(TEXT('.') == *pszExt);
  1091. UINT uFlags = SHGFI_USEFILEATTRIBUTES;
  1092. uFlags |= (fSmall ? (SHGFI_SMALLICON|SHGFI_ICON) : SHGFI_ICON);
  1093. if (SHGetFileInfo(pszExt, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), uFlags))
  1094. {
  1095. *piIcon = sfi.iIcon;
  1096. DestroyIcon(sfi.hIcon);
  1097. hres = S_OK;
  1098. }
  1099. return hres;
  1100. }
  1101. HRESULT CFTAssocInfo::_GetProgIDDocIcon(BOOL fSmall, int* piIcon)
  1102. {
  1103. HRESULT hres = E_FAIL;
  1104. SHFILEINFO sfi = {0};
  1105. LPTSTR pszProgID = _szInitStr1;
  1106. HIMAGELIST himl = fSmall ? _himlSysSmall : _himlSysLarge;
  1107. BOOL fHasNoExtension = FALSE;
  1108. // Try the extension(s) first, unless this is a progID without extension
  1109. IEnumAssocInfo* pEnum = NULL;
  1110. if (AIINIT_PROGID == _aiinitFlags1)
  1111. GetBOOL(AIBOOL_PROGIDHASNOEXT, &fHasNoExtension);
  1112. if (!fHasNoExtension)
  1113. {
  1114. CFTAssocStore* pAssocStore = new CFTAssocStore();
  1115. if (pAssocStore)
  1116. {
  1117. hres = pAssocStore->EnumAssocInfo(ASENUM_EXT, pszProgID, AIINIT_PROGID, &pEnum);
  1118. delete pAssocStore;
  1119. }
  1120. if (SUCCEEDED(hres))
  1121. {
  1122. IAssocInfo* pAI = NULL;
  1123. hres = E_FAIL;
  1124. while (FAILED(hres) && (S_OK == pEnum->Next(&pAI)))
  1125. {
  1126. TCHAR szExt[MAX_EXT];
  1127. DWORD cchExt = ARRAYSIZE(szExt);
  1128. hres = pAI->GetString(AISTR_DOTEXT, szExt, &cchExt);
  1129. if (SUCCEEDED(hres))
  1130. hres = _GetExtDocIcon(szExt, fSmall, piIcon);
  1131. pAI->Release();
  1132. }
  1133. pEnum->Release();
  1134. }
  1135. }
  1136. // Did it fail?
  1137. if (FAILED(hres))
  1138. {
  1139. // Yes get it from the progID "DefaultIcon" key, if any
  1140. hres = E_FAIL;
  1141. TCHAR szDefaultIcon[MAX_ICONLOCATION];
  1142. DWORD cchDefaultIcon = ARRAYSIZE(szDefaultIcon);
  1143. __InitImageLists();
  1144. if (RSGetTextValue(TEXT("DefaultIcon"), NULL, szDefaultIcon, &cchDefaultIcon) &&
  1145. szDefaultIcon[0])
  1146. {
  1147. int iIndex = PathParseIconLocation(szDefaultIcon);
  1148. *piIcon = Shell_GetCachedImageIndex(szDefaultIcon, iIndex, 0);
  1149. hres = ((-1 == *piIcon) ? E_FAIL : S_OK);
  1150. }
  1151. }
  1152. // Did it fail?
  1153. if (FAILED(hres))
  1154. {
  1155. // Yes, get simulated doc icon if from exe name
  1156. IQueryAssociations* pQA = NULL;
  1157. hres = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations,
  1158. (LPVOID*)&pQA);
  1159. if (SUCCEEDED(hres))
  1160. {
  1161. WCHAR szwProgID[MAX_PROGID];
  1162. SHTCharToUnicode(pszProgID, szwProgID, ARRAYSIZE(szwProgID));
  1163. hres = pQA->Init(0, szwProgID, NULL, NULL);
  1164. if (SUCCEEDED(hres))
  1165. {
  1166. TCHAR szExeName[MAX_PATH];
  1167. WCHAR szwExeName[MAX_PATH];
  1168. DWORD dwExeName = ARRAYSIZE(szwExeName);
  1169. hres = pQA->GetString(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, NULL,
  1170. szwExeName, &dwExeName);
  1171. if (SUCCEEDED(hres))
  1172. {
  1173. int iImage = 0;
  1174. SHUnicodeToTChar(szwExeName, szExeName, ARRAYSIZE(szExeName));
  1175. *piIcon = Shell_GetCachedImageIndex(szExeName, 0, GIL_SIMULATEDOC);
  1176. }
  1177. }
  1178. pQA->Release();
  1179. }
  1180. }
  1181. // Did it fail?
  1182. if (FAILED(hres))
  1183. {
  1184. // Yes, get the shell's default icon
  1185. *piIcon = II_DOCNOASSOC;
  1186. hres = S_OK;
  1187. }
  1188. return hres;
  1189. }
  1190. //static
  1191. HRESULT CFTAssocInfo::_GetProgIDDescr(LPTSTR pszProgIDDescr, DWORD* pcchProgIDdescr)
  1192. {
  1193. HRESULT hres = E_FAIL;
  1194. IQueryAssociations* pQA = NULL;
  1195. hres = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations,
  1196. (LPVOID*)&pQA);
  1197. if (SUCCEEDED(hres))
  1198. {
  1199. WCHAR szwProgID[MAX_PROGID];
  1200. SHTCharToUnicode(_szInitStr1, szwProgID, ARRAYSIZE(szwProgID));
  1201. hres = pQA->Init(0, szwProgID, NULL, NULL);
  1202. if (SUCCEEDED(hres))
  1203. {
  1204. WCHAR szwProgIDDescr[MAX_PROGIDDESCR];
  1205. // Prepare progID description
  1206. // Reuse szwProgID
  1207. hres = pQA->GetString(0, ASSOCSTR_FRIENDLYDOCNAME, NULL, szwProgIDDescr,
  1208. (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szwProgIDDescr)));
  1209. if (SUCCEEDED(hres))
  1210. SHUnicodeToTChar(szwProgIDDescr, pszProgIDDescr, *pcchProgIDdescr);
  1211. }
  1212. pQA->Release();
  1213. }
  1214. return hres;
  1215. }
  1216. HRESULT CFTAssocInfo::_OpenSubKey(LPTSTR pszSubKey, REGSAM samDesired, HKEY* phKey)
  1217. {
  1218. HRESULT hres = E_FAIL;
  1219. HKEY hkeyRoot = RSDuplicateRootKey();
  1220. if (hkeyRoot)
  1221. {
  1222. if (ERROR_SUCCESS == RegOpenKeyEx(hkeyRoot, pszSubKey, 0, MAXIMUM_ALLOWED, phKey))
  1223. hres = S_OK;
  1224. else
  1225. hres = E_FAIL;
  1226. RegCloseKey(hkeyRoot);
  1227. }
  1228. return hres;
  1229. }
  1230. HRESULT CFTAssocInfo::__InitImageLists()
  1231. {
  1232. if (!_himlSysLarge ||!_himlSysSmall)
  1233. Shell_GetImageLists(&_himlSysLarge, &_himlSysSmall);
  1234. return S_OK;
  1235. }
  1236. //IUnknown methods
  1237. HRESULT CFTAssocInfo::QueryInterface(REFIID riid, PVOID* ppv)
  1238. {
  1239. #if 0
  1240. static const QITAB qit[] = {
  1241. QITABENT(CFTAssocStore, IAssocStore),
  1242. { 0 },
  1243. };
  1244. return QISearch(this, qit, riid, ppvObj);
  1245. #endif
  1246. if (IsEqualIID(riid, IID_IUnknown))
  1247. *ppv = static_cast<IUnknown*>(this);
  1248. else
  1249. *ppv = static_cast<IAssocInfo*>(this);
  1250. return S_OK;
  1251. }
  1252. ULONG CFTAssocInfo::AddRef()
  1253. {
  1254. return InterlockedIncrement(&_cRef);
  1255. }
  1256. ULONG CFTAssocInfo::Release()
  1257. {
  1258. if (InterlockedDecrement(&_cRef) > 0)
  1259. return _cRef;
  1260. delete this;
  1261. return 0;
  1262. }
  1263. // for C callers
  1264. STDAPI_(BOOL) FT_GetIconLocationFromExt(LPTSTR pszExt, LPTSTR pszPath,
  1265. DWORD cchPath, int* piIconIndex)
  1266. {
  1267. BOOL fRet = FALSE;
  1268. CFTAssocStore* pAssocStore = new CFTAssocStore();
  1269. if (pAssocStore)
  1270. {
  1271. IAssocInfo* pAI = NULL;
  1272. HRESULT hres = pAssocStore->GetAssocInfo(pszExt, AIINIT_EXT, &pAI);
  1273. if (SUCCEEDED(hres))
  1274. {
  1275. hres = pAI->GetString(AISTR_ICONLOCATION, pszPath, &cchPath);
  1276. pAI->Release();
  1277. if (SUCCEEDED(hres))
  1278. {
  1279. *piIconIndex = PathParseIconLocation(pszPath);
  1280. fRet = TRUE;
  1281. }
  1282. }
  1283. delete pAssocStore;
  1284. }
  1285. return fRet;
  1286. }