Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1950 lines
60 KiB

/*++
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;
}