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
1950 lines
60 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
linkpif.c
|
|
|
|
Abstract:
|
|
|
|
Functions to query and modify LNK and PIF files.
|
|
|
|
Author:
|
|
|
|
Calin Negreanu (calinn) 07-Sep-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include <pif.h> // private\windows\inc
|
|
|
|
//
|
|
// Debug constants
|
|
//
|
|
|
|
#define DBG_VERSION "LnkPif"
|
|
#define MAXINISIZE 65536
|
|
|
|
//
|
|
// Strings
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Code
|
|
//
|
|
|
|
BOOL
|
|
InitCOMLinkA (
|
|
OUT IShellLinkA **ShellLink,
|
|
OUT IPersistFile **PersistFile
|
|
)
|
|
{
|
|
HRESULT hres;
|
|
BOOL result;
|
|
|
|
//
|
|
// Initialize COM
|
|
//
|
|
CoInitialize (NULL);
|
|
|
|
*ShellLink = NULL;
|
|
*PersistFile = NULL;
|
|
result = FALSE;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Get a pointer to the IShellLink interface.
|
|
//
|
|
hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkA, ShellLink);
|
|
|
|
if (!SUCCEEDED (hres)) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Get a pointer to the IPersistFile interface.
|
|
//
|
|
hres = (*ShellLink)->lpVtbl->QueryInterface ((*ShellLink), &IID_IPersistFile, PersistFile);
|
|
|
|
if (!SUCCEEDED (hres)) {
|
|
__leave;
|
|
}
|
|
|
|
result = TRUE;
|
|
|
|
}
|
|
__finally {
|
|
|
|
if (!result) {
|
|
|
|
if (*PersistFile) {
|
|
(*PersistFile)->lpVtbl->Release (*PersistFile);
|
|
*PersistFile = NULL;
|
|
}
|
|
|
|
if (*ShellLink) {
|
|
(*ShellLink)->lpVtbl->Release (*ShellLink);
|
|
*ShellLink = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!result) {
|
|
//
|
|
// Free COM
|
|
//
|
|
CoUninitialize ();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
InitCOMLinkW (
|
|
OUT IShellLinkW **ShellLink,
|
|
OUT IPersistFile **PersistFile
|
|
)
|
|
{
|
|
HRESULT hres;
|
|
BOOL result;
|
|
|
|
//
|
|
// Initialize COM
|
|
//
|
|
CoInitialize (NULL);
|
|
|
|
*ShellLink = NULL;
|
|
*PersistFile = NULL;
|
|
result = FALSE;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Get a pointer to the IShellLink interface.
|
|
//
|
|
hres = CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, ShellLink);
|
|
|
|
if (!SUCCEEDED (hres)) {
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Get a pointer to the IPersistFile interface.
|
|
//
|
|
hres = (*ShellLink)->lpVtbl->QueryInterface ((*ShellLink), &IID_IPersistFile, PersistFile);
|
|
|
|
if (!SUCCEEDED (hres)) {
|
|
__leave;
|
|
}
|
|
|
|
result = TRUE;
|
|
|
|
}
|
|
__finally {
|
|
|
|
if (!result) {
|
|
|
|
if (*PersistFile) {
|
|
(*PersistFile)->lpVtbl->Release (*PersistFile);
|
|
*PersistFile = NULL;
|
|
}
|
|
|
|
if (*ShellLink) {
|
|
(*ShellLink)->lpVtbl->Release (*ShellLink);
|
|
*ShellLink = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!result) {
|
|
//
|
|
// Free COM
|
|
//
|
|
CoUninitialize ();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
FreeCOMLinkA (
|
|
IN OUT IShellLinkA **ShellLink,
|
|
IN OUT IPersistFile **PersistFile
|
|
)
|
|
{
|
|
if (*PersistFile) {
|
|
(*PersistFile)->lpVtbl->Release (*PersistFile);
|
|
*PersistFile = NULL;
|
|
}
|
|
|
|
if (*ShellLink) {
|
|
(*ShellLink)->lpVtbl->Release (*ShellLink);
|
|
*ShellLink = NULL;
|
|
}
|
|
|
|
//
|
|
// Free COM
|
|
//
|
|
CoUninitialize ();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
FreeCOMLinkW (
|
|
IN OUT IShellLinkW **ShellLink,
|
|
IN OUT IPersistFile **PersistFile
|
|
)
|
|
{
|
|
if (*PersistFile) {
|
|
(*PersistFile)->lpVtbl->Release (*PersistFile);
|
|
*PersistFile = NULL;
|
|
}
|
|
|
|
if (*ShellLink) {
|
|
(*ShellLink)->lpVtbl->Release (*ShellLink);
|
|
*ShellLink = NULL;
|
|
}
|
|
|
|
//
|
|
// Free COM
|
|
//
|
|
CoUninitialize ();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PVOID
|
|
pFindEnhPifSignature (
|
|
IN PVOID FileImage,
|
|
IN PCSTR Signature
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
pFindEnhPifSignature finds a certain PIF structure inside a PIF file (if it exists)
|
|
based on a signature.
|
|
|
|
Arguments:
|
|
|
|
FileImage - image of the PIF file mapped into memory
|
|
|
|
Signature - structure signature
|
|
|
|
Return Value:
|
|
|
|
address of the PIF structure, or NULL if non existent
|
|
|
|
--*/
|
|
|
|
{
|
|
PBYTE tempPtr;
|
|
PBYTE lastPtr;
|
|
PVOID result = NULL;
|
|
BOOL finished = FALSE;
|
|
|
|
PPIFEXTHDR pifExtHdr;
|
|
|
|
lastPtr = (PBYTE) FileImage;
|
|
tempPtr = (PBYTE) FileImage;
|
|
tempPtr += sizeof (STDPIF);
|
|
|
|
pifExtHdr = (PPIFEXTHDR) tempPtr;
|
|
__try {
|
|
do {
|
|
if (tempPtr < lastPtr) {
|
|
result = NULL;
|
|
break;
|
|
} else {
|
|
lastPtr = tempPtr;
|
|
}
|
|
finished = pifExtHdr->extnxthdrfloff == LASTHDRPTR;
|
|
if (StringMatchA (pifExtHdr->extsig, Signature)) {
|
|
result = tempPtr + sizeof (PIFEXTHDR);
|
|
break;
|
|
}
|
|
else {
|
|
tempPtr = (PBYTE)FileImage + pifExtHdr->extnxthdrfloff;
|
|
pifExtHdr = (PPIFEXTHDR) tempPtr;
|
|
}
|
|
|
|
} while (!finished);
|
|
}
|
|
__except (1) {
|
|
// something went wrong trying to access PIF file. Let's exit with NULL
|
|
return NULL;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
ExtractPifInfoA(
|
|
IN PCSTR FileName,
|
|
OUT PCSTR *Target,
|
|
OUT PCSTR *Params,
|
|
OUT PCSTR *WorkDir,
|
|
OUT PCSTR *IconPath,
|
|
OUT PINT IconNumber,
|
|
OUT BOOL *MsDosMode,
|
|
OUT PLNK_EXTRA_DATAA ExtraData OPTIONAL
|
|
)
|
|
{
|
|
PVOID fileImage = NULL;
|
|
HANDLE mapHandle = NULL;
|
|
HANDLE fileHandle = INVALID_HANDLE_VALUE;
|
|
|
|
CHAR tempStr [MEMDB_MAX];
|
|
CHAR target1 [MEMDB_MAX];
|
|
PSTR strPtr;
|
|
PSTR dontCare;
|
|
|
|
PSTDPIF stdPif;
|
|
PWENHPIF40 wenhPif40;
|
|
PW386PIF30 w386ext30;
|
|
|
|
BOOL result = TRUE;
|
|
|
|
if (Target) {
|
|
*Target = NULL;
|
|
}
|
|
if (Params) {
|
|
*Params = NULL;
|
|
}
|
|
if (WorkDir) {
|
|
*WorkDir = NULL;
|
|
}
|
|
if (IconPath) {
|
|
*IconPath = NULL;
|
|
}
|
|
*IconNumber = 0;
|
|
*MsDosMode = FALSE;
|
|
|
|
if (ExtraData) {
|
|
ZeroMemory (ExtraData, sizeof(LNK_EXTRA_DATA));
|
|
}
|
|
|
|
__try {
|
|
fileImage = MapFileIntoMemoryA (FileName, &fileHandle, &mapHandle);
|
|
if (fileImage == NULL) {
|
|
__leave;
|
|
}
|
|
__try {
|
|
stdPif = (PSTDPIF) fileImage;
|
|
|
|
|
|
//
|
|
// getting working directory
|
|
//
|
|
_mbsncpy (tempStr, stdPif->defpath, PIFDEFPATHSIZE);
|
|
|
|
// we might have a path terminated with a wack, we don't want that
|
|
strPtr = _mbsdec (tempStr, GetEndOfStringA (tempStr));
|
|
if (strPtr) {
|
|
if (_mbsnextc (strPtr) == '\\') {
|
|
*strPtr = 0;
|
|
}
|
|
}
|
|
// now get the long path.
|
|
if (WorkDir) {
|
|
*WorkDir = DuplicatePathStringA (tempStr, 0);
|
|
}
|
|
|
|
//
|
|
// getting PIFs target
|
|
//
|
|
_mbsncpy (target1, stdPif->startfile, PIFSTARTLOCSIZE);
|
|
|
|
// in most cases, the target is without a path. We try to build the path, either
|
|
// by using WorkDir or by calling SearchPath to look for this file.
|
|
if (*target1) {//non empty target
|
|
strPtr = _mbsrchr (target1, '\\');
|
|
if (!strPtr) {
|
|
if (WorkDir && (*WorkDir)[0]) {
|
|
StringCopyA (tempStr, *WorkDir);
|
|
StringCatA (tempStr, "\\");
|
|
StringCatA (tempStr, target1);
|
|
}
|
|
else {
|
|
if (!SearchPathA (NULL, target1, NULL, MEMDB_MAX, tempStr, &dontCare)) {
|
|
DEBUGMSG ((DBG_WARNING, "Could not find path for PIF target:%s", FileName));
|
|
StringCopyA (tempStr, target1);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
StringCopyA (tempStr, target1);
|
|
}
|
|
// now get the long path
|
|
if (Target) {
|
|
*Target = DuplicatePathStringA (tempStr, 0);
|
|
}
|
|
}
|
|
|
|
//
|
|
// getting PIFs arguments
|
|
//
|
|
_mbsncpy (tempStr, stdPif->params, PIFPARAMSSIZE);
|
|
if (Params) {
|
|
*Params = DuplicatePathStringA (tempStr, 0);
|
|
}
|
|
|
|
//
|
|
// let's try to read the WENHPIF40 structure
|
|
//
|
|
wenhPif40 = pFindEnhPifSignature (fileImage, WENHHDRSIG40);
|
|
if (wenhPif40) {
|
|
if (IconPath) {
|
|
*IconPath = DuplicatePathStringA (wenhPif40->achIconFileProp, 0);
|
|
}
|
|
*IconNumber = wenhPif40->wIconIndexProp;
|
|
if (ExtraData) {
|
|
ExtraData->xSize = 80;
|
|
ExtraData->ySize = wenhPif40->vidProp.cScreenLines;
|
|
if (ExtraData->ySize < 25) {
|
|
ExtraData->ySize = 25;
|
|
}
|
|
ExtraData->QuickEdit = !(wenhPif40->mseProp.flMse & MSE_WINDOWENABLE);
|
|
ExtraData->CurrentCodePage = wenhPif40->fntProp.wCurrentCP;
|
|
// now let's do some crazy things trying to get the font used
|
|
{
|
|
LOGFONTA logFont;
|
|
HDC dc;
|
|
HFONT font;
|
|
HGDIOBJ oldObject;
|
|
TEXTMETRIC tm;
|
|
|
|
ZeroMemory (&logFont, sizeof (LOGFONTA));
|
|
logFont.lfHeight = wenhPif40->fntProp.cyFontActual;
|
|
logFont.lfWidth = wenhPif40->fntProp.cxFontActual;
|
|
logFont.lfEscapement = 0;
|
|
logFont.lfOrientation = 0;
|
|
logFont.lfWeight = FW_DONTCARE;
|
|
logFont.lfItalic = FALSE;
|
|
logFont.lfUnderline = FALSE;
|
|
logFont.lfStrikeOut = FALSE;
|
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
|
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
|
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
|
logFont.lfQuality = DEFAULT_QUALITY;
|
|
logFont.lfPitchAndFamily = DEFAULT_PITCH;
|
|
if (wenhPif40->fntProp.flFnt & FNT_TT) {
|
|
memcpy (logFont.lfFaceName, wenhPif40->fntProp.achTTFaceName, LF_FACESIZE);
|
|
memcpy (ExtraData->FontName, wenhPif40->fntProp.achTTFaceName, LF_FACESIZE);
|
|
} else {
|
|
memcpy (logFont.lfFaceName, wenhPif40->fntProp.achRasterFaceName, LF_FACESIZE);
|
|
memcpy (ExtraData->FontName, wenhPif40->fntProp.achRasterFaceName, LF_FACESIZE);
|
|
}
|
|
dc = CreateDCA ("DISPLAY", NULL, NULL, NULL);
|
|
if (dc) {
|
|
font = CreateFontIndirectA (&logFont);
|
|
if (font) {
|
|
oldObject = SelectObject (dc, font);
|
|
|
|
if (GetTextMetrics (dc, &tm)) {
|
|
ExtraData->xFontSize = tm.tmAveCharWidth;
|
|
ExtraData->yFontSize = tm.tmHeight;
|
|
ExtraData->FontWeight = tm.tmWeight;
|
|
ExtraData->FontFamily = tm.tmPitchAndFamily;
|
|
}
|
|
SelectObject (dc, oldObject);
|
|
DeleteObject (font);
|
|
}
|
|
DeleteDC (dc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
w386ext30 = pFindEnhPifSignature (fileImage, W386HDRSIG30);
|
|
if (w386ext30) {
|
|
if (((w386ext30->PfW386Flags & fRealMode ) == fRealMode ) ||
|
|
((w386ext30->PfW386Flags & fRealModeSilent) == fRealModeSilent)
|
|
) {
|
|
*MsDosMode = TRUE;
|
|
}
|
|
if (ExtraData) {
|
|
ExtraData->FullScreen = (w386ext30->PfW386Flags & fFullScreen) != 0;
|
|
}
|
|
}
|
|
}
|
|
__except (1) {
|
|
// something went wrong when we tried to read or write PIF file,
|
|
result = FALSE;
|
|
}
|
|
}
|
|
__finally {
|
|
UnmapFile (fileImage, mapHandle, fileHandle);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
ExtractPifInfoW(
|
|
IN PCWSTR FileName,
|
|
OUT PCWSTR *Target,
|
|
OUT PCWSTR *Params,
|
|
OUT PCWSTR *WorkDir,
|
|
OUT PCWSTR *IconPath,
|
|
OUT PINT IconNumber,
|
|
OUT BOOL *MsDosMode,
|
|
OUT PLNK_EXTRA_DATAW ExtraData OPTIONAL
|
|
)
|
|
{
|
|
PCSTR aTarget = NULL;
|
|
PCSTR aParams = NULL;
|
|
PCSTR aWorkDir = NULL;
|
|
PCSTR aIconPath = NULL;
|
|
PCSTR aFileName;
|
|
PCWSTR tempStrW;
|
|
BOOL result;
|
|
LNK_EXTRA_DATAA extraDataA;
|
|
|
|
aFileName = ConvertWtoA (FileName);
|
|
|
|
result = ExtractPifInfoA (
|
|
aFileName,
|
|
&aTarget,
|
|
&aParams,
|
|
&aWorkDir,
|
|
&aIconPath,
|
|
IconNumber,
|
|
MsDosMode,
|
|
ExtraData?&extraDataA:NULL
|
|
);
|
|
FreeConvertedStr (aFileName);
|
|
|
|
if (Target) {
|
|
*Target = NULL;
|
|
if (aTarget) {
|
|
tempStrW = ConvertAtoW (aTarget);
|
|
*Target = DuplicatePathStringW (tempStrW, 0);
|
|
FreeConvertedStr (tempStrW);
|
|
}
|
|
}
|
|
if (aTarget) {
|
|
FreePathStringA (aTarget);
|
|
}
|
|
|
|
if (Params) {
|
|
*Params = NULL;
|
|
if (aParams) {
|
|
tempStrW = ConvertAtoW (aParams);
|
|
*Params = DuplicatePathStringW (tempStrW, 0);
|
|
FreeConvertedStr (tempStrW);
|
|
}
|
|
}
|
|
if (aParams) {
|
|
FreePathStringA (aParams);
|
|
}
|
|
|
|
if (WorkDir) {
|
|
*WorkDir = NULL;
|
|
if (aWorkDir) {
|
|
tempStrW = ConvertAtoW (aWorkDir);
|
|
*WorkDir = DuplicatePathStringW (tempStrW, 0);
|
|
FreeConvertedStr (tempStrW);
|
|
}
|
|
}
|
|
if (aWorkDir) {
|
|
FreePathStringA (aWorkDir);
|
|
}
|
|
|
|
if (IconPath) {
|
|
*IconPath = NULL;
|
|
if (aIconPath) {
|
|
tempStrW = ConvertAtoW (aIconPath);
|
|
*IconPath = DuplicatePathStringW (tempStrW, 0);
|
|
FreeConvertedStr (tempStrW);
|
|
}
|
|
}
|
|
if (aIconPath) {
|
|
FreePathStringA (aIconPath);
|
|
}
|
|
|
|
if (ExtraData) {
|
|
ExtraData->FullScreen = extraDataA.FullScreen;
|
|
ExtraData->xSize = extraDataA.xSize;
|
|
ExtraData->ySize = extraDataA.ySize;
|
|
ExtraData->QuickEdit = extraDataA.QuickEdit;
|
|
tempStrW = ConvertAtoW (extraDataA.FontName);
|
|
StringCopyW (ExtraData->FontName, tempStrW);
|
|
FreeConvertedStr (tempStrW);
|
|
ExtraData->xFontSize = extraDataA.xFontSize;
|
|
ExtraData->yFontSize = extraDataA.yFontSize;
|
|
ExtraData->FontWeight = extraDataA.FontWeight;
|
|
ExtraData->FontFamily = extraDataA.FontFamily;
|
|
ExtraData->CurrentCodePage = extraDataA.CurrentCodePage;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
ExtractUrlInfoA(
|
|
IN PCSTR FileName,
|
|
OUT PCSTR *Target,
|
|
OUT PCSTR *IconPath,
|
|
OUT PINT IconNumber
|
|
)
|
|
{
|
|
CHAR buffer [MAXINISIZE];
|
|
|
|
buffer [0] = 0;
|
|
GetPrivateProfileStringA ("InternetShortcut", "URL", "", buffer, MAXINISIZE - 1, FileName);
|
|
if (Target) {
|
|
*Target = DuplicatePathStringA (buffer, 0);
|
|
}
|
|
|
|
buffer [0] = 0;
|
|
GetPrivateProfileStringA ("InternetShortcut", "IconFile", "", buffer, MAXINISIZE - 1, FileName);
|
|
if (IconPath) {
|
|
*IconPath = DuplicatePathStringA (buffer, 0);
|
|
}
|
|
|
|
if (IconNumber) {
|
|
*IconNumber = GetPrivateProfileIntA ("InternetShortcut", "IconIndex", 0, FileName);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ExtractUrlInfoW(
|
|
IN PCWSTR FileName,
|
|
OUT PCWSTR *Target,
|
|
OUT PCWSTR *IconPath,
|
|
OUT PINT IconNumber
|
|
)
|
|
{
|
|
WCHAR buffer [MAXINISIZE];
|
|
|
|
buffer [0] = 0;
|
|
GetPrivateProfileStringW (L"InternetShortcut", L"URL", L"", buffer, MAXINISIZE - 1, FileName);
|
|
if (Target) {
|
|
*Target = DuplicatePathStringW (buffer, 0);
|
|
}
|
|
|
|
buffer [0] = 0;
|
|
GetPrivateProfileStringW (L"InternetShortcut", L"IconFile", L"", buffer, MAXINISIZE - 1, FileName);
|
|
if (IconPath) {
|
|
*IconPath = DuplicatePathStringW (buffer, 0);
|
|
}
|
|
|
|
if (IconNumber) {
|
|
*IconNumber = GetPrivateProfileIntW (L"InternetShortcut", L"IconIndex", 0, FileName);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ExtractShellLinkInfoA (
|
|
IN PCSTR FileName,
|
|
OUT PCSTR *Target,
|
|
OUT PCSTR *Params,
|
|
OUT PCSTR *WorkDir,
|
|
OUT PCSTR *IconPath,
|
|
OUT PINT IconNumber,
|
|
OUT PWORD HotKey,
|
|
IN IShellLinkA *ShellLink,
|
|
IN IPersistFile *PersistFile
|
|
)
|
|
{
|
|
CHAR tempStr [MEMDB_MAX];
|
|
PCSTR sanitizedStr = NULL;
|
|
PCWSTR fileNameW;
|
|
PSTR strPtr;
|
|
HRESULT hres;
|
|
WIN32_FIND_DATAA fd;
|
|
IShellLinkDataList *shellLinkDataList;
|
|
LPEXP_SZ_LINK expSzLink;
|
|
LPITEMIDLIST idList;
|
|
IShellFolder *desktopFolder = NULL;
|
|
STRRET folderName;
|
|
PCSTR convStr;
|
|
|
|
if (Target) {
|
|
*Target = NULL;
|
|
}
|
|
if (Params) {
|
|
*Params = NULL;
|
|
}
|
|
if (WorkDir) {
|
|
*WorkDir = NULL;
|
|
}
|
|
if (IconPath) {
|
|
*IconPath = NULL;
|
|
}
|
|
|
|
fileNameW = ConvertAtoW (FileName);
|
|
hres = PersistFile->lpVtbl->Load(PersistFile, fileNameW, STGM_READ);
|
|
FreeConvertedStr (fileNameW);
|
|
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGA((DBG_WARNING, "Cannot load link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the link target
|
|
//
|
|
hres = ShellLink->lpVtbl->GetPath (
|
|
ShellLink,
|
|
tempStr,
|
|
sizeof (tempStr),
|
|
&fd,
|
|
SLGP_RAWPATH
|
|
);
|
|
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGA((DBG_WARNING, "Cannot read target for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
|
|
if (Target) {
|
|
sanitizedStr = SanitizePathA (tempStr);
|
|
*Target = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringA (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
|
|
// One more thing: let's see if the actual target is a EXPAND_SZ
|
|
hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &shellLinkDataList);
|
|
if (SUCCEEDED(hres)) {
|
|
hres = shellLinkDataList->lpVtbl->CopyDataBlock (shellLinkDataList, EXP_SZ_LINK_SIG, (LPVOID*)&expSzLink);
|
|
if (SUCCEEDED(hres)) {
|
|
if (expSzLink->szTarget [0]) {
|
|
FreePathStringA (*Target);
|
|
sanitizedStr = SanitizePathA (expSzLink->szTarget);
|
|
*Target = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringA (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
}
|
|
LocalFree (expSzLink);
|
|
}
|
|
shellLinkDataList->lpVtbl->Release (shellLinkDataList);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the link working directory
|
|
//
|
|
hres = ShellLink->lpVtbl->GetWorkingDirectory (
|
|
ShellLink,
|
|
tempStr,
|
|
sizeof (tempStr)
|
|
);
|
|
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGA((DBG_WARNING, "Cannot read target for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
|
|
if (WorkDir) {
|
|
sanitizedStr = SanitizePathA (tempStr);
|
|
if (sanitizedStr) {
|
|
strPtr = (PSTR)GetEndOfStringA (sanitizedStr);
|
|
if (strPtr) {
|
|
strPtr = _mbsdec (sanitizedStr, strPtr);
|
|
if (strPtr) {
|
|
if (_mbsnextc (strPtr) == '\\') {
|
|
*strPtr = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*WorkDir = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringA (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the arguments.
|
|
//
|
|
hres = ShellLink->lpVtbl->GetArguments (
|
|
ShellLink,
|
|
tempStr,
|
|
MEMDB_MAX
|
|
);
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGA((DBG_WARNING, "Cannot read arguments for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
if (Params) {
|
|
*Params = DuplicatePathStringA (tempStr, 0);
|
|
}
|
|
|
|
//
|
|
// Get icon path
|
|
//
|
|
hres = ShellLink->lpVtbl->GetIconLocation (
|
|
ShellLink,
|
|
tempStr,
|
|
sizeof (tempStr),
|
|
IconNumber
|
|
);
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGA((DBG_WARNING, "Cannot read icon path for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
if (IconPath) {
|
|
sanitizedStr = SanitizePathA (tempStr);
|
|
*IconPath = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringA (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
|
|
// One more thing: let's see if the actual icon path is a EXPAND_SZ
|
|
hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &shellLinkDataList);
|
|
if (SUCCEEDED(hres)) {
|
|
hres = shellLinkDataList->lpVtbl->CopyDataBlock (shellLinkDataList, EXP_SZ_ICON_SIG, (LPVOID*)&expSzLink);
|
|
if (SUCCEEDED(hres)) {
|
|
if (expSzLink->szTarget [0]) {
|
|
FreePathStringA (*IconPath);
|
|
sanitizedStr = SanitizePathA (expSzLink->szTarget);
|
|
*IconPath = DuplicatePathStringA (sanitizedStr?sanitizedStr:"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringA (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
}
|
|
LocalFree (expSzLink);
|
|
}
|
|
shellLinkDataList->lpVtbl->Release (shellLinkDataList);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get hot key
|
|
//
|
|
hres = ShellLink->lpVtbl->GetHotkey (
|
|
ShellLink,
|
|
HotKey
|
|
);
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGA((DBG_WARNING, "Cannot read hot key for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ExtractShellLinkInfoW (
|
|
IN PCWSTR FileName,
|
|
OUT PCWSTR *Target,
|
|
OUT PCWSTR *Params,
|
|
OUT PCWSTR *WorkDir,
|
|
OUT PCWSTR *IconPath,
|
|
OUT PINT IconNumber,
|
|
OUT PWORD HotKey,
|
|
IN IShellLinkW *ShellLink,
|
|
IN IPersistFile *PersistFile
|
|
)
|
|
{
|
|
WCHAR tempStr [MEMDB_MAX];
|
|
PCWSTR sanitizedStr = NULL;
|
|
PWSTR strPtr;
|
|
HRESULT hres;
|
|
WIN32_FIND_DATAW fd;
|
|
IShellLinkDataList *shellLinkDataList;
|
|
LPEXP_SZ_LINK expSzLink;
|
|
LPITEMIDLIST idList;
|
|
IShellFolder *desktopFolder = NULL;
|
|
STRRET folderName;
|
|
PCWSTR convStr;
|
|
|
|
if (Target) {
|
|
*Target = NULL;
|
|
}
|
|
if (Params) {
|
|
*Params = NULL;
|
|
}
|
|
if (WorkDir) {
|
|
*WorkDir = NULL;
|
|
}
|
|
if (IconPath) {
|
|
*IconPath = NULL;
|
|
}
|
|
|
|
hres = PersistFile->lpVtbl->Load(PersistFile, FileName, STGM_READ);
|
|
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGW((DBG_WARNING, "Cannot load link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the link target
|
|
//
|
|
hres = ShellLink->lpVtbl->GetPath (
|
|
ShellLink,
|
|
tempStr,
|
|
sizeof (tempStr),
|
|
&fd,
|
|
SLGP_RAWPATH
|
|
);
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGA((DBG_WARNING, "Cannot read target for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
|
|
if (Target) {
|
|
sanitizedStr = SanitizePathW (tempStr);
|
|
*Target = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringW (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
|
|
// One more thing: let's see if the actual icon path is a EXPAND_SZ
|
|
hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &shellLinkDataList);
|
|
if (SUCCEEDED(hres)) {
|
|
hres = shellLinkDataList->lpVtbl->CopyDataBlock (shellLinkDataList, EXP_SZ_LINK_SIG, (LPVOID*)&expSzLink);
|
|
if (SUCCEEDED(hres)) {
|
|
if (expSzLink->swzTarget [0]) {
|
|
FreePathStringW (*Target);
|
|
sanitizedStr = SanitizePathW (expSzLink->swzTarget);
|
|
*Target = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringW (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
}
|
|
LocalFree (expSzLink);
|
|
}
|
|
shellLinkDataList->lpVtbl->Release (shellLinkDataList);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the link working directory
|
|
//
|
|
hres = ShellLink->lpVtbl->GetWorkingDirectory (
|
|
ShellLink,
|
|
tempStr,
|
|
sizeof (tempStr)
|
|
);
|
|
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGW((DBG_WARNING, "Cannot read target for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
|
|
if (WorkDir) {
|
|
sanitizedStr = SanitizePathW (tempStr);
|
|
if (sanitizedStr) {
|
|
strPtr = GetEndOfStringW (sanitizedStr) - 1;
|
|
if (strPtr >= sanitizedStr) {
|
|
if (*strPtr == L'\\') {
|
|
*strPtr = 0;
|
|
}
|
|
}
|
|
}
|
|
*WorkDir = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringW (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the arguments.
|
|
//
|
|
hres = ShellLink->lpVtbl->GetArguments (
|
|
ShellLink,
|
|
tempStr,
|
|
MEMDB_MAX
|
|
);
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGW((DBG_WARNING, "Cannot read arguments for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
if (Params) {
|
|
*Params = DuplicatePathStringW (tempStr, 0);
|
|
}
|
|
|
|
//
|
|
// Get icon path
|
|
//
|
|
hres = ShellLink->lpVtbl->GetIconLocation (
|
|
ShellLink,
|
|
tempStr,
|
|
sizeof (tempStr),
|
|
IconNumber
|
|
);
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGW((DBG_WARNING, "Cannot read icon path for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
if (IconPath) {
|
|
sanitizedStr = SanitizePathW (tempStr);
|
|
*IconPath = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringW (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
|
|
// One more thing: let's see if the actual icon path is a EXPAND_SZ
|
|
hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &shellLinkDataList);
|
|
if (SUCCEEDED(hres)) {
|
|
hres = shellLinkDataList->lpVtbl->CopyDataBlock (shellLinkDataList, EXP_SZ_ICON_SIG, (LPVOID*)&expSzLink);
|
|
if (SUCCEEDED(hres)) {
|
|
if (expSzLink->swzTarget [0]) {
|
|
FreePathStringW (*IconPath);
|
|
sanitizedStr = SanitizePathW (expSzLink->swzTarget);
|
|
*IconPath = DuplicatePathStringW (sanitizedStr?sanitizedStr:L"", 0);
|
|
if (sanitizedStr) {
|
|
FreePathStringW (sanitizedStr);
|
|
sanitizedStr = NULL;
|
|
}
|
|
}
|
|
LocalFree (expSzLink);
|
|
}
|
|
shellLinkDataList->lpVtbl->Release (shellLinkDataList);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get hot key
|
|
//
|
|
hres = ShellLink->lpVtbl->GetHotkey (
|
|
ShellLink,
|
|
HotKey
|
|
);
|
|
|
|
if (!SUCCEEDED(hres)) {
|
|
DEBUGMSGW((DBG_WARNING, "Cannot read hot key for link %s", FileName));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ExtractShortcutInfoA (
|
|
IN PCSTR FileName,
|
|
OUT PCSTR *Target,
|
|
OUT PCSTR *Params,
|
|
OUT PCSTR *WorkDir,
|
|
OUT PCSTR *IconPath,
|
|
OUT PINT IconNumber,
|
|
OUT PWORD HotKey,
|
|
OUT BOOL *DosApp,
|
|
OUT BOOL *MsDosMode,
|
|
OUT PLNK_EXTRA_DATAA ExtraData, OPTIONAL
|
|
IN IShellLinkA *ShellLink,
|
|
IN IPersistFile *PersistFile
|
|
)
|
|
{
|
|
PCSTR shortcutExt = NULL;
|
|
|
|
*MsDosMode = FALSE;
|
|
*DosApp = FALSE;
|
|
*HotKey = 0;
|
|
|
|
if (Target) {
|
|
*Target = NULL;
|
|
}
|
|
if (Params) {
|
|
*Params = NULL;
|
|
}
|
|
if (WorkDir) {
|
|
*WorkDir = NULL;
|
|
}
|
|
if (IconPath) {
|
|
*IconPath = NULL;
|
|
}
|
|
if (ExtraData) {
|
|
ZeroMemory (ExtraData, sizeof (LNK_EXTRA_DATAA));
|
|
}
|
|
|
|
shortcutExt = GetFileExtensionFromPathA (FileName);
|
|
|
|
if (shortcutExt != NULL) {
|
|
if (StringIMatchA (shortcutExt, "LNK")) {
|
|
return ExtractShellLinkInfoA (
|
|
FileName,
|
|
Target,
|
|
Params,
|
|
WorkDir,
|
|
IconPath,
|
|
IconNumber,
|
|
HotKey,
|
|
ShellLink,
|
|
PersistFile
|
|
);
|
|
|
|
} else if (StringIMatchA (shortcutExt, "PIF")) {
|
|
|
|
*DosApp = TRUE;
|
|
return ExtractPifInfoA (
|
|
FileName,
|
|
Target,
|
|
Params,
|
|
WorkDir,
|
|
IconPath,
|
|
IconNumber,
|
|
MsDosMode,
|
|
ExtraData
|
|
);
|
|
|
|
} else if (StringIMatchA (shortcutExt, "URL")) {
|
|
|
|
*Params = NULL;
|
|
*WorkDir = NULL;
|
|
return ExtractUrlInfoA (
|
|
FileName,
|
|
Target,
|
|
IconPath,
|
|
IconNumber
|
|
);
|
|
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
ExtractShortcutInfoW (
|
|
IN PCWSTR FileName,
|
|
OUT PCWSTR *Target,
|
|
OUT PCWSTR *Params,
|
|
OUT PCWSTR *WorkDir,
|
|
OUT PCWSTR *IconPath,
|
|
OUT PINT IconNumber,
|
|
OUT PWORD HotKey,
|
|
OUT BOOL *DosApp,
|
|
OUT BOOL *MsDosMode,
|
|
OUT PLNK_EXTRA_DATAW ExtraData, OPTIONAL
|
|
IN IShellLinkW *ShellLink,
|
|
IN IPersistFile *PersistFile
|
|
)
|
|
{
|
|
PCWSTR shortcutExt = NULL;
|
|
|
|
*MsDosMode = FALSE;
|
|
*DosApp = FALSE;
|
|
*HotKey = 0;
|
|
|
|
if (Target) {
|
|
*Target = NULL;
|
|
}
|
|
if (Params) {
|
|
*Params = NULL;
|
|
}
|
|
if (WorkDir) {
|
|
*WorkDir = NULL;
|
|
}
|
|
if (IconPath) {
|
|
*IconPath = NULL;
|
|
}
|
|
if (ExtraData) {
|
|
ZeroMemory (ExtraData, sizeof (LNK_EXTRA_DATAW));
|
|
}
|
|
|
|
shortcutExt = GetFileExtensionFromPathW (FileName);
|
|
|
|
if (shortcutExt != NULL) {
|
|
if (StringIMatchW (shortcutExt, L"LNK")) {
|
|
return ExtractShellLinkInfoW (
|
|
FileName,
|
|
Target,
|
|
Params,
|
|
WorkDir,
|
|
IconPath,
|
|
IconNumber,
|
|
HotKey,
|
|
ShellLink,
|
|
PersistFile
|
|
);
|
|
|
|
} else if (StringIMatchW (shortcutExt, L"PIF")) {
|
|
|
|
*DosApp = TRUE;
|
|
return ExtractPifInfoW (
|
|
FileName,
|
|
Target,
|
|
Params,
|
|
WorkDir,
|
|
IconPath,
|
|
IconNumber,
|
|
MsDosMode,
|
|
ExtraData
|
|
);
|
|
|
|
} else if (StringIMatchW (shortcutExt, L"URL")) {
|
|
|
|
*Params = NULL;
|
|
*WorkDir = NULL;
|
|
return ExtractUrlInfoW (
|
|
FileName,
|
|
Target,
|
|
IconPath,
|
|
IconNumber
|
|
);
|
|
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
ModifyShellLinkFileA (
|
|
IN PCSTR FileName,
|
|
IN PCSTR Target, OPTIONAL
|
|
IN PCSTR Params, OPTIONAL
|
|
IN PCSTR WorkDir, OPTIONAL
|
|
IN PCSTR IconPath, OPTIONAL
|
|
IN INT IconNumber,
|
|
IN WORD HotKey,
|
|
IN PLNK_EXTRA_DATAA ExtraData, OPTIONAL
|
|
IN IShellLinkA *ShellLink,
|
|
IN IPersistFile *PersistFile
|
|
)
|
|
{
|
|
PCWSTR fileNameW = NULL;
|
|
PCWSTR faceNameW;
|
|
HRESULT comResult;
|
|
|
|
__try {
|
|
if (!DoesFileExistA (FileName)) {
|
|
__leave;
|
|
}
|
|
if (((Target == NULL) || (Target [0] == 0)) &&
|
|
((Params == NULL) || (Params [0] == 0)) &&
|
|
((WorkDir == NULL) || (WorkDir [0] == 0)) &&
|
|
((IconPath == NULL) || (IconPath [0] == 0)) &&
|
|
(HotKey == 0) &&
|
|
(ExtraData == NULL)
|
|
) {
|
|
__leave;
|
|
}
|
|
|
|
fileNameW = ConvertAtoW (FileName);
|
|
comResult = PersistFile->lpVtbl->Load(PersistFile, fileNameW, STGM_READ);
|
|
if (comResult != S_OK) {
|
|
LOGA ((LOG_ERROR, "LINKEDIT: Load failed for %s", FileName));
|
|
__leave;
|
|
}
|
|
|
|
if (Target != NULL) {
|
|
comResult = ShellLink->lpVtbl->SetPath (ShellLink, Target);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SetPath failed for %s", FileName));
|
|
}
|
|
}
|
|
if (Params != NULL) {
|
|
comResult = ShellLink->lpVtbl->SetArguments (ShellLink, Params);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SetArguments failed for %s", FileName));
|
|
}
|
|
}
|
|
if (WorkDir != NULL) {
|
|
comResult = ShellLink->lpVtbl->SetWorkingDirectory (ShellLink, WorkDir);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SetWorkingDirectory failed for %s", FileName));
|
|
}
|
|
}
|
|
if (IconPath != NULL) {
|
|
comResult = ShellLink->lpVtbl->SetIconLocation (ShellLink, IconPath, IconNumber);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SetIconLocation failed for %s", FileName));
|
|
}
|
|
}
|
|
// NTRAID#NTBUG9-153303-2000/08/01-jimschm Add HotKey processing here
|
|
|
|
//
|
|
// add NT_CONSOLE_PROPS
|
|
//
|
|
if (ExtraData) {
|
|
|
|
HRESULT hres;
|
|
NT_CONSOLE_PROPS props;
|
|
NT_CONSOLE_PROPS *oldProps;
|
|
|
|
IShellLinkDataList *psldl;
|
|
//
|
|
// Get a pointer to the IShellLinkDataList interface.
|
|
//
|
|
hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &psldl);
|
|
|
|
if (!SUCCEEDED (hres)) {
|
|
DEBUGMSGA ((DBG_WARNING, "Cannot get IShellLinkDataList interface"));
|
|
__leave;
|
|
}
|
|
|
|
ZeroMemory (&props, sizeof (NT_CONSOLE_PROPS));
|
|
props.cbSize = sizeof (NT_CONSOLE_PROPS);
|
|
props.dwSignature = NT_CONSOLE_PROPS_SIG;
|
|
|
|
//
|
|
// let's try to get the extra data
|
|
//
|
|
comResult = psldl->lpVtbl->CopyDataBlock (psldl, NT_CONSOLE_PROPS_SIG, &oldProps);
|
|
if ((comResult != S_OK) || (oldProps->cbSize != props.cbSize)) {
|
|
// no extra data exists. We need to fill some good data for this console
|
|
props.wFillAttribute = 0x0007;
|
|
props.wPopupFillAttribute = 0x00f5;
|
|
props.dwWindowOrigin.X = 0;
|
|
props.dwWindowOrigin.Y = 0;
|
|
props.nFont = 0;
|
|
props.nInputBufferSize = 0;
|
|
props.uCursorSize = 0x0019;
|
|
props.bInsertMode = FALSE;
|
|
props.bAutoPosition = TRUE;
|
|
props.uHistoryBufferSize = 0x0032;
|
|
props.uNumberOfHistoryBuffers = 0x0004;
|
|
props.bHistoryNoDup = FALSE;
|
|
props.ColorTable [0] = 0x00000000;
|
|
props.ColorTable [1] = 0x00800000;
|
|
props.ColorTable [2] = 0x00008000;
|
|
props.ColorTable [3] = 0x00808000;
|
|
props.ColorTable [4] = 0x00000080;
|
|
props.ColorTable [5] = 0x00800080;
|
|
props.ColorTable [6] = 0x00008080;
|
|
props.ColorTable [7] = 0x00c0c0c0;
|
|
props.ColorTable [8] = 0x00808080;
|
|
props.ColorTable [9] = 0x00ff0000;
|
|
props.ColorTable [10] = 0x0000ff00;
|
|
props.ColorTable [11] = 0x00ffff00;
|
|
props.ColorTable [12] = 0x000000ff;
|
|
props.ColorTable [13] = 0x00ff00ff;
|
|
props.ColorTable [14] = 0x0000ffff;
|
|
props.ColorTable [15] = 0x00ffffff;
|
|
} else {
|
|
props.wFillAttribute = oldProps->wFillAttribute;
|
|
props.wPopupFillAttribute = oldProps->wPopupFillAttribute;
|
|
props.dwWindowOrigin.X = oldProps->dwWindowOrigin.X;
|
|
props.dwWindowOrigin.Y = oldProps->dwWindowOrigin.Y;
|
|
props.nFont = oldProps->nFont;
|
|
props.nInputBufferSize = oldProps->nInputBufferSize;
|
|
props.uCursorSize = oldProps->uCursorSize;
|
|
props.bInsertMode = oldProps->bInsertMode;
|
|
props.bAutoPosition = oldProps->bAutoPosition;
|
|
props.uHistoryBufferSize = oldProps->uHistoryBufferSize;
|
|
props.uNumberOfHistoryBuffers = oldProps->uNumberOfHistoryBuffers;
|
|
props.bHistoryNoDup = oldProps->bHistoryNoDup;
|
|
props.ColorTable [0] = oldProps->ColorTable [0];
|
|
props.ColorTable [1] = oldProps->ColorTable [1];
|
|
props.ColorTable [2] = oldProps->ColorTable [2];
|
|
props.ColorTable [3] = oldProps->ColorTable [3];
|
|
props.ColorTable [4] = oldProps->ColorTable [4];
|
|
props.ColorTable [5] = oldProps->ColorTable [5];
|
|
props.ColorTable [6] = oldProps->ColorTable [6];
|
|
props.ColorTable [7] = oldProps->ColorTable [7];
|
|
props.ColorTable [8] = oldProps->ColorTable [8];
|
|
props.ColorTable [9] = oldProps->ColorTable [9];
|
|
props.ColorTable [10] = oldProps->ColorTable [10];
|
|
props.ColorTable [11] = oldProps->ColorTable [11];
|
|
props.ColorTable [12] = oldProps->ColorTable [12];
|
|
props.ColorTable [13] = oldProps->ColorTable [13];
|
|
props.ColorTable [14] = oldProps->ColorTable [14];
|
|
props.ColorTable [15] = oldProps->ColorTable [15];
|
|
psldl->lpVtbl->RemoveDataBlock (psldl, NT_CONSOLE_PROPS_SIG);
|
|
}
|
|
|
|
props.dwScreenBufferSize.X = (SHORT)ExtraData->xSize;
|
|
props.dwScreenBufferSize.Y = (SHORT)ExtraData->ySize;
|
|
props.dwWindowSize.X = (SHORT)ExtraData->xSize;
|
|
props.dwWindowSize.Y = (SHORT)ExtraData->ySize;
|
|
props.dwFontSize.X = (UINT)ExtraData->xFontSize;
|
|
props.dwFontSize.Y = (UINT)ExtraData->yFontSize;
|
|
props.uFontFamily = ExtraData->FontFamily;
|
|
props.uFontWeight = ExtraData->FontWeight;
|
|
faceNameW = ConvertAtoW (ExtraData->FontName);
|
|
StringCopyW (props.FaceName, faceNameW);
|
|
FreeConvertedStr (faceNameW);
|
|
props.bFullScreen = ExtraData->FullScreen;
|
|
props.bQuickEdit = ExtraData->QuickEdit;
|
|
comResult = psldl->lpVtbl->AddDataBlock (psldl, &props);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGA ((DBG_WARNING, "LINKEDIT: AddDataBlock failed for %s", FileName));
|
|
}
|
|
}
|
|
|
|
comResult = PersistFile->lpVtbl->Save (PersistFile, fileNameW, FALSE);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGA ((DBG_WARNING, "LINKEDIT: Save failed for %s", FileName));
|
|
}
|
|
|
|
comResult = PersistFile->lpVtbl->SaveCompleted (PersistFile, fileNameW);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGA ((DBG_WARNING, "LINKEDIT: SaveCompleted failed for %s", FileName));
|
|
}
|
|
|
|
FreeConvertedStr (fileNameW);
|
|
fileNameW = NULL;
|
|
}
|
|
__finally {
|
|
if (fileNameW) {
|
|
FreeConvertedStr (fileNameW);
|
|
fileNameW = NULL;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ModifyShellLinkFileW (
|
|
IN PCWSTR FileName,
|
|
IN PCWSTR Target, OPTIONAL
|
|
IN PCWSTR Params, OPTIONAL
|
|
IN PCWSTR WorkDir, OPTIONAL
|
|
IN PCWSTR IconPath, OPTIONAL
|
|
IN INT IconNumber,
|
|
IN WORD HotKey,
|
|
IN PLNK_EXTRA_DATAW ExtraData, OPTIONAL
|
|
IN IShellLinkW *ShellLink,
|
|
IN IPersistFile *PersistFile
|
|
)
|
|
{
|
|
HRESULT comResult;
|
|
|
|
__try {
|
|
if (!DoesFileExistW (FileName)) {
|
|
__leave;
|
|
}
|
|
if (((Target == NULL) || (Target [0] == 0)) &&
|
|
((Params == NULL) || (Params [0] == 0)) &&
|
|
((WorkDir == NULL) || (WorkDir [0] == 0)) &&
|
|
((IconPath == NULL) || (IconPath [0] == 0)) &&
|
|
(HotKey == 0) &&
|
|
(ExtraData == NULL)
|
|
) {
|
|
__leave;
|
|
}
|
|
|
|
comResult = PersistFile->lpVtbl->Load(PersistFile, FileName, STGM_READ);
|
|
if (comResult != S_OK) {
|
|
LOGW ((LOG_ERROR, "LINKEDIT: Load failed for %s", FileName));
|
|
__leave;
|
|
}
|
|
|
|
if (Target != NULL) {
|
|
comResult = ShellLink->lpVtbl->SetPath (ShellLink, Target);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SetPath failed for %s", FileName));
|
|
}
|
|
}
|
|
if (Params != NULL) {
|
|
comResult = ShellLink->lpVtbl->SetArguments (ShellLink, Params);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SetArguments failed for %s", FileName));
|
|
}
|
|
}
|
|
if (WorkDir != NULL) {
|
|
comResult = ShellLink->lpVtbl->SetWorkingDirectory (ShellLink, WorkDir);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SetWorkingDirectory failed for %s", FileName));
|
|
}
|
|
}
|
|
if (IconPath != NULL) {
|
|
comResult = ShellLink->lpVtbl->SetIconLocation (ShellLink, IconPath, IconNumber);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SetIconLocation failed for %s", FileName));
|
|
}
|
|
}
|
|
// NTRAID#NTBUG9-153303-2000/08/01-jimschm Add HotKey processing here
|
|
|
|
//
|
|
// add NT_CONSOLE_PROPS
|
|
//
|
|
if (ExtraData) {
|
|
|
|
HRESULT hres;
|
|
NT_CONSOLE_PROPS props;
|
|
NT_CONSOLE_PROPS *oldProps;
|
|
|
|
IShellLinkDataList *psldl;
|
|
//
|
|
// Get a pointer to the IShellLinkDataList interface.
|
|
//
|
|
hres = ShellLink->lpVtbl->QueryInterface (ShellLink, &IID_IShellLinkDataList, &psldl);
|
|
|
|
if (!SUCCEEDED (hres)) {
|
|
DEBUGMSGW ((DBG_WARNING, "Cannot get IShellLinkDataList interface"));
|
|
__leave;
|
|
}
|
|
|
|
ZeroMemory (&props, sizeof (NT_CONSOLE_PROPS));
|
|
props.cbSize = sizeof (NT_CONSOLE_PROPS);
|
|
props.dwSignature = NT_CONSOLE_PROPS_SIG;
|
|
|
|
//
|
|
// let's try to get the extra data
|
|
//
|
|
comResult = psldl->lpVtbl->CopyDataBlock (psldl, NT_CONSOLE_PROPS_SIG, &oldProps);
|
|
if ((comResult != S_OK) || (oldProps->cbSize != props.cbSize)) {
|
|
// no extra data exists. We need to fill some good data for this console
|
|
props.wFillAttribute = 0x0007;
|
|
props.wPopupFillAttribute = 0x00f5;
|
|
props.dwWindowOrigin.X = 0;
|
|
props.dwWindowOrigin.Y = 0;
|
|
props.nFont = 0;
|
|
props.nInputBufferSize = 0;
|
|
props.uCursorSize = 0x0019;
|
|
props.bInsertMode = FALSE;
|
|
props.bAutoPosition = TRUE;
|
|
props.uHistoryBufferSize = 0x0032;
|
|
props.uNumberOfHistoryBuffers = 0x0004;
|
|
props.bHistoryNoDup = FALSE;
|
|
props.ColorTable [0] = 0x00000000;
|
|
props.ColorTable [1] = 0x00800000;
|
|
props.ColorTable [2] = 0x00008000;
|
|
props.ColorTable [3] = 0x00808000;
|
|
props.ColorTable [4] = 0x00000080;
|
|
props.ColorTable [5] = 0x00800080;
|
|
props.ColorTable [6] = 0x00008080;
|
|
props.ColorTable [7] = 0x00c0c0c0;
|
|
props.ColorTable [8] = 0x00808080;
|
|
props.ColorTable [9] = 0x00ff0000;
|
|
props.ColorTable [10] = 0x0000ff00;
|
|
props.ColorTable [11] = 0x00ffff00;
|
|
props.ColorTable [12] = 0x000000ff;
|
|
props.ColorTable [13] = 0x00ff00ff;
|
|
props.ColorTable [14] = 0x0000ffff;
|
|
props.ColorTable [15] = 0x00ffffff;
|
|
} else {
|
|
props.wFillAttribute = oldProps->wFillAttribute;
|
|
props.wPopupFillAttribute = oldProps->wPopupFillAttribute;
|
|
props.dwWindowOrigin.X = oldProps->dwWindowOrigin.X;
|
|
props.dwWindowOrigin.Y = oldProps->dwWindowOrigin.Y;
|
|
props.nFont = oldProps->nFont;
|
|
props.nInputBufferSize = oldProps->nInputBufferSize;
|
|
props.uCursorSize = oldProps->uCursorSize;
|
|
props.bInsertMode = oldProps->bInsertMode;
|
|
props.bAutoPosition = oldProps->bAutoPosition;
|
|
props.uHistoryBufferSize = oldProps->uHistoryBufferSize;
|
|
props.uNumberOfHistoryBuffers = oldProps->uNumberOfHistoryBuffers;
|
|
props.bHistoryNoDup = oldProps->bHistoryNoDup;
|
|
props.ColorTable [0] = oldProps->ColorTable [0];
|
|
props.ColorTable [1] = oldProps->ColorTable [1];
|
|
props.ColorTable [2] = oldProps->ColorTable [2];
|
|
props.ColorTable [3] = oldProps->ColorTable [3];
|
|
props.ColorTable [4] = oldProps->ColorTable [4];
|
|
props.ColorTable [5] = oldProps->ColorTable [5];
|
|
props.ColorTable [6] = oldProps->ColorTable [6];
|
|
props.ColorTable [7] = oldProps->ColorTable [7];
|
|
props.ColorTable [8] = oldProps->ColorTable [8];
|
|
props.ColorTable [9] = oldProps->ColorTable [9];
|
|
props.ColorTable [10] = oldProps->ColorTable [10];
|
|
props.ColorTable [11] = oldProps->ColorTable [11];
|
|
props.ColorTable [12] = oldProps->ColorTable [12];
|
|
props.ColorTable [13] = oldProps->ColorTable [13];
|
|
props.ColorTable [14] = oldProps->ColorTable [14];
|
|
props.ColorTable [15] = oldProps->ColorTable [15];
|
|
psldl->lpVtbl->RemoveDataBlock (psldl, NT_CONSOLE_PROPS_SIG);
|
|
}
|
|
|
|
props.dwScreenBufferSize.X = (SHORT)ExtraData->xSize;
|
|
props.dwScreenBufferSize.Y = (SHORT)ExtraData->ySize;
|
|
props.dwWindowSize.X = (SHORT)ExtraData->xSize;
|
|
props.dwWindowSize.Y = (SHORT)ExtraData->ySize;
|
|
props.dwFontSize.X = (UINT)ExtraData->xFontSize;
|
|
props.dwFontSize.Y = (UINT)ExtraData->yFontSize;
|
|
props.uFontFamily = ExtraData->FontFamily;
|
|
props.uFontWeight = ExtraData->FontWeight;
|
|
StringCopyW (props.FaceName, ExtraData->FontName);
|
|
props.bFullScreen = ExtraData->FullScreen;
|
|
props.bQuickEdit = ExtraData->QuickEdit;
|
|
comResult = psldl->lpVtbl->AddDataBlock (psldl, &props);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGW ((DBG_WARNING, "LINKEDIT: AddDataBlock failed for %s", FileName));
|
|
}
|
|
}
|
|
|
|
comResult = PersistFile->lpVtbl->Save (PersistFile, FileName, FALSE);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGW ((DBG_WARNING, "LINKEDIT: Save failed for %s", FileName));
|
|
}
|
|
|
|
comResult = PersistFile->lpVtbl->SaveCompleted (PersistFile, FileName);
|
|
if (comResult != S_OK) {
|
|
DEBUGMSGW ((DBG_WARNING, "LINKEDIT: SaveCompleted failed for %s", FileName));
|
|
}
|
|
}
|
|
__finally {
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ModifyPifFileA (
|
|
IN PCSTR FileName,
|
|
IN PCSTR Target, OPTIONAL
|
|
IN PCSTR Params, OPTIONAL
|
|
IN PCSTR WorkDir, OPTIONAL
|
|
IN PCSTR IconPath, OPTIONAL
|
|
IN INT IconNumber
|
|
)
|
|
{
|
|
PCSTR fileImage = NULL;
|
|
HANDLE mapHandle = NULL;
|
|
HANDLE fileHandle = INVALID_HANDLE_VALUE;
|
|
PSTDPIF stdPif;
|
|
PWENHPIF40 wenhPif40;
|
|
PW386PIF30 w386ext30;
|
|
|
|
__try {
|
|
fileImage = MapFileIntoMemoryExA (FileName, &fileHandle, &mapHandle, TRUE);
|
|
if (fileImage == NULL) {
|
|
__leave;
|
|
}
|
|
__try {
|
|
stdPif = (PSTDPIF) fileImage;
|
|
if (Target != NULL) {
|
|
strncpy (stdPif->startfile, Target, PIFSTARTLOCSIZE);
|
|
}
|
|
|
|
if (Params != NULL) {
|
|
strncpy (stdPif->params, Params, PIFPARAMSSIZE);
|
|
}
|
|
|
|
if (WorkDir != NULL) {
|
|
strncpy (stdPif->defpath, WorkDir, PIFDEFPATHSIZE);
|
|
}
|
|
|
|
if (IconPath != NULL) {
|
|
wenhPif40 = (PWENHPIF40) pFindEnhPifSignature ((PVOID)fileImage, WENHHDRSIG40);
|
|
|
|
if (wenhPif40 != NULL) {
|
|
strncpy (wenhPif40->achIconFileProp, IconPath, PIFDEFFILESIZE);
|
|
wenhPif40->wIconIndexProp = (WORD)IconNumber;
|
|
}
|
|
}
|
|
// in all cases we want to take off MSDOS mode otherwise NT won't start these PIFs
|
|
w386ext30 = pFindEnhPifSignature ((PVOID)fileImage, W386HDRSIG30);
|
|
if (w386ext30) {
|
|
w386ext30->PfW386Flags = w386ext30->PfW386Flags & (~fRealMode);
|
|
w386ext30->PfW386Flags = w386ext30->PfW386Flags & (~fRealModeSilent);
|
|
}
|
|
}
|
|
__except (1) {
|
|
// something went wrong when we tried to read or write PIF file,
|
|
// let's just do nothing and exit from here
|
|
|
|
DEBUGMSGW ((DBG_WARNING, "Exception thrown when processing %s", FileName));
|
|
}
|
|
}
|
|
__finally {
|
|
UnmapFile ((PVOID) fileImage, mapHandle, fileHandle);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ModifyPifFileW (
|
|
IN PCWSTR FileName,
|
|
IN PCWSTR Target, OPTIONAL
|
|
IN PCWSTR Params, OPTIONAL
|
|
IN PCWSTR WorkDir, OPTIONAL
|
|
IN PCWSTR IconPath, OPTIONAL
|
|
IN INT IconNumber
|
|
)
|
|
{
|
|
PCSTR fileImage = NULL;
|
|
HANDLE mapHandle = NULL;
|
|
HANDLE fileHandle = INVALID_HANDLE_VALUE;
|
|
PCSTR AnsiStr = NULL;
|
|
PSTDPIF stdPif;
|
|
PWENHPIF40 wenhPif40;
|
|
PW386PIF30 w386ext30;
|
|
|
|
__try {
|
|
fileImage = MapFileIntoMemoryExW (FileName, &fileHandle, &mapHandle, TRUE);
|
|
if (fileImage == NULL) {
|
|
__leave;
|
|
}
|
|
__try {
|
|
stdPif = (PSTDPIF) fileImage;
|
|
if (Target != NULL) {
|
|
|
|
AnsiStr = ConvertWtoA (Target);
|
|
strncpy (stdPif->startfile, AnsiStr, PIFSTARTLOCSIZE);
|
|
FreeConvertedStr (AnsiStr);
|
|
}
|
|
|
|
if (Params != NULL) {
|
|
|
|
AnsiStr = ConvertWtoA (Params);
|
|
strncpy (stdPif->params, AnsiStr, PIFPARAMSSIZE);
|
|
FreeConvertedStr (AnsiStr);
|
|
}
|
|
|
|
if (WorkDir != NULL) {
|
|
|
|
AnsiStr = ConvertWtoA (WorkDir);
|
|
strncpy (stdPif->defpath, AnsiStr, PIFDEFPATHSIZE);
|
|
FreeConvertedStr (AnsiStr);
|
|
}
|
|
|
|
if (IconPath != NULL) {
|
|
wenhPif40 = (PWENHPIF40) pFindEnhPifSignature ((PVOID)fileImage, WENHHDRSIG40);
|
|
|
|
if (wenhPif40 != NULL) {
|
|
|
|
AnsiStr = ConvertWtoA (IconPath);
|
|
strncpy (wenhPif40->achIconFileProp, AnsiStr, PIFDEFFILESIZE);
|
|
FreeConvertedStr (AnsiStr);
|
|
|
|
wenhPif40->wIconIndexProp = (WORD)IconNumber;
|
|
}
|
|
}
|
|
// in all cases we want to take off MSDOS mode otherwise NT won't start these PIFs
|
|
w386ext30 = pFindEnhPifSignature ((PVOID)fileImage, W386HDRSIG30);
|
|
if (w386ext30) {
|
|
w386ext30->PfW386Flags = w386ext30->PfW386Flags & (~fRealMode);
|
|
w386ext30->PfW386Flags = w386ext30->PfW386Flags & (~fRealModeSilent);
|
|
}
|
|
}
|
|
__except (1) {
|
|
// something went wrong when we tried to read or write PIF file,
|
|
// let's just do nothing and exit from here
|
|
|
|
DEBUGMSGW ((DBG_WARNING, "Exception thrown when processing %s", FileName));
|
|
}
|
|
}
|
|
__finally {
|
|
UnmapFile ((PVOID) fileImage, mapHandle, fileHandle);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ModifyUrlFileA (
|
|
IN PCSTR FileName,
|
|
IN PCSTR Target, OPTIONAL
|
|
IN PCSTR IconPath, OPTIONAL
|
|
IN INT IconNumber
|
|
)
|
|
{
|
|
CHAR buffer [12];
|
|
|
|
if (Target != NULL) {
|
|
WritePrivateProfileStringA ("InternetShortcut", "URL", Target, FileName);
|
|
}
|
|
if (IconPath != NULL) {
|
|
WritePrivateProfileStringA ("InternetShortcut", "IconFile", IconPath, FileName);
|
|
wsprintfA (buffer, "%d", IconNumber);
|
|
WritePrivateProfileStringA ("InternetShortcut", "IconIndex", buffer, FileName);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ModifyUrlFileW (
|
|
IN PCWSTR FileName,
|
|
IN PCWSTR Target, OPTIONAL
|
|
IN PCWSTR IconPath, OPTIONAL
|
|
IN INT IconNumber
|
|
)
|
|
{
|
|
WCHAR buffer [12];
|
|
|
|
if (Target != NULL) {
|
|
WritePrivateProfileStringW (L"InternetShortcut", L"URL", Target, FileName);
|
|
}
|
|
if (IconPath != NULL) {
|
|
WritePrivateProfileStringW (L"InternetShortcut", L"IconFile", IconPath, FileName);
|
|
wsprintfW (buffer, L"%d", IconNumber);
|
|
WritePrivateProfileStringW (L"InternetShortcut", L"IconIndex", buffer, FileName);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ModifyShortcutFileExA (
|
|
IN PCSTR FileName,
|
|
IN PCSTR ForcedExtension, OPTIONAL
|
|
IN PCSTR Target, OPTIONAL
|
|
IN PCSTR Params, OPTIONAL
|
|
IN PCSTR WorkDir, OPTIONAL
|
|
IN PCSTR IconPath, OPTIONAL
|
|
IN INT IconNumber,
|
|
IN WORD HotKey,
|
|
IN PLNK_EXTRA_DATAA ExtraData, OPTIONAL
|
|
IN IShellLinkA *ShellLink,
|
|
IN IPersistFile *PersistFile
|
|
)
|
|
{
|
|
PCSTR shortcutExt;
|
|
|
|
__try {
|
|
shortcutExt = ForcedExtension;
|
|
if (!shortcutExt) {
|
|
shortcutExt = GetFileExtensionFromPathA (FileName);
|
|
}
|
|
if (shortcutExt) {
|
|
if (StringIMatchA (shortcutExt, "LNK")) {
|
|
return ModifyShellLinkFileA (
|
|
FileName,
|
|
Target,
|
|
Params,
|
|
WorkDir,
|
|
IconPath,
|
|
IconNumber,
|
|
HotKey,
|
|
NULL,
|
|
ShellLink,
|
|
PersistFile
|
|
);
|
|
|
|
} else if (StringIMatchA (shortcutExt, "PIF")) {
|
|
return ModifyPifFileA (
|
|
FileName,
|
|
Target,
|
|
Params,
|
|
WorkDir,
|
|
IconPath,
|
|
IconNumber
|
|
);
|
|
} else if (StringIMatchA (shortcutExt, "URL")) {
|
|
return ModifyUrlFileA (
|
|
FileName,
|
|
Target,
|
|
IconPath,
|
|
IconNumber
|
|
);
|
|
}
|
|
}
|
|
}
|
|
__except (1) {
|
|
LOGA ((LOG_ERROR, "Cannot process shortcut %s", FileName));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ModifyShortcutFileExW (
|
|
IN PCWSTR FileName,
|
|
IN PCWSTR ForcedExtension, OPTIONAL
|
|
IN PCWSTR Target, OPTIONAL
|
|
IN PCWSTR Params, OPTIONAL
|
|
IN PCWSTR WorkDir, OPTIONAL
|
|
IN PCWSTR IconPath, OPTIONAL
|
|
IN INT IconNumber,
|
|
IN WORD HotKey,
|
|
IN PLNK_EXTRA_DATAW ExtraData, OPTIONAL
|
|
IN IShellLinkW *ShellLink,
|
|
IN IPersistFile *PersistFile
|
|
)
|
|
{
|
|
PCWSTR shortcutExt;
|
|
|
|
__try {
|
|
shortcutExt = ForcedExtension;
|
|
if (!shortcutExt) {
|
|
shortcutExt = GetFileExtensionFromPathW (FileName);
|
|
}
|
|
if (shortcutExt) {
|
|
if (StringIMatchW (shortcutExt, L"LNK")) {
|
|
return ModifyShellLinkFileW (
|
|
FileName,
|
|
Target,
|
|
Params,
|
|
WorkDir,
|
|
IconPath,
|
|
IconNumber,
|
|
HotKey,
|
|
NULL,
|
|
ShellLink,
|
|
PersistFile
|
|
);
|
|
|
|
} else if (StringIMatchW (shortcutExt, L"PIF")) {
|
|
return ModifyPifFileW (
|
|
FileName,
|
|
Target,
|
|
Params,
|
|
WorkDir,
|
|
IconPath,
|
|
IconNumber
|
|
);
|
|
} else if (StringIMatchW (shortcutExt, L"URL")) {
|
|
return ModifyUrlFileW (
|
|
FileName,
|
|
Target,
|
|
IconPath,
|
|
IconNumber
|
|
);
|
|
}
|
|
}
|
|
}
|
|
__except (1) {
|
|
LOGW ((LOG_ERROR, "Cannot process shortcut %s", FileName));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|