windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/w95upgnt/migmain/shllink.c
2020-09-26 16:20:57 +08:00

401 lines
12 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
shllink.c
Abstract:
Functions to modify shell links (LNKs) and PIFs.
Author:
Mike Condra (mikeco) (Date unknown)
Revision History:
calinn 23-Sep-1998 Substantial redesign
calinn 15-May-1998 added GetLnkTarget and GetPifTarget
--*/
#include "pch.h"
#include "migmainp.h"
#include <shlobjp.h>
#include <shlguidp.h>
#ifndef UNICODE
#error UNICODE required for shllink.c
#endif
//
// Static prototypes
//
BOOL
pModifyLnkFile (
IN PCTSTR ShortcutName,
IN PCTSTR ShortcutTarget,
IN PCTSTR ShortcutArgs,
IN PCTSTR ShortcutWorkDir,
IN PCTSTR ShortcutIconPath,
IN INT ShortcutIconNr,
IN PLNK_EXTRA_DATA ExtraData, OPTIONAL
IN BOOL ForceToShowNormal
)
{
PTSTR NewShortcutName;
PTSTR fileExt;
IShellLink *psl = NULL;
IPersistFile *ppf = NULL;
HRESULT comResult;
if (FAILED (CoInitialize (NULL))) {
return FALSE;
}
__try {
if (!DoesFileExist (ShortcutName)) {
__leave;
}
if (((ShortcutTarget == NULL) || (ShortcutTarget [0] == 0)) &&
((ShortcutWorkDir == NULL) || (ShortcutWorkDir [0] == 0)) &&
((ShortcutIconPath == NULL) || (ShortcutIconPath [0] == 0)) &&
(ShortcutIconNr == 0) &&
(ExtraData == NULL)
) {
__leave;
}
if (ExtraData) {
NewShortcutName = DuplicatePathString (ShortcutName, 0);
fileExt = (PTSTR)GetFileExtensionFromPath (NewShortcutName);
MYASSERT (fileExt);
//
// We know for sure that this had PIF as extension so this copy is safe
//
StringCopy (fileExt, TEXT("LNK"));
} else {
NewShortcutName = (PTSTR)ShortcutName;
}
comResult = CoCreateInstance (
&CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IShellLink,
(void **) &psl);
if (comResult != S_OK) {
LOG ((LOG_ERROR, "LINKEDIT: CoCreateInstance failed for %s", NewShortcutName));
__leave;
}
comResult = psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile, (void **) &ppf);
if (comResult != S_OK) {
LOG ((LOG_ERROR, "LINKEDIT: QueryInterface failed for %s", NewShortcutName));
__leave;
}
//
// We only load if the file was really a LNK
//
if (!ExtraData) {
comResult = ppf->lpVtbl->Load(ppf, NewShortcutName, STGM_READ);
if (comResult != S_OK) {
LOG ((LOG_ERROR, "LINKEDIT: Load failed for %s", NewShortcutName));
__leave;
}
}
if (ShortcutTarget != NULL) {
comResult = psl->lpVtbl->SetPath (psl, ShortcutTarget);
if (comResult != S_OK) {
DEBUGMSG ((DBG_WARNING, "LINKEDIT: SetPath failed for %s", NewShortcutName));
}
}
if (ShortcutArgs != NULL) {
comResult = psl->lpVtbl->SetArguments (psl, ShortcutArgs);
if (comResult != S_OK) {
DEBUGMSG ((DBG_WARNING, "LINKEDIT: SetArguments failed for %s", ShortcutArgs));
}
}
if (ShortcutWorkDir != NULL) {
comResult = psl->lpVtbl->SetWorkingDirectory (psl, ShortcutWorkDir);
if (comResult != S_OK) {
DEBUGMSG ((DBG_WARNING, "LINKEDIT: SetWorkingDirectory failed for %s", NewShortcutName));
}
}
if (ShortcutIconPath != NULL) {
comResult = psl->lpVtbl->SetIconLocation (psl, ShortcutIconPath, ShortcutIconNr);
if (comResult != S_OK) {
DEBUGMSG ((DBG_WARNING, "LINKEDIT: SetIconLocation failed for %s", NewShortcutName));
}
}
if (ForceToShowNormal) {
comResult = psl->lpVtbl->SetShowCmd (psl, SW_SHOWNORMAL);
if (comResult != S_OK) {
DEBUGMSG ((DBG_WARNING, "LINKEDIT: SetShowCmd failed for %s", NewShortcutName));
}
}
//
// add NT_CONSOLE_PROPS here
//
if (ExtraData) {
HRESULT hres;
NT_CONSOLE_PROPS props;
IShellLinkDataList *psldl;
//
// Get a pointer to the IShellLinkDataList interface.
//
hres = psl->lpVtbl->QueryInterface (psl, &IID_IShellLinkDataList, &psldl);
if (!SUCCEEDED (hres)) {
DEBUGMSG ((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;
//
// We know that no extra data exists in this LNK because we just created it.
// We need to fill some good data for this console
//
props.wFillAttribute = 0x0007;
props.wPopupFillAttribute = 0x00f5;
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.dwWindowOrigin.X = 0;
props.dwWindowOrigin.Y = 0;
props.nFont = 0;
props.nInputBufferSize = 0;
props.dwFontSize.X = (UINT)ExtraData->xFontSize;
props.dwFontSize.Y = (UINT)ExtraData->yFontSize;
props.uFontFamily = ExtraData->FontFamily;
props.uFontWeight = ExtraData->FontWeight;
StringCopy (props.FaceName, ExtraData->FontName);
props.uCursorSize = 0x0019;
props.bFullScreen = ExtraData->FullScreen;
props.bQuickEdit = ExtraData->QuickEdit;
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;
comResult = psldl->lpVtbl->AddDataBlock (psldl, &props);
if (comResult != S_OK) {
DEBUGMSG ((DBG_WARNING, "LINKEDIT: AddDataBlock failed for %s", NewShortcutName));
}
}
comResult = ppf->lpVtbl->Save (ppf, NewShortcutName, FALSE);
if (comResult != S_OK) {
DEBUGMSG ((DBG_WARNING, "LINKEDIT: Save failed for %s", NewShortcutName));
}
if (ExtraData) {
ForceOperationOnPath (ShortcutName, OPERATION_CLEANUP);
}
comResult = ppf->lpVtbl->SaveCompleted (ppf, NewShortcutName);
if (comResult != S_OK) {
DEBUGMSG ((DBG_WARNING, "LINKEDIT: SaveCompleted failed for %s", NewShortcutName));
}
}
__finally {
if (ppf != NULL) {
ppf->lpVtbl->Release (ppf);
ppf = NULL;
}
if (psl != NULL) {
psl->lpVtbl->Release (psl);
psl = NULL;
}
CoUninitialize ();
}
return TRUE;
}
BOOL
pModifyPifFile (
IN PCTSTR ShortcutName,
IN PCTSTR ShortcutTarget,
IN PCTSTR ShortcutArgs,
IN PCTSTR ShortcutWorkDir,
IN PCTSTR ShortcutIconPath,
IN INT ShortcutIconNr
)
{
PCSTR fileImage = NULL;
HANDLE mapHandle = NULL;
HANDLE fileHandle = INVALID_HANDLE_VALUE;
PCSTR AnsiStr = NULL;
PSTDPIF stdPif;
PWENHPIF40 wenhPif40;
PW386PIF30 w386ext30;
__try {
fileImage = MapFileIntoMemoryEx (ShortcutName, &fileHandle, &mapHandle, TRUE);
if (fileImage == NULL) {
__leave;
}
__try {
stdPif = (PSTDPIF) fileImage;
if (ShortcutTarget != NULL) {
AnsiStr = CreateDbcs (ShortcutTarget);
strncpy (stdPif->startfile, AnsiStr, PIFSTARTLOCSIZE);
DestroyDbcs (AnsiStr);
}
if (ShortcutArgs != NULL) {
AnsiStr = CreateDbcs (ShortcutArgs);
strncpy (stdPif->params, AnsiStr, PIFPARAMSSIZE);
DestroyDbcs (AnsiStr);
}
if (ShortcutWorkDir != NULL) {
AnsiStr = CreateDbcs (ShortcutWorkDir);
strncpy (stdPif->defpath, AnsiStr, PIFDEFPATHSIZE);
DestroyDbcs (AnsiStr);
}
if (ShortcutIconPath != NULL) {
wenhPif40 = (PWENHPIF40) FindEnhPifSignature ((PVOID)fileImage, WENHHDRSIG40);
if (wenhPif40 != NULL) {
AnsiStr = CreateDbcs (ShortcutIconPath);
strncpy (wenhPif40->achIconFileProp, AnsiStr, PIFDEFFILESIZE);
DestroyDbcs (AnsiStr);
wenhPif40->wIconIndexProp = (WORD)ShortcutIconNr;
}
}
// in all cases we want to take off MSDOS mode otherwise NT won't start these PIFs
w386ext30 = FindEnhPifSignature ((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
DEBUGMSG ((DBG_WARNING, "Exception thrown when processing %s", ShortcutName));
}
}
__finally {
UnmapFile ((PVOID) fileImage, mapHandle, fileHandle);
}
return TRUE;
}
BOOL
ModifyShellLink(
IN PCWSTR ShortcutName,
IN PCWSTR ShortcutTarget,
IN PCWSTR ShortcutArgs,
IN PCWSTR ShortcutWorkDir,
IN PCWSTR ShortcutIconPath,
IN INT ShortcutIconNr,
IN BOOL ConvertToLnk,
IN PLNK_EXTRA_DATA ExtraData, OPTIONAL
IN BOOL ForceToShowNormal
)
{
PCTSTR shortcutExt;
__try {
shortcutExt = GetFileExtensionFromPath (ShortcutName);
MYASSERT (shortcutExt);
if (StringIMatch (shortcutExt, TEXT("LNK"))) {
return pModifyLnkFile (
ShortcutName,
ShortcutTarget,
ShortcutArgs,
ShortcutWorkDir,
ShortcutIconPath,
ShortcutIconNr,
NULL,
ForceToShowNormal
);
} else if (StringIMatch (shortcutExt, TEXT("PIF"))) {
if (ConvertToLnk) {
MYASSERT (ExtraData);
return pModifyLnkFile (
ShortcutName,
ShortcutTarget,
ShortcutArgs,
ShortcutWorkDir,
ShortcutIconPath,
ShortcutIconNr,
ExtraData,
ForceToShowNormal
);
} else {
return pModifyPifFile (
ShortcutName,
ShortcutTarget,
ShortcutArgs,
ShortcutWorkDir,
ShortcutIconPath,
ShortcutIconNr
);
}
}
}
__except (1) {
LOG ((LOG_ERROR, "Cannot process shortcut %s", ShortcutName));
}
return TRUE;
}