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