|
|
/*++
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"
//
// 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) { _mbsncpy (logFont.lfFaceName, wenhPif40->fntProp.achTTFaceName, LF_FACESIZE); _mbsncpy (ExtraData->FontName, wenhPif40->fntProp.achTTFaceName, LF_FACESIZE); } else { _mbsncpy (logFont.lfFaceName, wenhPif40->fntProp.achRasterFaceName, LF_FACESIZE); _mbsncpy (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 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;
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; } }
//
// 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;
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; } }
//
// 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;
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 { 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;
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 { 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 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 ); } } } __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 ); } } } __except (1) { LOGW ((LOG_ERROR, "Cannot process shortcut %s", FileName)); }
return TRUE; }
|