ReactOS 0.4.15-dev-8236-g99f0937
mkshelllink.c
Go to the documentation of this file.
1/* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS Shell Link maker
3 * FILE: tools/mkshelllink/mkshelllink.c
4 * PURPOSE: Shell Link maker
5 * PROGRAMMER: Rafal Harabien
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <ctype.h>
12
13#ifndef _MSC_VER
14#include <stdint.h>
15#else
16typedef unsigned __int8 uint8_t;
17typedef unsigned __int16 uint16_t;
18typedef unsigned __int32 uint32_t;
19#endif
20
21#define SW_SHOWNORMAL 1
22#define SW_SHOWMINNOACTIVE 7
23
24typedef struct _GUID
25{
31
32typedef struct _FILETIME {
36
37#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 } }
38DEFINE_GUID2(CLSID_ShellLink,0x00021401L,0,0,0xC0,0,0,0,0,0,0,0x46);
39DEFINE_GUID2(CLSID_MyComputer,0x20D04FE0,0x3AEA,0x1069,0xA2,0xD8,0x08,0x00,0x2B,0x30,0x30,0x9D);
40
41#define LINK_ID_LIST 0x01
42#define LINK_FILE 0x02
43#define LINK_DESCRIPTION 0x04
44#define LINK_RELATIVE_PATH 0x08
45#define LINK_WORKING_DIR 0x10
46#define LINK_CMD_LINE_ARGS 0x20
47#define LINK_ICON 0x40
48#define LINK_UNICODE 0x80
49
50#define LOCATOR_LOCAL 0x1
51#define LOCATOR_NETWORK 0x2
52
53#pragma pack(push, 1)
54
55/* Specification: http://ithreats.files.wordpress.com/2009/05/lnk_the_windows_shortcut_file_format.pdf */
56
57typedef struct _LNK_HEADER
58{
73
74typedef struct _LNK_LOCATOR_INFO
75{
83 char Data[0];
85
87{
89 uint32_t VolumeType; /* See GetDriveType */
92 char VolumeLabel[0];
94
95#define PT_GUID 0x1F
96#define PT_DRIVE1 0x2F
97#define PT_FOLDER 0x31
98#define PT_VALUE 0x32
99
100typedef struct _ID_LIST_FILE
101{
109 char szName[0];
111
112typedef struct _ID_LIST_GUID
113{
119
120typedef struct _ID_LIST_DRIVE
121{
124 char szDriveName[20];
127
128#pragma pack(pop)
129
130int main(int argc, const char *argv[])
131{
132 int i;
133 const char *pszOutputPath = "shortcut.lnk";
134 const char *pszTarget = NULL;
135 const char *pszDescription = "Description";
136 const char *pszWorkingDir = NULL;
137 const char *pszCmdLineArgs = NULL;
138 const char *pszIcon = NULL;
139 int IconNr = 0;
140 GUID Guid = CLSID_MyComputer;
141 int bHelp = 0, bMinimized = 0;
142 FILE *pFile;
144 uint16_t uhTmp;
145 uint32_t dwTmp;
146
147 for (i = 1; i < argc; ++i)
148 {
149 if (argv[i][0] != '-' && argv[i][0] != '/')
150 pszTarget = argv[i];
151 else if (!strcmp(argv[i] + 1, "h"))
152 bHelp = 1;
153 else if (!strcmp(argv[i] + 1, "o") && i + 1 < argc)
154 pszOutputPath = argv[++i];
155 else if (!strcmp(argv[i] + 1, "d") && i + 1 < argc)
156 pszDescription = argv[++i];
157 else if (!strcmp(argv[i] + 1, "w") && i + 1 < argc)
158 pszWorkingDir = argv[++i];
159 else if (!strcmp(argv[i] + 1, "c") && i + 1 < argc)
160 pszCmdLineArgs = argv[++i];
161 else if (!strcmp(argv[i] + 1, "i") && i + 1 < argc)
162 {
163 pszIcon = argv[++i];
164 if (i + 1 < argc && isdigit(argv[i + 1][0]))
165 IconNr = atoi(argv[++i]);
166 }
167 else if (!strcmp(argv[i] + 1, "m"))
168 bMinimized = 1;
169 else if (!strcmp(argv[i] + 1, "g") && i + 1 < argc)
170 {
171 unsigned Data4Tmp[8], j;
172
173 sscanf(argv[++i], "{%8x-%4hx-%4hx-%2x%2x-%2x%2x%2x%2x%2x%2x}",
174 &Guid.Data1, &Guid.Data2, &Guid.Data3,
175 &Data4Tmp[0], &Data4Tmp[1], &Data4Tmp[2], &Data4Tmp[3],
176 &Data4Tmp[4], &Data4Tmp[5], &Data4Tmp[6], &Data4Tmp[7]);
177 for (j = 0; j < 8; ++j)
178 Guid.Data4[j] = (uint8_t)Data4Tmp[j];
179 }
180 else
181 printf("Invalid option: %s\n", argv[i]);
182 }
183
184 if (!pszTarget || bHelp)
185 {
186 printf("Usage: %s [-o path][-d descr][-w path][-c cmd_line_args][-i icon_path [nr]][-h][-g guid] target\n"
187 "-o path\tSets output path\n"
188 "-d descr\tSets shortcut description\n"
189 "-w path\tSets working directory for executable\n"
190 "-c cmd_line_args\tSets command line arguments passed to program\n"
191 "-i icon_path [nr]\tSets icon file and optionally icon index\n"
192 "-m\tStart minimized\n"
193 "-g guid\tSets GUID to which target path is relative. Default value is MyComputer GUID.\n"
194 "target\tAbsolute or relative to guid specified with -g option path\n", argv[0]);
195 return 0;
196 }
197
198 pFile = fopen(pszOutputPath, "wb");
199 if (!pFile)
200 {
201 printf("Failed to open %s\n", pszOutputPath);
202 return -1;
203 }
204
205 // Header
206 memset(&Header, 0, sizeof(Header));
207 Header.Signature = (uint32_t)'L';
208 Header.Guid = CLSID_ShellLink;
209 Header.Flags = LINK_ID_LIST;
210 if (pszDescription)
211 Header.Flags |= LINK_DESCRIPTION;
212 if (pszWorkingDir)
213 Header.Flags |= LINK_WORKING_DIR;
214 if (pszCmdLineArgs)
215 Header.Flags |= LINK_CMD_LINE_ARGS;
216 if (pszIcon)
217 Header.Flags |= LINK_ICON;
218 Header.IconNr = IconNr;
219 Header.Show = bMinimized ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL;
220 fwrite(&Header, sizeof(Header), 1, pFile);
221
222 if (Header.Flags & LINK_ID_LIST)
223 {
224 ID_LIST_FILE IdListFile;
225 ID_LIST_GUID IdListGuid;
226 ID_LIST_DRIVE IdListDrive;
227 unsigned cbListSize = sizeof(IdListGuid) + sizeof(uint16_t), cchName;
228 const char *pszName = pszTarget;
229
230 // ID list
231 // It seems explorer does not accept links without id list. List is relative to desktop.
232
233 pszName = pszTarget;
234
235 if (pszName[0] && pszName[1] == ':')
236 {
237 cbListSize += sizeof(IdListDrive);
238 pszName += 2;
239 while (*pszName == '\\' || *pszName == '/')
240 ++pszName;
241 }
242
243 while (*pszName)
244 {
245 cchName = 0;
246 while (pszName[cchName] && pszName[cchName] != '\\' && pszName[cchName] != '/')
247 ++cchName;
248
249 if (cchName != 1 || pszName[0] != '.')
250 cbListSize += sizeof(IdListFile) + 2 * (cchName + 1);
251
252 pszName += cchName;
253 while (*pszName == '\\' || *pszName == '/')
254 ++pszName;
255 }
256
257 uhTmp = cbListSize;
258 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile); // size
259
260 IdListGuid.Size = sizeof(IdListGuid);
261 IdListGuid.Type = PT_GUID;
262 IdListGuid.dummy = 0x50;
263 IdListGuid.guid = Guid;
264 fwrite(&IdListGuid, sizeof(IdListGuid), 1, pFile);
265
266 pszName = pszTarget;
267
268 if (isalpha(pszName[0]) && pszName[1] == ':')
269 {
270 memset(&IdListDrive, 0, sizeof(IdListDrive));
271 IdListDrive.Size = sizeof(IdListDrive);
272 IdListDrive.Type = PT_DRIVE1;
273 sprintf(IdListDrive.szDriveName, "%c:\\", pszName[0]);
274 fwrite(&IdListDrive, sizeof(IdListDrive), 1, pFile);
275 pszName += 2;
276 while(*pszName == '\\' || *pszName == '/')
277 ++pszName;
278 }
279
280 while (*pszName)
281 {
282 cchName = 0;
283 while (pszName[cchName] && pszName[cchName] != '\\' && pszName[cchName] != '/')
284 ++cchName;
285
286 if (cchName != 1 || pszName[0] != '.')
287 {
288 memset(&IdListFile, 0, sizeof(IdListFile));
289 IdListFile.Size = sizeof(IdListFile) + 2 * (cchName + 1);
290 if (!pszName[cchName])
291 IdListFile.Type = PT_VALUE; // File
292 else
293 IdListFile.Type = PT_FOLDER;
294 fwrite(&IdListFile, sizeof(IdListFile), 1, pFile);
295 fwrite(pszName, cchName, 1, pFile);
296 fputc(0, pFile);
297 fwrite(pszName, cchName, 1, pFile);
298 fputc(0, pFile);
299 }
300
301 pszName += cchName;
302 while (*pszName == '\\' || *pszName == '/')
303 ++pszName;
304 }
305
306 uhTmp = 0; // list end
307 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
308 }
309
310 if (Header.Flags & LINK_DESCRIPTION)
311 {
312 // Dscription
313 uhTmp = strlen(pszDescription);
314 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
315 fputs(pszDescription, pFile);
316 }
317
318 if (Header.Flags & LINK_RELATIVE_PATH)
319 {
320 // Relative Path
321 uhTmp = strlen(pszTarget);
322 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
323 fputs(pszTarget, pFile);
324 }
325
326 if (Header.Flags & LINK_WORKING_DIR)
327 {
328 // Working Dir
329 uhTmp = strlen(pszWorkingDir);
330 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
331 fputs(pszWorkingDir, pFile);
332 }
333
334 if (Header.Flags & LINK_CMD_LINE_ARGS)
335 {
336 // Command line arguments
337 uhTmp = strlen(pszCmdLineArgs);
338 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
339 fputs(pszCmdLineArgs, pFile);
340 }
341
342 if (Header.Flags & LINK_ICON)
343 {
344 // Command line arguments
345 uhTmp = strlen(pszIcon);
346 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
347 fputs(pszIcon, pFile);
348 }
349
350 // Extra stuff
351 dwTmp = 0;
352 fwrite(&dwTmp, sizeof(dwTmp), 1, pFile);
353
354 fclose(pFile);
355
356 return 0;
357}
static int argc
Definition: ServiceArgs.c:12
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define isalpha(c)
Definition: acclib.h:74
#define isdigit(c)
Definition: acclib.h:68
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
unsigned short int uint16_t
Definition: acefiex.h:54
#define __int8
Definition: basetyps.h:25
#define __int16
Definition: basetyps.h:22
#define __int32
Definition: basetyps.h:19
Definition: Header.h:9
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
int main()
Definition: test.c:6
#define printf
Definition: freeldr.h:97
MdFileObject pFile
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
_Check_return_opt_ _CRTIMP int __cdecl fputs(_In_z_ const char *_Str, _Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP int __cdecl fputc(_In_ int _Ch, _Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP size_t __cdecl fwrite(_In_reads_bytes_(_Size *_Count) const void *_Str, _In_ size_t _Size, _In_ size_t _Count, _Inout_ FILE *_File)
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define argv
Definition: mplay32.c:18
BYTE uint8_t
Definition: msvideo1.c:66
#define uint32_t
Definition: nsiface.idl:61
#define uint16_t
Definition: nsiface.idl:60
#define uint8_t
Definition: nsiface.idl:59
#define memset(x, y, z)
Definition: compat.h:39
uint32_t dwHighDateTime
Definition: mkshelllink.c:34
uint32_t dwLowDateTime
Definition: mkshelllink.c:33
Definition: scsiwmi.h:51
unsigned char Data4[8]
Definition: scsiwmi.h:55
uint16_t Data2
Definition: mkshelllink.c:27
uint32_t Data1
Definition: mkshelllink.c:26
uint16_t Data3
Definition: mkshelllink.c:28
uint16_t unknown
Definition: mkshelllink.c:125
char szDriveName[20]
Definition: mkshelllink.c:124
uint16_t Size
Definition: mkshelllink.c:122
char szName[0]
Definition: mkshelllink.c:109
uint16_t uFileDate
Definition: mkshelllink.c:106
uint32_t dwFileSize
Definition: mkshelllink.c:105
uint8_t Type
Definition: mkshelllink.c:103
uint16_t uFileTime
Definition: mkshelllink.c:107
uint8_t dummy
Definition: mkshelllink.c:104
uint16_t Size
Definition: mkshelllink.c:102
uint16_t uFileAttribs
Definition: mkshelllink.c:108
uint8_t Type
Definition: mkshelllink.c:115
uint8_t dummy
Definition: mkshelllink.c:116
uint16_t Size
Definition: mkshelllink.c:114
uint32_t Signature
Definition: mkshelllink.c:59
uint32_t Flags
Definition: mkshelllink.c:61
uint32_t Attributes
Definition: mkshelllink.c:62
uint32_t IconNr
Definition: mkshelllink.c:67
FILETIME ModificationTime
Definition: mkshelllink.c:64
uint32_t Unknown2
Definition: mkshelllink.c:71
uint32_t Hotkey
Definition: mkshelllink.c:69
FILETIME CreationTime
Definition: mkshelllink.c:63
uint32_t FileSize
Definition: mkshelllink.c:66
uint32_t Show
Definition: mkshelllink.c:68
FILETIME LastAccessTime
Definition: mkshelllink.c:65
uint32_t Unknown
Definition: mkshelllink.c:70
uint32_t DataOffset
Definition: mkshelllink.c:77
uint32_t LocalBasePathnameOffset
Definition: mkshelllink.c:80
uint32_t LocalVolumeInfoOffset
Definition: mkshelllink.c:79
uint32_t RemainingPathnameOffset
Definition: mkshelllink.c:82
uint32_t NetworkVolumeInfoOffset
Definition: mkshelllink.c:81
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
_In_ PSID _Out_writes_to_opt_ cchName LPSTR _Inout_ LPDWORD cchName
Definition: winbase.h:2767