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.

803 lines
22 KiB

  1. /*
  2. * url.cpp - IUniformResourceLocator implementation for InternetShortcut class.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.hpp"
  7. #pragma hdrstop
  8. #include "assoc.h"
  9. #include "resource.h"
  10. #define DECL_CRTFREE
  11. #include <crtfree.h>
  12. /* Module Constants
  13. *******************/
  14. #pragma data_seg(DATA_SEG_READ_ONLY)
  15. PRIVATE_DATA const char s_cszURLSeparator[] = ":";
  16. PRIVATE_DATA const char s_cchURLSuffixSlash = '/';
  17. PRIVATE_DATA const char s_cszURLPrefixesKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\Prefixes";
  18. PRIVATE_DATA const char s_cszDefaultURLPrefixKey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\DefaultPrefix";
  19. #pragma data_seg()
  20. /***************************** Private Functions *****************************/
  21. PRIVATE_CODE PCSTR SkipLeadingSlashes(PCSTR pcszURL)
  22. {
  23. PCSTR pcszURLStart;
  24. ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
  25. // Skip two leading slashes.
  26. if (pcszURL[0] == s_cchURLSuffixSlash &&
  27. pcszURL[1] == s_cchURLSuffixSlash)
  28. {
  29. pcszURLStart = CharNext(pcszURL);
  30. pcszURLStart = CharNext(pcszURLStart);
  31. }
  32. else
  33. pcszURLStart = pcszURL;
  34. ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR) &&
  35. EVAL(IsStringContained(pcszURL, pcszURLStart)));
  36. return(pcszURLStart);
  37. }
  38. PRIVATE_CODE HRESULT ApplyURLPrefix(PCSTR pcszURL, PSTR *ppszTranslatedURL)
  39. {
  40. HRESULT hr = S_FALSE;
  41. HKEY hkeyPrefixes;
  42. ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
  43. ASSERT(IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR));
  44. *ppszTranslatedURL = NULL;
  45. if (RegOpenKey(g_hkeyURLSettings, s_cszURLPrefixesKey, &hkeyPrefixes)
  46. == ERROR_SUCCESS)
  47. {
  48. PCSTR pcszURLStart;
  49. DWORD dwiValue;
  50. char rgchValueName[MAX_PATH_LEN];
  51. DWORD dwcbValueNameLen;
  52. DWORD dwType;
  53. char rgchPrefix[MAX_PATH_LEN];
  54. DWORD dwcbPrefixLen;
  55. pcszURLStart = SkipLeadingSlashes(pcszURL);
  56. dwcbValueNameLen = sizeof(rgchValueName);
  57. dwcbPrefixLen = sizeof(rgchPrefix);
  58. for (dwiValue = 0;
  59. RegEnumValue(hkeyPrefixes, dwiValue, rgchValueName,
  60. &dwcbValueNameLen, NULL, &dwType, (PBYTE)rgchPrefix,
  61. &dwcbPrefixLen) == ERROR_SUCCESS;
  62. dwiValue++)
  63. {
  64. if (! lstrnicmp(pcszURLStart, rgchValueName, dwcbValueNameLen))
  65. {
  66. DWORD cbUrl = lstrlen(pcszURLStart);
  67. // If the url==prefix, then we're calling the executable.
  68. if (cbUrl >= dwcbPrefixLen)
  69. {
  70. // dwcbPrefixLen includes null terminator.
  71. *ppszTranslatedURL = new(char[dwcbPrefixLen + cbUrl]);
  72. if (*ppszTranslatedURL)
  73. {
  74. lstrcpy(*ppszTranslatedURL, rgchPrefix);
  75. lstrcat(*ppszTranslatedURL, pcszURLStart);
  76. // (+ 1) for null terminator.
  77. ASSERT(lstrlen(*ppszTranslatedURL) + 1 == (int)dwcbPrefixLen + lstrlen(pcszURLStart));
  78. hr = S_OK;
  79. }
  80. else
  81. hr = E_OUTOFMEMORY;
  82. }
  83. break;
  84. }
  85. dwcbValueNameLen = sizeof(rgchValueName);
  86. dwcbPrefixLen = sizeof(rgchPrefix);
  87. }
  88. RegCloseKey(hkeyPrefixes);
  89. switch (hr)
  90. {
  91. case S_OK:
  92. TRACE_OUT(("ApplyURLPrefix(): Prefix %s prepended to prefix %s of %s to yield URL %s.",
  93. rgchValueName,
  94. rgchPrefix,
  95. pcszURL,
  96. *ppszTranslatedURL));
  97. break;
  98. case S_FALSE:
  99. TRACE_OUT(("ApplyURLPrefix(): No matching prefix found for URL %s.",
  100. pcszURL));
  101. break;
  102. default:
  103. ASSERT(hr == E_OUTOFMEMORY);
  104. break;
  105. }
  106. }
  107. else
  108. TRACE_OUT(("ApplyURLPrefix(): No URL prefixes registered."));
  109. ASSERT((hr == S_OK &&
  110. IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
  111. ((hr == S_FALSE ||
  112. hr == E_OUTOFMEMORY) &&
  113. ! *ppszTranslatedURL));
  114. return(hr);
  115. }
  116. PRIVATE_CODE HRESULT ApplyDefaultURLPrefix(PCSTR pcszURL,
  117. PSTR *ppszTranslatedURL)
  118. {
  119. HRESULT hr;
  120. char rgchDefaultURLPrefix[MAX_PATH_LEN];
  121. DWORD dwcbDefaultURLPrefixLen;
  122. ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
  123. ASSERT(IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR));
  124. *ppszTranslatedURL = NULL;
  125. dwcbDefaultURLPrefixLen = sizeof(rgchDefaultURLPrefix);
  126. if (GetDefaultRegKeyValue(g_hkeyURLSettings, s_cszDefaultURLPrefixKey,
  127. rgchDefaultURLPrefix, &dwcbDefaultURLPrefixLen)
  128. == ERROR_SUCCESS)
  129. {
  130. // (+ 1) for null terminator.
  131. *ppszTranslatedURL = new(char[dwcbDefaultURLPrefixLen +
  132. lstrlen(pcszURL) + 1]);
  133. if (*ppszTranslatedURL)
  134. {
  135. PCSTR pcszURLStart;
  136. pcszURLStart = SkipLeadingSlashes(pcszURL);
  137. lstrcpy(*ppszTranslatedURL, rgchDefaultURLPrefix);
  138. lstrcat(*ppszTranslatedURL, pcszURLStart);
  139. // (+ 1) for null terminator.
  140. ASSERT(lstrlen(*ppszTranslatedURL) + 1 == (int)dwcbDefaultURLPrefixLen + lstrlen(pcszURLStart));
  141. hr = S_OK;
  142. }
  143. else
  144. hr = E_OUTOFMEMORY;
  145. }
  146. else
  147. hr = S_FALSE;
  148. switch (hr)
  149. {
  150. case S_OK:
  151. TRACE_OUT(("ApplyDefaultURLPrefix(): Default prefix %s prepended to %s to yield URL %s.",
  152. rgchDefaultURLPrefix,
  153. pcszURL,
  154. *ppszTranslatedURL));
  155. break;
  156. case S_FALSE:
  157. TRACE_OUT(("ApplyDefaultURLPrefix(): No default URL prefix registered."));
  158. break;
  159. default:
  160. ASSERT(hr == E_OUTOFMEMORY);
  161. break;
  162. }
  163. ASSERT((hr == S_OK &&
  164. IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
  165. ((hr == S_FALSE ||
  166. hr == E_OUTOFMEMORY) &&
  167. ! *ppszTranslatedURL));
  168. return(hr);
  169. }
  170. PRIVATE_CODE HRESULT MyTranslateURL(PCSTR pcszURL, DWORD dwFlags,
  171. PSTR *ppszTranslatedURL)
  172. {
  173. HRESULT hr;
  174. PARSEDURL pu;
  175. ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
  176. ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_TRANSLATEURL_FLAGS));
  177. ASSERT(IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR));
  178. // Check URL syntax.
  179. pu.cbSize = sizeof(pu);
  180. if (ParseURL(pcszURL, &pu) == S_OK)
  181. {
  182. *ppszTranslatedURL = NULL;
  183. hr = S_FALSE;
  184. }
  185. else
  186. {
  187. if (IS_FLAG_SET(dwFlags, TRANSLATEURL_FL_GUESS_PROTOCOL))
  188. hr = ApplyURLPrefix(pcszURL, ppszTranslatedURL);
  189. else
  190. hr = S_FALSE;
  191. if (hr == S_FALSE &&
  192. IS_FLAG_SET(dwFlags, TRANSLATEURL_FL_USE_DEFAULT_PROTOCOL))
  193. hr = ApplyDefaultURLPrefix(pcszURL, ppszTranslatedURL);
  194. }
  195. ASSERT((hr == S_OK &&
  196. IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
  197. ((hr == S_FALSE ||
  198. hr == E_OUTOFMEMORY) &&
  199. ! *ppszTranslatedURL));
  200. return(hr);
  201. }
  202. #ifdef DEBUG
  203. PRIVATE_CODE IsValidPCURLINVOKECOMMANDINFO(PCURLINVOKECOMMANDINFO pcurlici)
  204. {
  205. return(IS_VALID_READ_PTR(pcurlici, CURLINVOKECOMMANDINFO) &&
  206. EVAL(pcurlici->dwcbSize >= sizeof(*pcurlici)) &&
  207. FLAGS_ARE_VALID(pcurlici->dwFlags, ALL_IURL_INVOKECOMMAND_FLAGS) &&
  208. (IS_FLAG_CLEAR(pcurlici->dwFlags, IURL_INVOKECOMMAND_FL_ALLOW_UI) ||
  209. IS_VALID_HANDLE(pcurlici->hwndParent, WND)) &&
  210. (IS_FLAG_SET(pcurlici->dwFlags, IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB) ||
  211. IS_VALID_STRING_PTR(pcurlici->pcszVerb, CSTR)));
  212. }
  213. #endif
  214. /********************************** Methods **********************************/
  215. HRESULT STDMETHODCALLTYPE InternetShortcut::RegisterProtocolHandler(
  216. HWND hwndParent,
  217. PSTR pszAppBuf,
  218. UINT ucAppBufLen)
  219. {
  220. HRESULT hr;
  221. DWORD dwFlags = 0;
  222. DebugEntry(InternetShortcut::RegisterProtocolHandler);
  223. ASSERT(! hwndParent ||
  224. IS_VALID_HANDLE(hwndParent, WND));
  225. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszAppBuf, STR, ucAppBufLen));
  226. ASSERT(IS_VALID_STRING_PTR(m_pszURL, STR));
  227. SET_FLAG(dwFlags, URLASSOCDLG_FL_REGISTER_ASSOC);
  228. if (! m_pszFile)
  229. SET_FLAG(dwFlags, URLASSOCDLG_FL_USE_DEFAULT_NAME);
  230. hr = URLAssociationDialog(hwndParent, dwFlags, m_pszFile, m_pszURL,
  231. pszAppBuf, ucAppBufLen);
  232. switch (hr)
  233. {
  234. case S_FALSE:
  235. TRACE_OUT(("InternetShortcut::RegisterProtocolHandler(): One time execution of %s via %s requested.",
  236. m_pszURL,
  237. pszAppBuf));
  238. break;
  239. case S_OK:
  240. TRACE_OUT(("InternetShortcut::RegisterProtocolHandler(): Protocol handler registered for %s.",
  241. m_pszURL));
  242. break;
  243. default:
  244. ASSERT(FAILED(hr));
  245. break;
  246. }
  247. ASSERT(! ucAppBufLen ||
  248. (IS_VALID_STRING_PTR(pszAppBuf, STR) &&
  249. (UINT)lstrlen(pszAppBuf) < ucAppBufLen));
  250. DebugExitHRESULT(InternetShortcut::RegisterProtocolHandler, hr);
  251. return(hr);
  252. }
  253. HRESULT STDMETHODCALLTYPE InternetShortcut::SetURL(PCSTR pcszURL,
  254. DWORD dwInFlags)
  255. {
  256. HRESULT hr;
  257. BOOL bChanged;
  258. PSTR pszNewURL = NULL;
  259. DebugEntry(InternetShortcut::SetURL);
  260. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  261. ASSERT(! pcszURL ||
  262. IS_VALID_STRING_PTR(pcszURL, CSTR));
  263. ASSERT(FLAGS_ARE_VALID(dwInFlags, ALL_IURL_SETURL_FLAGS));
  264. bChanged = ! ((! pcszURL && ! m_pszURL) ||
  265. (pcszURL && m_pszURL &&
  266. ! lstrcmp(pcszURL, m_pszURL)));
  267. if (bChanged && pcszURL)
  268. {
  269. DWORD dwTranslateURLFlags;
  270. PSTR pszTranslatedURL;
  271. dwTranslateURLFlags = 0;
  272. if (IS_FLAG_SET(dwInFlags, IURL_SETURL_FL_GUESS_PROTOCOL))
  273. SET_FLAG(dwTranslateURLFlags, TRANSLATEURL_FL_GUESS_PROTOCOL);
  274. if (IS_FLAG_SET(dwInFlags, IURL_SETURL_FL_USE_DEFAULT_PROTOCOL))
  275. SET_FLAG(dwTranslateURLFlags, TRANSLATEURL_FL_USE_DEFAULT_PROTOCOL);
  276. hr = TranslateURL(pcszURL, dwTranslateURLFlags, &pszTranslatedURL);
  277. if (SUCCEEDED(hr))
  278. {
  279. PCSTR pcszURLToUse;
  280. // Still different?
  281. if (hr == S_OK)
  282. {
  283. bChanged = (lstrcmp(pszTranslatedURL, m_pszURL) != 0);
  284. pcszURLToUse = pszTranslatedURL;
  285. }
  286. else
  287. {
  288. ASSERT(hr == S_FALSE);
  289. pcszURLToUse = pcszURL;
  290. }
  291. if (bChanged)
  292. {
  293. PARSEDURL pu;
  294. // Validate URL syntax.
  295. pu.cbSize = sizeof(pu);
  296. hr = ParseURL(pcszURLToUse, &pu);
  297. if (hr == S_OK)
  298. {
  299. pszNewURL = new(char[lstrlen(pcszURLToUse) + 1]);
  300. if (pszNewURL)
  301. lstrcpy(pszNewURL, pcszURLToUse);
  302. else
  303. hr = E_OUTOFMEMORY;
  304. }
  305. }
  306. else
  307. hr = S_OK;
  308. }
  309. if (pszTranslatedURL)
  310. {
  311. LocalFree(pszTranslatedURL);
  312. pszTranslatedURL = NULL;
  313. }
  314. }
  315. else
  316. hr = S_OK;
  317. if (hr == S_OK)
  318. {
  319. if (bChanged)
  320. {
  321. if (m_pszURL)
  322. delete m_pszURL;
  323. m_pszURL = pszNewURL;
  324. Dirty(TRUE);
  325. TRACE_OUT(("InternetShortcut::SetURL(): Set URL to %s.",
  326. CHECK_STRING(m_pszURL)));
  327. }
  328. else
  329. TRACE_OUT(("InternetShortcut::SetURL(): URL already %s.",
  330. CHECK_STRING(m_pszURL)));
  331. }
  332. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  333. ASSERT(hr == S_OK ||
  334. hr == E_OUTOFMEMORY ||
  335. hr == URL_E_INVALID_SYNTAX);
  336. DebugExitHRESULT(InternetShortcut::SetURL, hr);
  337. return(hr);
  338. }
  339. HRESULT STDMETHODCALLTYPE InternetShortcut::GetURL(PSTR *ppszURL)
  340. {
  341. HRESULT hr;
  342. DebugEntry(InternetShortcut::GetURL);
  343. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  344. ASSERT(IS_VALID_WRITE_PTR(ppszURL, PSTR));
  345. *ppszURL = NULL;
  346. if (m_pszURL)
  347. {
  348. // (+ 1) for null terminator.
  349. *ppszURL = (PSTR)SHAlloc(lstrlen(m_pszURL) + 1);
  350. if (*ppszURL)
  351. {
  352. lstrcpy(*ppszURL, m_pszURL);
  353. hr = S_OK;
  354. TRACE_OUT(("InternetShortcut::GetURL(): Got URL %s.",
  355. *ppszURL));
  356. }
  357. else
  358. hr = E_OUTOFMEMORY;
  359. }
  360. else
  361. // No URL.
  362. hr = S_FALSE;
  363. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  364. ASSERT((hr == S_OK &&
  365. IS_VALID_STRING_PTR(*ppszURL, STR)) ||
  366. ((hr == S_FALSE ||
  367. hr == E_OUTOFMEMORY) &&
  368. ! *ppszURL));
  369. DebugExitHRESULT(InternetShortcut::GetURL, hr);
  370. return(hr);
  371. }
  372. HRESULT STDMETHODCALLTYPE InternetShortcut::InvokeCommand(
  373. PURLINVOKECOMMANDINFO purlici)
  374. {
  375. HRESULT hr = E_INVALIDARG;
  376. char szOneShotApp[MAX_PATH_LEN];
  377. BOOL bExecFailedWhine = FALSE;
  378. DebugEntry(InternetShortcut::InvokeCommand);
  379. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  380. ASSERT(IS_VALID_STRUCT_PTR(purlici, CURLINVOKECOMMANDINFO));
  381. if (purlici && EVAL(sizeof(*purlici) == purlici->dwcbSize))
  382. {
  383. if (m_pszURL)
  384. {
  385. PSTR pszProtocol;
  386. hr = CopyURLProtocol(m_pszURL, &pszProtocol);
  387. if (hr == S_OK)
  388. {
  389. hr = IsProtocolRegistered(pszProtocol);
  390. if (hr == URL_E_UNREGISTERED_PROTOCOL &&
  391. IS_FLAG_SET(purlici->dwFlags, IURL_INVOKECOMMAND_FL_ALLOW_UI))
  392. {
  393. TRACE_OUT(("InternetShortcut::InvokeCommand(): Unregistered URL protocol %s. Invoking URL protocol handler association dialog.",
  394. pszProtocol));
  395. hr = RegisterProtocolHandler(purlici->hwndParent, szOneShotApp,
  396. sizeof(szOneShotApp));
  397. }
  398. switch (hr)
  399. {
  400. case S_OK:
  401. {
  402. SHELLEXECUTEINFO sei;
  403. char szDefaultVerb[MAX_PATH_LEN];
  404. // Execute URL via registered protocol handler.
  405. ZeroMemory(&sei, sizeof(sei));
  406. sei.fMask = (SEE_MASK_CLASSNAME | SEE_MASK_NO_HOOKS);
  407. if (IS_FLAG_CLEAR(purlici->dwFlags,
  408. IURL_INVOKECOMMAND_FL_ALLOW_UI))
  409. SET_FLAG(sei.fMask, SEE_MASK_FLAG_NO_UI);
  410. if (IS_FLAG_CLEAR(purlici->dwFlags,
  411. IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB))
  412. sei.lpVerb = purlici->pcszVerb;
  413. else
  414. {
  415. if (GetClassDefaultVerb(pszProtocol, szDefaultVerb,
  416. sizeof(szDefaultVerb)))
  417. sei.lpVerb = szDefaultVerb;
  418. else
  419. ASSERT(! sei.lpVerb);
  420. }
  421. sei.cbSize = sizeof(sei);
  422. sei.hwnd = purlici->hwndParent;
  423. sei.lpFile = m_pszURL;
  424. sei.lpDirectory = m_pszWorkingDirectory;
  425. sei.nShow = m_nShowCmd;
  426. sei.lpClass = pszProtocol;
  427. TRACE_OUT(("InternetShortcut::InvokeCommand(): Invoking %s verb on URL %s.",
  428. sei.lpVerb ? sei.lpVerb : "open",
  429. sei.lpFile));
  430. hr = ShellExecuteEx(&sei) ? S_OK : IS_E_EXEC_FAILED;
  431. if (hr == S_OK)
  432. TRACE_OUT(("InternetShortcut::InvokeCommand(): ShellExecuteEx() via registered protcol handler succeeded for %s.",
  433. m_pszURL));
  434. else
  435. WARNING_OUT(("InternetShortcut::InvokeCommand(): ShellExecuteEx() via registered protcol handler failed for %s.",
  436. m_pszURL));
  437. break;
  438. }
  439. case S_FALSE:
  440. hr = MyExecute(szOneShotApp, m_pszURL, 0);
  441. switch (hr)
  442. {
  443. case E_FAIL:
  444. bExecFailedWhine = TRUE;
  445. hr = IS_E_EXEC_FAILED;
  446. break;
  447. default:
  448. break;
  449. }
  450. break;
  451. default:
  452. ASSERT(FAILED(hr));
  453. break;
  454. }
  455. delete pszProtocol;
  456. pszProtocol = NULL;
  457. }
  458. }
  459. else
  460. // No URL. Not an error.
  461. hr = S_FALSE;
  462. if (FAILED(hr) &&
  463. IS_FLAG_SET(purlici->dwFlags, IURL_INVOKECOMMAND_FL_ALLOW_UI))
  464. {
  465. int nResult;
  466. switch (hr)
  467. {
  468. case IS_E_EXEC_FAILED:
  469. if (bExecFailedWhine)
  470. {
  471. ASSERT(IS_VALID_STRING_PTR(szOneShotApp, STR));
  472. if (MyMsgBox(purlici->hwndParent,
  473. MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  474. MAKEINTRESOURCE(IDS_EXEC_FAILED),
  475. (MB_OK | MB_ICONEXCLAMATION), &nResult,
  476. szOneShotApp)) {
  477. ASSERT(nResult == IDOK);
  478. }
  479. }
  480. break;
  481. case URL_E_INVALID_SYNTAX:
  482. ASSERT(IS_VALID_STRING_PTR(m_pszURL, STR));
  483. if (MyMsgBox(purlici->hwndParent,
  484. MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  485. MAKEINTRESOURCE(IDS_EXEC_INVALID_SYNTAX),
  486. (MB_OK | MB_ICONEXCLAMATION), &nResult, m_pszURL)) {
  487. ASSERT(nResult == IDOK);
  488. }
  489. break;
  490. case URL_E_UNREGISTERED_PROTOCOL:
  491. {
  492. PSTR pszProtocol;
  493. ASSERT(IS_VALID_STRING_PTR(m_pszURL, STR));
  494. if (CopyURLProtocol(m_pszURL, &pszProtocol) == S_OK)
  495. {
  496. if (MyMsgBox(purlici->hwndParent,
  497. MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  498. MAKEINTRESOURCE(IDS_EXEC_UNREGISTERED_PROTOCOL),
  499. (MB_OK | MB_ICONEXCLAMATION), &nResult,
  500. pszProtocol)) {
  501. ASSERT(nResult == IDOK);
  502. }
  503. delete pszProtocol;
  504. pszProtocol = NULL;
  505. }
  506. break;
  507. }
  508. case E_OUTOFMEMORY:
  509. if (MyMsgBox(purlici->hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  510. MAKEINTRESOURCE(IDS_EXEC_OUT_OF_MEMORY),
  511. (MB_OK | MB_ICONEXCLAMATION), &nResult)) {
  512. ASSERT(nResult == IDOK);
  513. }
  514. break;
  515. default:
  516. ASSERT(hr == E_ABORT);
  517. break;
  518. }
  519. }
  520. }
  521. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  522. ASSERT(hr == S_OK ||
  523. hr == E_ABORT ||
  524. hr == E_OUTOFMEMORY ||
  525. hr == E_INVALIDARG ||
  526. hr == URL_E_INVALID_SYNTAX ||
  527. hr == URL_E_UNREGISTERED_PROTOCOL ||
  528. hr == IS_E_EXEC_FAILED);
  529. DebugExitHRESULT(InternetShortcut::InvokeCommand, hr);
  530. return(hr);
  531. }
  532. /***************************** Exported Functions ****************************/
  533. INTSHCUTAPI HRESULT WINAPI TranslateURLA(PCSTR pcszURL, DWORD dwInFlags,
  534. PSTR *ppszTranslatedURL)
  535. {
  536. HRESULT hr;
  537. DebugEntry(TranslateURLA);
  538. *ppszTranslatedURL = NULL;
  539. #ifdef EXPV
  540. /* Verify parameters. */
  541. if (IS_VALID_STRING_PTR(pcszURL, CSTR) &&
  542. IS_VALID_WRITE_PTR(ppszTranslatedURL, PSTR))
  543. {
  544. if (FLAGS_ARE_VALID(dwInFlags, ALL_TRANSLATEURL_FLAGS))
  545. #endif
  546. {
  547. PSTR pszTempTranslatedURL;
  548. hr = MyTranslateURL(pcszURL, dwInFlags, &pszTempTranslatedURL);
  549. if (hr == S_OK)
  550. {
  551. // (+ 1) for null terminator.
  552. *ppszTranslatedURL = (PSTR)LocalAlloc(
  553. LMEM_FIXED,
  554. lstrlen(pszTempTranslatedURL) + 1);
  555. if (*ppszTranslatedURL)
  556. {
  557. lstrcpy(*ppszTranslatedURL, pszTempTranslatedURL);
  558. ASSERT(lstrlen(*ppszTranslatedURL) == lstrlen(pszTempTranslatedURL));
  559. }
  560. else
  561. hr = E_OUTOFMEMORY;
  562. delete pszTempTranslatedURL;
  563. pszTempTranslatedURL = NULL;
  564. }
  565. }
  566. #ifdef EXPV
  567. else
  568. hr = E_FLAGS;
  569. }
  570. else
  571. hr = E_POINTER;
  572. #endif
  573. switch (hr)
  574. {
  575. case S_FALSE:
  576. TRACE_OUT(("TranslateURLA(): URL %s does not require translation.",
  577. pcszURL));
  578. break;
  579. case S_OK:
  580. TRACE_OUT(("TranslateURLA(): URL %s translated to URL %s.",
  581. pcszURL,
  582. *ppszTranslatedURL));
  583. break;
  584. default:
  585. ASSERT(hr == E_OUTOFMEMORY ||
  586. hr == E_POINTER);
  587. break;
  588. }
  589. ASSERT((hr == S_OK &&
  590. IS_VALID_STRING_PTR(*ppszTranslatedURL, STR)) ||
  591. ((hr == S_FALSE ||
  592. hr == E_OUTOFMEMORY ||
  593. hr == E_POINTER ||
  594. hr == E_FLAGS) &&
  595. ! *ppszTranslatedURL));
  596. DebugExitHRESULT(TranslateURLA, hr);
  597. return(hr);
  598. }
  599. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  600. INTSHCUTAPI HRESULT WINAPI TranslateURLW(PCWSTR pcszURL, DWORD dwInFlags,
  601. PWSTR UNALIGNED *ppszTranslatedURL)
  602. {
  603. HRESULT hr;
  604. DebugEntry(TranslateURLW);
  605. SetLastError(ERROR_NOT_SUPPORTED);
  606. hr = E_NOTIMPL;
  607. DebugExitHRESULT(TranslateURLW, hr);
  608. return(hr);
  609. }
  610. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */