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.

939 lines
24 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. linkpif.c
  5. Abstract:
  6. Functions to query and modify LNK and PIF files.
  7. Author:
  8. Calin Negreanu (calinn) 07-Sep-1998
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include <pif.h> // private\windows\inc
  13. BOOL
  14. InitCOMLinkA (
  15. OUT IShellLinkA **ShellLink,
  16. OUT IPersistFile **PersistFile
  17. )
  18. {
  19. HRESULT hres;
  20. BOOL result;
  21. //
  22. // Initialize COM
  23. //
  24. hres = CoInitialize (NULL);
  25. if (!SUCCEEDED (hres)) {
  26. return FALSE;
  27. }
  28. *ShellLink = NULL;
  29. *PersistFile = NULL;
  30. result = FALSE;
  31. __try {
  32. //
  33. // Get a pointer to the IShellLink interface.
  34. //
  35. hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkA, ShellLink);
  36. if (!SUCCEEDED (hres)) {
  37. __leave;
  38. }
  39. //
  40. // Get a pointer to the IPersistFile interface.
  41. //
  42. hres = (*ShellLink)->lpVtbl->QueryInterface ((*ShellLink), &IID_IPersistFile, PersistFile);
  43. if (!SUCCEEDED (hres)) {
  44. __leave;
  45. }
  46. result = TRUE;
  47. }
  48. __finally {
  49. if (!result) {
  50. if (*PersistFile) {
  51. (*PersistFile)->lpVtbl->Release (*PersistFile);
  52. *PersistFile = NULL;
  53. }
  54. if (*ShellLink) {
  55. (*ShellLink)->lpVtbl->Release (*ShellLink);
  56. *ShellLink = NULL;
  57. }
  58. }
  59. }
  60. if (!result) {
  61. //
  62. // Free COM
  63. //
  64. CoUninitialize ();
  65. }
  66. return result;
  67. }
  68. BOOL
  69. InitCOMLinkW (
  70. OUT IShellLinkW **ShellLink,
  71. OUT IPersistFile **PersistFile
  72. )
  73. {
  74. HRESULT hres;
  75. BOOL result;
  76. //
  77. // Initialize COM
  78. //
  79. hres = CoInitialize (NULL);
  80. if (!SUCCEEDED (hres)) {
  81. return FALSE;
  82. }
  83. *ShellLink = NULL;
  84. *PersistFile = NULL;
  85. result = FALSE;
  86. __try {
  87. //
  88. // Get a pointer to the IShellLink interface.
  89. //
  90. hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, ShellLink);
  91. if (!SUCCEEDED (hres)) {
  92. __leave;
  93. }
  94. //
  95. // Get a pointer to the IPersistFile interface.
  96. //
  97. hres = (*ShellLink)->lpVtbl->QueryInterface ((*ShellLink), &IID_IPersistFile, PersistFile);
  98. if (!SUCCEEDED (hres)) {
  99. __leave;
  100. }
  101. result = TRUE;
  102. }
  103. __finally {
  104. if (!result) {
  105. if (*PersistFile) {
  106. (*PersistFile)->lpVtbl->Release (*PersistFile);
  107. *PersistFile = NULL;
  108. }
  109. if (*ShellLink) {
  110. (*ShellLink)->lpVtbl->Release (*ShellLink);
  111. *ShellLink = NULL;
  112. }
  113. }
  114. }
  115. if (!result) {
  116. //
  117. // Free COM
  118. //
  119. CoUninitialize ();
  120. }
  121. return result;
  122. }
  123. BOOL
  124. FreeCOMLinkA (
  125. IN OUT IShellLinkA **ShellLink,
  126. IN OUT IPersistFile **PersistFile
  127. )
  128. {
  129. if (*PersistFile) {
  130. (*PersistFile)->lpVtbl->Release (*PersistFile);
  131. *PersistFile = NULL;
  132. }
  133. if (*ShellLink) {
  134. (*ShellLink)->lpVtbl->Release (*ShellLink);
  135. *ShellLink = NULL;
  136. }
  137. //
  138. // Free COM
  139. //
  140. CoUninitialize ();
  141. return TRUE;
  142. }
  143. BOOL
  144. FreeCOMLinkW (
  145. IN OUT IShellLinkW **ShellLink,
  146. IN OUT IPersistFile **PersistFile
  147. )
  148. {
  149. if (*PersistFile) {
  150. (*PersistFile)->lpVtbl->Release (*PersistFile);
  151. *PersistFile = NULL;
  152. }
  153. if (*ShellLink) {
  154. (*ShellLink)->lpVtbl->Release (*ShellLink);
  155. *ShellLink = NULL;
  156. }
  157. //
  158. // Free COM
  159. //
  160. CoUninitialize ();
  161. return TRUE;
  162. }
  163. PVOID
  164. FindEnhPifSignature (
  165. IN PVOID FileImage,
  166. IN PCSTR Signature
  167. )
  168. /*++
  169. Routine Description:
  170. FindEnhPifSignature finds a certain PIF structure inside a PIF file (if it exists)
  171. based on a signature.
  172. Arguments:
  173. FileImage - image of the PIF file mapped into memory
  174. Signature - structure signature
  175. Return Value:
  176. address of the PIF structure, or NULL if non existent
  177. --*/
  178. {
  179. PBYTE tempPtr;
  180. PBYTE lastPtr;
  181. PVOID result = NULL;
  182. BOOL finished = FALSE;
  183. PPIFEXTHDR pifExtHdr;
  184. lastPtr = (PBYTE) FileImage;
  185. tempPtr = (PBYTE) FileImage;
  186. tempPtr += sizeof (STDPIF);
  187. pifExtHdr = (PPIFEXTHDR) tempPtr;
  188. __try {
  189. do {
  190. if (tempPtr < lastPtr) {
  191. result = NULL;
  192. break;
  193. } else {
  194. lastPtr = tempPtr;
  195. }
  196. finished = pifExtHdr->extnxthdrfloff == LASTHDRPTR;
  197. if (StringMatchA (pifExtHdr->extsig, Signature)) {
  198. result = tempPtr + sizeof (PIFEXTHDR);
  199. break;
  200. }
  201. else {
  202. tempPtr = (PBYTE)FileImage + pifExtHdr->extnxthdrfloff;
  203. pifExtHdr = (PPIFEXTHDR) tempPtr;
  204. }
  205. } while (!finished);
  206. }
  207. __except (1) {
  208. // something went wrong trying to access PIF file. Let's exit with NULL
  209. return NULL;
  210. }
  211. return result;
  212. }
  213. BOOL
  214. ExtractPifInfoA(
  215. OUT PSTR Target,
  216. OUT PSTR Params,
  217. OUT PSTR WorkDir,
  218. OUT PSTR IconPath,
  219. OUT PINT IconNumber,
  220. OUT BOOL *MsDosMode,
  221. OUT PLNK_EXTRA_DATAA ExtraData, OPTIONAL
  222. IN PCSTR FileName
  223. )
  224. {
  225. PVOID fileImage = NULL;
  226. HANDLE mapHandle = NULL;
  227. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  228. CHAR tempStr [MEMDB_MAX];
  229. PSTR strPtr;
  230. PSTR dontCare;
  231. PSTDPIF stdPif;
  232. PWENHPIF40 wenhPif40;
  233. PW386PIF30 w386ext30;
  234. BOOL result = TRUE;
  235. *Target = *Params = *WorkDir = *IconPath = 0;
  236. *IconNumber = 0;
  237. *MsDosMode = FALSE;
  238. if (ExtraData) {
  239. ZeroMemory (ExtraData, sizeof(LNK_EXTRA_DATA));
  240. }
  241. __try {
  242. fileImage = MapFileIntoMemoryA (FileName, &fileHandle, &mapHandle);
  243. if (fileImage == NULL) {
  244. __leave;
  245. }
  246. __try {
  247. stdPif = (PSTDPIF) fileImage;
  248. //
  249. // getting working directory
  250. //
  251. _mbsncpy (tempStr, stdPif->defpath, PIFDEFPATHSIZE);
  252. // we might have a path terminated with a wack, we don't want that
  253. strPtr = _mbsdec (tempStr, GetEndOfStringA (tempStr));
  254. if (strPtr) {
  255. if (_mbsnextc (strPtr) == '\\') {
  256. *strPtr = 0;
  257. }
  258. }
  259. // now get the long path.
  260. CopyFileSpecToLongA (tempStr, WorkDir);
  261. //
  262. // getting PIFs target
  263. //
  264. _mbsncpy (Target, stdPif->startfile, PIFSTARTLOCSIZE);
  265. // in most cases, the target is without a path. We try to build the path, either
  266. // by using WorkDir or by calling SearchPath to look for this file.
  267. if (*Target) {//non empty target
  268. if (!DoesFileExist (Target)) {
  269. if (*WorkDir) {
  270. StringCopyA (tempStr, WorkDir);
  271. StringCatA (tempStr, "\\");
  272. StringCatA (tempStr, Target);
  273. }
  274. if (!DoesFileExist (tempStr)) {
  275. StringCopyA (tempStr, FileName);
  276. strPtr = _mbsrchr (tempStr, '\\');
  277. if (strPtr) {
  278. strPtr = _mbsinc (strPtr);
  279. if (strPtr) {
  280. StringCopyA (strPtr, Target);
  281. }
  282. }
  283. }
  284. if (!DoesFileExist (tempStr)) {
  285. strPtr = (PSTR)GetFileNameFromPathA (Target);
  286. if (!strPtr) {
  287. strPtr = Target;
  288. }
  289. if (!SearchPathA (NULL, Target, NULL, MEMDB_MAX, tempStr, &dontCare)) {
  290. DEBUGMSG ((DBG_WARNING, "Could not find path for PIF target: %s", FileName));
  291. StringCopyA (tempStr, Target);
  292. }
  293. }
  294. } else {
  295. StringCopyA (tempStr, Target);
  296. }
  297. // now get the long path
  298. CopyFileSpecToLongA (tempStr, Target);
  299. }
  300. //
  301. // getting PIFs arguments
  302. //
  303. _mbsncpy (Params, stdPif->params, PIFPARAMSSIZE);
  304. //
  305. // let's try to read the WENHPIF40 structure
  306. //
  307. wenhPif40 = FindEnhPifSignature (fileImage, WENHHDRSIG40);
  308. if (wenhPif40) {
  309. CopyFileSpecToLongA (wenhPif40->achIconFileProp, IconPath);
  310. *IconNumber = wenhPif40->wIconIndexProp;
  311. if (ExtraData) {
  312. ExtraData->xSize = 80;
  313. ExtraData->ySize = wenhPif40->vidProp.cScreenLines;
  314. if (ExtraData->ySize < 25) {
  315. ExtraData->ySize = 25;
  316. }
  317. ExtraData->QuickEdit = !(wenhPif40->mseProp.flMse & MSE_WINDOWENABLE);
  318. ExtraData->CurrentCodePage = wenhPif40->fntProp.wCurrentCP;
  319. // now let's do some crazy things trying to get the font used
  320. {
  321. LOGFONTA logFont;
  322. HDC dc;
  323. HFONT font;
  324. HGDIOBJ oldObject;
  325. TEXTMETRIC tm;
  326. ZeroMemory (&logFont, sizeof (LOGFONTA));
  327. logFont.lfHeight = wenhPif40->fntProp.cyFontActual;
  328. logFont.lfWidth = wenhPif40->fntProp.cxFontActual;
  329. logFont.lfEscapement = 0;
  330. logFont.lfOrientation = 0;
  331. logFont.lfWeight = FW_DONTCARE;
  332. logFont.lfItalic = FALSE;
  333. logFont.lfUnderline = FALSE;
  334. logFont.lfStrikeOut = FALSE;
  335. logFont.lfCharSet = DEFAULT_CHARSET;
  336. logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  337. logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  338. logFont.lfQuality = DEFAULT_QUALITY;
  339. logFont.lfPitchAndFamily = DEFAULT_PITCH;
  340. if (wenhPif40->fntProp.flFnt & FNT_TT) {
  341. _mbsncpy (logFont.lfFaceName, wenhPif40->fntProp.achTTFaceName, LF_FACESIZE);
  342. _mbsncpy (ExtraData->FontName, wenhPif40->fntProp.achTTFaceName, LF_FACESIZE);
  343. } else {
  344. _mbsncpy (logFont.lfFaceName, wenhPif40->fntProp.achRasterFaceName, LF_FACESIZE);
  345. _mbsncpy (ExtraData->FontName, wenhPif40->fntProp.achRasterFaceName, LF_FACESIZE);
  346. }
  347. dc = CreateDCA ("DISPLAY", NULL, NULL, NULL);
  348. if (dc) {
  349. font = CreateFontIndirectA (&logFont);
  350. if (font) {
  351. oldObject = SelectObject (dc, font);
  352. if (GetTextMetrics (dc, &tm)) {
  353. ExtraData->xFontSize = tm.tmAveCharWidth;
  354. ExtraData->yFontSize = tm.tmHeight;
  355. ExtraData->FontWeight = tm.tmWeight;
  356. ExtraData->FontFamily = tm.tmPitchAndFamily;
  357. }
  358. SelectObject (dc, oldObject);
  359. DeleteObject (font);
  360. }
  361. DeleteDC (dc);
  362. }
  363. }
  364. }
  365. }
  366. w386ext30 = FindEnhPifSignature (fileImage, W386HDRSIG30);
  367. if (w386ext30) {
  368. if (((w386ext30->PfW386Flags & fRealMode ) == fRealMode ) ||
  369. ((w386ext30->PfW386Flags & fRealModeSilent) == fRealModeSilent)
  370. ) {
  371. *MsDosMode = TRUE;
  372. }
  373. if (ExtraData) {
  374. ExtraData->FullScreen = (w386ext30->PfW386Flags & fFullScreen) != 0;
  375. }
  376. }
  377. }
  378. __except (1) {
  379. // something went wrong when we tried to read or write PIF file,
  380. result = FALSE;
  381. }
  382. }
  383. __finally {
  384. UnmapFile (fileImage, mapHandle, fileHandle);
  385. }
  386. return result;
  387. }
  388. BOOL
  389. ExtractPifInfoW(
  390. OUT PWSTR Target,
  391. OUT PWSTR Params,
  392. OUT PWSTR WorkDir,
  393. OUT PWSTR IconPath,
  394. OUT PINT IconNumber,
  395. OUT BOOL *MsDosMode,
  396. OUT PLNK_EXTRA_DATAW ExtraData, OPTIONAL
  397. IN PCWSTR FileName
  398. )
  399. {
  400. CHAR aTarget [MEMDB_MAX];
  401. CHAR aParams [MEMDB_MAX];
  402. CHAR aWorkDir [MEMDB_MAX];
  403. CHAR aIconPath [MEMDB_MAX];
  404. PCSTR aFileName;
  405. PCWSTR tempStrW;
  406. BOOL result;
  407. LNK_EXTRA_DATAA extraDataA;
  408. aFileName = ConvertWtoA (FileName);
  409. result = ExtractPifInfoA (
  410. aTarget,
  411. aParams,
  412. aWorkDir,
  413. aIconPath,
  414. IconNumber,
  415. MsDosMode,
  416. ExtraData?&extraDataA:NULL,
  417. aFileName
  418. );
  419. FreeConvertedStr (aFileName);
  420. tempStrW = ConvertAtoW (aTarget);
  421. StringCopyW (Target, tempStrW);
  422. FreeConvertedStr (tempStrW);
  423. tempStrW = ConvertAtoW (aParams);
  424. StringCopyW (Params, tempStrW);
  425. FreeConvertedStr (tempStrW);
  426. tempStrW = ConvertAtoW (aWorkDir);
  427. StringCopyW (WorkDir, tempStrW);
  428. FreeConvertedStr (tempStrW);
  429. tempStrW = ConvertAtoW (aIconPath);
  430. StringCopyW (IconPath, tempStrW);
  431. FreeConvertedStr (tempStrW);
  432. if (ExtraData) {
  433. ExtraData->FullScreen = extraDataA.FullScreen;
  434. ExtraData->xSize = extraDataA.xSize;
  435. ExtraData->ySize = extraDataA.ySize;
  436. ExtraData->QuickEdit = extraDataA.QuickEdit;
  437. tempStrW = ConvertAtoW (extraDataA.FontName);
  438. StringCopyW (ExtraData->FontName, tempStrW);
  439. FreeConvertedStr (tempStrW);
  440. ExtraData->xFontSize = extraDataA.xFontSize;
  441. ExtraData->yFontSize = extraDataA.yFontSize;
  442. ExtraData->FontWeight = extraDataA.FontWeight;
  443. ExtraData->FontFamily = extraDataA.FontFamily;
  444. ExtraData->CurrentCodePage = extraDataA.CurrentCodePage;
  445. }
  446. return result;
  447. }
  448. BOOL
  449. ExtractShellLinkInfoA (
  450. OUT PSTR Target,
  451. OUT PSTR Params,
  452. OUT PSTR WorkDir,
  453. OUT PSTR IconPath,
  454. OUT PINT IconNumber,
  455. OUT PWORD HotKey,
  456. OUT PINT ShowMode, OPTIONAL
  457. IN PCSTR FileName,
  458. IN IShellLinkA *ShellLink,
  459. IN IPersistFile *PersistFile
  460. )
  461. {
  462. CHAR tempStr [MEMDB_MAX];
  463. PCSTR expandedStr;
  464. PCWSTR fileNameW;
  465. PSTR strPtr;
  466. HRESULT hres;
  467. WIN32_FIND_DATAA fd;
  468. fileNameW = ConvertAtoW (FileName);
  469. hres = PersistFile->lpVtbl->Load(PersistFile, fileNameW, STGM_READ);
  470. FreeConvertedStr (fileNameW);
  471. if (!SUCCEEDED(hres)) {
  472. DEBUGMSGA((DBG_WARNING, "Cannot load link %s", FileName));
  473. return FALSE;
  474. }
  475. //
  476. // Get the link target
  477. //
  478. hres = ShellLink->lpVtbl->GetPath (
  479. ShellLink,
  480. tempStr,
  481. sizeof (tempStr),
  482. &fd,
  483. SLGP_RAWPATH
  484. );
  485. if (!SUCCEEDED(hres)) {
  486. DEBUGMSGA((DBG_WARNING, "Cannot read target for link %s", FileName));
  487. return FALSE;
  488. }
  489. expandedStr = ExpandEnvironmentTextA (tempStr);
  490. CopyFileSpecToLongA (expandedStr, Target);
  491. FreeTextA (expandedStr);
  492. //
  493. // Get the link working directory
  494. //
  495. hres = ShellLink->lpVtbl->GetWorkingDirectory (
  496. ShellLink,
  497. tempStr,
  498. sizeof (tempStr)
  499. );
  500. if (!SUCCEEDED(hres)) {
  501. DEBUGMSGA((DBG_WARNING, "Cannot read target for link %s", FileName));
  502. return FALSE;
  503. }
  504. strPtr = GetEndOfStringA (tempStr);
  505. if (strPtr) {
  506. strPtr = _mbsdec (tempStr, strPtr);
  507. if (strPtr) {
  508. if (_mbsnextc (strPtr) == '\\') {
  509. *strPtr = 0;
  510. }
  511. }
  512. }
  513. CopyFileSpecToLongA (tempStr, WorkDir);
  514. //
  515. // Get the arguments.
  516. //
  517. hres = ShellLink->lpVtbl->GetArguments (
  518. ShellLink,
  519. Params,
  520. MEMDB_MAX
  521. );
  522. if (!SUCCEEDED(hres)) {
  523. DEBUGMSGA((DBG_WARNING, "Cannot read arguments for link %s", FileName));
  524. return FALSE;
  525. }
  526. //
  527. // Get icon path
  528. //
  529. hres = ShellLink->lpVtbl->GetIconLocation (
  530. ShellLink,
  531. tempStr,
  532. sizeof (tempStr),
  533. IconNumber
  534. );
  535. if (!SUCCEEDED(hres)) {
  536. DEBUGMSGA((DBG_WARNING, "Cannot read icon path for link %s", FileName));
  537. return FALSE;
  538. }
  539. CopyFileSpecToLongA (tempStr, IconPath);
  540. //
  541. // Get hot key
  542. //
  543. hres = ShellLink->lpVtbl->GetHotkey (ShellLink, HotKey);
  544. if (!SUCCEEDED(hres)) {
  545. DEBUGMSGA((DBG_WARNING, "Cannot read hot key for link %s", FileName));
  546. return FALSE;
  547. }
  548. //
  549. // Get show command
  550. //
  551. if (ShowMode) {
  552. hres = ShellLink->lpVtbl->GetShowCmd (ShellLink, ShowMode);
  553. if (!SUCCEEDED(hres)) {
  554. DEBUGMSGA((DBG_WARNING, "Cannot read show mode for link %s", FileName));
  555. return FALSE;
  556. }
  557. }
  558. return TRUE;
  559. }
  560. BOOL
  561. ExtractShellLinkInfoW (
  562. OUT PWSTR Target,
  563. OUT PWSTR Params,
  564. OUT PWSTR WorkDir,
  565. OUT PWSTR IconPath,
  566. OUT PINT IconNumber,
  567. OUT PWORD HotKey,
  568. OUT PINT ShowMode,
  569. IN PCWSTR FileName,
  570. IN IShellLinkW *ShellLink,
  571. IN IPersistFile *PersistFile
  572. )
  573. {
  574. WCHAR tempStr [MEMDB_MAX];
  575. PCWSTR expandedStr;
  576. PWSTR strPtr;
  577. HRESULT hres;
  578. WIN32_FIND_DATAW fd;
  579. hres = PersistFile->lpVtbl->Load(PersistFile, FileName, STGM_READ);
  580. if (!SUCCEEDED(hres)) {
  581. DEBUGMSGW((DBG_WARNING, "Cannot load link %s", FileName));
  582. return FALSE;
  583. }
  584. //
  585. // Get the link target
  586. //
  587. hres = ShellLink->lpVtbl->GetPath (
  588. ShellLink,
  589. tempStr,
  590. sizeof (tempStr),
  591. &fd,
  592. SLGP_RAWPATH
  593. );
  594. if (!SUCCEEDED(hres)) {
  595. DEBUGMSGA((DBG_WARNING, "Cannot read target for link %s", FileName));
  596. return FALSE;
  597. }
  598. expandedStr = ExpandEnvironmentTextW (tempStr);
  599. CopyFileSpecToLongW (expandedStr, Target);
  600. FreeTextW (expandedStr);
  601. //
  602. // Get the link working directory
  603. //
  604. hres = ShellLink->lpVtbl->GetWorkingDirectory (
  605. ShellLink,
  606. tempStr,
  607. sizeof (tempStr)
  608. );
  609. if (!SUCCEEDED(hres)) {
  610. DEBUGMSGW((DBG_WARNING, "Cannot read target for link %s", FileName));
  611. return FALSE;
  612. }
  613. strPtr = GetEndOfStringW (tempStr) - 1;
  614. if (strPtr >= tempStr) {
  615. if (*strPtr == '\\') {
  616. *strPtr = 0;
  617. }
  618. }
  619. CopyFileSpecToLongW (tempStr, WorkDir);
  620. //
  621. // Get the arguments.
  622. //
  623. hres = ShellLink->lpVtbl->GetArguments (
  624. ShellLink,
  625. Params,
  626. MEMDB_MAX
  627. );
  628. if (!SUCCEEDED(hres)) {
  629. DEBUGMSGW((DBG_WARNING, "Cannot read arguments for link %s", FileName));
  630. return FALSE;
  631. }
  632. //
  633. // Get icon path
  634. //
  635. hres = ShellLink->lpVtbl->GetIconLocation (
  636. ShellLink,
  637. tempStr,
  638. sizeof (tempStr),
  639. IconNumber
  640. );
  641. if (!SUCCEEDED(hres)) {
  642. DEBUGMSGW((DBG_WARNING, "Cannot read icon path for link %s", FileName));
  643. return FALSE;
  644. }
  645. CopyFileSpecToLongW (tempStr, IconPath);
  646. //
  647. // Get hot key
  648. //
  649. hres = ShellLink->lpVtbl->GetHotkey (ShellLink, HotKey);
  650. if (!SUCCEEDED(hres)) {
  651. DEBUGMSGW((DBG_WARNING, "Cannot read hot key for link %s", FileName));
  652. return FALSE;
  653. }
  654. //
  655. // Get show command
  656. //
  657. if (ShowMode) {
  658. hres = ShellLink->lpVtbl->GetShowCmd (ShellLink, ShowMode);
  659. if (!SUCCEEDED(hres)) {
  660. DEBUGMSGW((DBG_WARNING, "Cannot read show mode for link %s", FileName));
  661. return FALSE;
  662. }
  663. }
  664. return TRUE;
  665. }
  666. BOOL
  667. ExtractShortcutInfoA (
  668. OUT PSTR Target,
  669. OUT PSTR Params,
  670. OUT PSTR WorkDir,
  671. OUT PSTR IconPath,
  672. OUT PINT IconNumber,
  673. OUT PWORD HotKey,
  674. OUT BOOL *DosApp,
  675. OUT BOOL *MsDosMode,
  676. OUT PINT ShowMode, OPTIONAL
  677. OUT PLNK_EXTRA_DATAA ExtraData, OPTIONAL
  678. IN PCSTR FileName,
  679. IN IShellLinkA *ShellLink,
  680. IN IPersistFile *PersistFile
  681. )
  682. {
  683. PCSTR shortcutExt = NULL;
  684. *MsDosMode = FALSE;
  685. *DosApp = FALSE;
  686. *HotKey = 0;
  687. if (ShowMode) {
  688. *ShowMode = SW_NORMAL;
  689. }
  690. shortcutExt = GetFileExtensionFromPathA (FileName);
  691. if (shortcutExt != NULL) {
  692. if (StringIMatchA (shortcutExt, "LNK")) {
  693. return ExtractShellLinkInfoA (
  694. Target,
  695. Params,
  696. WorkDir,
  697. IconPath,
  698. IconNumber,
  699. HotKey,
  700. ShowMode,
  701. FileName,
  702. ShellLink,
  703. PersistFile
  704. );
  705. } else if (StringIMatchA (shortcutExt, "PIF")) {
  706. *DosApp = TRUE;
  707. return ExtractPifInfoA (
  708. Target,
  709. Params,
  710. WorkDir,
  711. IconPath,
  712. IconNumber,
  713. MsDosMode,
  714. ExtraData,
  715. FileName
  716. );
  717. } else {
  718. return FALSE;
  719. }
  720. } else {
  721. return FALSE;
  722. }
  723. }
  724. BOOL
  725. ExtractShortcutInfoW (
  726. OUT PWSTR Target,
  727. OUT PWSTR Params,
  728. OUT PWSTR WorkDir,
  729. OUT PWSTR IconPath,
  730. OUT PINT IconNumber,
  731. OUT PWORD HotKey,
  732. OUT BOOL *DosApp,
  733. OUT BOOL *MsDosMode,
  734. OUT PINT ShowMode, OPTIONAL
  735. OUT PLNK_EXTRA_DATAW ExtraData, OPTIONAL
  736. IN PCWSTR FileName,
  737. IN IShellLinkW *ShellLink,
  738. IN IPersistFile *PersistFile
  739. )
  740. {
  741. PCWSTR shortcutExt = NULL;
  742. *MsDosMode = FALSE;
  743. *DosApp = FALSE;
  744. *HotKey = 0;
  745. if (ShowMode) {
  746. *ShowMode = SW_NORMAL;
  747. }
  748. shortcutExt = GetFileExtensionFromPathW (FileName);
  749. if (shortcutExt != NULL) {
  750. if (StringIMatchW (shortcutExt, L"LNK")) {
  751. return ExtractShellLinkInfoW (
  752. Target,
  753. Params,
  754. WorkDir,
  755. IconPath,
  756. IconNumber,
  757. HotKey,
  758. ShowMode,
  759. FileName,
  760. ShellLink,
  761. PersistFile
  762. );
  763. } else if (StringIMatchW (shortcutExt, L"PIF")) {
  764. *DosApp = TRUE;
  765. return ExtractPifInfoW (
  766. Target,
  767. Params,
  768. WorkDir,
  769. IconPath,
  770. IconNumber,
  771. MsDosMode,
  772. ExtraData,
  773. FileName
  774. );
  775. } else {
  776. return FALSE;
  777. }
  778. } else {
  779. return FALSE;
  780. }
  781. }