ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mkshelllink.c
Go to the documentation of this file.
00001 /* COPYRIGHT:       See COPYING in the top level directory
00002  * PROJECT:         ReactOS Shell Link maker
00003  * FILE:            tools/mkshelllink/mkshelllink.c
00004  * PURPOSE:         Shell Link maker
00005  * PROGRAMMER:      Rafal Harabien
00006  */
00007 
00008 #include <stdio.h>
00009 #include <string.h>
00010 #include <ctype.h>
00011 #ifndef _MSC_VER
00012 #include <stdint.h>
00013 #else
00014 typedef unsigned __int8 uint8_t;
00015 typedef unsigned __int16 uint16_t;
00016 typedef unsigned __int32 uint32_t;
00017 #endif
00018 
00019 #define SW_SHOWNORMAL 1
00020 #define SW_SHOWMINNOACTIVE 7
00021 
00022 typedef struct _GUID {
00023     uint32_t Data1;
00024     uint16_t  Data2;
00025     uint16_t  Data3;
00026     uint8_t  Data4[8];
00027 } GUID;
00028 
00029 typedef struct _FILETIME {
00030     uint32_t dwLowDateTime;
00031     uint32_t dwHighDateTime;
00032 } FILETIME, *PFILETIME;
00033 
00034 #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 } }
00035 DEFINE_GUID2(CLSID_ShellLink,0x00021401L,0,0,0xC0,0,0,0,0,0,0,0x46);
00036 DEFINE_GUID2(CLSID_MyComputer,0x20D04FE0,0x3AEA,0x1069,0xA2,0xD8,0x08,0x00,0x2B,0x30,0x30,0x9D);
00037 
00038 #define LINK_ID_LIST       0x01
00039 #define LINK_FILE          0x02
00040 #define LINK_DESCRIPTION   0x04
00041 #define LINK_RELATIVE_PATH 0x08
00042 #define LINK_WORKING_DIR   0x10
00043 #define LINK_CMD_LINE_ARGS 0x20
00044 #define LINK_ICON          0x40
00045 #define LINK_UNICODE       0x80
00046 
00047 #define LOCATOR_LOCAL   0x1
00048 #define LOCATOR_NETWORK 0x2
00049 
00050 #pragma pack(push, 1)
00051 
00052 /* Specification: http://ithreats.files.wordpress.com/2009/05/lnk_the_windows_shortcut_file_format.pdf */
00053 
00054 typedef struct _LNK_HEADER
00055 {
00056     uint32_t Signature;
00057     GUID Guid;
00058     uint32_t Flags;
00059     uint32_t Attributes;
00060     FILETIME CreationTime;
00061     FILETIME ModificationTime;
00062     FILETIME LastAccessTime;
00063     uint32_t FileSize;
00064     uint32_t IconNr;
00065     uint32_t Show;
00066     uint32_t Hotkey;
00067     uint32_t Unknown;
00068     uint32_t Unknown2;
00069 } LNK_HEADER;
00070 
00071 typedef struct _LNK_LOCATOR_INFO
00072 {
00073     uint32_t Size;
00074     uint32_t DataOffset;
00075     uint32_t Flags;
00076     uint32_t LocalVolumeInfoOffset;
00077     uint32_t LocalBasePathnameOffset;
00078     uint32_t NetworkVolumeInfoOffset;
00079     uint32_t RemainingPathnameOffset;
00080     char Data[0];
00081 } LNK_LOCATOR_INFO;
00082 
00083 typedef struct _LNK_LOCAL_VOLUME_INFO
00084 {
00085     uint32_t Size;
00086     uint32_t VolumeType; /* See GetDriveType */
00087     uint32_t SerialNumber;
00088     uint32_t VolumeNameOffset;
00089     char VolumeLabel[0];
00090 } LNK_LOCAL_VOLUME_INFO;
00091 
00092 #define PT_GUID     0x1F
00093 #define PT_DRIVE1   0x2F
00094 #define PT_FOLDER   0x31
00095 #define PT_VALUE    0x32
00096 
00097 typedef struct _ID_LIST_FILE
00098 {
00099     uint16_t Size;
00100     uint8_t Type;
00101     uint8_t dummy;
00102     uint32_t dwFileSize;
00103     uint16_t uFileDate;
00104     uint16_t uFileTime;
00105     uint16_t uFileAttribs;
00106     char szName[0];
00107 } ID_LIST_FILE;
00108 
00109 typedef struct _ID_LIST_GUID
00110 {
00111     uint16_t Size;
00112     uint8_t Type;
00113     uint8_t dummy;
00114     GUID guid;
00115 } ID_LIST_GUID;
00116 
00117 typedef struct _ID_LIST_DRIVE
00118 {
00119     uint16_t Size;
00120     uint8_t Type;
00121     char szDriveName[20];
00122     uint16_t unknown;
00123 } ID_LIST_DRIVE;
00124 
00125 #pragma pack(pop)
00126 
00127 int main(int argc, const char *argv[])
00128 {
00129     unsigned i;
00130     const char *pszOutputPath = "shortcut.lnk";
00131     const char *pszTarget = NULL;
00132     const char *pszDescription = "Description";
00133     const char *pszWorkingDir = NULL;
00134     const char *pszCmdLineArgs = NULL;
00135     const char *pszIcon = NULL;
00136     int IconNr = 0;
00137     GUID Guid = CLSID_MyComputer;
00138     int bHelp = 0, bMinimized = 0;
00139     FILE *pFile;
00140     LNK_HEADER Header;
00141     uint16_t uhTmp;
00142     uint32_t dwTmp;
00143     
00144     for (i = 1; i < argc; ++i)
00145     {
00146         if (argv[i][0] != '-' && argv[i][0] != '/')
00147             pszTarget = argv[i];
00148         else if (!strcmp(argv[i] + 1, "h"))
00149             bHelp = 1;
00150         else if (!strcmp(argv[i] + 1, "o") && i + 1 < argc)
00151             pszOutputPath = argv[++i];
00152         else if (!strcmp(argv[i] + 1, "d") && i + 1 < argc)
00153             pszDescription = argv[++i];
00154         else if (!strcmp(argv[i] + 1, "w") && i + 1 < argc)
00155             pszWorkingDir = argv[++i];
00156         else if (!strcmp(argv[i] + 1, "c") && i + 1 < argc)
00157             pszCmdLineArgs = argv[++i];
00158         else if (!strcmp(argv[i] + 1, "i") && i + 1 < argc)
00159         {
00160             pszIcon = argv[++i];
00161             if (i + 1 < argc && isdigit(argv[i + 1][0]))
00162                 IconNr = atoi(argv[++i]);
00163         }
00164         else if (!strcmp(argv[i] + 1, "m"))
00165             bMinimized = 1;
00166         else if (!strcmp(argv[i] + 1, "g") && i + 1 < argc)
00167         {
00168             unsigned Data4Tmp[8], j;
00169             
00170             sscanf(argv[++i], "{%8lx-%4hx-%4hx-%2x%2x-%2x%2x%2x%2x%2x%2x}",
00171                   &Guid.Data1, &Guid.Data2, &Guid.Data3,
00172                   &Data4Tmp[0], &Data4Tmp[1], &Data4Tmp[2], &Data4Tmp[3],
00173                   &Data4Tmp[4], &Data4Tmp[5], &Data4Tmp[6], &Data4Tmp[7]);
00174             for (j = 0; j < 8; ++j)
00175                 Guid.Data4[j] = (uint8_t)Data4Tmp[j];
00176         }
00177         else
00178             printf("Invalid option: %s\n", argv[i]);
00179     }
00180     
00181     if (!pszTarget || bHelp)
00182     {
00183         printf("Usage: %s [-o path][-d descr][-w path][-c cmd_line_args][-i icon_path [nr]][-h][-g guid] target\n"
00184                "-o path\tSets output path\n"
00185                "-d descr\tSets shortcut description\n"
00186                "-w path\tSets working directory for executable\n"
00187                "-c cmd_line_args\tSets command line arguments passed to program\n"
00188                "-i icon_path [nr]\tSets icon file and optionally icon index\n"
00189                "-m\tStart minimized\n"
00190                "-g guid\tSets GUID to which target path is relative. Default value is MyComputer GUID.\n"
00191                "target\tAbsolute or relative to guid specified with -g option path\n", argv[0]);
00192         return 0;
00193     }
00194     
00195     pFile = fopen(pszOutputPath, "wb");
00196     if (!pFile)
00197     {
00198         printf("Failed to open %s\n", pszOutputPath);
00199         return -1;
00200     }
00201     
00202     // Header
00203     memset(&Header, 0, sizeof(Header));
00204     Header.Signature = (uint32_t)'L';
00205     Header.Guid = CLSID_ShellLink;
00206     Header.Flags = LINK_ID_LIST;
00207     if (pszDescription)
00208         Header.Flags |= LINK_DESCRIPTION;
00209     if (pszWorkingDir)
00210         Header.Flags |= LINK_WORKING_DIR;
00211     if (pszCmdLineArgs)
00212         Header.Flags |= LINK_CMD_LINE_ARGS;
00213     if (pszIcon)
00214         Header.Flags |= LINK_ICON;
00215     Header.IconNr = IconNr;
00216     Header.Show = bMinimized ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL;
00217     fwrite(&Header, sizeof(Header), 1, pFile);
00218     
00219     if (Header.Flags & LINK_ID_LIST)
00220     {
00221         ID_LIST_FILE IdListFile;
00222         ID_LIST_GUID IdListGuid;
00223         ID_LIST_DRIVE IdListDrive;
00224         unsigned cbListSize = sizeof(IdListGuid) + sizeof(uint16_t), cchName;
00225         const char *pszName = pszTarget;
00226         
00227         // ID list
00228         // It seems explorer does not accept links without id list. List is relative to desktop.
00229         
00230         pszName = pszTarget;
00231         
00232         if (pszName[0] && pszName[1] == ':')
00233         {
00234             cbListSize += sizeof(IdListDrive);
00235             pszName += 2;
00236             while (*pszName == '\\' || *pszName == '/')
00237                 ++pszName;
00238         }
00239         
00240         while (*pszName)
00241         {
00242             cchName = 0;
00243             while (pszName[cchName] && pszName[cchName] != '\\' && pszName[cchName] != '/')
00244                 ++cchName;
00245             
00246             if (cchName != 1 || pszName[0] != '.')
00247                 cbListSize += sizeof(IdListFile) + 2 * (cchName + 1);
00248             
00249             pszName += cchName;
00250             while (*pszName == '\\' || *pszName == '/')
00251                 ++pszName;
00252         }
00253         
00254         uhTmp = cbListSize;
00255         fwrite(&uhTmp, sizeof(uhTmp), 1, pFile); // size
00256         
00257         IdListGuid.Size = sizeof(IdListGuid);
00258         IdListGuid.Type = PT_GUID;
00259         IdListGuid.dummy = 0x50;
00260         IdListGuid.guid = Guid;
00261         fwrite(&IdListGuid, sizeof(IdListGuid), 1, pFile);
00262         
00263         pszName = pszTarget;
00264         
00265         if (isalpha(pszName[0]) && pszName[1] == ':')
00266         {
00267             memset(&IdListDrive, 0, sizeof(IdListDrive));
00268             IdListDrive.Size = sizeof(IdListDrive);
00269             IdListDrive.Type = PT_DRIVE1;
00270             sprintf(IdListDrive.szDriveName, "%c:\\", pszName[0]);
00271             fwrite(&IdListDrive, sizeof(IdListDrive), 1, pFile);
00272             pszName += 2;
00273             while(*pszName == '\\' || *pszName == '/')
00274                 ++pszName;
00275         }
00276         
00277         while (*pszName)
00278         {
00279             cchName = 0;
00280             while (pszName[cchName] && pszName[cchName] != '\\' && pszName[cchName] != '/')
00281                 ++cchName;
00282             
00283             if (cchName != 1 || pszName[0] != '.')
00284             {
00285                 memset(&IdListFile, 0, sizeof(IdListFile));
00286                 IdListFile.Size = sizeof(IdListFile) + 2 * (cchName + 1);
00287                 if (!pszName[cchName])
00288                     IdListFile.Type = PT_VALUE; // File
00289                 else
00290                     IdListFile.Type = PT_FOLDER;
00291                 fwrite(&IdListFile, sizeof(IdListFile), 1, pFile);
00292                 fwrite(pszName, cchName, 1, pFile);
00293                 fputc(0, pFile);
00294                 fwrite(pszName, cchName, 1, pFile);
00295                 fputc(0, pFile);
00296             }
00297             
00298             pszName += cchName;
00299             while (*pszName == '\\' || *pszName == '/')
00300                 ++pszName;
00301         }
00302         
00303         uhTmp = 0; // list end
00304         fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
00305     }
00306     
00307     if (Header.Flags & LINK_DESCRIPTION)
00308     {
00309         // Dscription
00310         uhTmp = strlen(pszDescription);
00311         fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
00312         fputs(pszDescription, pFile);
00313     }
00314     
00315     if (Header.Flags & LINK_RELATIVE_PATH)
00316     {
00317         // Relative Path
00318         uhTmp = strlen(pszTarget);
00319         fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
00320         fputs(pszTarget, pFile);
00321     }
00322     
00323     if (Header.Flags & LINK_WORKING_DIR)
00324     {
00325         // Working Dir
00326         uhTmp = strlen(pszWorkingDir);
00327         fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
00328         fputs(pszWorkingDir, pFile);
00329     }
00330     
00331     if (Header.Flags & LINK_CMD_LINE_ARGS)
00332     {
00333         // Command line arguments
00334         uhTmp = strlen(pszCmdLineArgs);
00335         fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
00336         fputs(pszCmdLineArgs, pFile);
00337     }
00338     
00339     if (Header.Flags & LINK_ICON)
00340     {
00341         // Command line arguments
00342         uhTmp = strlen(pszIcon);
00343         fwrite(&uhTmp, sizeof(uhTmp), 1, pFile);
00344         fputs(pszIcon, pFile);
00345     }
00346     
00347     // Extra stuff
00348     dwTmp = 0;
00349     fwrite(&dwTmp, sizeof(dwTmp), 1, pFile);
00350     
00351     fclose(pFile);
00352     
00353     return 0;
00354 }

Generated on Sun May 27 2012 04:37:46 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.