ReactOS 0.4.17-dev-186-g2161146
mkshelllink.c File Reference
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>
Include dependency graph for mkshelllink.c:

Go to the source code of this file.

Classes

struct  _GUID
 
struct  _FILETIME
 
struct  _LNK_HEADER
 
struct  _LNK_LOCATOR_INFO
 
struct  _LNK_LOCAL_VOLUME_INFO
 
struct  _ID_LIST_GUID
 
struct  _ID_LIST_DRIVE
 
struct  _ID_LIST_FILE
 
struct  _EXP_SPECIAL_FOLDER
 
struct  _EXP_SZ_LINK
 
struct  SPECIALFOLDER
 

Macros

#define C_ASSERT(expr)   extern char (*c_assert(void)) [(expr) ? 1 : -1]
 
#define __cdecl
 
#define _countof(_Array)   (sizeof(_Array) / sizeof(_Array[0]))
 
#define min(a, b)   (((a) < (b)) ? (a) : (b))
 
#define SW_SHOWNORMAL   1
 
#define SW_SHOWMINNOACTIVE   7
 
#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 LOCATOR_LOCAL   0x1
 
#define LOCATOR_NETWORK   0x2
 
#define SLDF_DEFAULT   0x00000000
 
#define SLDF_HAS_ID_LIST   0x00000001
 
#define SLDF_HAS_LINK_INFO   0x00000002
 
#define SLDF_HAS_NAME   0x00000004
 
#define SLDF_HAS_RELPATH   0x00000008
 
#define SLDF_HAS_WORKINGDIR   0x00000010
 
#define SLDF_HAS_ARGS   0x00000020
 
#define SLDF_HAS_ICONLOCATION   0x00000040
 
#define SLDF_UNICODE   0x00000080
 
#define SLDF_HAS_EXP_SZ   0x00000200
 
#define SLDF_HAS_EXP_ICON_SZ   0x00004000
 
#define LINK_ID_LIST   SLDF_HAS_ID_LIST
 
#define LINK_FILE   SLDF_HAS_LINK_INFO
 
#define LINK_DESCRIPTION   SLDF_HAS_NAME
 
#define LINK_RELATIVE_PATH   SLDF_HAS_RELPATH
 
#define LINK_WORKING_DIR   SLDF_HAS_WORKINGDIR
 
#define LINK_CMDLINE_ARGS   SLDF_HAS_ARGS
 
#define LINK_ICON   SLDF_HAS_ICONLOCATION
 
#define LINK_UNICODE   SLDF_UNICODE
 
#define PT_GUID   0x1F
 
#define PT_DRIVE1   0x2F
 
#define PT_FOLDER   0x31
 
#define PT_VALUE   0x32
 
#define REGITEMORDER_DEFAULT   0x80
 
#define REGITEMORDER_LIBRARIES   0x42
 
#define REGITEMORDER_USERSFILEFOLDER   0x44
 
#define REGITEMORDER_MYCOMPUTER   0x50
 
#define EXP_SPECIAL_FOLDER_SIG   0xA0000005
 
#define MAX_PATH   260
 
#define EXP_SZ_LINK_SIG   0xA0000001
 
#define EXP_SZ_ICON_SIG   0xA0000007
 
#define CSIDL_WINDOWS   0x24
 
#define CSIDL_SYSTEM   0x25
 
#define mbstowcs   my_mbstowcs
 

Typedefs

typedef struct _GUID GUID
 
typedef struct _FILETIME FILETIME
 
typedef struct _FILETIMEPFILETIME
 
typedef struct _LNK_HEADER LNK_HEADER
 
typedef struct _LNK_LOCATOR_INFO LNK_LOCATOR_INFO
 
typedef struct _LNK_LOCAL_VOLUME_INFO LNK_LOCAL_VOLUME_INFO
 
typedef struct _ID_LIST_GUID ID_LIST_GUID
 
typedef struct _ID_LIST_DRIVE ID_LIST_DRIVE
 
typedef struct _ID_LIST_FILE ID_LIST_FILE
 
typedef struct _EXP_SPECIAL_FOLDER EXP_SPECIAL_FOLDER
 
typedef struct _EXP_SZ_LINK EXP_SZ_LINK
 

Functions

 C_ASSERT (sizeof(wchar_t)==sizeof(uint16_t))
 
 C_ASSERT (sizeof(GUID)==16)
 
 DEFINE_GUID2 (CLSID_ShellLink, 0x00021401, 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)
 
size_t my_mbstowcs (wchar_t *wcstr, const char *mbstr, size_t count)
 
static void __cdecl trace (const char *format,...)
 
static bool is_path_separator (char c)
 
static bool has_env_variables (const char *str)
 
static void strip_quotes_and_unescape_envvars (char **pstr)
 
static const struct SPECIALFOLDERget_special_folder (const char *target)
 
static void write_string (FILE *pFile, bool bUnicode, const char *str)
 
int main (int argc, const char *argv[])
 

Variables

static bool g_Verbose = false
 
static const struct SPECIALFOLDER g_specialfolders []
 

Macro Definition Documentation

◆ __cdecl

#define __cdecl

Definition at line 25 of file mkshelllink.c.

◆ _countof

#define _countof (   _Array)    (sizeof(_Array) / sizeof(_Array[0]))

Definition at line 40 of file mkshelllink.c.

◆ C_ASSERT

#define C_ASSERT (   expr)    extern char (*c_assert(void)) [(expr) ? 1 : -1]

Definition at line 20 of file mkshelllink.c.

◆ CSIDL_SYSTEM

#define CSIDL_SYSTEM   0x25

Definition at line 226 of file mkshelllink.c.

◆ CSIDL_WINDOWS

#define CSIDL_WINDOWS   0x24

Definition at line 225 of file mkshelllink.c.

◆ DEFINE_GUID2

#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 } }

Definition at line 71 of file mkshelllink.c.

◆ EXP_SPECIAL_FOLDER_SIG

#define EXP_SPECIAL_FOLDER_SIG   0xA0000005

Definition at line 196 of file mkshelllink.c.

◆ EXP_SZ_ICON_SIG

#define EXP_SZ_ICON_SIG   0xA0000007

Definition at line 208 of file mkshelllink.c.

◆ EXP_SZ_LINK_SIG

#define EXP_SZ_LINK_SIG   0xA0000001

Definition at line 207 of file mkshelllink.c.

◆ LINK_CMDLINE_ARGS

#define LINK_CMDLINE_ARGS   SLDF_HAS_ARGS

Definition at line 105 of file mkshelllink.c.

◆ LINK_DESCRIPTION

#define LINK_DESCRIPTION   SLDF_HAS_NAME

Definition at line 102 of file mkshelllink.c.

◆ LINK_FILE

#define LINK_FILE   SLDF_HAS_LINK_INFO

Definition at line 101 of file mkshelllink.c.

◆ LINK_ICON

#define LINK_ICON   SLDF_HAS_ICONLOCATION

Definition at line 106 of file mkshelllink.c.

◆ LINK_ID_LIST

#define LINK_ID_LIST   SLDF_HAS_ID_LIST

Definition at line 100 of file mkshelllink.c.

◆ LINK_RELATIVE_PATH

#define LINK_RELATIVE_PATH   SLDF_HAS_RELPATH

Definition at line 103 of file mkshelllink.c.

◆ LINK_UNICODE

#define LINK_UNICODE   SLDF_UNICODE

Definition at line 107 of file mkshelllink.c.

◆ LINK_WORKING_DIR

#define LINK_WORKING_DIR   SLDF_HAS_WORKINGDIR

Definition at line 104 of file mkshelllink.c.

◆ LOCATOR_LOCAL

#define LOCATOR_LOCAL   0x1

Definition at line 75 of file mkshelllink.c.

◆ LOCATOR_NETWORK

#define LOCATOR_NETWORK   0x2

Definition at line 76 of file mkshelllink.c.

◆ MAX_PATH

#define MAX_PATH   260

Definition at line 205 of file mkshelllink.c.

◆ mbstowcs

#define mbstowcs   my_mbstowcs

Definition at line 272 of file mkshelllink.c.

◆ min

#define min (   a,
  b 
)    (((a) < (b)) ? (a) : (b))

Definition at line 43 of file mkshelllink.c.

◆ PT_DRIVE1

#define PT_DRIVE1   0x2F

Definition at line 153 of file mkshelllink.c.

◆ PT_FOLDER

#define PT_FOLDER   0x31

Definition at line 154 of file mkshelllink.c.

◆ PT_GUID

#define PT_GUID   0x1F

Definition at line 152 of file mkshelllink.c.

◆ PT_VALUE

#define PT_VALUE   0x32

Definition at line 155 of file mkshelllink.c.

◆ REGITEMORDER_DEFAULT

#define REGITEMORDER_DEFAULT   0x80

Definition at line 158 of file mkshelllink.c.

◆ REGITEMORDER_LIBRARIES

#define REGITEMORDER_LIBRARIES   0x42

Definition at line 159 of file mkshelllink.c.

◆ REGITEMORDER_MYCOMPUTER

#define REGITEMORDER_MYCOMPUTER   0x50

Definition at line 161 of file mkshelllink.c.

◆ REGITEMORDER_USERSFILEFOLDER

#define REGITEMORDER_USERSFILEFOLDER   0x44

Definition at line 160 of file mkshelllink.c.

◆ SLDF_DEFAULT

#define SLDF_DEFAULT   0x00000000

Definition at line 88 of file mkshelllink.c.

◆ SLDF_HAS_ARGS

#define SLDF_HAS_ARGS   0x00000020

Definition at line 94 of file mkshelllink.c.

◆ SLDF_HAS_EXP_ICON_SZ

#define SLDF_HAS_EXP_ICON_SZ   0x00004000

Definition at line 98 of file mkshelllink.c.

◆ SLDF_HAS_EXP_SZ

#define SLDF_HAS_EXP_SZ   0x00000200

Definition at line 97 of file mkshelllink.c.

◆ SLDF_HAS_ICONLOCATION

#define SLDF_HAS_ICONLOCATION   0x00000040

Definition at line 95 of file mkshelllink.c.

◆ SLDF_HAS_ID_LIST

#define SLDF_HAS_ID_LIST   0x00000001

Definition at line 89 of file mkshelllink.c.

◆ SLDF_HAS_LINK_INFO

#define SLDF_HAS_LINK_INFO   0x00000002

Definition at line 90 of file mkshelllink.c.

◆ SLDF_HAS_NAME

#define SLDF_HAS_NAME   0x00000004

Definition at line 91 of file mkshelllink.c.

◆ SLDF_HAS_RELPATH

#define SLDF_HAS_RELPATH   0x00000008

Definition at line 92 of file mkshelllink.c.

◆ SLDF_HAS_WORKINGDIR

#define SLDF_HAS_WORKINGDIR   0x00000010

Definition at line 93 of file mkshelllink.c.

◆ SLDF_UNICODE

#define SLDF_UNICODE   0x00000080

Definition at line 96 of file mkshelllink.c.

◆ SW_SHOWMINNOACTIVE

#define SW_SHOWMINNOACTIVE   7

Definition at line 54 of file mkshelllink.c.

◆ SW_SHOWNORMAL

#define SW_SHOWNORMAL   1

Definition at line 53 of file mkshelllink.c.

Typedef Documentation

◆ EXP_SPECIAL_FOLDER

◆ EXP_SZ_LINK

◆ FILETIME

◆ GUID

typedef struct _GUID GUID

◆ ID_LIST_DRIVE

◆ ID_LIST_FILE

◆ ID_LIST_GUID

◆ LNK_HEADER

◆ LNK_LOCAL_VOLUME_INFO

◆ LNK_LOCATOR_INFO

◆ PFILETIME

Function Documentation

◆ C_ASSERT() [1/2]

C_ASSERT ( sizeof(GUID = =16)

◆ C_ASSERT() [2/2]

C_ASSERT ( sizeof(wchar_t = =sizeof(uint16_t))

◆ DEFINE_GUID2() [1/2]

DEFINE_GUID2 ( CLSID_MyComputer  ,
0x20D04FE0  ,
0x3AEA  ,
0x1069  ,
0xA2  ,
0xD8  ,
0x08  ,
0x00  ,
0x2B  ,
0x30  ,
0x30  ,
0x9D   
)

◆ DEFINE_GUID2() [2/2]

DEFINE_GUID2 ( CLSID_ShellLink  ,
0x00021401  ,
,
,
0xC0  ,
,
,
,
,
,
,
0x46   
)

◆ get_special_folder()

static const struct SPECIALFOLDER * get_special_folder ( const char target)
static

Definition at line 335 of file mkshelllink.c.

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}
#define NULL
Definition: types.h:112
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
#define strcasecmp
Definition: fake.h:9
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
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
strncpy
Definition: string.h:335
const char * name
Definition: mkshelllink.c:230
Definition: tools.h:99

Referenced by main().

◆ has_env_variables()

static bool has_env_variables ( const char str)
static

Definition at line 293 of file mkshelllink.c.

294{
295 const char *ptr = strchr(str, '%');
296 return (ptr && strchr(ptr + 1, '%'));
297}
_ACRTIMP char *__cdecl strchr(const char *, int)
Definition: string.c:3286
static PVOID ptr
Definition: dispmode.c:27
const WCHAR * str

Referenced by main().

◆ is_path_separator()

static bool is_path_separator ( char  c)
static

Definition at line 286 of file mkshelllink.c.

287{
288 return (c == '\\' || c == '/');
289}
const GLubyte * c
Definition: glext.h:8905

Referenced by get_special_folder(), and main().

◆ main()

int main ( int  argc,
const char argv[] 
)

Definition at line 384 of file mkshelllink.c.

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 isalpha(c)
Definition: acclib.h:74
#define trace
Definition: atltest.h:70
Definition: Header.h:9
INT32 int32_t
Definition: types.h:71
UINT32 uint32_t
Definition: types.h:75
MonoAssembly int argc
Definition: metahost.c:107
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
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 int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
static const WCHAR IconIndex[]
Definition: install.c:52
#define printf
Definition: freeldr.h:103
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 GLint GLint j
Definition: glfuncs.h:250
#define sprintf
Definition: sprintf.c:45
#define argv
Definition: mplay32.c:18
#define uint16_t
Definition: nsiface.idl:60
#define memset(x, y, z)
Definition: compat.h:39
DWORD idSpecialFolder
Definition: shlobj.h:2049
const char * unexpPath
Definition: mkshelllink.c:232
const char * dummyPath
Definition: mkshelllink.c:231
unsigned char csidl
Definition: mkshelllink.c:229
char szDriveName[20]
Definition: mkshelllink.c:177
uint16_t Size
Definition: mkshelllink.c:175
uint8_t Type
Definition: mkshelllink.c:185
uint16_t Size
Definition: mkshelllink.c:184
uint8_t uSortOrder
Definition: mkshelllink.c:168
uint8_t Type
Definition: mkshelllink.c:167
uint16_t Size
Definition: mkshelllink.c:166
_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

◆ my_mbstowcs()

size_t my_mbstowcs ( wchar_t wcstr,
const char mbstr,
size_t  count 
)

Definition at line 249 of file mkshelllink.c.

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}
GLuint GLuint GLsizei count
Definition: gl.h:1545

◆ strip_quotes_and_unescape_envvars()

static void strip_quotes_and_unescape_envvars ( char **  pstr)
static

Definition at line 299 of file mkshelllink.c.

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}
#define isspace(c)
Definition: acclib.h:69
GLenum GLenum dst
Definition: glext.h:6340

Referenced by main().

◆ trace()

static void __cdecl trace ( const char format,
  ... 
)
static

Definition at line 274 of file mkshelllink.c.

275{
277
278 if (!g_Verbose)
279 return;
280
283 va_end(args);
284}
int CDECL vprintf(const char *format, va_list valist)
Definition: file.c:5517
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
char * va_list
Definition: vadefs.h:50
#define args
Definition: format.c:66
Definition: match.c:390
Definition: format.c:58

◆ write_string()

static void write_string ( FILE pFile,
bool  bUnicode,
const char str 
)
static

Definition at line 363 of file mkshelllink.c.

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}

Referenced by main().

Variable Documentation

◆ g_specialfolders

const struct SPECIALFOLDER g_specialfolders[]
static
Initial value:
= {
{ CSIDL_WINDOWS, "windows", "X:\\reactos", "%SystemRoot%" },
{ CSIDL_SYSTEM, "system", "X:\\reactos\\system32", "%SystemRoot%\\system32" },
{ 0, NULL, NULL, NULL }
}

Referenced by get_special_folder().

◆ g_Verbose

bool g_Verbose = false
static

Definition at line 222 of file mkshelllink.c.

Referenced by main(), and trace().