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.

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