diff --git a/boot/bootdata/CMakeLists.txt b/boot/bootdata/CMakeLists.txt index 8704c96d1e4..e0c3545df44 100644 --- a/boot/bootdata/CMakeLists.txt +++ b/boot/bootdata/CMakeLists.txt @@ -59,13 +59,26 @@ add_cd_file(FILE ${CMAKE_CURRENT_SOURCE_DIR}/livecd/unattend.inf DESTINATION rea # LiveImage shortcuts add_custom_target(livecd_links) -function(add_livecd_shortcut name app) - cmake_parse_arguments(_shortcut "" "" "DESTINATION" ${ARGN}) +function(add_livecd_shortcut name path) + cmake_parse_arguments(_shortcut "" "WORKDIR;CMDLINE_ARGS;ICON;ICON_INDEX" "DESTINATION" ${ARGN}) if(NOT _shortcut_DESTINATION) message(FATAL_ERROR "You must provide at least one destination") endif() - add_link(${name} livecd_start.cmd GUID "{450D8FBA-AD25-11D0-98A8-0800361B1103}" CMD_LINE_ARGS ${app} ICON ${app} MINIMIZE) + if(DEFINED _shortcut_WORKDIR) + set(_shortcut_WORKDIR WORKDIR "${_shortcut_WORKDIR}") + endif() + if(DEFINED _shortcut_CMDLINE_ARGS) + set(_shortcut_CMDLINE_ARGS CMDLINE_ARGS "${_shortcut_CMDLINE_ARGS}") + endif() + if(DEFINED _shortcut_ICON) + set(_shortcut_ICON ICON "${_shortcut_ICON}") + endif() + if(DEFINED _shortcut_ICON_INDEX) + set(_shortcut_ICON_INDEX ICON_INDEX ${_shortcut_ICON_INDEX}) + endif() + + add_link(${name} ${path} ${_shortcut_WORKDIR} ${_shortcut_CMDLINE_ARGS} ${_shortcut_ICON} ${_shortcut_ICON_INDEX}) # Only on CMake 3.20+: target_sources(livecd_links PRIVATE ...) set_property(TARGET livecd_links APPEND PROPERTY SOURCES "${CMAKE_CURRENT_BINARY_DIR}/${name}.lnk") @@ -80,7 +93,14 @@ endfunction() ## NOTE: What would be nice is to create this list using /media/inf/shortcuts.inf ## and taking their default english translation! -add_cd_file(FILE "${CMAKE_CURRENT_SOURCE_DIR}/livecd_start.cmd" DESTINATION "Profiles/Default User/My Documents" FOR livecd) +set(env_percent "%") +# Win32: Use pseudo-escapes '^%' to work-around variables expansion by CMD.EXE +if (CMAKE_HOST_WIN32) + set(env_percent "^%") +endif() +set(envvar_systemroot "${env_percent}SystemRoot${env_percent}") +set(envvar_homedrive "${env_percent}HOMEDRIVE${env_percent}") +set(envvar_homepath "${env_percent}HOMEPATH${env_percent}") set(dir_allusers_desktop "Profiles/All Users/Desktop") set(dir_startmenu_programs "Profiles/All Users/Start Menu/Programs") @@ -93,32 +113,94 @@ set(dir_startmenu_entertainment "${dir_startmenu_accessories}/Entertainment") set(dir_startmenu_systemtools "${dir_startmenu_accessories}/System Tools") set(dir_quicklaunch "Profiles/Default User/Application Data/Microsoft/Internet Explorer/Quick Launch") -add_livecd_shortcut("Read Me" readme.txt DESTINATION "${dir_allusers_desktop}") -add_livecd_shortcut("ReactOS Explorer" explorer.exe +add_livecd_shortcut("Read Me" + "shell:windows\\readme.txt" + ICON "${envvar_systemroot}\\system32\\shell32.dll" ICON_INDEX -152 + DESTINATION "${dir_allusers_desktop}") +add_livecd_shortcut("ReactOS Explorer" + "shell:windows\\explorer.exe" ICON_INDEX 1 + WORKDIR "${envvar_homedrive}${envvar_homepath}" DESTINATION "${dir_startmenu_programs}" "${dir_quicklaunch}") -add_livecd_shortcut("Command Prompt" cmd.exe +add_livecd_shortcut("Command Prompt" + "shell:system\\cmd.exe" ICON_INDEX 0 + WORKDIR "${envvar_homedrive}${envvar_homepath}" DESTINATION "${dir_allusers_desktop}" "${dir_startmenu_accessories}" "${dir_quicklaunch}") -add_livecd_shortcut("Device Manager" devmgmt.exe DESTINATION "${dir_startmenu_admintools}") -add_livecd_shortcut("Event Viewer" eventvwr.exe DESTINATION "${dir_startmenu_admintools}") -add_livecd_shortcut("Service Manager" servman.exe DESTINATION "${dir_startmenu_admintools}") -add_livecd_shortcut("System Configuration" msconfig.exe DESTINATION "${dir_startmenu_admintools}") -add_livecd_shortcut("Accessibility Utility Manager" utilman.exe DESTINATION "${dir_startmenu_accessibility}") -add_livecd_shortcut("Magnify" magnify.exe DESTINATION "${dir_startmenu_accessibility}") -add_livecd_shortcut("On-Screen Keyboard" osk.exe DESTINATION "${dir_startmenu_accessibility}") -add_livecd_shortcut("Remote Desktop Connection" mstsc.exe DESTINATION "${dir_startmenu_comms}") -add_livecd_shortcut("Multimedia Player" mplay32.exe DESTINATION "${dir_startmenu_entertainment}") -add_livecd_shortcut("Sound Recorder" sndrec32.exe DESTINATION "${dir_startmenu_entertainment}") -add_livecd_shortcut("Volume Control" sndvol32.exe DESTINATION "${dir_startmenu_entertainment}") -add_livecd_shortcut("Character Map" charmap.exe DESTINATION "${dir_startmenu_systemtools}") -add_livecd_shortcut("Clipboard Viewer" clipbrd.exe DESTINATION "${dir_startmenu_systemtools}") -add_livecd_shortcut("Keyboard Layout Switcher" kbswitch.exe DESTINATION "${dir_startmenu_systemtools}") -add_livecd_shortcut("ReactX Diagnostic" dxdiag.exe DESTINATION "${dir_startmenu_systemtools}") -add_livecd_shortcut("Registry Editor" regedit.exe DESTINATION "${dir_startmenu_systemtools}") -add_livecd_shortcut("Task Manager" taskmgr.exe DESTINATION "${dir_startmenu_systemtools}") -add_livecd_shortcut("Calculator" calc.exe DESTINATION "${dir_startmenu_accessories}") -add_livecd_shortcut("Paint" mspaint.exe DESTINATION "${dir_startmenu_accessories}") -add_livecd_shortcut("Notepad" notepad.exe DESTINATION "${dir_startmenu_accessories}") -add_livecd_shortcut("WordPad" wordpad.exe DESTINATION "${dir_startmenu_accessories}") -add_livecd_shortcut("Solitaire" sol.exe DESTINATION "${dir_startmenu_games}") -add_livecd_shortcut("Spider Solitaire" spider.exe DESTINATION "${dir_startmenu_games}") -add_livecd_shortcut("WineMine" winmine.exe DESTINATION "${dir_startmenu_games}") +add_livecd_shortcut("Device Manager" + "shell:system\\devmgmt.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_admintools}") +add_livecd_shortcut("Event Viewer" + "shell:system\\eventvwr.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_admintools}") +add_livecd_shortcut("Service Manager" + "shell:system\\servman.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_admintools}") +add_livecd_shortcut("System Configuration" + "shell:system\\msconfig.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_admintools}") +add_livecd_shortcut("Accessibility Utility Manager" + "shell:system\\utilman.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_accessibility}") +add_livecd_shortcut("Magnify" + "shell:system\\magnify.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_accessibility}") +add_livecd_shortcut("On-Screen Keyboard" + "shell:system\\osk.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_accessibility}") +add_livecd_shortcut("Remote Desktop Connection" + "shell:system\\mstsc.exe" ICON_INDEX 0 + WORKDIR "${envvar_homedrive}${envvar_homepath}" + DESTINATION "${dir_startmenu_comms}") +add_livecd_shortcut("Multimedia Player" + "shell:system\\mplay32.exe" ICON_INDEX 0 + WORKDIR "${envvar_homedrive}${envvar_homepath}" + DESTINATION "${dir_startmenu_entertainment}") +add_livecd_shortcut("Sound Recorder" + "shell:system\\sndrec32.exe" ICON_INDEX 0 + WORKDIR "${envvar_homedrive}${envvar_homepath}" + DESTINATION "${dir_startmenu_entertainment}") +add_livecd_shortcut("Volume Control" + "shell:system\\sndvol32.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_entertainment}") +add_livecd_shortcut("Character Map" + "shell:system\\charmap.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_systemtools}") +add_livecd_shortcut("Clipboard Viewer" + "shell:system\\clipbrd.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_systemtools}") +add_livecd_shortcut("Keyboard Layout Switcher" + "shell:system\\kbswitch.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_systemtools}") +add_livecd_shortcut("ReactX Diagnostic" + "shell:system\\dxdiag.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_systemtools}") +add_livecd_shortcut("Registry Editor" + "shell:windows\\regedit.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_systemtools}") +add_livecd_shortcut("Task Manager" + "shell:system\\taskmgr.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_systemtools}") +add_livecd_shortcut("Calculator" + "shell:system\\calc.exe" ICON_INDEX 0 + WORKDIR "${envvar_homedrive}${envvar_homepath}" + DESTINATION "${dir_startmenu_accessories}") +add_livecd_shortcut("Paint" + "shell:system\\mspaint.exe" ICON_INDEX 0 + WORKDIR "${envvar_homedrive}${envvar_homepath}" + DESTINATION "${dir_startmenu_accessories}") +add_livecd_shortcut("Notepad" + "shell:system\\notepad.exe" ICON_INDEX 0 + WORKDIR "${envvar_homedrive}${envvar_homepath}" + DESTINATION "${dir_startmenu_accessories}") +add_livecd_shortcut("WordPad" + "shell:system\\wordpad.exe" ICON_INDEX 0 + WORKDIR "${envvar_homedrive}${envvar_homepath}" + DESTINATION "${dir_startmenu_accessories}") +add_livecd_shortcut("Solitaire" + "shell:system\\sol.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_games}") +add_livecd_shortcut("Spider Solitaire" + "shell:system\\spider.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_games}") +add_livecd_shortcut("WineMine" + "shell:system\\winmine.exe" ICON_INDEX 0 + DESTINATION "${dir_startmenu_games}") diff --git a/boot/bootdata/livecd_start.cmd b/boot/bootdata/livecd_start.cmd deleted file mode 100644 index 2437786961b..00000000000 --- a/boot/bootdata/livecd_start.cmd +++ /dev/null @@ -1 +0,0 @@ -@start %1 \ No newline at end of file diff --git a/sdk/cmake/CMakeMacros.cmake b/sdk/cmake/CMakeMacros.cmake index 3f8cd915c66..7e35591603a 100644 --- a/sdk/cmake/CMakeMacros.cmake +++ b/sdk/cmake/CMakeMacros.cmake @@ -54,28 +54,44 @@ function(add_message_headers _type) endfunction() function(add_link name path) - cmake_parse_arguments(_LINK "MINIMIZE" "CMD_LINE_ARGS;ICON;GUID" "" ${ARGN}) + cmake_parse_arguments(_LINK "MINIMIZE" "WORKDIR;CMDLINE_ARGS;ICON;ICON_INDEX;GUID" "" ${ARGN}) - if(_LINK_CMD_LINE_ARGS) - set(_LINK_CMD_LINE_ARGS -c ${_LINK_CMD_LINE_ARGS}) + if(DEFINED _LINK_WORKDIR) + set(_LINK_WORKDIR -w "${_LINK_WORKDIR}") + endif() + if(DEFINED _LINK_CMDLINE_ARGS) + set(_LINK_CMDLINE_ARGS -c "${_LINK_CMDLINE_ARGS}") endif() - if(_LINK_ICON) - set(_LINK_ICON -i ${_LINK_ICON}) + if(DEFINED _LINK_ICON) + #set(_LINK_ICON -i "${_LINK_ICON}") + #if(DEFINED _LINK_ICON_INDEX) + # set(_LINK_ICON "${_LINK_ICON},${_LINK_ICON_INDEX}") + #endif() + if(DEFINED _LINK_ICON_INDEX) + set(_LINK_ICON -i "${_LINK_ICON},${_LINK_ICON_INDEX}") + else() + set(_LINK_ICON -i "${_LINK_ICON}") + endif() + elseif(DEFINED _LINK_ICON_INDEX) + set(_LINK_ICON -i ${_LINK_ICON_INDEX}) endif() - if(_LINK_GUID) - set(_LINK_GUID -g ${_LINK_GUID}) + if(DEFINED _LINK_GUID) + set(_LINK_GUID -g "${_LINK_GUID}") endif() if(_LINK_MINIMIZE) - set(_LINK_MINIMIZE "-m") + set(_LINK_MINIMIZE -m) + else() + set(_LINK_MINIMIZE) endif() add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.lnk - COMMAND native-mkshelllink -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.lnk ${_LINK_CMD_LINE_ARGS} ${_LINK_ICON} ${_LINK_GUID} ${_LINK_MINIMIZE} ${path} - DEPENDS native-mkshelllink) + COMMAND native-mkshelllink -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.lnk ${_LINK_WORKDIR} ${_LINK_CMDLINE_ARGS} ${_LINK_ICON} ${_LINK_GUID} ${_LINK_MINIMIZE} ${path} + DEPENDS native-mkshelllink + VERBATIM) endfunction() # @@ -241,7 +257,6 @@ macro(dir_to_num dir var) elseif(${dir} STREQUAL reactos/winsxs/arm64_microsoft.windows.gdiplus_6595b64144ccf1df_1.0.14393.0_none_deadbeef) set(${var} 81) - else() message(FATAL_ERROR "Wrong destination: ${dir}") endif() diff --git a/sdk/tools/mkshelllink/mkshelllink.c b/sdk/tools/mkshelllink/mkshelllink.c index 9f4348bd884..d6003368653 100644 --- a/sdk/tools/mkshelllink/mkshelllink.c +++ b/sdk/tools/mkshelllink/mkshelllink.c @@ -296,6 +296,42 @@ static bool has_env_variables(const char *str) return (ptr && strchr(ptr + 1, '%')); } +static void strip_quotes_and_unescape_envvars(char **pstr) +{ + char *str = *pstr; + char *ptr, *dst; + + /* Skip leading spaces */ + while (isspace(*str)) + ++str; + + /* Strip trailing spaces */ + ptr = str + strlen(str); + while ((ptr > str) && isspace(*(ptr-1))) + --ptr; + *ptr = '\0'; + + /* If quoted, skip the leading and strip the trailing quotes */ + if ((ptr > str + 1) && (*str == '"') && (*(ptr-1) == '"')) + { + ++str; + *(--ptr) = '\0'; + } + + /* Un-escape the '^%' in environment variables names */ + for (dst = ptr = str; *ptr; ++ptr, ++dst) + { + if (*ptr == '^' && *(ptr+1) == '%') + ++ptr; + if (ptr > dst) // Copy characters as soon as source advances destination. + *dst = *ptr; + } + *dst = '\0'; + + /* Return the string */ + *pstr = str; +} + static const struct SPECIALFOLDER* get_special_folder(const char *target) { char buf[256]; @@ -419,12 +455,6 @@ int main(int argc, const char *argv[]) ++i; trace("argv[%d]: %s\n", i, argv[i]); pszIcon = argv[i]; - if ((i + 1 < argc) && isdigit(argv[i + 1][0])) - { - ++i; - trace("argv[%d]: %s\n", i, argv[i]); - IconIndex = atoi(argv[i]); - } } else if (!strcmp(argv[i] + 1, "m")) bMinimized = true; @@ -452,7 +482,7 @@ int main(int argc, const char *argv[]) if (!pszTarget || bHelp) { - printf("Usage: %s [-h][-v][-o path][-u][-d descr][-w path][-c cmdline_args][-i icon_path [nr]][-g guid] target\n" + printf("Usage: %s [-h][-v][-o path][-u][-d descr][-w path][-c cmdline_args][-i [icon_path[,nr]]][-g guid] target\n" "-h\tShows this help.\n" "-v\tEnables verbose mode for diagnostics.\n" "-o path\tSets the output path.\n" @@ -460,13 +490,53 @@ int main(int argc, const char *argv[]) "-d descr\tSets the shortcut description.\n" "-w path\tSets the working directory for the executable.\n" "-c cmdline_args\tSets the command-line arguments passed to the program.\n" - "-i icon_path [nr]\tSets the icon file and optionally its index.\n" + "-i [icon_path[,nr]]\tSets the icon path and optionally its index. If only an index is given (but no path), the target file is used instead.\n" "-m\tStart minimized.\n" "-g guid\tSets the GUID to which the target path is relative. Default value is MyComputer GUID.\n" "target\tAbsolute or relative to GUID specified with the -g option path.\n", argv[0]); return 0; } + /* Process the parameters */ + if (pszTarget) + strip_quotes_and_unescape_envvars((char**)&pszTarget); + if (pszWorkingDir) + strip_quotes_and_unescape_envvars((char**)&pszWorkingDir); + if (pszCmdLineArgs) + strip_quotes_and_unescape_envvars((char**)&pszCmdLineArgs); + if (pszIcon) + { + char *ptr, *endptr; + + strip_quotes_and_unescape_envvars((char**)&pszIcon); + + /* Check whether only an icon index was given */ + dwTmp = strtol(pszIcon, &endptr, 0); + if (endptr && endptr != pszIcon) + { + /* Only an index was given; save it, and use the target as the icon file */ + IconIndex = dwTmp; + pszIcon = (char*)1; // Canary value to tell to use pszTarget, once resolved. + } + else + { + /* No index was given: this is a file path, optionally followed by the icon index */ + ptr = strrchr(pszIcon, ','); + if (ptr) // && isdigit(ptr[1]) + { + /* We may have an index that follows the icon path */ + dwTmp = strtol(ptr+1, &endptr, 0); + if (endptr && endptr != (ptr+1)) + { + /* It's valid, retrieve it and truncate the string to where the icon path ends */ + IconIndex = dwTmp; + *ptr = '\0'; + } + } + pszIcon = pszIcon; + } + } + trace("OutputPath = %s\n" "Target = %s\n" "Description = %s\n" @@ -475,7 +545,7 @@ int main(int argc, const char *argv[]) "Icon = %s (%d)\n\n", pszOutputPath, pszTarget, pszDescription, pszWorkingDir, pszCmdLineArgs, - pszIcon, IconIndex); + (pszIcon == (char*)1) ? pszTarget : pszIcon, IconIndex); pFile = fopen(pszOutputPath, "wb"); if (!pFile) @@ -521,8 +591,14 @@ int main(int argc, const char *argv[]) if (special && special->unexpPath && has_env_variables(special->unexpPath)) Header.Flags |= SLDF_HAS_EXP_SZ; - /* Check whether the icon path contains Win32 environment variables */ - if (pszIcon && has_env_variables(pszIcon)) + /* + * For the icon, first check the canary value that tells to use the target path. + * If present, the icon path will contain Win32 environment variables if the target has them. + * Otherwise, explicitly check whether the specified icon path contains environment variables. + */ + if ((pszIcon == (char*)1) && (Header.Flags & SLDF_HAS_EXP_SZ)) + Header.Flags |= SLDF_HAS_EXP_ICON_SZ; + else if (pszIcon && has_env_variables(pszIcon)) Header.Flags |= SLDF_HAS_EXP_ICON_SZ; trace("Header.Flags = 0x%08x\n" @@ -655,6 +731,10 @@ int main(int argc, const char *argv[]) } } + /* Now, set the icon path to the target path if it has the specific canary value */ + if (pszIcon == (char*)1) + pszIcon = pszTarget; + if (Header.Flags & SLDF_HAS_EXP_SZ) { memset(&SzLinkBlock, 0, sizeof(SzLinkBlock));