Leaked source code of windows server 2003
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.

974 lines
25 KiB

  1. /*
  2. * isshlink.cpp - IShellLink implementation for Intshcut class.
  3. */
  4. #include "priv.h"
  5. #include "ishcut.h"
  6. #include "resource.h"
  7. #include <mluisupp.h>
  8. /* Types
  9. ********/
  10. typedef enum isl_getpath_flags
  11. {
  12. // flag combinations
  13. ALL_ISL_GETPATH_FLAGS = (SLGP_SHORTPATH |
  14. SLGP_UNCPRIORITY)
  15. }
  16. ISL_GETPATH_FLAGS;
  17. typedef enum isl_resolve_flags
  18. {
  19. // flag combinations
  20. ALL_ISL_RESOLVE_FLAGS = (SLR_NO_UI |
  21. SLR_ANY_MATCH |
  22. SLR_UPDATE)
  23. }
  24. ISL_RESOLVE_FLAGS;
  25. /********************************** Methods **********************************/
  26. /*----------------------------------------------------------
  27. Purpose: IShellLink::SetPath method for Intshcut
  28. Note:
  29. 1. SetURL clears the internal pidl.
  30. */
  31. STDMETHODIMP
  32. Intshcut::SetPath(
  33. LPCTSTR pcszPath)
  34. {
  35. HRESULT hr;
  36. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  37. ASSERT(IS_VALID_STRING_PTR(pcszPath, -1));
  38. // Treat path as literal URL.
  39. hr = SetURL(pcszPath, 0);
  40. return(hr);
  41. }
  42. /*----------------------------------------------------------
  43. Purpose: IShellLink::GetPath handler for Intshcut
  44. */
  45. STDMETHODIMP
  46. Intshcut::GetPath(
  47. IN LPTSTR pszBuf,
  48. IN int cchBuf,
  49. OUT PWIN32_FIND_DATA pwfd, OPTIONAL
  50. IN DWORD dwFlags)
  51. {
  52. HRESULT hres = E_FAIL;
  53. // We make no distinction between raw paths and cooked paths
  54. dwFlags &= ~SLGP_RAWPATH;
  55. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  56. ASSERT(IS_VALID_WRITE_BUFFER(pszBuf, TCHAR, cchBuf));
  57. ASSERT(NULL == pwfd || IS_VALID_WRITE_PTR(pwfd, WIN32_FIND_DATA));
  58. ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_ISL_GETPATH_FLAGS));
  59. // Init to default values
  60. if (pwfd)
  61. ZeroMemory(pwfd, SIZEOF(*pwfd));
  62. if (cchBuf > 0)
  63. *pszBuf = '\0';
  64. // Ignore dwFlags.
  65. hres = InitProp();
  66. if (SUCCEEDED(hres))
  67. hres = m_pprop->GetProp(PID_IS_URL, pszBuf, cchBuf);
  68. return hres;
  69. }
  70. /*----------------------------------------------------------
  71. Purpose: IShellLink::SetRelativePath method for Intshcut
  72. */
  73. STDMETHODIMP Intshcut::SetRelativePath(LPCTSTR pcszRelativePath, DWORD dwReserved)
  74. {
  75. HRESULT hr;
  76. // dwReserved may be any value.
  77. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  78. ASSERT(IS_VALID_STRING_PTR(pcszRelativePath, -1));
  79. hr = E_NOTIMPL;
  80. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  81. return(hr);
  82. }
  83. /*----------------------------------------------------------
  84. Purpose: IShellLink::SetIDList method for Intshcut
  85. Note:
  86. 1. SetIDList also does SetPath implicitly to update the path (URL)
  87. to match the pidl.
  88. 2. SetPath only clears the pidl to NULL, so internally we know
  89. if we really have a pidl for the shortcut. Although GetIDList
  90. will generate a pidl from path (URL) if we don't have a pidl.
  91. */
  92. STDMETHODIMP Intshcut::SetIDList(LPCITEMIDLIST pcidl)
  93. {
  94. HRESULT hr;
  95. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  96. ASSERT(IS_VALID_READ_PTR(pcidl, ITEMIDLIST));
  97. hr = InitProp();
  98. if (SUCCEEDED(hr))
  99. {
  100. hr = m_pprop->SetIDListProp(pcidl);
  101. if (SUCCEEDED(hr))
  102. {
  103. // if the pidl was set successfully, update the path.
  104. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  105. hr = IEGetDisplayName(pcidl, szURL, SHGDN_FORPARSING);
  106. if (SUCCEEDED(hr))
  107. m_pprop->SetURLProp(szURL, 0);
  108. }
  109. }
  110. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  111. return(hr);
  112. }
  113. /*----------------------------------------------------------
  114. Purpose: Get the original pidl set by SetIDList.
  115. Note:
  116. 1. Do not generate a pidl from path if we don't have a pidl.
  117. 2. Return S_OK if we have a pidl, caller must NOT check for
  118. SUCCEEDED() return.
  119. */
  120. STDMETHODIMP Intshcut::GetIDListInternal(LPITEMIDLIST *ppidl)
  121. {
  122. HRESULT hres = InitProp();
  123. if (SUCCEEDED(hres))
  124. {
  125. IStream *pStream;
  126. hres = m_pprop->GetProp(PID_IS_IDLIST, &pStream);
  127. if ((hres == S_OK) && pStream)
  128. {
  129. const LARGE_INTEGER li = {0, 0};
  130. // reset the seek pointer
  131. hres = pStream->Seek(li, STREAM_SEEK_SET, NULL);
  132. if (SUCCEEDED(hres))
  133. hres = ILLoadFromStream(pStream, ppidl);
  134. pStream->Release();
  135. }
  136. }
  137. return hres;
  138. }
  139. /*----------------------------------------------------------
  140. Purpose: IShellLink::GetIDList method for Intshcut
  141. Note:
  142. 1. If we don't have a pidl from SetIDList, generate a pidl
  143. from path.
  144. */
  145. STDMETHODIMP Intshcut::GetIDList(LPITEMIDLIST *ppidl)
  146. {
  147. HRESULT hres;
  148. ASSERT(IS_VALID_WRITE_PTR(ppidl, LPITEMIDLIST));
  149. if (!ppidl)
  150. return E_INVALIDARG;
  151. *ppidl = NULL;
  152. hres = InitProp();
  153. if (SUCCEEDED(hres))
  154. {
  155. // check if it already as a pidl.
  156. hres = GetIDListInternal(ppidl);
  157. if (hres != S_OK)
  158. {
  159. // it doesn't have a pidl, get the URL and make a pidl.
  160. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  161. hres = m_pprop->GetProp(PID_IS_URL, szURL, ARRAYSIZE(szURL));
  162. if (SUCCEEDED(hres))
  163. {
  164. hres = IECreateFromPath(szURL, ppidl);
  165. }
  166. }
  167. }
  168. return hres;
  169. }
  170. /*----------------------------------------------------------
  171. Purpose: IShellLink::SetDescription method for Intshcut
  172. */
  173. STDMETHODIMP Intshcut::SetDescription(LPCTSTR pcszDescription)
  174. {
  175. HRESULT hr;
  176. BOOL bDifferent;
  177. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  178. ASSERT(IS_VALID_STRING_PTR(pcszDescription, -1));
  179. // Set m_pszFile to description.
  180. bDifferent = (! m_pszDescription ||
  181. StrCmp(pcszDescription, m_pszDescription) != 0);
  182. if (Str_SetPtr(&m_pszDescription, pcszDescription))
  183. {
  184. if (bDifferent)
  185. Dirty(TRUE);
  186. hr = S_OK;
  187. }
  188. else
  189. hr = E_OUTOFMEMORY;
  190. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  191. return(hr);
  192. }
  193. STDMETHODIMP Intshcut::_ComputeDescription()
  194. {
  195. HRESULT hres;
  196. BSTR bstrTitle = NULL;
  197. if (_punkSite)
  198. {
  199. // Get the title element
  200. IWebBrowser *pwb;
  201. hres = _punkSite->QueryInterface(IID_IWebBrowser, (void **)&pwb);
  202. if (S_OK == hres)
  203. {
  204. IDispatch *pDisp;
  205. hres = pwb->get_Document(&pDisp);
  206. if (S_OK == hres)
  207. {
  208. IHTMLDocument2 *pDoc;
  209. hres = pDisp->QueryInterface(IID_IHTMLDocument2, (void **)&pDoc);
  210. if (S_OK == hres)
  211. {
  212. hres = pDoc->get_title(&bstrTitle);
  213. pDoc->Release();
  214. }
  215. pDisp->Release();
  216. }
  217. pwb->Release();
  218. }
  219. }
  220. TCHAR *pszUrl; // The url for this shortcut
  221. hres = GetURL(&pszUrl);
  222. if (S_OK == hres)
  223. {
  224. TCHAR szDescription[MAX_PATH] = TEXT("");
  225. // We gamble that the URL will always have displayable characters.
  226. // This is a bad assumption but if this assumption is violated then
  227. // there is a good chance that the URL probably cannot even
  228. // be navigated to
  229. // This description is used as the name of the file verbatim
  230. // during drag drop - hence it should look like a .url file name
  231. GetShortcutFileName(pszUrl, bstrTitle, NULL, szDescription, ARRAYSIZE(szDescription));
  232. //PathYetAnotherMakeUniqueName(szTempFileName, szTempFileName, NULL, NULL);
  233. PathCleanupSpec(NULL, szDescription);
  234. // Sometimes PathCleanupSpec can end up simply mangling the description if
  235. // it cannot properly convert the title to ANSI
  236. // hence we check that we have a proper description
  237. if((0 == *szDescription) || (0 == StrCmp(szDescription,TEXT(".url"))))
  238. {
  239. // recompute the description without the title
  240. GetShortcutFileName(pszUrl, NULL, NULL, szDescription, ARRAYSIZE(szDescription));
  241. PathCleanupSpec(NULL, szDescription);
  242. }
  243. hres = SetDescription(szDescription);
  244. SHFree(pszUrl);
  245. }
  246. SysFreeString(bstrTitle);
  247. return hres;
  248. }
  249. // IShellLink::GetDescription method for Intshcut
  250. STDMETHODIMP Intshcut::GetDescription(LPTSTR pszDescription, int cchBuf)
  251. {
  252. HRESULT hr;
  253. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  254. ASSERT(IS_VALID_WRITE_BUFFER(pszDescription, TCHAR, cchBuf));
  255. // Get description from m_pszDescription.
  256. if (NULL == m_pszDescription)
  257. {
  258. _ComputeDescription();
  259. }
  260. if (m_pszDescription)
  261. StrCpyN(pszDescription, m_pszDescription, cchBuf);
  262. else if (m_pszFile)
  263. {
  264. StrCpyN(pszDescription, m_pszFile, cchBuf);
  265. }
  266. else
  267. {
  268. // use default shortcut name
  269. MLLoadString(IDS_NEW_INTSHCUT, pszDescription, cchBuf);
  270. }
  271. hr = S_OK;
  272. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  273. ASSERT(hr == S_OK &&
  274. (cchBuf <= 0 ||
  275. (IS_VALID_STRING_PTR(pszDescription, -1) &&
  276. EVAL(lstrlen(pszDescription) < cchBuf))));
  277. return(hr);
  278. }
  279. // IShellLink::SetArguments method for Intshcut
  280. STDMETHODIMP Intshcut::SetArguments(LPCTSTR pcszArgs)
  281. {
  282. return E_NOTIMPL;
  283. }
  284. // IShellLink::GetArguments for Intshcut
  285. STDMETHODIMP Intshcut::GetArguments(LPTSTR pszArgs, int cchBuf)
  286. {
  287. return E_NOTIMPL;
  288. }
  289. // IShellLink::SetWorkingDirectory handler for Intshcut
  290. STDMETHODIMP Intshcut::SetWorkingDirectory(LPCTSTR pcszWorkingDirectory)
  291. {
  292. HRESULT hres = S_OK;
  293. TCHAR rgchNewPath[MAX_PATH];
  294. BOOL bChanged = FALSE;
  295. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  296. ASSERT(! pcszWorkingDirectory ||
  297. IS_VALID_STRING_PTR(pcszWorkingDirectory, -1));
  298. if (! AnyMeat(pcszWorkingDirectory))
  299. pcszWorkingDirectory = NULL;
  300. if (pcszWorkingDirectory)
  301. {
  302. LPTSTR pszFileName;
  303. if (GetFullPathName(pcszWorkingDirectory, SIZECHARS(rgchNewPath),
  304. rgchNewPath, &pszFileName) > 0)
  305. pcszWorkingDirectory = rgchNewPath;
  306. else
  307. hres = E_PATH_NOT_FOUND;
  308. }
  309. if (hres == S_OK)
  310. {
  311. TCHAR szDir[MAX_PATH];
  312. hres = InitProp();
  313. if (SUCCEEDED(hres))
  314. {
  315. hres = m_pprop->GetProp(PID_IS_WORKINGDIR, szDir, SIZECHARS(szDir));
  316. bChanged = ! ((! pcszWorkingDirectory && S_FALSE == hres) ||
  317. (pcszWorkingDirectory && S_OK == hres &&
  318. ! StrCmp(pcszWorkingDirectory, szDir)));
  319. hres = S_OK;
  320. if (bChanged)
  321. {
  322. hres = m_pprop->SetProp(PID_IS_WORKINGDIR, pcszWorkingDirectory);
  323. }
  324. }
  325. }
  326. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  327. return hres;
  328. }
  329. /*----------------------------------------------------------
  330. Purpose: IShellLink::GetWorkingDirectory handler for Intshcut
  331. */
  332. STDMETHODIMP
  333. Intshcut::GetWorkingDirectory(
  334. IN LPTSTR pszBuf,
  335. IN int cchBuf)
  336. {
  337. HRESULT hres;
  338. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  339. ASSERT(IS_VALID_WRITE_BUFFER(pszBuf, TCHAR, cchBuf));
  340. if (cchBuf > 0)
  341. *pszBuf = '\0';
  342. hres = InitProp();
  343. if (SUCCEEDED(hres))
  344. hres = m_pprop->GetProp(PID_IS_WORKINGDIR, pszBuf, cchBuf);
  345. return hres;
  346. }
  347. /*----------------------------------------------------------
  348. Purpose: IShellLink::SetHotkey handler for Intshcut
  349. */
  350. STDMETHODIMP
  351. Intshcut::SetHotkey(
  352. IN WORD wHotkey)
  353. {
  354. HRESULT hres;
  355. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  356. hres = InitProp();
  357. if (SUCCEEDED(hres))
  358. hres = m_pprop->SetProp(PID_IS_HOTKEY, wHotkey);
  359. return hres;
  360. }
  361. /*----------------------------------------------------------
  362. Purpose: IShellLink::GetHotkey handler for Intshcut
  363. */
  364. STDMETHODIMP
  365. Intshcut::GetHotkey(
  366. PWORD pwHotkey)
  367. {
  368. HRESULT hres;
  369. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  370. ASSERT(IS_VALID_WRITE_PTR(pwHotkey, WORD));
  371. hres = InitProp();
  372. if (SUCCEEDED(hres))
  373. {
  374. m_pprop->GetProp(PID_IS_HOTKEY, pwHotkey);
  375. hres = S_OK;
  376. }
  377. return hres;
  378. }
  379. /*----------------------------------------------------------
  380. Purpose: IShellLink::SetShowCmd handler for Intshcut
  381. */
  382. STDMETHODIMP
  383. Intshcut::SetShowCmd(
  384. IN int nShowCmd)
  385. {
  386. HRESULT hres;
  387. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  388. ASSERT(IsValidShowCmd(nShowCmd));
  389. hres = InitProp();
  390. if (SUCCEEDED(hres))
  391. hres = m_pprop->SetProp(PID_IS_SHOWCMD, nShowCmd);
  392. return hres;
  393. }
  394. /*----------------------------------------------------------
  395. Purpose: IShellLink::GetShowCmd handler for Intshcut
  396. */
  397. STDMETHODIMP
  398. Intshcut::GetShowCmd(
  399. OUT int *pnShowCmd)
  400. {
  401. HRESULT hres;
  402. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  403. ASSERT(IS_VALID_WRITE_PTR(pnShowCmd, INT));
  404. hres = InitProp();
  405. if (SUCCEEDED(hres))
  406. {
  407. hres = m_pprop->GetProp(PID_IS_SHOWCMD, pnShowCmd);
  408. if (S_OK != hres)
  409. *pnShowCmd = SW_NORMAL;
  410. hres = S_OK;
  411. }
  412. return hres;
  413. }
  414. /*----------------------------------------------------------
  415. Purpose: IShellLink::SetIconLocation handler for Intshcut
  416. */
  417. STDMETHODIMP
  418. Intshcut::SetIconLocation(
  419. IN LPCTSTR pszFile,
  420. IN int niIcon)
  421. {
  422. HRESULT hres = S_OK;
  423. BOOL bNewMeat;
  424. TCHAR szNewPath[MAX_PATH];
  425. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  426. ASSERT(IsValidIconIndex(pszFile ? S_OK : S_FALSE, pszFile, MAX_PATH, niIcon));
  427. bNewMeat = AnyMeat(pszFile);
  428. if (bNewMeat)
  429. {
  430. if (PathSearchAndQualify(pszFile, szNewPath, SIZECHARS(szNewPath)))
  431. {
  432. hres = S_OK;
  433. }
  434. else
  435. {
  436. hres = E_FILE_NOT_FOUND;
  437. }
  438. }
  439. if (hres == S_OK)
  440. {
  441. TCHAR szOldPath[MAX_PATH];
  442. int niOldIcon;
  443. UINT uFlags;
  444. hres = GetIconLocation(0, szOldPath, SIZECHARS(szOldPath), &niOldIcon,
  445. &uFlags);
  446. if (SUCCEEDED(hres))
  447. {
  448. BOOL bOldMeat;
  449. BOOL bChanged = FALSE;
  450. bOldMeat = AnyMeat(szOldPath);
  451. ASSERT(! *szOldPath ||
  452. bOldMeat);
  453. bChanged = ((! bOldMeat && bNewMeat) ||
  454. (bOldMeat && ! bNewMeat) ||
  455. (bOldMeat && bNewMeat &&
  456. (StrCmp(szOldPath, szNewPath) != 0 ||
  457. niIcon != niOldIcon)));
  458. hres = S_OK;
  459. if (bChanged && bNewMeat)
  460. {
  461. hres = InitProp();
  462. if (SUCCEEDED(hres))
  463. {
  464. hres = m_pprop->SetProp(PID_IS_ICONFILE, szNewPath);
  465. if (SUCCEEDED(hres))
  466. hres = m_pprop->SetProp(PID_IS_ICONINDEX, niIcon);
  467. }
  468. }
  469. }
  470. }
  471. return hres;
  472. }
  473. VOID UrlMunge(
  474. TCHAR *lpszSrc,
  475. TCHAR *lpszDest,
  476. UINT cchDestBufSize,
  477. BOOL fRecentlyChanged)
  478. {
  479. TCHAR *lpszTemp = lpszSrc;
  480. if(fRecentlyChanged)
  481. cchDestBufSize--; // Save up a character
  482. while(*lpszTemp != TEXT('\0') && (cchDestBufSize > 1)) // not End of line and save up one char for \0 in munged string
  483. {
  484. if(TEXT('/') == *lpszTemp)
  485. {
  486. *lpszDest = TEXT('\1');
  487. }
  488. else
  489. {
  490. *lpszDest = *lpszTemp;
  491. }
  492. lpszDest++;
  493. lpszTemp++;
  494. cchDestBufSize--;
  495. }
  496. if(fRecentlyChanged)
  497. {
  498. *lpszDest = TEXT('\2');
  499. lpszDest++;
  500. }
  501. *lpszDest = TEXT('\0');
  502. return;
  503. }
  504. HRESULT HelperForReadIconInfoFromPropStg(
  505. IN LPTSTR pszBuf,
  506. IN int cchBuf,
  507. OUT int * pniIcon,
  508. IPropertyStorage *pPropStg,
  509. PROPSPEC *ppropspec,
  510. IN LPTSTR pszActualUrlBuf,
  511. IN INT cchActualUrlBuf,
  512. BOOL fRecentlyChanged)
  513. {
  514. HRESULT hres;
  515. PROPVARIANT rgpropvar[2];
  516. ASSERT((0 == pszActualUrlBuf) || (cchActualUrlBuf >= MAX_URL_STRING));
  517. if(pszActualUrlBuf)
  518. *pszActualUrlBuf = TEXT('\0');
  519. // Init to default values
  520. *pniIcon = 0;
  521. if (cchBuf > 0)
  522. *pszBuf = TEXT('\0');
  523. hres = pPropStg->ReadMultiple(2, ppropspec, rgpropvar);
  524. if (SUCCEEDED(hres))
  525. {
  526. if (VT_LPWSTR == rgpropvar[1].vt)
  527. {
  528. if(FALSE == PathFileExistsW(rgpropvar[1].pwszVal))
  529. {
  530. UrlMunge(rgpropvar[1].pwszVal, pszBuf, cchBuf, fRecentlyChanged);
  531. }
  532. else
  533. {
  534. // We will just send the icon file and index back with no attempt
  535. // to hash it or fill out the URL field
  536. if(lstrlenW(rgpropvar[1].pwszVal) >= cchBuf)
  537. {
  538. // need a larger buf - simply fail it
  539. hres = E_FAIL;
  540. }
  541. else
  542. {
  543. StrCpyN(pszBuf, rgpropvar[1].pwszVal, cchBuf);
  544. }
  545. }
  546. if(SUCCEEDED(hres) && pszActualUrlBuf)
  547. {
  548. hres = StringCchCopy(pszActualUrlBuf, cchActualUrlBuf, rgpropvar[1].pwszVal);
  549. }
  550. }
  551. if (VT_I4 == rgpropvar[0].vt)
  552. *pniIcon = rgpropvar[0].lVal;
  553. FreePropVariantArray(ARRAYSIZE(rgpropvar), rgpropvar);
  554. }
  555. return hres;
  556. }
  557. //
  558. // Functions from isexicon.cpp
  559. //
  560. /*----------------------------------------------------------
  561. *
  562. *
  563. Purpose: IShellLink::GetIconLocation handler for Intshcut
  564. *
  565. *----------------------------------------------------------*/
  566. STDMETHODIMP
  567. Intshcut::_GetIconLocationWithURLHelper(
  568. IN LPTSTR pszBuf,
  569. IN int cchBuf,
  570. OUT int * pniIcon,
  571. IN LPTSTR pszActualUrl,
  572. UINT cchActualUrlBuf,
  573. BOOL fRecentlyChanged)
  574. {
  575. HRESULT hres;
  576. PROPSPEC rgpropspec[2];
  577. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  578. ASSERT(IS_VALID_WRITE_BUFFER(pszBuf, TCHAR, cchBuf));
  579. ASSERT(IS_VALID_WRITE_PTR(pniIcon, int));
  580. if(!pszBuf)
  581. return E_INVALIDARG;
  582. rgpropspec[0].ulKind = PRSPEC_PROPID;
  583. rgpropspec[1].ulKind = PRSPEC_PROPID;
  584. if(pszActualUrl)
  585. *pszActualUrl = TEXT('\0');
  586. *pszBuf = TEXT('\0');
  587. hres = InitProp();
  588. if (SUCCEEDED(hres))
  589. {
  590. rgpropspec[0].propid = PID_IS_ICONINDEX;
  591. rgpropspec[1].propid = PID_IS_ICONFILE;
  592. hres = HelperForReadIconInfoFromPropStg(
  593. pszBuf, cchBuf, pniIcon, m_pprop,
  594. rgpropspec, pszActualUrl, cchActualUrlBuf,
  595. fRecentlyChanged);
  596. }
  597. if(TEXT('\0') == *pszBuf)
  598. {
  599. // Didn't find it in the shortcut itself
  600. // Poke around the intsite database and if it is there,
  601. // simply stuff it into the shortcut file if you do find
  602. // one
  603. IPropertyStorage *ppropstg = NULL;
  604. hres = Open(FMTID_InternetSite, STGM_READWRITE, &ppropstg);
  605. if(S_OK == hres)
  606. {
  607. // Look for an icon for this specific url
  608. ASSERT(ppropstg);
  609. rgpropspec[0].propid = PID_INTSITE_ICONINDEX;
  610. rgpropspec[1].propid = PID_INTSITE_ICONFILE;
  611. hres = HelperForReadIconInfoFromPropStg(pszBuf, cchBuf, pniIcon,
  612. ppropstg, rgpropspec, pszActualUrl,
  613. cchActualUrlBuf, fRecentlyChanged);
  614. ppropstg->Release();
  615. }
  616. if((S_OK == hres) && (*pszBuf) && pszActualUrl && (*pszActualUrl))
  617. {
  618. // Write this info to the shortcut file
  619. WCHAR *pwszTempBuf;
  620. pwszTempBuf = pszActualUrl;
  621. PROPVARIANT var = {0};
  622. ASSERT(1 == *pniIcon);
  623. var.vt = VT_BSTR;
  624. var.bstrVal = SysAllocString(pwszTempBuf);
  625. if(var.bstrVal)
  626. {
  627. hres = WritePropertyNPB(ISHCUT_INISTRING_SECTIONW, ISHCUT_INISTRING_ICONFILEW,
  628. &var);
  629. SysFreeString(var.bstrVal);
  630. if(S_OK == hres)
  631. {
  632. var.bstrVal = SysAllocString(L"1");
  633. if(var.bstrVal)
  634. {
  635. hres = WritePropertyNPB(ISHCUT_INISTRING_SECTIONW, ISHCUT_INISTRING_ICONINDEXW,
  636. &var);
  637. SysFreeString(var.bstrVal);
  638. }
  639. }
  640. }
  641. hres = S_OK; // retun OK if you found icon and could not write out for whatever reason
  642. }
  643. }
  644. return hres;
  645. }
  646. // IShellLink::GetIconLocation handler for Intshcut
  647. STDMETHODIMP Intshcut::GetIconLocation(LPTSTR pszBuf, int cchBuf, int *pniIcon)
  648. {
  649. UINT uTmp;
  650. return GetIconLocation(0, pszBuf, cchBuf, pniIcon, &uTmp);
  651. }
  652. // IShellLink::Resolve method for Intshcut
  653. STDMETHODIMP Intshcut::Resolve(HWND hwnd, DWORD dwFlags)
  654. {
  655. return S_OK;
  656. }
  657. //====================================================================================
  658. // Now the A or W functions that depend on unicode or ansi machines...
  659. // Will setup forwarders to the native one for the OS...
  660. //----------------------------------------------------------
  661. STDMETHODIMP Intshcut::SetPath(LPCSTR pcszPath)
  662. {
  663. WCHAR wszT[INTERNET_MAX_URL_LENGTH];
  664. if (!pcszPath)
  665. return SetPath((LPCWSTR)NULL);
  666. SHAnsiToUnicode(pcszPath, wszT, ARRAYSIZE(wszT));
  667. return SetPath(wszT);
  668. }
  669. STDMETHODIMP Intshcut::GetPath(LPSTR pszBuf, int cchBuf, PWIN32_FIND_DATAA pwfd, DWORD dwFlags)
  670. {
  671. WCHAR wszT[INTERNET_MAX_URL_LENGTH];
  672. HRESULT hres;
  673. // Init to default values (Note pwfd is not actually set so don't worry about thunking...
  674. if (pwfd)
  675. ZeroMemory(pwfd, SIZEOF(*pwfd));
  676. hres = GetPath(wszT, ARRAYSIZE(wszT), NULL, dwFlags);
  677. if (SUCCEEDED(hres))
  678. SHUnicodeToAnsi(wszT, pszBuf, cchBuf);
  679. return hres;
  680. }
  681. STDMETHODIMP Intshcut::SetRelativePath(LPCSTR pcszRelativePath, DWORD dwReserved)
  682. {
  683. WCHAR wszT[MAX_PATH];
  684. if (!pcszRelativePath)
  685. return SetRelativePath((LPCWSTR)NULL, dwReserved);
  686. SHAnsiToUnicode(pcszRelativePath, wszT, ARRAYSIZE(wszT));
  687. return SetRelativePath(wszT, dwReserved);
  688. }
  689. STDMETHODIMP Intshcut::SetDescription(LPCSTR pcszDescription)
  690. {
  691. WCHAR wszT[MAX_PATH];
  692. if (!pcszDescription)
  693. return SetDescription((LPCWSTR)NULL);
  694. SHAnsiToUnicode(pcszDescription, wszT, ARRAYSIZE(wszT));
  695. return SetDescription(wszT);
  696. }
  697. STDMETHODIMP Intshcut::GetDescription(LPSTR pszDescription,int cchBuf)
  698. {
  699. WCHAR wszT[MAX_PATH];
  700. HRESULT hres;
  701. hres = GetDescription(wszT, ARRAYSIZE(wszT));
  702. if (SUCCEEDED(hres))
  703. SHUnicodeToAnsi(wszT, pszDescription, cchBuf);
  704. return hres;
  705. }
  706. STDMETHODIMP Intshcut::SetArguments(LPCSTR pcszArgs)
  707. {
  708. WCHAR wszT[2*MAX_PATH];
  709. if (!pcszArgs)
  710. return SetArguments((LPCWSTR)NULL);
  711. SHAnsiToUnicode(pcszArgs, wszT, ARRAYSIZE(wszT));
  712. return SetArguments(wszT);
  713. }
  714. STDMETHODIMP Intshcut::GetArguments(LPSTR pszArgs,int cchBuf)
  715. {
  716. WCHAR wszT[2*MAX_PATH];
  717. HRESULT hres;
  718. hres = GetArguments(wszT, ARRAYSIZE(wszT));
  719. if (SUCCEEDED(hres))
  720. SHUnicodeToAnsi(wszT, pszArgs, cchBuf);
  721. return hres;
  722. }
  723. STDMETHODIMP Intshcut::SetWorkingDirectory(LPCSTR pcszWorkingDirectory)
  724. {
  725. WCHAR wszT[MAX_PATH];
  726. if (!pcszWorkingDirectory)
  727. return SetWorkingDirectory((LPCWSTR)NULL);
  728. SHAnsiToUnicode(pcszWorkingDirectory, wszT, ARRAYSIZE(wszT));
  729. return SetWorkingDirectory(wszT);
  730. }
  731. STDMETHODIMP Intshcut::GetWorkingDirectory(LPSTR pszBuf, int cchBuf)
  732. {
  733. WCHAR wszT[MAX_PATH];
  734. HRESULT hres;
  735. hres = GetWorkingDirectory(wszT, ARRAYSIZE(wszT));
  736. if (SUCCEEDED(hres))
  737. SHUnicodeToAnsi(wszT, pszBuf, cchBuf);
  738. return hres;
  739. }
  740. STDMETHODIMP Intshcut::SetIconLocation(LPCSTR pszFile, int niIcon)
  741. {
  742. WCHAR wszT[MAX_PATH];
  743. if (!pszFile)
  744. return SetIconLocation((LPCWSTR)NULL, niIcon);
  745. SHAnsiToUnicode(pszFile, wszT, ARRAYSIZE(wszT));
  746. return SetIconLocation(wszT, niIcon);
  747. }
  748. STDMETHODIMP Intshcut::GetIconLocation(LPSTR pszBuf, int cchBuf, int *pniIcon)
  749. {
  750. WCHAR wszT[MAX_PATH];
  751. HRESULT hres;
  752. hres = GetIconLocation(wszT, ARRAYSIZE(wszT), pniIcon);
  753. if (SUCCEEDED(hres))
  754. SHUnicodeToAnsi(wszT, pszBuf, cchBuf);
  755. return hres;
  756. }