Author: rharabien
Date: Sun Nov 27 19:41:52 2011
New Revision: 54512
URL:
http://svn.reactos.org/svn/reactos?rev=54512&view=rev
Log:
[MKSHELLLINK]
- Add host tool for creating .lnk files
Added:
trunk/reactos/tools/mkshelllink/ (with props)
trunk/reactos/tools/mkshelllink/CMakeLists.txt (with props)
trunk/reactos/tools/mkshelllink/mkshelllink.c (with props)
trunk/reactos/tools/mkshelllink/mkshelllink.rbuild (with props)
Modified:
trunk/reactos/tools/CMakeLists.txt
trunk/reactos/tools/tools.rbuild
Modified: trunk/reactos/tools/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/CMakeLists.txt?rev=5…
==============================================================================
--- trunk/reactos/tools/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/tools/CMakeLists.txt [iso-8859-1] Sun Nov 27 19:41:52 2011
@@ -13,6 +13,7 @@
add_subdirectory(obj2bin)
add_subdirectory(spec2def)
add_subdirectory(unicode)
+add_subdirectory(mkshelllink)
if(NOT MSVC)
add_subdirectory(rsym)
Propchange: trunk/reactos/tools/mkshelllink/
------------------------------------------------------------------------------
--- bugtraq:logregex (added)
+++ bugtraq:logregex Sun Nov 27 19:41:52 2011
@@ -1,0 +1,2 @@
+([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))?
+(\d+)
Propchange: trunk/reactos/tools/mkshelllink/
------------------------------------------------------------------------------
bugtraq:message = See issue #%BUGID% for more details.
Propchange: trunk/reactos/tools/mkshelllink/
------------------------------------------------------------------------------
bugtraq:url =
http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: trunk/reactos/tools/mkshelllink/
------------------------------------------------------------------------------
tsvn:logminsize = 10
Added: trunk/reactos/tools/mkshelllink/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/mkshelllink/CMakeLis…
==============================================================================
--- trunk/reactos/tools/mkshelllink/CMakeLists.txt (added)
+++ trunk/reactos/tools/mkshelllink/CMakeLists.txt [iso-8859-1] Sun Nov 27 19:41:52 2011
@@ -1,0 +1,2 @@
+
+add_executable(mkshelllink mkshelllink.c)
Propchange: trunk/reactos/tools/mkshelllink/CMakeLists.txt
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: trunk/reactos/tools/mkshelllink/CMakeLists.txt
------------------------------------------------------------------------------
svn:keywords = Author Date Id Rev URL
Added: trunk/reactos/tools/mkshelllink/mkshelllink.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/mkshelllink/mkshelll…
==============================================================================
--- trunk/reactos/tools/mkshelllink/mkshelllink.c (added)
+++ trunk/reactos/tools/mkshelllink/mkshelllink.c [iso-8859-1] Sun Nov 27 19:41:52 2011
@@ -1,0 +1,333 @@
+/* COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Shell Link maker
+ * FILE: tools/mkshelllink/mkshelllink.c
+ * PURPOSE: Shell Link maker
+ * PROGRAMMER: Rafal Harabien
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <windows.h>
+
+#define DEFINE_GUID2(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID name = { l,w1,w2,{
b1,b2,b3,b4,b5,b6,b7,b8 } }
+DEFINE_GUID2(CLSID_ShellLink,0x00021401L,0,0,0xC0,0,0,0,0,0,0,0x46);
+DEFINE_GUID2(CLSID_MyComputer,0x20D04FE0,0x3AEA,0x1069,0xA2,0xD8,0x08,0x00,0x2B,0x30,0x30,0x9D);
+
+#define LINK_ID_LIST 0x01
+#define LINK_FILE 0x02
+#define LINK_DESCRIPTION 0x04
+#define LINK_RELATIVE_PATH 0x08
+#define LINK_WORKING_DIR 0x10
+#define LINK_CMD_LINE_ARGS 0x20
+#define LINK_ICON 0x40
+#define LINK_UNICODE 0x80
+
+#define LOCATOR_LOCAL 0x1
+#define LOCATOR_NETWORK 0x2
+
+#pragma pack(push, 1)
+
+/* Specification:
http://ithreats.files.wordpress.com/2009/05/lnk_the_windows_shortcut_file_f… */
+
+typedef struct _LNK_HEADER
+{
+ DWORD Signature;
+ GUID Guid;
+ DWORD Flags;
+ DWORD Attributes;
+ FILETIME CreationTime;
+ FILETIME ModificationTime;
+ FILETIME LastAccessTime;
+ DWORD FileSize;
+ DWORD IconNr;
+ DWORD Show;
+ DWORD Hotkey;
+ DWORD Unknown;
+ DWORD Unknown2;
+} LNK_HEADER;
+
+typedef struct _LNK_LOCATOR_INFO
+{
+ DWORD Size;
+ DWORD DataOffset;
+ DWORD Flags;
+ DWORD LocalVolumeInfoOffset;
+ DWORD LocalBasePathnameOffset;
+ DWORD NetworkVolumeInfoOffset;
+ DWORD RemainingPathnameOffset;
+ char Data[0];
+} LNK_LOCATOR_INFO;
+
+typedef struct _LNK_LOCAL_VOLUME_INFO
+{
+ DWORD Size;
+ DWORD VolumeType; /* See GetDriveType */
+ DWORD SerialNumber;
+ DWORD VolumeNameOffset;
+ char VolumeLabel[0];
+} LNK_LOCAL_VOLUME_INFO;
+
+#define PT_GUID 0x1F
+#define PT_DRIVE1 0x2F
+#define PT_FOLDER 0x31
+#define PT_VALUE 0x32
+
+typedef struct _ID_LIST_FILE
+{
+ WORD Size;
+ BYTE Type;
+ BYTE dummy;
+ DWORD dwFileSize;
+ WORD uFileDate;
+ WORD uFileTime;
+ WORD uFileAttribs;
+ char szName[0];
+} ID_LIST_FILE;
+
+typedef struct _ID_LIST_GUID
+{
+ WORD Size;
+ BYTE Type;
+ BYTE dummy;
+ GUID guid;
+} ID_LIST_GUID;
+
+typedef struct _ID_LIST_DRIVE
+{
+ WORD Size;
+ BYTE Type;
+ CHAR szDriveName[20];
+ WORD unknown;
+} ID_LIST_DRIVE;
+
+#pragma pack(pop)
+
+int main(int argc, const char *argv[])
+{
+ unsigned i;
+ const char *pszOutputPath = "shortcut.lnk";
+ const char *pszTarget = NULL;
+ const char *pszDescription = "Description";
+ const char *pszWorkingDir = NULL;
+ const char *pszCmdLineArgs = NULL;
+ const char *pszIcon = NULL;
+ int IconNr = 0;
+ GUID Guid = CLSID_MyComputer;
+ BOOL bHelp = FALSE, bMinimized = FALSE;
+ FILE *pFile;
+ LNK_HEADER Header;
+ USHORT uhTmp;
+ DWORD dwTmp;
+
+ for (i = 1; i < argc; ++i)
+ {
+ if (argv[i][0] != '-' && argv[i][0] != '/')
+ pszTarget = argv[i];
+ else if (!stricmp(argv[i] + 1, "h"))
+ bHelp = TRUE;
+ else if (!stricmp(argv[i] + 1, "o") && i + 1 < argc)
+ pszOutputPath = argv[++i];
+ else if (!stricmp(argv[i] + 1, "d") && i + 1 < argc)
+ pszDescription = argv[++i];
+ else if (!stricmp(argv[i] + 1, "w") && i + 1 < argc)
+ pszWorkingDir = argv[++i];
+ else if (!stricmp(argv[i] + 1, "c") && i + 1 < argc)
+ pszCmdLineArgs = argv[++i];
+ else if (!stricmp(argv[i] + 1, "i") && i + 1 < argc)
+ {
+ pszIcon = argv[++i];
+ if (i + 1 < argc && isdigit(argv[i + 1][0]))
+ IconNr = atoi(argv[++i]);
+ }
+ else if (!stricmp(argv[i] + 1, "m"))
+ bMinimized = TRUE;
+ else if (!stricmp(argv[i] + 1, "g") && i + 1 < argc)
+ {
+ unsigned Data4Tmp[8], j;
+
+ sscanf(argv[++i], "{%8lx-%4hx-%4hx-%2x%2x-%2x%2x%2x%2x%2x%2x}",
+ &Guid.Data1, &Guid.Data2, &Guid.Data3,
+ &Data4Tmp[0], &Data4Tmp[1], &Data4Tmp[2],
&Data4Tmp[3],
+ &Data4Tmp[4], &Data4Tmp[5], &Data4Tmp[6],
&Data4Tmp[7]);
+ for (j = 0; j < 8; ++j)
+ Guid.Data4[j] = (BYTE)Data4Tmp[j];
+ }
+ else
+ printf("Invalid option: %s\n", argv[i]);
+ }
+
+ if (!pszTarget || bHelp)
+ {
+ printf("Usage: %s [-o path][-d descr][-w path][-c cmd_line_args][-i
icon_path [nr]][-h][-g guid] target\n"
+ "-o path\tSets output path\n"
+ "-d descr\tSets shortcut description\n"
+ "-w path\tSets working directory for executable\n"
+ "-c cmd_line_args\tSets command line arguments passed to
program\n"
+ "-i icon_path [nr]\tSets icon file and optionally icon index\n"
+ "-m\tStart minimized\n"
+ "-g guid\tSets GUID to which target path is relative. Default value
is MyComputer GUID.\n"
+ "target\tAbsolute or relative to guid specified with -g option
path\n", argv[0]);
+ return 0;
+ }
+
+ pFile = fopen(pszOutputPath, "wb");
+ if (!pFile)
+ {
+ printf("Failed to open %s\n", pszOutputPath);
+ return -1;
+ }
+
+ // Header
+ memset(&Header, 0, sizeof(Header));
+ Header.Signature = (DWORD)'L';
+ Header.Guid = CLSID_ShellLink;
+ Header.Flags = LINK_ID_LIST;
+ if (pszDescription)
+ Header.Flags |= LINK_DESCRIPTION;
+ if (pszWorkingDir)
+ Header.Flags |= LINK_WORKING_DIR;
+ if (pszCmdLineArgs)
+ Header.Flags |= LINK_CMD_LINE_ARGS;
+ if (pszIcon)
+ Header.Flags |= LINK_ICON;
+ Header.IconNr = IconNr;
+ Header.Show = bMinimized ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL;
+ fwrite(&Header, sizeof(Header), 1, pFile);
+
+ if (Header.Flags & LINK_ID_LIST)
+ {
+ ID_LIST_FILE IdListFile;
+ ID_LIST_GUID IdListGuid;
+ ID_LIST_DRIVE IdListDrive;
+ unsigned cbListSize = sizeof(IdListGuid) + sizeof(WORD), cchName;
+ const char *pszName = pszTarget;
+
+ // ID list
+ // It seems explorer does not accept links without id list. List is relative to
desktop.
+
+ pszName = pszTarget;
+
+ if (pszName[0] && pszName[1] == ':')
+ {
+ cbListSize += sizeof(IdListDrive);
+ pszName += 2;
+ while (*pszName == '\\' || *pszName == '/')
+ ++pszName;
+ }
+
+ while (*pszName)
+ {
+ cchName = 0;
+ while (pszName[cchName] && pszName[cchName] != '\\'
&& pszName[cchName] != '/')
+ ++cchName;
+
+ if (cchName != 1 || pszName[0] != '.')
+ cbListSize += sizeof(IdListFile) + 2 * (cchName + 1);
+
+ pszName += cchName;
+ while (*pszName == '\\' || *pszName == '/')
+ ++pszName;
+ }
+
+ uhTmp = cbListSize;
+ fwrite(&uhTmp, sizeof(uhTmp), 1, pFile); // size
+
+ IdListGuid.Size = sizeof(IdListGuid);
+ IdListGuid.Type = PT_GUID;
+ IdListGuid.dummy = 0x50;
+ IdListGuid.guid = Guid;
+ fwrite(&IdListGuid, sizeof(IdListGuid), 1, pFile);
+
+ pszName = pszTarget;
+
+ if (isalpha(pszName[0]) && pszName[1] == ':')
+ {
+ memset(&IdListDrive, 0, sizeof(IdListDrive));
+ IdListDrive.Size = sizeof(IdListDrive);
+ IdListDrive.Type = PT_DRIVE1;
+ sprintf(IdListDrive.szDriveName, "%c:\\", pszName[0]);
+ fwrite(&IdListDrive, sizeof(IdListDrive), 1, pFile);
+ pszName += 2;
+ while(*pszName == '\\' || *pszName == '/')
+ ++pszName;
+ }
+
+ while (*pszName)
+ {
+ cchName = 0;
+ while (pszName[cchName] && pszName[cchName] != '\\'
&& pszName[cchName] != '/')
+ ++cchName;
+
+ if (cchName != 1 || pszName[0] != '.')
+ {
+ memset(&IdListFile, 0, sizeof(IdListFile));
+ IdListFile.Size = sizeof(IdListFile) + 2 * (cchName + 1);
+ if (!pszName[cchName])
+ IdListFile.Type = PT_VALUE; // File
+ else
+ IdListFile.Type = PT_FOLDER;
+ fwrite(&IdListFile, sizeof(IdListFile), 1, pFile);
+ fwrite(pszName, cchName, 1, pFile);
+ fputc(0, pFile);
+ fwrite(pszName, cchName, 1, pFile);
+ fputc(0, pFile);
+ }
+
+ pszName += cchName;
+ while (*pszName == '\\' || *pszName == '/')
+ ++pszName;
+ }
+
+ uhTmp = 0; // list end
+ fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
+ }
+
+ if (Header.Flags & LINK_DESCRIPTION)
+ {
+ // Dscription
+ uhTmp = strlen(pszDescription);
+ fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
+ fputs(pszDescription, pFile);
+ }
+
+ if (Header.Flags & LINK_RELATIVE_PATH)
+ {
+ // Relative Path
+ uhTmp = strlen(pszTarget);
+ fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
+ fputs(pszTarget, pFile);
+ }
+
+ if (Header.Flags & LINK_WORKING_DIR)
+ {
+ // Working Dir
+ uhTmp = strlen(pszWorkingDir);
+ fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
+ fputs(pszWorkingDir, pFile);
+ }
+
+ if (Header.Flags & LINK_CMD_LINE_ARGS)
+ {
+ // Command line arguments
+ uhTmp = strlen(pszCmdLineArgs);
+ fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
+ fputs(pszCmdLineArgs, pFile);
+ }
+
+ if (Header.Flags & LINK_ICON)
+ {
+ // Command line arguments
+ uhTmp = strlen(pszIcon);
+ fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
+ fputs(pszIcon, pFile);
+ }
+
+ // Extra stuff
+ dwTmp = 0;
+ fwrite(&dwTmp, sizeof(dwTmp), 1, pFile);
+
+ fclose(pFile);
+
+ return 0;
+}
Propchange: trunk/reactos/tools/mkshelllink/mkshelllink.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/tools/mkshelllink/mkshelllink.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/mkshelllink/mkshelll…
==============================================================================
--- trunk/reactos/tools/mkshelllink/mkshelllink.rbuild (added)
+++ trunk/reactos/tools/mkshelllink/mkshelllink.rbuild [iso-8859-1] Sun Nov 27 19:41:52
2011
@@ -1,0 +1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../tools/rbuild/project.dtd">
+<module name="mkshelllink" type="buildtool">
+ <file>mkshelllink.c</file>
+</module>
Propchange: trunk/reactos/tools/mkshelllink/mkshelllink.rbuild
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/tools/tools.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/tools/tools.rbuild?rev=545…
==============================================================================
--- trunk/reactos/tools/tools.rbuild [iso-8859-1] (original)
+++ trunk/reactos/tools/tools.rbuild [iso-8859-1] Sun Nov 27 19:41:52 2011
@@ -46,4 +46,7 @@
<directory name="rbuild_helper">
<xi:include href="rbuild_helper/rbuild_helper.rbuild" />
</directory>
+<directory name="mkshelllink">
+ <xi:include href="mkshelllink/mkshelllink.rbuild" />
+</directory>
</group>