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.

1950 lines
60 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. //
  12. // Includes
  13. //
  14. #include "pch.h"
  15. #include <pif.h> // private\windows\inc
  16. //
  17. // Debug constants
  18. //
  19. #define DBG_VERSION "LnkPif"
  20. #define MAXINISIZE 65536
  21. //
  22. // Strings
  23. //
  24. // None
  25. //
  26. // Constants
  27. //
  28. // None
  29. //
  30. // Macros
  31. //
  32. // None
  33. //
  34. // Types
  35. //
  36. // None
  37. //
  38. // Globals
  39. //
  40. // None
  41. //
  42. // Macro expansion list
  43. //
  44. // None
  45. //
  46. // Private function prototypes
  47. //
  48. // None
  49. //
  50. // Macro expansion definition
  51. //
  52. // None
  53. //
  54. // Code
  55. //
  56. BOOL
  57. InitCOMLinkA (
  58. OUT IShellLinkA **ShellLink,
  59. OUT IPersistFile **PersistFile
  60. )
  61. {
  62. HRESULT hres;
  63. BOOL result;
  64. //
  65. // Initialize COM
  66. //
  67. CoInitialize (NULL);
  68. *ShellLink = NULL;
  69. *PersistFile = NULL;
  70. result = FALSE;
  71. __try {
  72. //
  73. // Get a pointer to the IShellLink interface.
  74. //
  75. hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkA, ShellLink);
  76. if (!SUCCEEDED (hres)) {
  77. __leave;
  78. }
  79. //
  80. // Get a pointer to the IPersistFile interface.
  81. //
  82. hres = (*ShellLink)->lpVtbl->QueryInterface ((*ShellLink), &IID_IPersistFile, PersistFile);
  83. if (!SUCCEEDED (hres)) {
  84. __leave;
  85. }
  86. result = TRUE;
  87. }
  88. __finally {
  89. if (!result) {
  90. if (*PersistFile) {
  91. (*PersistFile)->lpVtbl->Release (*PersistFile);
  92. *PersistFile = NULL;
  93. }
  94. if (*ShellLink) {
  95. (*ShellLink)->lpVtbl->Release (*ShellLink);
  96. *ShellLink = NULL;
  97. }
  98. }
  99. }
  100. if (!result) {
  101. //
  102. // Free COM
  103. //
  104. CoUninitialize ();
  105. }
  106. return result;
  107. }
  108. BOOL
  109. InitCOMLinkW (
  110. OUT IShellLinkW **ShellLink,
  111. OUT IPersistFile **PersistFile
  112. )
  113. {
  114. HRESULT hres;
  115. BOOL result;
  116. //
  117. // Initialize COM
  118. //
  119. CoInitialize (NULL);
  120. *ShellLink = NULL;
  121. *PersistFile = NULL;
  122. result = FALSE;
  123. __try {
  124. //
  125. // Get a pointer to the IShellLink interface.
  126. //
  127. hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, ShellLink);
  128. if (!SUCCEEDED (hres)) {
  129. __leave;
  130. }
  131. //
  132. // Get a pointer to the IPersistFile interface.
  133. //
  134. hres = (*ShellLink)->lpVtbl->QueryInterface ((*ShellLink), &IID_IPersistFile, PersistFile);
  135. if (!SUCCEEDED (hres)) {
  136. __leave;
  137. }
  138. result = TRUE;
  139. }
  140. __finally {
  141. if (!result) {
  142. if (*PersistFile) {
  143. (*PersistFile)->lpVtbl->Release (*PersistFile);
  144. *PersistFile = NULL;
  145. }
  146. if (*ShellLink) {
  147. (*ShellLink)->lpVtbl->Release (*ShellLink);
  148. *ShellLink = NULL;
  149. }
  150. }
  151. }
  152. if (!result) {
  153. //
  154. // Free COM
  155. //
  156. CoUninitialize ();
  157. }
  158. return result;
  159. }
  160. BOOL
  161. FreeCOMLinkA (
  162. IN OUT IShellLinkA **ShellLink,
  163. IN OUT IPersistFile **PersistFile
  164. )
  165. {
  166. if (*PersistFile) {
  167. (*PersistFile)->lpVtbl->Release (*PersistFile);
  168. *PersistFile = NULL;
  169. }
  170. if (*ShellLink) {
  171. (*ShellLink)->lpVtbl->Release (*ShellLink);
  172. *ShellLink = NULL;
  173. }
  174. //
  175. // Free COM
  176. //
  177. CoUninitialize ();
  178. return TRUE;
  179. }
  180. BOOL
  181. FreeCOMLinkW (
  182. IN OUT IShellLinkW **ShellLink,
  183. IN OUT IPersistFile **PersistFile
  184. )
  185. {
  186. if (*PersistFile) {
  187. (*PersistFile)->lpVtbl->Release (*PersistFile);
  188. *PersistFile = NULL;
  189. }
  190. if (*ShellLink) {
  191. (*ShellLink)->lpVtbl->Release (*ShellLink);
  192. *ShellLink = NULL;
  193. }
  194. //
  195. // Free COM
  196. //
  197. CoUninitialize ();
  198. return TRUE;
  199. }
  200. PVOID
  201. pFindEnhPifSignature (
  202. IN PVOID FileImage,
  203. IN PCSTR Signature
  204. )
  205. /*++
  206. Routine Description:
  207. pFindEnhPifSignature finds a certain PIF structure inside a PIF file (if it exists)
  208. based on a signature.
  209. Arguments:
  210. FileImage - image of the PIF file mapped into memory
  211. Signature - structure signature
  212. Return Value:
  213. address of the PIF structure, or NULL if non existent
  214. --*/
  215. {
  216. PBYTE tempPtr;
  217. PBYTE lastPtr;
  218. PVOID result = NULL;
  219. BOOL finished = FALSE;
  220. PPIFEXTHDR pifExtHdr;
  221. lastPtr = (PBYTE) FileImage;
  222. tempPtr = (PBYTE) FileImage;
  223. tempPtr += sizeof (STDPIF);
  224. pifExtHdr = (PPIFEXTHDR) tempPtr;
  225. __try {
  226. do {
  227. if (tempPtr < lastPtr) {
  228. result = NULL;
  229. break;
  230. } else {
  231. lastPtr = tempPtr;
  232. }
  233. finished = pifExtHdr->extnxthdrfloff == LASTHDRPTR;
  234. if (StringMatchA (pifExtHdr->extsig, Signature)) {
  235. result = tempPtr + sizeof (PIFEXTHDR);
  236. break;
  237. }
  238. else {
  239. tempPtr = (PBYTE)FileImage + pifExtHdr->extnxthdrfloff;
  240. pifExtHdr = (PPIFEXTHDR) tempPtr;
  241. }
  242. } while (!finished);
  243. }
  244. __except (1) {
  245. // something went wrong trying to access PIF file. Let's exit with NULL
  246. return NULL;
  247. }
  248. return result;
  249. }
  250. BOOL
  251. ExtractPifInfoA(
  252. IN PCSTR FileName,
  253. OUT PCSTR *Target,
  254. OUT PCSTR *Params,
  255. OUT PCSTR *WorkDir,
  256. OUT PCSTR *IconPath,
  257. OUT PINT IconNumber,
  258. OUT BOOL *MsDosMode,
  259. OUT PLNK_EXTRA_DATAA ExtraData OPTIONAL
  260. )
  261. {
  262. PVOID fileImage = NULL;
  263. HANDLE mapHandle = NULL;
  264. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  265. CHAR tempStr [MEMDB_MAX];
  266. CHAR target1 [MEMDB_MAX];
  267. PSTR strPtr;
  268. PSTR dontCare;
  269. PSTDPIF stdPif;
  270. PWENHPIF40 wenhPif40;
  271. PW386PIF30 w386ext30;
  272. BOOL result = TRUE;
  273. if (Target) {
  274. *Target = NULL;
  275. }
  276. if (Params) {
  277. *Params = NULL;
  278. }
  279. if (WorkDir) {
  280. *WorkDir = NULL;
  281. }
  282. if (IconPath) {
  283. *IconPath = NULL;
  284. }
  285. *IconNumber = 0;
  286. *MsDosMode = FALSE;
  287. if (ExtraData) {
  288. ZeroMemory (ExtraData, sizeof(LNK_EXTRA_DATA));
  289. }
  290. __try {
  291. fileImage = MapFileIntoMemoryA (FileName, &fileHandle, &mapHandle);
  292. if (fileImage == NULL) {
  293. __leave;
  294. }
  295. __try {
  296. stdPif = (PSTDPIF) fileImage;
  297. //
  298. // getting working directory
  299. //
  300. _mbsncpy (tempStr, stdPif->defpath, PIFDEFPATHSIZE);
  301. // we might have a path terminated with a wack, we don't want that
  302. strPtr = _mbsdec (tempStr, GetEndOfStringA (tempStr));
  303. if (strPtr) {
  304. if (_mbsnextc (strPtr) == '\\') {
  305. *strPtr = 0;
  306. }
  307. }
  308. // now get the long path.
  309. if (WorkDir) {
  310. *WorkDir = DuplicatePathStringA (tempStr, 0);
  311. }
  312. //
  313. // getting PIFs target
  314. //
  315. _mbsncpy (target1, stdPif->startfile, PIFSTARTLOCSIZE);
  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 (*target1) {//non empty target
  319. strPtr = _mbsrchr (target1, '\\');
  320. if (!strPtr) {
  321. if (WorkDir && (*WorkDir)[0]) {
  322. StringCopyA (tempStr, *WorkDir);
  323. StringCatA (tempStr, "\\");
  324. StringCatA (tempStr, target1);
  325. }
  326. else {
  327. if (!SearchPathA (NULL, target1, NULL, MEMDB_MAX, tempStr, &dontCare)) {
  328. DEBUGMSG ((DBG_WARNING, "Could not find path for PIF target:%s", FileName));
  329. StringCopyA (tempStr, target1);
  330. }
  331. }
  332. }
  333. else {
  334. StringCopyA (tempStr, target1);
  335. }
  336. // now get the long path
  337. if (Target) {
  338. *Target = DuplicatePathStringA (tempStr, 0);
  339. }
  340. }
  341. //
  342. // getting PIFs arguments
  343. //
  344. _mbsncpy (tempStr, stdPif->params, PIFPARAMSSIZE);
  345. if (Params) {
  346. *Params = DuplicatePathStringA (tempStr, 0);
  347. }
  348. //
  349. // let's try to read the WENHPIF40 structure
  350. //
  351. wenhPif40 = pFindEnhPifSignature (fileImage, WENHHDRSIG40);
  352. if (wenhPif40) {
  353. if (IconPath) {
  354. *IconPath = DuplicatePathStringA (wenhPif40->achIconFileProp, 0);
  355. }
  356. *IconNumber = wenhPif40->wIconIndexProp;
  357. if (ExtraData) {
  358. ExtraData->xSize = 80;
  359. ExtraData->ySize = wenhPif40->vidProp.cScreenLines;
  360. if (ExtraData->ySize < 25) {
  361. ExtraData->ySize = 25;
  362. }
  363. ExtraData->QuickEdit = !(wenhPif40->mseProp.flMse & MSE_WINDOWENABLE);
  364. ExtraData->CurrentCodePage = wenhPif40->fntProp.wCurrentCP;
  365. // now let's do some crazy things trying to get the font used
  366. {
  367. LOGFONTA logFont;
  368. HDC dc;
  369. HFONT font;
  370. HGDIOBJ oldObject;
  371. TEXTMETRIC tm;
  372. ZeroMemory (&logFont, sizeof (LOGFONTA));
  373. logFont.lfHeight = wenhPif40->fntProp.cyFontActual;
  374. logFont.lfWidth = wenhPif40->fntProp.cxFontActual;
  375. logFont.lfEscapement = 0;
  376. logFont.lfOrientation = 0;
  377. logFont.lfWeight = FW_DONTCARE;
  378. logFont.lfItalic = FALSE;
  379. logFont.lfUnderline = FALSE;
  380. logFont.lfStrikeOut = FALSE;
  381. logFont.lfCharSet = DEFAULT_CHARSET;
  382. logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  383. logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  384. logFont.lfQuality = DEFAULT_QUALITY;
  385. logFont.lfPitchAndFamily = DEFAULT_PITCH;
  386. if (wenhPif40->fntProp.flFnt & FNT_TT) {
  387. memcpy (logFont.lfFaceName, wenhPif40->fntProp.achTTFaceName, LF_FACESIZE);
  388. memcpy (ExtraData->FontName, wenhPif40->fntProp.achTTFaceName, LF_FACESIZE);
  389. } else {
  390. memcpy (logFont.lfFaceName, wenhPif40->fntProp.achRasterFaceName, LF_FACESIZE);
  391. memcpy (ExtraData->FontName, wenhPif40->fntProp.achRasterFaceName, LF_FACESIZE);
  392. }
  393. dc = CreateDCA ("DISPLAY", NULL, NULL, NULL);
  394. if (dc) {
  395. font = CreateFontIndirectA (&logFont);
  396. if (font) {
  397. oldObject = SelectObject (dc, font);
  398. if (GetTextMetrics (dc, &tm)) {
  399. ExtraData->xFontSize = tm.tmAveCharWidth;
  400. ExtraData->yFontSize = tm.tmHeight;
  401. ExtraData->FontWeight = tm.tmWeight;
  402. ExtraData->FontFamily = tm.tmPitchAndFamily;
  403. }
  404. SelectObject (dc, oldObject);
  405. DeleteObject (font);
  406. }
  407. DeleteDC (dc);
  408. }
  409. }
  410. }
  411. }
  412. w386ext30 = pFindEnhPifSignature (fileImage, W386HDRSIG30);
  413. if (w386ext30) {
  414. if (((w386ext30->PfW386Flags & fRealMode ) == fRealMode ) ||
  415. ((w386ext30->PfW386Flags & fRealModeSilent) == fRealModeSilent)
  416. ) {
  417. *MsDosMode = TRUE;
  418. }
  419. if (ExtraData) {
  420. ExtraData->FullScreen = (w386ext30->PfW386Flags & fFullScreen) != 0;
  421. }
  422. }
  423. }
  424. __except (1) {
  425. // something went wrong when we tried to read or write PIF file,
  426. result = FALSE;
  427. }
  428. }
  429. __finally {
  430. UnmapFile (fileImage, mapHandle, fileHandle);
  431. }
  432. return result;
  433. }
  434. BOOL
  435. ExtractPifInfoW(
  436. IN PCWSTR FileName,
  437. OUT PCWSTR *Target,
  438. OUT PCWSTR *Params,
  439. OUT PCWSTR *WorkDir,
  440. OUT PCWSTR *IconPath,
  441. OUT PINT IconNumber,
  442. OUT BOOL *MsDosMode,
  443. OUT PLNK_EXTRA_DATAW ExtraData OPTIONAL
  444. )
  445. {
  446. PCSTR aTarget = NULL;
  447. PCSTR aParams = NULL;
  448. PCSTR aWorkDir = NULL;
  449. PCSTR aIconPath = NULL;
  450. PCSTR aFileName;
  451. PCWSTR tempStrW;
  452. BOOL result;
  453. LNK_EXTRA_DATAA extraDataA;
  454. aFileName = ConvertWtoA (FileName);
  455. result = ExtractPifInfoA (
  456. aFileName,
  457. &aTarget,
  458. &aParams,
  459. &aWorkDir,
  460. &aIconPath,
  461. IconNumber,
  462. MsDosMode,
  463. ExtraData?&extraDataA:NULL
  464. );
  465. FreeConvertedStr (aFileName);
  466. if (Target) {
  467. *Target = NULL;
  468. if (aTarget) {
  469. tempStrW = ConvertAtoW (aTarget);
  470. *Target = DuplicatePathStringW (tempStrW, 0);
  471. FreeConvertedStr (tempStrW);
  472. }
  473. }
  474. if (aTarget) {
  475. FreePathStringA (aTarget);
  476. }
  477. if (Params) {
  478. *Params = NULL;
  479. if (aParams) {
  480. tempStrW = ConvertAtoW (aParams);
  481. *Params = DuplicatePathStringW (tempStrW, 0);
  482. FreeConvertedStr (tempStrW);
  483. }
  484. }
  485. if (aParams) {
  486. FreePathStringA (aParams);
  487. }
  488. if (WorkDir) {
  489. *WorkDir = NULL;
  490. if (aWorkDir) {
  491. tempStrW = ConvertAtoW (aWorkDir);
  492. *WorkDir = DuplicatePathStringW (tempStrW, 0);
  493. FreeConvertedStr (tempStrW);
  494. }
  495. }
  496. if (aWorkDir) {
  497. FreePathStringA (aWorkDir);
  498. }
  499. if (IconPath) {
  500. *IconPath = NULL;
  501. if (aIconPath) {
  502. tempStrW = ConvertAtoW (aIconPath);
  503. *IconPath = DuplicatePathStringW (tempStrW, 0);
  504. FreeConvertedStr (tempStrW);
  505. }
  506. }
  507. if (aIconPath) {
  508. FreePathStringA (aIconPath);
  509. }
  510. if (ExtraData) {
  511. ExtraData->FullScreen = extraDataA.FullScreen;
  512. ExtraData->xSize = extraDataA.xSize;
  513. ExtraData->ySize = extraDataA.ySize;
  514. ExtraData->QuickEdit = extraDataA.QuickEdit;
  515. tempStrW = ConvertAtoW (extraDataA.FontName);
  516. StringCopyW (ExtraData->FontName, tempStrW);
  517. FreeConvertedStr (tempStrW);
  518. ExtraData->xFontSize = extraDataA.xFontSize;
  519. ExtraData->yFontSize = extraDataA.yFontSize;
  520. ExtraData->FontWeight = extraDataA.FontWeight;
  521. ExtraData->FontFamily = extraDataA.FontFamily;
  522. ExtraData->CurrentCodePage = extraDataA.CurrentCodePage;
  523. }
  524. return result;
  525. }
  526. BOOL
  527. ExtractUrlInfoA(
  528. IN PCSTR FileName,
  529. OUT PCSTR *Target,
  530. OUT PCSTR *IconPath,
  531. OUT PINT IconNumber
  532. )
  533. {
  534. CHAR buffer [MAXINISIZE];
  535. buffer [0] = 0;
  536. GetPrivateProfileStringA ("InternetShortcut", "URL", "", buffer, MAXINISIZE - 1, FileName);
  537. if (Target) {
  538. *Target = DuplicatePathStringA (buffer, 0);
  539. }
  540. buffer [0] = 0;
  541. GetPrivateProfileStringA ("InternetShortcut", "IconFile", "", buffer, MAXINISIZE - 1, FileName);
  542. if (IconPath) {
  543. *IconPath = DuplicatePathStringA (buffer, 0);
  544. }
  545. if (IconNumber) {
  546. *IconNumber = GetPrivateProfileIntA ("InternetShortcut", "IconIndex", 0, FileName);
  547. }
  548. return TRUE;
  549. }
  550. BOOL
  551. ExtractUrlInfoW(
  552. IN PCWSTR FileName,
  553. OUT PCWSTR *Target,
  554. OUT PCWSTR *IconPath,
  555. OUT PINT IconNumber
  556. )
  557. {
  558. WCHAR buffer [MAXINISIZE];
  559. buffer [0] = 0;
  560. GetPrivateProfileStringW (L"InternetShortcut", L"URL", L"", buffer, MAXINISIZE - 1, FileName);
  561. if (Target) {
  562. *Target = DuplicatePathStringW (buffer, 0);
  563. }
  564. buffer [0] = 0;
  565. GetPrivateProfileStringW (L"InternetShortcut", L"IconFile", L"", buffer, MAXINISIZE - 1, FileName);
  566. if (IconPath) {
  567. *IconPath = DuplicatePathStringW (buffer, 0);
  568. }
  569. if (IconNumber) {
  570. *IconNumber = GetPrivateProfileIntW (L"InternetShortcut", L"IconIndex", 0, FileName);
  571. }
  572. return TRUE;
  573. }
  574. BOOL
  575. ExtractShellLinkInfoA (
  576. IN PCSTR FileName,
  577. OUT PCSTR *Target,
  578. OUT PCSTR *Params,
  579. OUT PCSTR *WorkDir,
  580. OUT PCSTR *IconPath,
  581. OUT PINT IconNumber,
  582. OUT PWORD HotKey,
  583. IN IShellLinkA *ShellLink,
  584. IN IPersistFile *PersistFile
  585. )
  586. {
  587. CHAR tempStr [MEMDB_MAX];
  588. PCSTR sanitizedStr = NULL;
  589. PCWSTR fileNameW;
  590. PSTR strPtr;
  591. HRESULT hres;
  592. WIN32_FIND_DATAA fd;
  593. IShellLinkDataList *shellLinkDataList;
  594. LPEXP_SZ_LINK expSzLink;
  595. LPITEMIDLIST idList;
  596. IShellFolder *desktopFolder = NULL;
  597. STRRET folderName;
  598. PCSTR convStr;
  599. if (Target) {
  600. *Target = NULL;
  601. }
  602. if (Params) {
  603. *Params = NULL;
  604. }
  605. if (WorkDir) {
  606. *WorkDir = NULL;
  607. }
  608. if (IconPath) {
  609. *IconPath = NULL;
  610. }
  611. fileNameW = ConvertAtoW (FileName);
  612. hres = PersistFile->lpVtbl->Load(PersistFile, fileNameW, STGM_READ);
  613. FreeConvertedStr (fileNameW);
  614. if (!SUCCEEDED(hres)) {
  615. DEBUGMSGA((DBG_WARNING, "Cannot load link %s", FileName));
  616. return FALSE;
  617. }
  618. //
  619. // Get the link target
  620. //
  621. hres = ShellLink->lpVtbl->GetPath (
  622. ShellLink,
  623. tempStr,
  624. sizeof (tempStr),
  625. &fd,
  626. SLGP_RAWPATH
  627. );
  628. if (!SUCCEEDED(hres)) {
  629. DEBUGMSGA((DBG_WARNING, "Cannot read target for link %s", FileName));
  630. return FALSE;
  631. }
  632. if (Target) {
  633. sanitizedStr = SanitizePathA (tempStr);
  634. *Target = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
  635. if (sanitizedStr) {
  636. FreePathStringA (sanitizedStr);
  637. sanitizedStr = NULL;
  638. }
  639. // One more thing: let's see if the actual target is a EXPAND_SZ
  640. hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &shellLinkDataList);
  641. if (SUCCEEDED(hres)) {
  642. hres = shellLinkDataList->lpVtbl->CopyDataBlock (shellLinkDataList, EXP_SZ_LINK_SIG, (LPVOID*)&expSzLink);
  643. if (SUCCEEDED(hres)) {
  644. if (expSzLink->szTarget [0]) {
  645. FreePathStringA (*Target);
  646. sanitizedStr = SanitizePathA (expSzLink->szTarget);
  647. *Target = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
  648. if (sanitizedStr) {
  649. FreePathStringA (sanitizedStr);
  650. sanitizedStr = NULL;
  651. }
  652. }
  653. LocalFree (expSzLink);
  654. }
  655. shellLinkDataList->lpVtbl->Release (shellLinkDataList);
  656. }
  657. }
  658. //
  659. // Get the link working directory
  660. //
  661. hres = ShellLink->lpVtbl->GetWorkingDirectory (
  662. ShellLink,
  663. tempStr,
  664. sizeof (tempStr)
  665. );
  666. if (!SUCCEEDED(hres)) {
  667. DEBUGMSGA((DBG_WARNING, "Cannot read target for link %s", FileName));
  668. return FALSE;
  669. }
  670. if (WorkDir) {
  671. sanitizedStr = SanitizePathA (tempStr);
  672. if (sanitizedStr) {
  673. strPtr = (PSTR)GetEndOfStringA (sanitizedStr);
  674. if (strPtr) {
  675. strPtr = _mbsdec (sanitizedStr, strPtr);
  676. if (strPtr) {
  677. if (_mbsnextc (strPtr) == '\\') {
  678. *strPtr = 0;
  679. }
  680. }
  681. }
  682. }
  683. *WorkDir = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
  684. if (sanitizedStr) {
  685. FreePathStringA (sanitizedStr);
  686. sanitizedStr = NULL;
  687. }
  688. }
  689. //
  690. // Get the arguments.
  691. //
  692. hres = ShellLink->lpVtbl->GetArguments (
  693. ShellLink,
  694. tempStr,
  695. MEMDB_MAX
  696. );
  697. if (!SUCCEEDED(hres)) {
  698. DEBUGMSGA((DBG_WARNING, "Cannot read arguments for link %s", FileName));
  699. return FALSE;
  700. }
  701. if (Params) {
  702. *Params = DuplicatePathStringA (tempStr, 0);
  703. }
  704. //
  705. // Get icon path
  706. //
  707. hres = ShellLink->lpVtbl->GetIconLocation (
  708. ShellLink,
  709. tempStr,
  710. sizeof (tempStr),
  711. IconNumber
  712. );
  713. if (!SUCCEEDED(hres)) {
  714. DEBUGMSGA((DBG_WARNING, "Cannot read icon path for link %s", FileName));
  715. return FALSE;
  716. }
  717. if (IconPath) {
  718. sanitizedStr = SanitizePathA (tempStr);
  719. *IconPath = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
  720. if (sanitizedStr) {
  721. FreePathStringA (sanitizedStr);
  722. sanitizedStr = NULL;
  723. }
  724. // One more thing: let's see if the actual icon path is a EXPAND_SZ
  725. hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &shellLinkDataList);
  726. if (SUCCEEDED(hres)) {
  727. hres = shellLinkDataList->lpVtbl->CopyDataBlock (shellLinkDataList, EXP_SZ_ICON_SIG, (LPVOID*)&expSzLink);
  728. if (SUCCEEDED(hres)) {
  729. if (expSzLink->szTarget [0]) {
  730. FreePathStringA (*IconPath);
  731. sanitizedStr = SanitizePathA (expSzLink->szTarget);
  732. *IconPath = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
  733. if (sanitizedStr) {
  734. FreePathStringA (sanitizedStr);
  735. sanitizedStr = NULL;
  736. }
  737. }
  738. LocalFree (expSzLink);
  739. }
  740. shellLinkDataList->lpVtbl->Release (shellLinkDataList);
  741. }
  742. }
  743. //
  744. // Get hot key
  745. //
  746. hres = ShellLink->lpVtbl->GetHotkey (
  747. ShellLink,
  748. HotKey
  749. );
  750. if (!SUCCEEDED(hres)) {
  751. DEBUGMSGA((DBG_WARNING, "Cannot read hot key for link %s", FileName));
  752. return FALSE;
  753. }
  754. return TRUE;
  755. }
  756. BOOL
  757. ExtractShellLinkInfoW (
  758. IN PCWSTR FileName,
  759. OUT PCWSTR *Target,
  760. OUT PCWSTR *Params,
  761. OUT PCWSTR *WorkDir,
  762. OUT PCWSTR *IconPath,
  763. OUT PINT IconNumber,
  764. OUT PWORD HotKey,
  765. IN IShellLinkW *ShellLink,
  766. IN IPersistFile *PersistFile
  767. )
  768. {
  769. WCHAR tempStr [MEMDB_MAX];
  770. PCWSTR sanitizedStr = NULL;
  771. PWSTR strPtr;
  772. HRESULT hres;
  773. WIN32_FIND_DATAW fd;
  774. IShellLinkDataList *shellLinkDataList;
  775. LPEXP_SZ_LINK expSzLink;
  776. LPITEMIDLIST idList;
  777. IShellFolder *desktopFolder = NULL;
  778. STRRET folderName;
  779. PCWSTR convStr;
  780. if (Target) {
  781. *Target = NULL;
  782. }
  783. if (Params) {
  784. *Params = NULL;
  785. }
  786. if (WorkDir) {
  787. *WorkDir = NULL;
  788. }
  789. if (IconPath) {
  790. *IconPath = NULL;
  791. }
  792. hres = PersistFile->lpVtbl->Load(PersistFile, FileName, STGM_READ);
  793. if (!SUCCEEDED(hres)) {
  794. DEBUGMSGW((DBG_WARNING, "Cannot load link %s", FileName));
  795. return FALSE;
  796. }
  797. //
  798. // Get the link target
  799. //
  800. hres = ShellLink->lpVtbl->GetPath (
  801. ShellLink,
  802. tempStr,
  803. sizeof (tempStr),
  804. &fd,
  805. SLGP_RAWPATH
  806. );
  807. if (!SUCCEEDED(hres)) {
  808. DEBUGMSGA((DBG_WARNING, "Cannot read target for link %s", FileName));
  809. return FALSE;
  810. }
  811. if (Target) {
  812. sanitizedStr = SanitizePathW (tempStr);
  813. *Target = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
  814. if (sanitizedStr) {
  815. FreePathStringW (sanitizedStr);
  816. sanitizedStr = NULL;
  817. }
  818. // One more thing: let's see if the actual icon path is a EXPAND_SZ
  819. hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &shellLinkDataList);
  820. if (SUCCEEDED(hres)) {
  821. hres = shellLinkDataList->lpVtbl->CopyDataBlock (shellLinkDataList, EXP_SZ_LINK_SIG, (LPVOID*)&expSzLink);
  822. if (SUCCEEDED(hres)) {
  823. if (expSzLink->swzTarget [0]) {
  824. FreePathStringW (*Target);
  825. sanitizedStr = SanitizePathW (expSzLink->swzTarget);
  826. *Target = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
  827. if (sanitizedStr) {
  828. FreePathStringW (sanitizedStr);
  829. sanitizedStr = NULL;
  830. }
  831. }
  832. LocalFree (expSzLink);
  833. }
  834. shellLinkDataList->lpVtbl->Release (shellLinkDataList);
  835. }
  836. }
  837. //
  838. // Get the link working directory
  839. //
  840. hres = ShellLink->lpVtbl->GetWorkingDirectory (
  841. ShellLink,
  842. tempStr,
  843. sizeof (tempStr)
  844. );
  845. if (!SUCCEEDED(hres)) {
  846. DEBUGMSGW((DBG_WARNING, "Cannot read target for link %s", FileName));
  847. return FALSE;
  848. }
  849. if (WorkDir) {
  850. sanitizedStr = SanitizePathW (tempStr);
  851. if (sanitizedStr) {
  852. strPtr = GetEndOfStringW (sanitizedStr) - 1;
  853. if (strPtr >= sanitizedStr) {
  854. if (*strPtr == L'\\') {
  855. *strPtr = 0;
  856. }
  857. }
  858. }
  859. *WorkDir = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
  860. if (sanitizedStr) {
  861. FreePathStringW (sanitizedStr);
  862. sanitizedStr = NULL;
  863. }
  864. }
  865. //
  866. // Get the arguments.
  867. //
  868. hres = ShellLink->lpVtbl->GetArguments (
  869. ShellLink,
  870. tempStr,
  871. MEMDB_MAX
  872. );
  873. if (!SUCCEEDED(hres)) {
  874. DEBUGMSGW((DBG_WARNING, "Cannot read arguments for link %s", FileName));
  875. return FALSE;
  876. }
  877. if (Params) {
  878. *Params = DuplicatePathStringW (tempStr, 0);
  879. }
  880. //
  881. // Get icon path
  882. //
  883. hres = ShellLink->lpVtbl->GetIconLocation (
  884. ShellLink,
  885. tempStr,
  886. sizeof (tempStr),
  887. IconNumber
  888. );
  889. if (!SUCCEEDED(hres)) {
  890. DEBUGMSGW((DBG_WARNING, "Cannot read icon path for link %s", FileName));
  891. return FALSE;
  892. }
  893. if (IconPath) {
  894. sanitizedStr = SanitizePathW (tempStr);
  895. *IconPath = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
  896. if (sanitizedStr) {
  897. FreePathStringW (sanitizedStr);
  898. sanitizedStr = NULL;
  899. }
  900. // One more thing: let's see if the actual icon path is a EXPAND_SZ
  901. hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &shellLinkDataList);
  902. if (SUCCEEDED(hres)) {
  903. hres = shellLinkDataList->lpVtbl->CopyDataBlock (shellLinkDataList, EXP_SZ_ICON_SIG, (LPVOID*)&expSzLink);
  904. if (SUCCEEDED(hres)) {
  905. if (expSzLink->swzTarget [0]) {
  906. FreePathStringW (*IconPath);
  907. sanitizedStr = SanitizePathW (expSzLink->swzTarget);
  908. *IconPath = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
  909. if (sanitizedStr) {
  910. FreePathStringW (sanitizedStr);
  911. sanitizedStr = NULL;
  912. }
  913. }
  914. LocalFree (expSzLink);
  915. }
  916. shellLinkDataList->lpVtbl->Release (shellLinkDataList);
  917. }
  918. }
  919. //
  920. // Get hot key
  921. //
  922. hres = ShellLink->lpVtbl->GetHotkey (
  923. ShellLink,
  924. HotKey
  925. );
  926. if (!SUCCEEDED(hres)) {
  927. DEBUGMSGW((DBG_WARNING, "Cannot read hot key for link %s", FileName));
  928. return FALSE;
  929. }
  930. return TRUE;
  931. }
  932. BOOL
  933. ExtractShortcutInfoA (
  934. IN PCSTR FileName,
  935. OUT PCSTR *Target,
  936. OUT PCSTR *Params,
  937. OUT PCSTR *WorkDir,
  938. OUT PCSTR *IconPath,
  939. OUT PINT IconNumber,
  940. OUT PWORD HotKey,
  941. OUT BOOL *DosApp,
  942. OUT BOOL *MsDosMode,
  943. OUT PLNK_EXTRA_DATAA ExtraData, OPTIONAL
  944. IN IShellLinkA *ShellLink,
  945. IN IPersistFile *PersistFile
  946. )
  947. {
  948. PCSTR shortcutExt = NULL;
  949. *MsDosMode = FALSE;
  950. *DosApp = FALSE;
  951. *HotKey = 0;
  952. if (Target) {
  953. *Target = NULL;
  954. }
  955. if (Params) {
  956. *Params = NULL;
  957. }
  958. if (WorkDir) {
  959. *WorkDir = NULL;
  960. }
  961. if (IconPath) {
  962. *IconPath = NULL;
  963. }
  964. if (ExtraData) {
  965. ZeroMemory (ExtraData, sizeof (LNK_EXTRA_DATAA));
  966. }
  967. shortcutExt = GetFileExtensionFromPathA (FileName);
  968. if (shortcutExt != NULL) {
  969. if (StringIMatchA (shortcutExt, "LNK")) {
  970. return ExtractShellLinkInfoA (
  971. FileName,
  972. Target,
  973. Params,
  974. WorkDir,
  975. IconPath,
  976. IconNumber,
  977. HotKey,
  978. ShellLink,
  979. PersistFile
  980. );
  981. } else if (StringIMatchA (shortcutExt, "PIF")) {
  982. *DosApp = TRUE;
  983. return ExtractPifInfoA (
  984. FileName,
  985. Target,
  986. Params,
  987. WorkDir,
  988. IconPath,
  989. IconNumber,
  990. MsDosMode,
  991. ExtraData
  992. );
  993. } else if (StringIMatchA (shortcutExt, "URL")) {
  994. *Params = NULL;
  995. *WorkDir = NULL;
  996. return ExtractUrlInfoA (
  997. FileName,
  998. Target,
  999. IconPath,
  1000. IconNumber
  1001. );
  1002. } else {
  1003. return FALSE;
  1004. }
  1005. } else {
  1006. return FALSE;
  1007. }
  1008. }
  1009. BOOL
  1010. ExtractShortcutInfoW (
  1011. IN PCWSTR FileName,
  1012. OUT PCWSTR *Target,
  1013. OUT PCWSTR *Params,
  1014. OUT PCWSTR *WorkDir,
  1015. OUT PCWSTR *IconPath,
  1016. OUT PINT IconNumber,
  1017. OUT PWORD HotKey,
  1018. OUT BOOL *DosApp,
  1019. OUT BOOL *MsDosMode,
  1020. OUT PLNK_EXTRA_DATAW ExtraData, OPTIONAL
  1021. IN IShellLinkW *ShellLink,
  1022. IN IPersistFile *PersistFile
  1023. )
  1024. {
  1025. PCWSTR shortcutExt = NULL;
  1026. *MsDosMode = FALSE;
  1027. *DosApp = FALSE;
  1028. *HotKey = 0;
  1029. if (Target) {
  1030. *Target = NULL;
  1031. }
  1032. if (Params) {
  1033. *Params = NULL;
  1034. }
  1035. if (WorkDir) {
  1036. *WorkDir = NULL;
  1037. }
  1038. if (IconPath) {
  1039. *IconPath = NULL;
  1040. }
  1041. if (ExtraData) {
  1042. ZeroMemory (ExtraData, sizeof (LNK_EXTRA_DATAW));
  1043. }
  1044. shortcutExt = GetFileExtensionFromPathW (FileName);
  1045. if (shortcutExt != NULL) {
  1046. if (StringIMatchW (shortcutExt, L"LNK")) {
  1047. return ExtractShellLinkInfoW (
  1048. FileName,
  1049. Target,
  1050. Params,
  1051. WorkDir,
  1052. IconPath,
  1053. IconNumber,
  1054. HotKey,
  1055. ShellLink,
  1056. PersistFile
  1057. );
  1058. } else if (StringIMatchW (shortcutExt, L"PIF")) {
  1059. *DosApp = TRUE;
  1060. return ExtractPifInfoW (
  1061. FileName,
  1062. Target,
  1063. Params,
  1064. WorkDir,
  1065. IconPath,
  1066. IconNumber,
  1067. MsDosMode,
  1068. ExtraData
  1069. );
  1070. } else if (StringIMatchW (shortcutExt, L"URL")) {
  1071. *Params = NULL;
  1072. *WorkDir = NULL;
  1073. return ExtractUrlInfoW (
  1074. FileName,
  1075. Target,
  1076. IconPath,
  1077. IconNumber
  1078. );
  1079. } else {
  1080. return FALSE;
  1081. }
  1082. } else {
  1083. return FALSE;
  1084. }
  1085. }
  1086. BOOL
  1087. ModifyShellLinkFileA (
  1088. IN PCSTR FileName,
  1089. IN PCSTR Target, OPTIONAL
  1090. IN PCSTR Params, OPTIONAL
  1091. IN PCSTR WorkDir, OPTIONAL
  1092. IN PCSTR IconPath, OPTIONAL
  1093. IN INT IconNumber,
  1094. IN WORD HotKey,
  1095. IN PLNK_EXTRA_DATAA ExtraData, OPTIONAL
  1096. IN IShellLinkA *ShellLink,
  1097. IN IPersistFile *PersistFile
  1098. )
  1099. {
  1100. PCWSTR fileNameW = NULL;
  1101. PCWSTR faceNameW;
  1102. HRESULT comResult;
  1103. __try {
  1104. if (!DoesFileExistA (FileName)) {
  1105. __leave;
  1106. }
  1107. if (((Target == NULL) || (Target [0] == 0)) &&
  1108. ((Params == NULL) || (Params [0] == 0)) &&
  1109. ((WorkDir == NULL) || (WorkDir [0] == 0)) &&
  1110. ((IconPath == NULL) || (IconPath [0] == 0)) &&
  1111. (HotKey == 0) &&
  1112. (ExtraData == NULL)
  1113. ) {
  1114. __leave;
  1115. }
  1116. fileNameW = ConvertAtoW (FileName);
  1117. comResult = PersistFile->lpVtbl->Load(PersistFile, fileNameW, STGM_READ);
  1118. if (comResult != S_OK) {
  1119. LOGA ((LOG_ERROR, "LINKEDIT: Load failed for %s", FileName));
  1120. __leave;
  1121. }
  1122. if (Target != NULL) {
  1123. comResult = ShellLink->lpVtbl->SetPath (ShellLink, Target);
  1124. if (comResult != S_OK) {
  1125. DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SetPath failed for %s", FileName));
  1126. }
  1127. }
  1128. if (Params != NULL) {
  1129. comResult = ShellLink->lpVtbl->SetArguments (ShellLink, Params);
  1130. if (comResult != S_OK) {
  1131. DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SetArguments failed for %s", FileName));
  1132. }
  1133. }
  1134. if (WorkDir != NULL) {
  1135. comResult = ShellLink->lpVtbl->SetWorkingDirectory (ShellLink, WorkDir);
  1136. if (comResult != S_OK) {
  1137. DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SetWorkingDirectory failed for %s", FileName));
  1138. }
  1139. }
  1140. if (IconPath != NULL) {
  1141. comResult = ShellLink->lpVtbl->SetIconLocation (ShellLink, IconPath, IconNumber);
  1142. if (comResult != S_OK) {
  1143. DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SetIconLocation failed for %s", FileName));
  1144. }
  1145. }
  1146. // NTRAID#NTBUG9-153303-2000/08/01-jimschm Add HotKey processing here
  1147. //
  1148. // add NT_CONSOLE_PROPS
  1149. //
  1150. if (ExtraData) {
  1151. HRESULT hres;
  1152. NT_CONSOLE_PROPS props;
  1153. NT_CONSOLE_PROPS *oldProps;
  1154. IShellLinkDataList *psldl;
  1155. //
  1156. // Get a pointer to the IShellLinkDataList interface.
  1157. //
  1158. hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &psldl);
  1159. if (!SUCCEEDED (hres)) {
  1160. DEBUGMSGA ((DBG_WARNING, "Cannot get IShellLinkDataList interface"));
  1161. __leave;
  1162. }
  1163. ZeroMemory (&props, sizeof (NT_CONSOLE_PROPS));
  1164. props.cbSize = sizeof (NT_CONSOLE_PROPS);
  1165. props.dwSignature = NT_CONSOLE_PROPS_SIG;
  1166. //
  1167. // let's try to get the extra data
  1168. //
  1169. comResult = psldl->lpVtbl->CopyDataBlock (psldl, NT_CONSOLE_PROPS_SIG, &oldProps);
  1170. if ((comResult != S_OK) || (oldProps->cbSize != props.cbSize)) {
  1171. // no extra data exists. We need to fill some good data for this console
  1172. props.wFillAttribute = 0x0007;
  1173. props.wPopupFillAttribute = 0x00f5;
  1174. props.dwWindowOrigin.X = 0;
  1175. props.dwWindowOrigin.Y = 0;
  1176. props.nFont = 0;
  1177. props.nInputBufferSize = 0;
  1178. props.uCursorSize = 0x0019;
  1179. props.bInsertMode = FALSE;
  1180. props.bAutoPosition = TRUE;
  1181. props.uHistoryBufferSize = 0x0032;
  1182. props.uNumberOfHistoryBuffers = 0x0004;
  1183. props.bHistoryNoDup = FALSE;
  1184. props.ColorTable [0] = 0x00000000;
  1185. props.ColorTable [1] = 0x00800000;
  1186. props.ColorTable [2] = 0x00008000;
  1187. props.ColorTable [3] = 0x00808000;
  1188. props.ColorTable [4] = 0x00000080;
  1189. props.ColorTable [5] = 0x00800080;
  1190. props.ColorTable [6] = 0x00008080;
  1191. props.ColorTable [7] = 0x00c0c0c0;
  1192. props.ColorTable [8] = 0x00808080;
  1193. props.ColorTable [9] = 0x00ff0000;
  1194. props.ColorTable [10] = 0x0000ff00;
  1195. props.ColorTable [11] = 0x00ffff00;
  1196. props.ColorTable [12] = 0x000000ff;
  1197. props.ColorTable [13] = 0x00ff00ff;
  1198. props.ColorTable [14] = 0x0000ffff;
  1199. props.ColorTable [15] = 0x00ffffff;
  1200. } else {
  1201. props.wFillAttribute = oldProps->wFillAttribute;
  1202. props.wPopupFillAttribute = oldProps->wPopupFillAttribute;
  1203. props.dwWindowOrigin.X = oldProps->dwWindowOrigin.X;
  1204. props.dwWindowOrigin.Y = oldProps->dwWindowOrigin.Y;
  1205. props.nFont = oldProps->nFont;
  1206. props.nInputBufferSize = oldProps->nInputBufferSize;
  1207. props.uCursorSize = oldProps->uCursorSize;
  1208. props.bInsertMode = oldProps->bInsertMode;
  1209. props.bAutoPosition = oldProps->bAutoPosition;
  1210. props.uHistoryBufferSize = oldProps->uHistoryBufferSize;
  1211. props.uNumberOfHistoryBuffers = oldProps->uNumberOfHistoryBuffers;
  1212. props.bHistoryNoDup = oldProps->bHistoryNoDup;
  1213. props.ColorTable [0] = oldProps->ColorTable [0];
  1214. props.ColorTable [1] = oldProps->ColorTable [1];
  1215. props.ColorTable [2] = oldProps->ColorTable [2];
  1216. props.ColorTable [3] = oldProps->ColorTable [3];
  1217. props.ColorTable [4] = oldProps->ColorTable [4];
  1218. props.ColorTable [5] = oldProps->ColorTable [5];
  1219. props.ColorTable [6] = oldProps->ColorTable [6];
  1220. props.ColorTable [7] = oldProps->ColorTable [7];
  1221. props.ColorTable [8] = oldProps->ColorTable [8];
  1222. props.ColorTable [9] = oldProps->ColorTable [9];
  1223. props.ColorTable [10] = oldProps->ColorTable [10];
  1224. props.ColorTable [11] = oldProps->ColorTable [11];
  1225. props.ColorTable [12] = oldProps->ColorTable [12];
  1226. props.ColorTable [13] = oldProps->ColorTable [13];
  1227. props.ColorTable [14] = oldProps->ColorTable [14];
  1228. props.ColorTable [15] = oldProps->ColorTable [15];
  1229. psldl->lpVtbl->RemoveDataBlock (psldl, NT_CONSOLE_PROPS_SIG);
  1230. }
  1231. props.dwScreenBufferSize.X = (SHORT)ExtraData->xSize;
  1232. props.dwScreenBufferSize.Y = (SHORT)ExtraData->ySize;
  1233. props.dwWindowSize.X = (SHORT)ExtraData->xSize;
  1234. props.dwWindowSize.Y = (SHORT)ExtraData->ySize;
  1235. props.dwFontSize.X = (UINT)ExtraData->xFontSize;
  1236. props.dwFontSize.Y = (UINT)ExtraData->yFontSize;
  1237. props.uFontFamily = ExtraData->FontFamily;
  1238. props.uFontWeight = ExtraData->FontWeight;
  1239. faceNameW = ConvertAtoW (ExtraData->FontName);
  1240. StringCopyW (props.FaceName, faceNameW);
  1241. FreeConvertedStr (faceNameW);
  1242. props.bFullScreen = ExtraData->FullScreen;
  1243. props.bQuickEdit = ExtraData->QuickEdit;
  1244. comResult = psldl->lpVtbl->AddDataBlock (psldl, &props);
  1245. if (comResult != S_OK) {
  1246. DEBUGMSGA ((DBG_WARNING, "LINKEDIT: AddDataBlock failed for %s", FileName));
  1247. }
  1248. }
  1249. comResult = PersistFile->lpVtbl->Save (PersistFile, fileNameW, FALSE);
  1250. if (comResult != S_OK) {
  1251. DEBUGMSGA ((DBG_WARNING, "LINKEDIT: Save failed for %s", FileName));
  1252. }
  1253. comResult = PersistFile->lpVtbl->SaveCompleted (PersistFile, fileNameW);
  1254. if (comResult != S_OK) {
  1255. DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SaveCompleted failed for %s", FileName));
  1256. }
  1257. FreeConvertedStr (fileNameW);
  1258. fileNameW = NULL;
  1259. }
  1260. __finally {
  1261. if (fileNameW) {
  1262. FreeConvertedStr (fileNameW);
  1263. fileNameW = NULL;
  1264. }
  1265. }
  1266. return TRUE;
  1267. }
  1268. BOOL
  1269. ModifyShellLinkFileW (
  1270. IN PCWSTR FileName,
  1271. IN PCWSTR Target, OPTIONAL
  1272. IN PCWSTR Params, OPTIONAL
  1273. IN PCWSTR WorkDir, OPTIONAL
  1274. IN PCWSTR IconPath, OPTIONAL
  1275. IN INT IconNumber,
  1276. IN WORD HotKey,
  1277. IN PLNK_EXTRA_DATAW ExtraData, OPTIONAL
  1278. IN IShellLinkW *ShellLink,
  1279. IN IPersistFile *PersistFile
  1280. )
  1281. {
  1282. HRESULT comResult;
  1283. __try {
  1284. if (!DoesFileExistW (FileName)) {
  1285. __leave;
  1286. }
  1287. if (((Target == NULL) || (Target [0] == 0)) &&
  1288. ((Params == NULL) || (Params [0] == 0)) &&
  1289. ((WorkDir == NULL) || (WorkDir [0] == 0)) &&
  1290. ((IconPath == NULL) || (IconPath [0] == 0)) &&
  1291. (HotKey == 0) &&
  1292. (ExtraData == NULL)
  1293. ) {
  1294. __leave;
  1295. }
  1296. comResult = PersistFile->lpVtbl->Load(PersistFile, FileName, STGM_READ);
  1297. if (comResult != S_OK) {
  1298. LOGW ((LOG_ERROR, "LINKEDIT: Load failed for %s", FileName));
  1299. __leave;
  1300. }
  1301. if (Target != NULL) {
  1302. comResult = ShellLink->lpVtbl->SetPath (ShellLink, Target);
  1303. if (comResult != S_OK) {
  1304. DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SetPath failed for %s", FileName));
  1305. }
  1306. }
  1307. if (Params != NULL) {
  1308. comResult = ShellLink->lpVtbl->SetArguments (ShellLink, Params);
  1309. if (comResult != S_OK) {
  1310. DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SetArguments failed for %s", FileName));
  1311. }
  1312. }
  1313. if (WorkDir != NULL) {
  1314. comResult = ShellLink->lpVtbl->SetWorkingDirectory (ShellLink, WorkDir);
  1315. if (comResult != S_OK) {
  1316. DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SetWorkingDirectory failed for %s", FileName));
  1317. }
  1318. }
  1319. if (IconPath != NULL) {
  1320. comResult = ShellLink->lpVtbl->SetIconLocation (ShellLink, IconPath, IconNumber);
  1321. if (comResult != S_OK) {
  1322. DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SetIconLocation failed for %s", FileName));
  1323. }
  1324. }
  1325. // NTRAID#NTBUG9-153303-2000/08/01-jimschm Add HotKey processing here
  1326. //
  1327. // add NT_CONSOLE_PROPS
  1328. //
  1329. if (ExtraData) {
  1330. HRESULT hres;
  1331. NT_CONSOLE_PROPS props;
  1332. NT_CONSOLE_PROPS *oldProps;
  1333. IShellLinkDataList *psldl;
  1334. //
  1335. // Get a pointer to the IShellLinkDataList interface.
  1336. //
  1337. hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &psldl);
  1338. if (!SUCCEEDED (hres)) {
  1339. DEBUGMSGW ((DBG_WARNING, "Cannot get IShellLinkDataList interface"));
  1340. __leave;
  1341. }
  1342. ZeroMemory (&props, sizeof (NT_CONSOLE_PROPS));
  1343. props.cbSize = sizeof (NT_CONSOLE_PROPS);
  1344. props.dwSignature = NT_CONSOLE_PROPS_SIG;
  1345. //
  1346. // let's try to get the extra data
  1347. //
  1348. comResult = psldl->lpVtbl->CopyDataBlock (psldl, NT_CONSOLE_PROPS_SIG, &oldProps);
  1349. if ((comResult != S_OK) || (oldProps->cbSize != props.cbSize)) {
  1350. // no extra data exists. We need to fill some good data for this console
  1351. props.wFillAttribute = 0x0007;
  1352. props.wPopupFillAttribute = 0x00f5;
  1353. props.dwWindowOrigin.X = 0;
  1354. props.dwWindowOrigin.Y = 0;
  1355. props.nFont = 0;
  1356. props.nInputBufferSize = 0;
  1357. props.uCursorSize = 0x0019;
  1358. props.bInsertMode = FALSE;
  1359. props.bAutoPosition = TRUE;
  1360. props.uHistoryBufferSize = 0x0032;
  1361. props.uNumberOfHistoryBuffers = 0x0004;
  1362. props.bHistoryNoDup = FALSE;
  1363. props.ColorTable [0] = 0x00000000;
  1364. props.ColorTable [1] = 0x00800000;
  1365. props.ColorTable [2] = 0x00008000;
  1366. props.ColorTable [3] = 0x00808000;
  1367. props.ColorTable [4] = 0x00000080;
  1368. props.ColorTable [5] = 0x00800080;
  1369. props.ColorTable [6] = 0x00008080;
  1370. props.ColorTable [7] = 0x00c0c0c0;
  1371. props.ColorTable [8] = 0x00808080;
  1372. props.ColorTable [9] = 0x00ff0000;
  1373. props.ColorTable [10] = 0x0000ff00;
  1374. props.ColorTable [11] = 0x00ffff00;
  1375. props.ColorTable [12] = 0x000000ff;
  1376. props.ColorTable [13] = 0x00ff00ff;
  1377. props.ColorTable [14] = 0x0000ffff;
  1378. props.ColorTable [15] = 0x00ffffff;
  1379. } else {
  1380. props.wFillAttribute = oldProps->wFillAttribute;
  1381. props.wPopupFillAttribute = oldProps->wPopupFillAttribute;
  1382. props.dwWindowOrigin.X = oldProps->dwWindowOrigin.X;
  1383. props.dwWindowOrigin.Y = oldProps->dwWindowOrigin.Y;
  1384. props.nFont = oldProps->nFont;
  1385. props.nInputBufferSize = oldProps->nInputBufferSize;
  1386. props.uCursorSize = oldProps->uCursorSize;
  1387. props.bInsertMode = oldProps->bInsertMode;
  1388. props.bAutoPosition = oldProps->bAutoPosition;
  1389. props.uHistoryBufferSize = oldProps->uHistoryBufferSize;
  1390. props.uNumberOfHistoryBuffers = oldProps->uNumberOfHistoryBuffers;
  1391. props.bHistoryNoDup = oldProps->bHistoryNoDup;
  1392. props.ColorTable [0] = oldProps->ColorTable [0];
  1393. props.ColorTable [1] = oldProps->ColorTable [1];
  1394. props.ColorTable [2] = oldProps->ColorTable [2];
  1395. props.ColorTable [3] = oldProps->ColorTable [3];
  1396. props.ColorTable [4] = oldProps->ColorTable [4];
  1397. props.ColorTable [5] = oldProps->ColorTable [5];
  1398. props.ColorTable [6] = oldProps->ColorTable [6];
  1399. props.ColorTable [7] = oldProps->ColorTable [7];
  1400. props.ColorTable [8] = oldProps->ColorTable [8];
  1401. props.ColorTable [9] = oldProps->ColorTable [9];
  1402. props.ColorTable [10] = oldProps->ColorTable [10];
  1403. props.ColorTable [11] = oldProps->ColorTable [11];
  1404. props.ColorTable [12] = oldProps->ColorTable [12];
  1405. props.ColorTable [13] = oldProps->ColorTable [13];
  1406. props.ColorTable [14] = oldProps->ColorTable [14];
  1407. props.ColorTable [15] = oldProps->ColorTable [15];
  1408. psldl->lpVtbl->RemoveDataBlock (psldl, NT_CONSOLE_PROPS_SIG);
  1409. }
  1410. props.dwScreenBufferSize.X = (SHORT)ExtraData->xSize;
  1411. props.dwScreenBufferSize.Y = (SHORT)ExtraData->ySize;
  1412. props.dwWindowSize.X = (SHORT)ExtraData->xSize;
  1413. props.dwWindowSize.Y = (SHORT)ExtraData->ySize;
  1414. props.dwFontSize.X = (UINT)ExtraData->xFontSize;
  1415. props.dwFontSize.Y = (UINT)ExtraData->yFontSize;
  1416. props.uFontFamily = ExtraData->FontFamily;
  1417. props.uFontWeight = ExtraData->FontWeight;
  1418. StringCopyW (props.FaceName, ExtraData->FontName);
  1419. props.bFullScreen = ExtraData->FullScreen;
  1420. props.bQuickEdit = ExtraData->QuickEdit;
  1421. comResult = psldl->lpVtbl->AddDataBlock (psldl, &props);
  1422. if (comResult != S_OK) {
  1423. DEBUGMSGW ((DBG_WARNING, "LINKEDIT: AddDataBlock failed for %s", FileName));
  1424. }
  1425. }
  1426. comResult = PersistFile->lpVtbl->Save (PersistFile, FileName, FALSE);
  1427. if (comResult != S_OK) {
  1428. DEBUGMSGW ((DBG_WARNING, "LINKEDIT: Save failed for %s", FileName));
  1429. }
  1430. comResult = PersistFile->lpVtbl->SaveCompleted (PersistFile, FileName);
  1431. if (comResult != S_OK) {
  1432. DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SaveCompleted failed for %s", FileName));
  1433. }
  1434. }
  1435. __finally {
  1436. }
  1437. return TRUE;
  1438. }
  1439. BOOL
  1440. ModifyPifFileA (
  1441. IN PCSTR FileName,
  1442. IN PCSTR Target, OPTIONAL
  1443. IN PCSTR Params, OPTIONAL
  1444. IN PCSTR WorkDir, OPTIONAL
  1445. IN PCSTR IconPath, OPTIONAL
  1446. IN INT IconNumber
  1447. )
  1448. {
  1449. PCSTR fileImage = NULL;
  1450. HANDLE mapHandle = NULL;
  1451. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  1452. PSTDPIF stdPif;
  1453. PWENHPIF40 wenhPif40;
  1454. PW386PIF30 w386ext30;
  1455. __try {
  1456. fileImage = MapFileIntoMemoryExA (FileName, &fileHandle, &mapHandle, TRUE);
  1457. if (fileImage == NULL) {
  1458. __leave;
  1459. }
  1460. __try {
  1461. stdPif = (PSTDPIF) fileImage;
  1462. if (Target != NULL) {
  1463. strncpy (stdPif->startfile, Target, PIFSTARTLOCSIZE);
  1464. }
  1465. if (Params != NULL) {
  1466. strncpy (stdPif->params, Params, PIFPARAMSSIZE);
  1467. }
  1468. if (WorkDir != NULL) {
  1469. strncpy (stdPif->defpath, WorkDir, PIFDEFPATHSIZE);
  1470. }
  1471. if (IconPath != NULL) {
  1472. wenhPif40 = (PWENHPIF40) pFindEnhPifSignature ((PVOID)fileImage, WENHHDRSIG40);
  1473. if (wenhPif40 != NULL) {
  1474. strncpy (wenhPif40->achIconFileProp, IconPath, PIFDEFFILESIZE);
  1475. wenhPif40->wIconIndexProp = (WORD)IconNumber;
  1476. }
  1477. }
  1478. // in all cases we want to take off MSDOS mode otherwise NT won't start these PIFs
  1479. w386ext30 = pFindEnhPifSignature ((PVOID)fileImage, W386HDRSIG30);
  1480. if (w386ext30) {
  1481. w386ext30->PfW386Flags = w386ext30->PfW386Flags & (~fRealMode);
  1482. w386ext30->PfW386Flags = w386ext30->PfW386Flags & (~fRealModeSilent);
  1483. }
  1484. }
  1485. __except (1) {
  1486. // something went wrong when we tried to read or write PIF file,
  1487. // let's just do nothing and exit from here
  1488. DEBUGMSGW ((DBG_WARNING, "Exception thrown when processing %s", FileName));
  1489. }
  1490. }
  1491. __finally {
  1492. UnmapFile ((PVOID) fileImage, mapHandle, fileHandle);
  1493. }
  1494. return TRUE;
  1495. }
  1496. BOOL
  1497. ModifyPifFileW (
  1498. IN PCWSTR FileName,
  1499. IN PCWSTR Target, OPTIONAL
  1500. IN PCWSTR Params, OPTIONAL
  1501. IN PCWSTR WorkDir, OPTIONAL
  1502. IN PCWSTR IconPath, OPTIONAL
  1503. IN INT IconNumber
  1504. )
  1505. {
  1506. PCSTR fileImage = NULL;
  1507. HANDLE mapHandle = NULL;
  1508. HANDLE fileHandle = INVALID_HANDLE_VALUE;
  1509. PCSTR AnsiStr = NULL;
  1510. PSTDPIF stdPif;
  1511. PWENHPIF40 wenhPif40;
  1512. PW386PIF30 w386ext30;
  1513. __try {
  1514. fileImage = MapFileIntoMemoryExW (FileName, &fileHandle, &mapHandle, TRUE);
  1515. if (fileImage == NULL) {
  1516. __leave;
  1517. }
  1518. __try {
  1519. stdPif = (PSTDPIF) fileImage;
  1520. if (Target != NULL) {
  1521. AnsiStr = ConvertWtoA (Target);
  1522. strncpy (stdPif->startfile, AnsiStr, PIFSTARTLOCSIZE);
  1523. FreeConvertedStr (AnsiStr);
  1524. }
  1525. if (Params != NULL) {
  1526. AnsiStr = ConvertWtoA (Params);
  1527. strncpy (stdPif->params, AnsiStr, PIFPARAMSSIZE);
  1528. FreeConvertedStr (AnsiStr);
  1529. }
  1530. if (WorkDir != NULL) {
  1531. AnsiStr = ConvertWtoA (WorkDir);
  1532. strncpy (stdPif->defpath, AnsiStr, PIFDEFPATHSIZE);
  1533. FreeConvertedStr (AnsiStr);
  1534. }
  1535. if (IconPath != NULL) {
  1536. wenhPif40 = (PWENHPIF40) pFindEnhPifSignature ((PVOID)fileImage, WENHHDRSIG40);
  1537. if (wenhPif40 != NULL) {
  1538. AnsiStr = ConvertWtoA (IconPath);
  1539. strncpy (wenhPif40->achIconFileProp, AnsiStr, PIFDEFFILESIZE);
  1540. FreeConvertedStr (AnsiStr);
  1541. wenhPif40->wIconIndexProp = (WORD)IconNumber;
  1542. }
  1543. }
  1544. // in all cases we want to take off MSDOS mode otherwise NT won't start these PIFs
  1545. w386ext30 = pFindEnhPifSignature ((PVOID)fileImage, W386HDRSIG30);
  1546. if (w386ext30) {
  1547. w386ext30->PfW386Flags = w386ext30->PfW386Flags & (~fRealMode);
  1548. w386ext30->PfW386Flags = w386ext30->PfW386Flags & (~fRealModeSilent);
  1549. }
  1550. }
  1551. __except (1) {
  1552. // something went wrong when we tried to read or write PIF file,
  1553. // let's just do nothing and exit from here
  1554. DEBUGMSGW ((DBG_WARNING, "Exception thrown when processing %s", FileName));
  1555. }
  1556. }
  1557. __finally {
  1558. UnmapFile ((PVOID) fileImage, mapHandle, fileHandle);
  1559. }
  1560. return TRUE;
  1561. }
  1562. BOOL
  1563. ModifyUrlFileA (
  1564. IN PCSTR FileName,
  1565. IN PCSTR Target, OPTIONAL
  1566. IN PCSTR IconPath, OPTIONAL
  1567. IN INT IconNumber
  1568. )
  1569. {
  1570. CHAR buffer [12];
  1571. if (Target != NULL) {
  1572. WritePrivateProfileStringA ("InternetShortcut", "URL", Target, FileName);
  1573. }
  1574. if (IconPath != NULL) {
  1575. WritePrivateProfileStringA ("InternetShortcut", "IconFile", IconPath, FileName);
  1576. wsprintfA (buffer, "%d", IconNumber);
  1577. WritePrivateProfileStringA ("InternetShortcut", "IconIndex", buffer, FileName);
  1578. }
  1579. return TRUE;
  1580. }
  1581. BOOL
  1582. ModifyUrlFileW (
  1583. IN PCWSTR FileName,
  1584. IN PCWSTR Target, OPTIONAL
  1585. IN PCWSTR IconPath, OPTIONAL
  1586. IN INT IconNumber
  1587. )
  1588. {
  1589. WCHAR buffer [12];
  1590. if (Target != NULL) {
  1591. WritePrivateProfileStringW (L"InternetShortcut", L"URL", Target, FileName);
  1592. }
  1593. if (IconPath != NULL) {
  1594. WritePrivateProfileStringW (L"InternetShortcut", L"IconFile", IconPath, FileName);
  1595. wsprintfW (buffer, L"%d", IconNumber);
  1596. WritePrivateProfileStringW (L"InternetShortcut", L"IconIndex", buffer, FileName);
  1597. }
  1598. return TRUE;
  1599. }
  1600. BOOL
  1601. ModifyShortcutFileExA (
  1602. IN PCSTR FileName,
  1603. IN PCSTR ForcedExtension, OPTIONAL
  1604. IN PCSTR Target, OPTIONAL
  1605. IN PCSTR Params, OPTIONAL
  1606. IN PCSTR WorkDir, OPTIONAL
  1607. IN PCSTR IconPath, OPTIONAL
  1608. IN INT IconNumber,
  1609. IN WORD HotKey,
  1610. IN PLNK_EXTRA_DATAA ExtraData, OPTIONAL
  1611. IN IShellLinkA *ShellLink,
  1612. IN IPersistFile *PersistFile
  1613. )
  1614. {
  1615. PCSTR shortcutExt;
  1616. __try {
  1617. shortcutExt = ForcedExtension;
  1618. if (!shortcutExt) {
  1619. shortcutExt = GetFileExtensionFromPathA (FileName);
  1620. }
  1621. if (shortcutExt) {
  1622. if (StringIMatchA (shortcutExt, "LNK")) {
  1623. return ModifyShellLinkFileA (
  1624. FileName,
  1625. Target,
  1626. Params,
  1627. WorkDir,
  1628. IconPath,
  1629. IconNumber,
  1630. HotKey,
  1631. NULL,
  1632. ShellLink,
  1633. PersistFile
  1634. );
  1635. } else if (StringIMatchA (shortcutExt, "PIF")) {
  1636. return ModifyPifFileA (
  1637. FileName,
  1638. Target,
  1639. Params,
  1640. WorkDir,
  1641. IconPath,
  1642. IconNumber
  1643. );
  1644. } else if (StringIMatchA (shortcutExt, "URL")) {
  1645. return ModifyUrlFileA (
  1646. FileName,
  1647. Target,
  1648. IconPath,
  1649. IconNumber
  1650. );
  1651. }
  1652. }
  1653. }
  1654. __except (1) {
  1655. LOGA ((LOG_ERROR, "Cannot process shortcut %s", FileName));
  1656. }
  1657. return TRUE;
  1658. }
  1659. BOOL
  1660. ModifyShortcutFileExW (
  1661. IN PCWSTR FileName,
  1662. IN PCWSTR ForcedExtension, OPTIONAL
  1663. IN PCWSTR Target, OPTIONAL
  1664. IN PCWSTR Params, OPTIONAL
  1665. IN PCWSTR WorkDir, OPTIONAL
  1666. IN PCWSTR IconPath, OPTIONAL
  1667. IN INT IconNumber,
  1668. IN WORD HotKey,
  1669. IN PLNK_EXTRA_DATAW ExtraData, OPTIONAL
  1670. IN IShellLinkW *ShellLink,
  1671. IN IPersistFile *PersistFile
  1672. )
  1673. {
  1674. PCWSTR shortcutExt;
  1675. __try {
  1676. shortcutExt = ForcedExtension;
  1677. if (!shortcutExt) {
  1678. shortcutExt = GetFileExtensionFromPathW (FileName);
  1679. }
  1680. if (shortcutExt) {
  1681. if (StringIMatchW (shortcutExt, L"LNK")) {
  1682. return ModifyShellLinkFileW (
  1683. FileName,
  1684. Target,
  1685. Params,
  1686. WorkDir,
  1687. IconPath,
  1688. IconNumber,
  1689. HotKey,
  1690. NULL,
  1691. ShellLink,
  1692. PersistFile
  1693. );
  1694. } else if (StringIMatchW (shortcutExt, L"PIF")) {
  1695. return ModifyPifFileW (
  1696. FileName,
  1697. Target,
  1698. Params,
  1699. WorkDir,
  1700. IconPath,
  1701. IconNumber
  1702. );
  1703. } else if (StringIMatchW (shortcutExt, L"URL")) {
  1704. return ModifyUrlFileW (
  1705. FileName,
  1706. Target,
  1707. IconPath,
  1708. IconNumber
  1709. );
  1710. }
  1711. }
  1712. }
  1713. __except (1) {
  1714. LOGW ((LOG_ERROR, "Cannot process shortcut %s", FileName));
  1715. }
  1716. return TRUE;
  1717. }