Created
October 18, 2024 08:33
-
-
Save Buggem/c40758856c3b947d7789c0c9cefb26f2 to your computer and use it in GitHub Desktop.
English version of Mamachine's mslink.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
############################################################################################# | |
# mslink.sh v1.0 | |
############################################################################################# | |
# This script allows you to create a Windows Shortcut (.LNK File) | |
# Script created based on the doc | |
# http://msdn.microsoft.com/en-us/library/dd871305.aspx | |
############################################################################################# | |
OPTIONS=$(getopt -q -n ${0} -o hl:o:p -l help,lnk-target:,output-file:,printer-link -- "$@") | |
eval set -- ${OPTIONS} | |
IS_PRINTER_LNK=0 | |
while true; do | |
case "$1" in | |
-h|--help) HELP=1 ;; | |
-l|--lnk-target) LNK_TARGET="$2" ; shift ;; | |
-o|--output-file) OUTPUT_FILE="$2" ; shift ;; | |
-p|--printer-link) IS_PRINTER_LNK=1 ;; | |
--) shift ; break ;; | |
*) echo "Unknown option: $1" ; exit 1 ;; | |
esac | |
shift | |
done | |
if [ $# -ne 0 ]; then | |
echo "Unknown options: $@" | |
exit 1 | |
fi | |
[ ${#LNK_TARGET} -eq 0 ] || [ ${#OUTPUT_FILE} -eq 0 ] && echo " | |
Usage: | |
${0} -l target_of_lnk_file -o my_file.lnk [-p] | |
Options: | |
-l, --lnk-target Specifies the target of the shortcut | |
-o, --output-file The file which to save the shortcut | |
-p, --printer-link Generates a network printer shortcut | |
" && exit 1 | |
############################################################################################# | |
# Functions | |
############################################################################################# | |
function ascii2hex() { | |
echo $(echo -n ${1} | hexdump -v -e '/1 " x%02x"'|sed s/\ /\\\\/g) | |
} | |
function gen_IDLIST() { | |
ITEM_SIZE=$(printf '%04x' $((${#1}/4+2))) | |
echo '\x'${ITEM_SIZE:2:2}'\x'${ITEM_SIZE:0:2}${1} | |
} | |
function convert_CLSID_to_DATA() { | |
echo -n ${1:6:2}${1:4:2}${1:2:2}${1:0:2}${1:11:2}${1:9:2}${1:16:2}${1:14:2}${1:19:4}${1:24:12}|sed s/"\([A-Fa-f0-9][A-Fa-f0-9]\)"/\\\\x\\1/g | |
} | |
############################################################################################# | |
# Variables from the official Microsoft documentation | |
############################################################################################# | |
HeaderSize='\x4c\x00\x00\x00' # HeaderSize | |
LinkCLSID=$(convert_CLSID_to_DATA "00021401-0000-0000-c000-000000000046") # LinkCLSID | |
LinkFlags='\x01\x01\x00\x00' # HasLinkTargetIDList ForceNoLinkInfo | |
FileAttributes_Directory='\x10\x00\x00\x00' # FILE_ATTRIBUTE_DIRECTORY | |
FileAttributes_File='\x20\x00\x00\x00' # FILE_ATTRIBUTE_ARCHIVE | |
CreationTime='\x00\x00\x00\x00\x00\x00\x00\x00' | |
AccessTime='\x00\x00\x00\x00\x00\x00\x00\x00' | |
WriteTime='\x00\x00\x00\x00\x00\x00\x00\x00' | |
FileSize='\x00\x00\x00\x00' | |
IconIndex='\x00\x00\x00\x00' | |
ShowCommand='\x01\x00\x00\x00' # SW_SHOWNORMAL | |
Hotkey='\x00\x00' # No Hotkey | |
Reserved='\x00\x00' # Unchangeable value | |
Reserved2='\x00\x00\x00\x00' # Unchangeable value | |
Reserved3='\x00\x00\x00\x00' # Unchangeable value | |
TerminalID='\x00\x00' # Unchangeable value | |
CLSID_Computer="20d04fe0-3aea-1069-a2d8-08002b30309d" # Workstation CLSID | |
CLSID_Network="208d2c60-3aea-1069-a2d7-08002b30309d" # Network CLSID | |
############################################################################################# | |
# Constants found from .lnk file analysis | |
############################################################################################# | |
PREFIX_LOCAL_ROOT='\x2f' # Local Disk | |
PREFIX_FOLDER='\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' # Folder | |
PREFIX_FILE='\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' # File | |
PREFIX_NETWORK_ROOT='\xc3\x01\x81' # Network fileserver root | |
PREFIX_NETWORK_PRINTER='\xc3\x02\xc1' # Network printer root | |
END_OF_STRING='\x00' | |
############################################################################################# | |
# We remove the final backslash if there is one | |
LNK_TARGET=${LNK_TARGET%\\} | |
# We separate the root path of the link from the final target | |
# We also distinguish whether the link is local or network | |
# We define the Item_Data value depending on the case of a network or local link | |
IS_ROOT_LNK=0 | |
IS_NETWORK_LNK=0 | |
if [[ ${LNK_TARGET} == \\\\* ]]; then | |
IS_NETWORK_LNK=1 | |
PREFIX_ROOT=${PREFIX_NETWORK_ROOT} | |
Item_Data='\x1f\x58'$(convert_CLSID_to_DATA ${CLSID_Network}) | |
TARGET_ROOT=${LNK_TARGET%\\*} | |
if [[ ${LNK_TARGET} == \\\\*\\* ]]; then | |
TARGET_LEAF=${LNK_TARGET##*\\} | |
fi | |
if [ ${TARGET_ROOT} == \\ ]; then | |
TARGET_ROOT=${LNK_TARGET} | |
fi | |
else | |
PREFIX_ROOT=${PREFIX_LOCAL_ROOT} | |
Item_Data='\x1f\x50'$(convert_CLSID_to_DATA ${CLSID_Computer}) | |
TARGET_ROOT=${LNK_TARGET%%\\*} | |
if [[ ${LNK_TARGET} == *\\* ]]; then | |
TARGET_LEAF=${LNK_TARGET#*\\} | |
fi | |
[[ ! ${TARGET_ROOT} == *\\ ]] && TARGET_ROOT=${TARGET_ROOT}'\' | |
fi | |
if [ ${IS_PRINTER_LNK} -eq 1 ]; then | |
PREFIX_ROOT=${PREFIX_NETWORK_PRINTER} | |
TARGET_ROOT=${LNK_TARGET} | |
IS_ROOT_LNK=1 | |
fi | |
[ ${#TARGET_LEAF} -eq 0 ] && IS_ROOT_LNK=1 | |
############################################################################################# | |
# Select the prefix that will be used to display the shortcut icon | |
if [[ ${TARGET_LEAF} == *.??? ]]; then | |
PREFIX_OF_TARGET=${PREFIX_FILE} | |
TYPE_TARGET="file" | |
FileAttributes=${FileAttributes_File} | |
else | |
PREFIX_OF_TARGET=${PREFIX_FOLDER} | |
TYPE_TARGET="folder" | |
FileAttributes=${FileAttributes_Directory} | |
fi | |
# Convert the target values into binary | |
TARGET_ROOT=$(ascii2hex ${TARGET_ROOT}) | |
TARGET_ROOT=${TARGET_ROOT}$(for i in `seq 1 21`;do echo -n '\x00';done) # Nécessaire à partir de Vista et supérieur sinon le lien est considéré comme vide (je n'ai trouvé nul part d'informations à ce sujet) | |
TARGET_LEAF=$(ascii2hex ${TARGET_LEAF}) | |
# Create the IDLIST which represents the core of the .lnk file | |
if [ ${IS_ROOT_LNK} -eq 1 ];then | |
IDLIST_ITEMS=$(gen_IDLIST ${Item_Data})$(gen_IDLIST ${PREFIX_ROOT}${TARGET_ROOT}${END_OF_STRING}) | |
else | |
IDLIST_ITEMS=$(gen_IDLIST ${Item_Data})$(gen_IDLIST ${PREFIX_ROOT}${TARGET_ROOT}${END_OF_STRING})$(gen_IDLIST ${PREFIX_OF_TARGET}${TARGET_LEAF}${END_OF_STRING}) | |
fi | |
IDLIST=$(gen_IDLIST ${IDLIST_ITEMS}) | |
############################################################################################# | |
if [ ${IS_NETWORK_LNK} -eq 1 ]; then | |
TYPE_LNK="network" | |
if [ ${IS_PRINTER_LNK} -eq 1 ]; then | |
TYPE_TARGET="printer" | |
fi | |
else | |
TYPE_LNK="local" | |
fi | |
echo "Creating a shortcut of type \""${TYPE_TARGET}" "${TYPE_LNK}"\" with target "${LNK_TARGET} 1>&2 | |
echo -ne ${HeaderSize}${LinkCLSID}${LinkFlags}${FileAttributes}${CreationTime}${AccessTime}${WriteTime}${FileSize}${IconIndex}${ShowCommand}${Hotkey}${Reserved}${Reserved2}${Reserved3}${IDLIST}${TerminalID} > "${OUTPUT_FILE}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment