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.

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