ReactOS 0.4.17-dev-243-g1369312
mkshelllink.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Shell Link maker
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Shell Link maker
5 * COPYRIGHT: Copyright 2011 Rafal Harabien <rafalh@reactos.org>
6 * Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
7 * Copyright 2026 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
8 */
9
10/* INCLUDES ******************************************************************/
11
12#include <stdarg.h>
13#include <stdbool.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <ctype.h> // For isalpha(), isdigit()
18
19#ifndef C_ASSERT
20#define C_ASSERT(expr) extern char (*c_assert(void)) [(expr) ? 1 : -1]
21#endif
22
23/* Function attributes for GCC */
24#if !defined(_MSC_VER) && !defined(__cdecl)
25#define __cdecl // __attribute__((cdecl)) // warning: ‘cdecl’ attribute ignored
26#endif
27
28#ifndef _MSC_VER
29#include <stdint.h>
30#else
31typedef unsigned __int8 uint8_t;
32typedef unsigned __int16 uint16_t;
33typedef unsigned __int32 uint32_t;
34typedef __int32 int32_t;
35#endif
36
37C_ASSERT(sizeof(wchar_t) == sizeof(uint16_t)); // Ensure wchar_t is 16-bit (UTF16 character)
38
39#ifndef _countof
40#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
41#endif
42#ifndef min
43#define min(a,b) (((a) < (b)) ? (a) : (b))
44#endif
45
46#ifdef _WIN32
47#define strcasecmp _stricmp
48#endif
49
50
51/* SHELL LINK DEFINITIONS ****************************************************/
52
53#define SW_SHOWNORMAL 1
54#define SW_SHOWMINNOACTIVE 7
55
56typedef struct _GUID
57{
63C_ASSERT(sizeof(GUID) == 16);
64
65typedef struct _FILETIME
66{
70
71#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 } }
72DEFINE_GUID2(CLSID_ShellLink, 0x00021401,0,0,0xC0,0,0,0,0,0,0,0x46);
73DEFINE_GUID2(CLSID_MyComputer,0x20D04FE0,0x3AEA,0x1069,0xA2,0xD8,0x08,0x00,0x2B,0x30,0x30,0x9D);
74
75#define LOCATOR_LOCAL 0x1
76#define LOCATOR_NETWORK 0x2
77
78#pragma pack(push, 1)
79
80/*
81 * Specification:
82 * "[MS-SHLLINK]: Shell Link (.LNK) Binary File Format"
83 * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/16cb4ca1-9339-4d0c-a68d-bf1d6cc0f943
84 * Definitions adapted from undocshell.h
85 */
86
87/* SHELL_LINK_HEADER flags. SHELL_LINK_DATA_FLAGS definitions taken from shlobj.h */
88#define SLDF_DEFAULT 0x00000000
89#define SLDF_HAS_ID_LIST 0x00000001
90#define SLDF_HAS_LINK_INFO 0x00000002
91#define SLDF_HAS_NAME 0x00000004
92#define SLDF_HAS_RELPATH 0x00000008
93#define SLDF_HAS_WORKINGDIR 0x00000010
94#define SLDF_HAS_ARGS 0x00000020
95#define SLDF_HAS_ICONLOCATION 0x00000040
96#define SLDF_UNICODE 0x00000080
97#define SLDF_HAS_EXP_SZ 0x00000200
98#define SLDF_HAS_EXP_ICON_SZ 0x00004000
99
100#define LINK_ID_LIST SLDF_HAS_ID_LIST
101#define LINK_FILE SLDF_HAS_LINK_INFO
102#define LINK_DESCRIPTION SLDF_HAS_NAME
103#define LINK_RELATIVE_PATH SLDF_HAS_RELPATH
104#define LINK_WORKING_DIR SLDF_HAS_WORKINGDIR
105#define LINK_CMDLINE_ARGS SLDF_HAS_ARGS
106#define LINK_ICON SLDF_HAS_ICONLOCATION
107#define LINK_UNICODE SLDF_UNICODE
108
109// SHELL_LINK_HEADER
110typedef struct _LNK_HEADER
111{
119 uint32_t FileSizeLow; /* Only the least significant 32 bits */
127
128// SHELL_LINK_INFOA
129typedef struct _LNK_LOCATOR_INFO
130{
138 char Data[0];
140
141// SHELL_LINK_INFO_VOLUME_IDA
143{
145 uint32_t VolumeType; /* See GetDriveType */
148 char VolumeLabel[0];
150
151/* For ITEMIDLIST/SHITEMID */
152#define PT_GUID 0x1F
153#define PT_DRIVE1 0x2F
154#define PT_FOLDER 0x31
155#define PT_VALUE 0x32
156
157/* uSortOrder values */
158#define REGITEMORDER_DEFAULT 0x80
159#define REGITEMORDER_LIBRARIES 0x42
160#define REGITEMORDER_USERSFILEFOLDER 0x44
161#define REGITEMORDER_MYCOMPUTER 0x50
162
163// struct tagGUIDStruct
164typedef struct _ID_LIST_GUID
165{
171
172// struct tagDriveStruct
173typedef struct _ID_LIST_DRIVE
174{
177 char szDriveName[20];
180
181// struct tagFileStruct
182typedef struct _ID_LIST_FILE
183{
191 /* Here are coming two strings. The first is the long name.
192 The second the dos name when needed or just 0x00 */
193 char szName[0];
195
196#define EXP_SPECIAL_FOLDER_SIG 0xA0000005
198{
204
205#define MAX_PATH 260
206
207#define EXP_SZ_LINK_SIG 0xA0000001
208#define EXP_SZ_ICON_SIG 0xA0000007
209typedef struct _EXP_SZ_LINK
210{
216
217#pragma pack(pop)
218
219
220/* GLOBALS *******************************************************************/
221
222static bool g_Verbose = false;
223
224/* For a complete list, see: https://smallvoid.com/article/winnt-shell-keyword.html */
225#define CSIDL_WINDOWS 0x24
226#define CSIDL_SYSTEM 0x25
227static const struct SPECIALFOLDER
228{
229 unsigned char csidl;
230 const char* name;
231 const char* dummyPath;
232 const char* unexpPath;
233} g_specialfolders[] = {
234 { CSIDL_WINDOWS, "windows", "X:\\reactos", "%SystemRoot%" },
235 { CSIDL_SYSTEM, "system", "X:\\reactos\\system32", "%SystemRoot%\\system32" },
236 { 0, NULL, NULL, NULL }
238
239
240/* FUNCTIONS *****************************************************************/
241
242/*
243 * Poor-man ANSI-to-UTF16LE conversion.
244 * We cannot use the host mbstowcs() routine, since on *nix systems the iconv
245 * library being used may have been compiled with a 32-bit wchar_t (even if
246 * the tool is compiled with: `-fshort-wchar -fwide-exec-charset=UTF-16LE`).
247 */
248size_t
250 wchar_t *wcstr,
251 const char *mbstr,
252 size_t count)
253{
254 size_t i;
255 size_t len = strlen(mbstr) + 1; // Count the NUL-terminator.
256
257 /* Convert up to the NUL-terminator (included) and at most 'count' characters */
258 count = min(count, len);
259
260 /* POSIX extension: if wcstr is NULL, return the number of wide
261 * characters that would be written to wcstr, if converted. */
262 if (!wcstr)
263 return count;
264
265 if (count == 0)
266 return (size_t)0; // dest string exists, but 0 bytes converted.
267 for (i = 0; i < count; ++i)
268 wcstr[i] = (wchar_t)mbstr[i];
269 /* Return the number of wide characters, excluding the NUL-terminator, written to wcstr */
270 return (i - 1);
271}
272#define mbstowcs my_mbstowcs
273
274static void __cdecl trace(const char *format, ...)
275{
277
278 if (!g_Verbose)
279 return;
280
283 va_end(args);
284}
285
286static bool is_path_separator(char c)
287{
288 return (c == '\\' || c == '/');
289}
290
291/* Check whether a string contains Win32 environment variables,
292 * by searching for a pair of '%'. */
293static bool has_env_variables(const char *str)
294{
295 const char *ptr = strchr(str, '%');
296 return (ptr && strchr(ptr + 1, '%'));
297}
298
299static void strip_quotes_and_unescape_envvars(char **pstr)
300{
301 char *str = *pstr;
302 char *ptr, *dst;
303
304 /* Skip leading spaces */
305 while (isspace(*str))
306 ++str;
307
308 /* Strip trailing spaces */
309 ptr = str + strlen(str);
310 while ((ptr > str) && isspace(*(ptr-1)))
311 --ptr;
312 *ptr = '\0';
313
314 /* If quoted, skip the leading and strip the trailing quotes */
315 if ((ptr > str + 1) && (*str == '"') && (*(ptr-1) == '"'))
316 {
317 ++str;
318 *(--ptr) = '\0';
319 }
320
321 /* Un-escape the '^%' in environment variables names */
322 for (dst = ptr = str; *ptr; ++ptr, ++dst)
323 {
324 if (*ptr == '^' && *(ptr+1) == '%')
325 ++ptr;
326 if (ptr > dst) // Copy characters as soon as source advances destination.
327 *dst = *ptr;
328 }
329 *dst = '\0';
330
331 /* Return the string */
332 *pstr = str;
333}
334
335static const struct SPECIALFOLDER* get_special_folder(const char *target)
336{
337 char buf[256];
338
339 strncpy(buf, target, sizeof(buf));
340 buf[sizeof("shell:") - 1] = '\0';
341 if (strcasecmp("shell:", buf))
342 return NULL;
343
344 target += sizeof("shell:") - 1;
345 for (unsigned long i = 0;; ++i)
346 {
347 unsigned long len;
348 const struct SPECIALFOLDER *special = &g_specialfolders[i];
349 if (!special->name)
350 return NULL;
351 len = strlen(special->name);
352 strncpy(buf, target, sizeof(buf));
353 buf[len] = '\0';
354 if (!strcasecmp(special->name, buf) && (is_path_separator(target[len]) || !target[len]))
355 return &g_specialfolders[i];
356 }
357}
358
359/*
360 * Write an ANSI string buffer to the shell link,
361 * converting it to UTF16LE Unicode if necessary.
362 */
363static void write_string(FILE *pFile, bool bUnicode, const char *str)
364{
365 uint16_t uhTmp;
366
367 /* String length in number of ANSI or Unicode characters */
368 uhTmp = strlen(str);
369 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
370
371 /* String data (ANSI or Unicode) */
372 if (!bUnicode)
373 {
374 fwrite(str, uhTmp, 1, pFile);
375 }
376 else
377 {
378 wchar_t tmpBufferU[1024]; // Large-enough buffer for string conversions.
379 uhTmp = (uint16_t)mbstowcs(tmpBufferU, str, _countof(tmpBufferU));
380 fwrite(tmpBufferU, uhTmp * sizeof(wchar_t), 1, pFile);
381 }
382}
383
384int main(int argc, const char *argv[])
385{
386 const char *pszOutputPath = "shortcut.lnk";
387 const char *pszTarget = NULL;
388 const char *pszDescription = NULL;
389 const char *pszWorkingDir = NULL;
390 const char *pszCmdLineArgs = NULL;
391 const char *pszIcon = NULL;
392 char targetpath[MAX_PATH];
393 int32_t IconIndex = 0;
394 GUID Guid = CLSID_MyComputer;
395 bool bHelp = false, bUnicode = false, bMinimized = false;
396 int i;
397 FILE *pFile;
399 uint32_t dwTmp;
400 const struct SPECIALFOLDER *special;
401 EXP_SPECIAL_FOLDER CsidlBlock, *pCsidlBlock = NULL;
402 EXP_SZ_LINK SzLinkBlock, *pSzLinkBlock = NULL;
403 EXP_SZ_LINK SzIconBlock, *pSzIconBlock = NULL;
404
405 /* Check for verbose mode in the command-line */
406 for (i = 1; i < argc; ++i)
407 {
408 if ((argv[i][0] == '-' || argv[i][0] == '/') &&
409 !strcmp(argv[i] + 1, "v"))
410 {
411 g_Verbose = true;
412 break;
413 }
414 }
415
416 /* Parse the command-line */
417 for (i = 1; i < argc; ++i)
418 {
419 trace("argv[%d]: %s\n", i, argv[i]);
420
421 if (argv[i][0] != '-' && argv[i][0] != '/')
422 pszTarget = argv[i];
423 else if (!strcmp(argv[i] + 1, "h"))
424 bHelp = true;
425 else if (!strcmp(argv[i] + 1, "v"))
426 /* Verbose mode, separately handled above */;
427 else if (!strcmp(argv[i] + 1, "o") && (i + 1 < argc))
428 {
429 ++i;
430 trace("argv[%d]: %s\n", i, argv[i]);
431 pszOutputPath = argv[i];
432 }
433 else if (!strcmp(argv[i] + 1, "u"))
434 bUnicode = true;
435 else if (!strcmp(argv[i] + 1, "d") && (i + 1 < argc))
436 {
437 ++i;
438 trace("argv[%d]: %s\n", i, argv[i]);
439 pszDescription = argv[i];
440 }
441 else if (!strcmp(argv[i] + 1, "w") && (i + 1 < argc))
442 {
443 ++i;
444 trace("argv[%d]: %s\n", i, argv[i]);
445 pszWorkingDir = argv[i];
446 }
447 else if (!strcmp(argv[i] + 1, "c") && (i + 1 < argc))
448 {
449 ++i;
450 trace("argv[%d]: %s\n", i, argv[i]);
451 pszCmdLineArgs = argv[i];
452 }
453 else if (!strcmp(argv[i] + 1, "i") && (i + 1 < argc))
454 {
455 ++i;
456 trace("argv[%d]: %s\n", i, argv[i]);
457 pszIcon = argv[i];
458 }
459 else if (!strcmp(argv[i] + 1, "m"))
460 bMinimized = true;
461 else if (!strcmp(argv[i] + 1, "g") && (i + 1 < argc))
462 {
463 unsigned Data4Tmp[8], j;
464
465 ++i;
466 trace("argv[%d]: %s\n", i, argv[i]);
467 sscanf(argv[i], "{%8x-%4hx-%4hx-%2x%2x-%2x%2x%2x%2x%2x%2x}",
468 &Guid.Data1, &Guid.Data2, &Guid.Data3,
469 &Data4Tmp[0], &Data4Tmp[1], &Data4Tmp[2], &Data4Tmp[3],
470 &Data4Tmp[4], &Data4Tmp[5], &Data4Tmp[6], &Data4Tmp[7]);
471 for (j = 0; j < 8; ++j)
472 Guid.Data4[j] = (uint8_t)Data4Tmp[j];
473 }
474 else
475 {
476 printf("Invalid option: %s\n", argv[i]);
477 bHelp = true;
478 }
479 }
480 if (argc > 1)
481 trace("\n");
482
483 if (!pszTarget || bHelp)
484 {
485 printf("Usage: %s [-h][-v][-o path][-u][-d descr][-w path][-c cmdline_args][-i [icon_path[,nr]]][-g guid] target\n"
486 "-h\tShows this help.\n"
487 "-v\tEnables verbose mode for diagnostics.\n"
488 "-o path\tSets the output path.\n"
489 "-u\tCreates a Unicode-aware shortcut.\n"
490 "-d descr\tSets the shortcut description.\n"
491 "-w path\tSets the working directory for the executable.\n"
492 "-c cmdline_args\tSets the command-line arguments passed to the program.\n"
493 "-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"
494 "-m\tStart minimized.\n"
495 "-g guid\tSets the GUID to which the target path is relative. Default value is MyComputer GUID.\n"
496 "target\tAbsolute or relative to GUID specified with the -g option path.\n", argv[0]);
497 return 0;
498 }
499
500 /* Process the parameters */
501 if (pszTarget)
502 strip_quotes_and_unescape_envvars((char**)&pszTarget);
503 if (pszWorkingDir)
504 strip_quotes_and_unescape_envvars((char**)&pszWorkingDir);
505 if (pszCmdLineArgs)
506 strip_quotes_and_unescape_envvars((char**)&pszCmdLineArgs);
507 if (pszIcon)
508 {
509 char *ptr, *endptr;
510
511 strip_quotes_and_unescape_envvars((char**)&pszIcon);
512
513 /* Check whether only an icon index was given */
514 dwTmp = strtol(pszIcon, &endptr, 0);
515 if (endptr && endptr != pszIcon)
516 {
517 /* Only an index was given; save it, and use the target as the icon file */
518 IconIndex = dwTmp;
519 pszIcon = (char*)1; // Canary value to tell to use pszTarget, once resolved.
520 }
521 else
522 {
523 /* No index was given: this is a file path, optionally followed by the icon index */
524 ptr = strrchr(pszIcon, ',');
525 if (ptr) // && isdigit(ptr[1])
526 {
527 /* We may have an index that follows the icon path */
528 dwTmp = strtol(ptr+1, &endptr, 0);
529 if (endptr && endptr != (ptr+1))
530 {
531 /* It's valid, retrieve it and truncate the string to where the icon path ends */
532 IconIndex = dwTmp;
533 *ptr = '\0';
534 }
535 }
536 pszIcon = pszIcon;
537 }
538 }
539
540 trace("OutputPath = %s\n"
541 "Target = %s\n"
542 "Description = %s\n"
543 "WorkingDir = %s\n"
544 "CmdLineArgs = %s\n"
545 "Icon = %s (%d)\n\n",
546 pszOutputPath, pszTarget, pszDescription,
547 pszWorkingDir, pszCmdLineArgs,
548 (pszIcon == (char*)1) ? pszTarget : pszIcon, IconIndex);
549
550 pFile = fopen(pszOutputPath, "wb");
551 if (!pFile)
552 {
553 printf("Failed to open %s\n", pszOutputPath);
554 return -1;
555 }
556
557 /* Header */
558 memset(&Header, 0, sizeof(Header));
559 Header.Size = sizeof(Header);
560 Header.Guid = CLSID_ShellLink;
561 Header.Flags = LINK_ID_LIST;
562 if (bUnicode)
563 Header.Flags |= LINK_UNICODE;
564 if (pszDescription)
565 Header.Flags |= LINK_DESCRIPTION;
566 if (pszWorkingDir)
567 Header.Flags |= LINK_WORKING_DIR;
568 if (pszCmdLineArgs)
569 Header.Flags |= LINK_CMDLINE_ARGS;
570 if (pszIcon)
571 Header.Flags |= LINK_ICON;
572 Header.IconIndex = IconIndex;
573 Header.ShowCmd = (bMinimized ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL);
574
575 /* Verify the target type before proceeding further */
576 special = get_special_folder(pszTarget);
577 if (special)
578 Header.Flags |= LINK_ID_LIST; // Definitively needed in this case.
579
580 /* Check whether the target path contains Win32 environment variables */
581 if (has_env_variables(pszTarget))
582 {
583 Header.Flags |= SLDF_HAS_EXP_SZ;
584 Header.Flags &= ~LINK_ID_LIST; // We cannot deal with PIDLs in this case.
585 }
586 if ((Header.Flags & LINK_ID_LIST) && special)
587 Header.Flags &= ~LINK_RELATIVE_PATH;
588
589 /* If it's not a direct target, check whether it uses a special
590 * folder that is defined using Win32 environment variables */
591 if (special && special->unexpPath && has_env_variables(special->unexpPath))
592 Header.Flags |= SLDF_HAS_EXP_SZ;
593
594 /*
595 * For the icon, first check the canary value that tells to use the target path.
596 * If present, the icon path will contain Win32 environment variables if the target has them.
597 * Otherwise, explicitly check whether the specified icon path contains environment variables.
598 */
599 if ((pszIcon == (char*)1) && (Header.Flags & SLDF_HAS_EXP_SZ))
601 else if (pszIcon && has_env_variables(pszIcon))
603
604 trace("Header.Flags = 0x%08x\n"
605 "Header.IconIndex = %d\n"
606 "Header.ShowCmd = %u\n",
607 Header.Flags, Header.IconIndex, Header.ShowCmd);
608
609 fwrite(&Header, sizeof(Header), 1, pFile);
610
611 if (Header.Flags & LINK_ID_LIST)
612 {
613 ID_LIST_GUID IdListGuid;
614 ID_LIST_DRIVE IdListDrive;
615 ID_LIST_FILE IdListFile;
616 unsigned int cbListSize = sizeof(IdListGuid) + sizeof(uint16_t);
617 unsigned int cchName;
618 const char *pszName;
619 const char *pszOrgTarget = pszTarget;
620 size_t specialPathLen = 0;
621 uint16_t uhTmp;
622
623 /* ID list. It appears explorer does not accept links
624 * without an ID list. It is relative to desktop. */
625 if (special)
626 {
627 CsidlBlock.cbSize = sizeof(CsidlBlock);
629 CsidlBlock.idSpecialFolder = special->csidl;
630 specialPathLen = strlen(special->dummyPath);
631 sprintf(targetpath, "%s\\%s", special->dummyPath, pszOrgTarget + sizeof("shell:") + strlen(special->name));
632 pszTarget = targetpath;
633 }
634 pszName = pszTarget;
635
636 if (pszName[0] && pszName[0] != ':' && pszName[1] == ':')
637 {
638 cbListSize += sizeof(IdListDrive);
639 pszName += 2;
640 while (is_path_separator(*pszName))
641 ++pszName;
642 }
643
644 while (*pszName)
645 {
646 cchName = 0;
647 while (pszName[cchName] && !is_path_separator(pszName[cchName]))
648 ++cchName;
649
650 if (cchName != 1 || pszName[0] != '.')
651 {
652 /* Don't care about the DOS name */
653 //cbListSize += sizeof(IdListFile) + 2 * (cchName + 1);
654 cbListSize += sizeof(IdListFile) + (cchName + 1) + 1;
655 }
656
657 if (special && ((pszName+cchName)-pszTarget == specialPathLen))
658 {
659 /* Point the special folder block to the rest of the path in the ID list */
660 CsidlBlock.cbOffset = cbListSize - sizeof(uint16_t);
661 pCsidlBlock = &CsidlBlock;
662 }
663
664 pszName += cchName;
665 while (is_path_separator(*pszName))
666 ++pszName;
667 }
668
669 /* ID list size */
670 uhTmp = cbListSize;
671 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
672
673 IdListGuid.Size = sizeof(IdListGuid);
674 IdListGuid.Type = PT_GUID;
676 IdListGuid.guid = Guid;
677 fwrite(&IdListGuid, sizeof(IdListGuid), 1, pFile);
678
679 pszName = pszTarget;
680
681 if (isalpha(pszName[0]) && pszName[1] == ':')
682 {
683 memset(&IdListDrive, 0, sizeof(IdListDrive));
684 IdListDrive.Size = sizeof(IdListDrive);
685 IdListDrive.Type = PT_DRIVE1;
686 sprintf(IdListDrive.szDriveName, "%c:\\", pszName[0]);
687 fwrite(&IdListDrive, sizeof(IdListDrive), 1, pFile);
688 pszName += 2;
689 while (is_path_separator(*pszName))
690 ++pszName;
691 }
692
693 while (*pszName)
694 {
695 cchName = 0;
696 while (pszName[cchName] && !is_path_separator(pszName[cchName]))
697 ++cchName;
698
699 if (cchName != 1 || pszName[0] != '.')
700 {
701 memset(&IdListFile, 0, sizeof(IdListFile));
702 /* Don't care about the DOS name */
703 //IdListFile.Size = sizeof(IdListFile) + 2 * (cchName + 1);
704 IdListFile.Size = sizeof(IdListFile) + (cchName + 1) + 1;
705 if (!pszName[cchName])
706 IdListFile.Type = PT_VALUE; // File
707 else
708 IdListFile.Type = PT_FOLDER;
709 fwrite(&IdListFile, sizeof(IdListFile), 1, pFile);
710 fwrite(pszName, cchName, 1, pFile);
711 fputc(0, pFile); // NUL-terminate
712 /* Don't care about the DOS name */
713 //fwrite(pszName, cchName, 1, pFile);
714 fputc(0, pFile); // NUL-terminate
715 }
716
717 pszName += cchName;
718 while (is_path_separator(*pszName))
719 ++pszName;
720 }
721
722 /* End of ID list */
723 uhTmp = 0;
724 fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
725
726 /* Reset the target path to the actual unexpanded path */
727 if (special)
728 {
729 sprintf(targetpath, "%s\\%s", special->unexpPath, pszOrgTarget + sizeof("shell:") + strlen(special->name));
730 pszTarget = targetpath;
731 }
732 }
733
734 /* Now, set the icon path to the target path if it has the specific canary value */
735 if (pszIcon == (char*)1)
736 pszIcon = pszTarget;
737
738 if (Header.Flags & SLDF_HAS_EXP_SZ)
739 {
740 memset(&SzLinkBlock, 0, sizeof(SzLinkBlock));
741 SzLinkBlock.cbSize = sizeof(SzLinkBlock);
742 SzLinkBlock.dwSignature = EXP_SZ_LINK_SIG;
743
744 /* We have to store both ANSI and UTF16 versions of the string! */
745 strncpy(SzLinkBlock.szTarget, pszTarget, _countof(SzLinkBlock.szTarget));
746 mbstowcs(SzLinkBlock.szwTarget, pszTarget, _countof(SzLinkBlock.szwTarget));
747
748 pSzLinkBlock = &SzLinkBlock;
749 }
750
751 if (Header.Flags & SLDF_HAS_EXP_ICON_SZ)
752 {
753 memset(&SzIconBlock, 0, sizeof(SzIconBlock));
754 SzIconBlock.cbSize = sizeof(SzIconBlock);
755 SzIconBlock.dwSignature = EXP_SZ_ICON_SIG;
756
757 /* We have to store both ANSI and UTF16 versions of the string! */
758 strncpy(SzIconBlock.szTarget, pszIcon, _countof(SzIconBlock.szTarget));
759 mbstowcs(SzIconBlock.szwTarget, pszIcon, _countof(SzIconBlock.szwTarget));
760
761 pSzIconBlock = &SzIconBlock;
762 }
763
764 /* Description */
765 if (Header.Flags & LINK_DESCRIPTION)
766 write_string(pFile, bUnicode, pszDescription);
767
768 /* Relative path */
769 if (Header.Flags & LINK_RELATIVE_PATH)
770 write_string(pFile, bUnicode, pszTarget);
771
772 /* Working directory */
773 if (Header.Flags & LINK_WORKING_DIR)
774 write_string(pFile, bUnicode, pszWorkingDir);
775
776 /* Command-line arguments */
777 if (Header.Flags & LINK_CMDLINE_ARGS)
778 write_string(pFile, bUnicode, pszCmdLineArgs);
779
780 /* Icon path */
781 if (Header.Flags & LINK_ICON)
782 write_string(pFile, bUnicode, pszIcon);
783
784 /* Write the data block list */
785 if (pCsidlBlock)
786 fwrite(pCsidlBlock, sizeof(*pCsidlBlock), 1, pFile);
787 if (pSzLinkBlock)
788 fwrite(pSzLinkBlock, sizeof(*pSzLinkBlock), 1, pFile);
789 if (pSzIconBlock)
790 fwrite(pSzIconBlock, sizeof(*pSzIconBlock), 1, pFile);
791 /* End of data block list */
792 dwTmp = 0;
793 fwrite(&dwTmp, sizeof(dwTmp), 1, pFile);
794
795 fclose(pFile);
796
797 return 0;
798}
#define isspace(c)
Definition: acclib.h:69
#define isalpha(c)
Definition: acclib.h:74
#define trace
Definition: atltest.h:70
Definition: Header.h:9
#define NULL
Definition: types.h:112
INT32 int32_t
Definition: types.h:71
UINT32 uint32_t
Definition: types.h:75
MonoAssembly int argc
Definition: metahost.c:107
int CDECL vprintf(const char *format, va_list valist)
Definition: file.c:5517
int CDECL fclose(FILE *file)
Definition: file.c:3757
FILE *CDECL fopen(const char *path, const char *mode)
Definition: file.c:4310
int CDECL fputc(int c, FILE *file)
Definition: file.c:4360
size_t CDECL fwrite(const void *ptr, size_t size, size_t nmemb, FILE *file)
Definition: file.c:4129
#define __int8
Definition: corecrt.h:60
#define __int16
Definition: corecrt.h:63
#define __int32
Definition: corecrt.h:66
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
unsigned short uint16_t
Definition: stdint.h:35
unsigned char uint8_t
Definition: stdint.h:33
_ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl sscanf(const char *, const char *,...) __WINE_CRT_SCANF_ATTR(2
_ACRTIMP __msvcrt_long __cdecl strtol(const char *, char **, int)
Definition: string.c:1833
_ACRTIMP char *__cdecl strchr(const char *, int)
Definition: string.c:3286
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
char * va_list
Definition: vadefs.h:50
static const WCHAR IconIndex[]
Definition: install.c:52
int main()
Definition: test.c:6
#define strcasecmp
Definition: fake.h:9
#define printf
Definition: freeldr.h:103
MdFileObject pFile
GLuint GLuint GLsizei count
Definition: gl.h:1545
const GLubyte * c
Definition: glext.h:8905
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLenum GLsizei len
Definition: glext.h:6722
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
static PVOID ptr
Definition: dispmode.c:27
#define sprintf
Definition: sprintf.c:45
#define argv
Definition: mplay32.c:18
#define uint32_t
Definition: nsiface.idl:61
#define int32_t
Definition: nsiface.idl:56
#define uint16_t
Definition: nsiface.idl:60
#define uint8_t
Definition: nsiface.idl:59
const WCHAR * str
strncpy
Definition: string.h:335
#define memset(x, y, z)
Definition: compat.h:39
#define args
Definition: format.c:66
DWORD idSpecialFolder
Definition: shlobj.h:2049
const char * name
Definition: mkshelllink.c:230
const char * unexpPath
Definition: mkshelllink.c:232
const char * dummyPath
Definition: mkshelllink.c:231
unsigned char csidl
Definition: mkshelllink.c:229
uint32_t idSpecialFolder
Definition: mkshelllink.c:201
uint32_t dwHighDateTime
Definition: mkshelllink.c:68
uint32_t dwLowDateTime
Definition: mkshelllink.c:67
Definition: scsiwmi.h:51
unsigned char Data4[8]
Definition: scsiwmi.h:55
uint16_t Data2
Definition: mkshelllink.c:59
uint32_t Data1
Definition: mkshelllink.c:58
uint16_t Data3
Definition: mkshelllink.c:60
uint16_t unknown
Definition: mkshelllink.c:178
char szDriveName[20]
Definition: mkshelllink.c:177
uint16_t Size
Definition: mkshelllink.c:175
char szName[0]
Definition: mkshelllink.c:193
uint16_t uFileDate
Definition: mkshelllink.c:188
uint32_t dwFileSize
Definition: mkshelllink.c:187
uint8_t Type
Definition: mkshelllink.c:185
uint16_t uFileTime
Definition: mkshelllink.c:189
uint8_t dummy
Definition: mkshelllink.c:186
uint16_t Size
Definition: mkshelllink.c:184
uint16_t uFileAttribs
Definition: mkshelllink.c:190
uint8_t uSortOrder
Definition: mkshelllink.c:168
uint8_t Type
Definition: mkshelllink.c:167
uint16_t Size
Definition: mkshelllink.c:166
uint32_t ShowCmd
Definition: mkshelllink.c:121
int32_t IconIndex
Definition: mkshelllink.c:120
uint32_t Flags
Definition: mkshelllink.c:114
uint32_t Attributes
Definition: mkshelllink.c:115
uint32_t Size
Definition: mkshelllink.c:112
uint16_t HotKey
Definition: mkshelllink.c:122
FILETIME CreationTime
Definition: mkshelllink.c:116
uint32_t FileSizeLow
Definition: mkshelllink.c:119
uint16_t Reserved1
Definition: mkshelllink.c:123
FILETIME LastWriteTime
Definition: mkshelllink.c:118
FILETIME LastAccessTime
Definition: mkshelllink.c:117
uint32_t Reserved3
Definition: mkshelllink.c:125
uint32_t Reserved2
Definition: mkshelllink.c:124
uint32_t DataOffset
Definition: mkshelllink.c:132
uint32_t LocalBasePathnameOffset
Definition: mkshelllink.c:135
uint32_t LocalVolumeInfoOffset
Definition: mkshelllink.c:134
uint32_t RemainingPathnameOffset
Definition: mkshelllink.c:137
uint32_t NetworkVolumeInfoOffset
Definition: mkshelllink.c:136
Definition: match.c:390
Definition: format.c:58
Definition: tools.h:99
_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:2521