WINEDUMP: add dumping of lnk files

Mike McCormack mike at codeweavers.com
Thu Feb 17 00:41:58 CST 2005


Dump lnk files, including the MSI Advertised Shortcut fields.

Mike


ChangeLog:
* add dumping of lnk files
-------------- next part --------------
? tools/winedump/lnk.c
Index: tools/winedump/Makefile.in
===================================================================
RCS file: /home/wine/wine/tools/winedump/Makefile.in,v
retrieving revision 1.11
diff -u -p -r1.11 Makefile.in
--- tools/winedump/Makefile.in	4 Jan 2005 20:32:25 -0000	1.11
+++ tools/winedump/Makefile.in	17 Feb 2005 06:37:05 -0000
@@ -12,6 +12,7 @@ C_SRCS = \
 	debug.c \
 	emf.c \
 	le.c \
+	lnk.c \
 	main.c  \
 	misc.c  \
 	msmangle.c  \
Index: tools/winedump/main.c
===================================================================
RCS file: /home/wine/wine/tools/winedump/main.c,v
retrieving revision 1.17
diff -u -p -r1.17 main.c
--- tools/winedump/main.c	4 Jan 2005 20:32:25 -0000	1.17
+++ tools/winedump/main.c	17 Feb 2005 06:37:06 -0000
@@ -86,6 +86,13 @@ static void do_dumpemf(void)
 }
 
 
+static void do_dumplnk(void)
+{
+    if (globals.mode != NONE) fatal("Only one mode can be specified\n");
+    globals.mode = LNK;
+}
+
+
 static void do_code (void)
 {
   globals.do_code = 1;
@@ -221,6 +228,7 @@ static const struct option option_table[
   {"-j",    DUMP, 1, do_dumpsect, "-j sect_name Dumps only the content of section sect_name (import, export, debug, resource, tls)"},
   {"-x",    DUMP, 0, do_dumpall,  "-x           Dumps everything"},
   {"emf",   EMF,  0, do_dumpemf,  "emf          Dumps an Enhanced Meta File"},
+  {"lnk",   LNK,  0, do_dumplnk,  "lnk          Dumps a shortcut (.lnk) file"},
   {NULL,    NONE, 0, NULL,        NULL}
 };
 
@@ -249,6 +257,10 @@ void do_usage (void)
     for (opt = option_table; opt->name; opt++)
 	if (opt->mode == EMF)
 	    printf ("\t   %s\n", opt->usage);
+    printf ("\tWhen used in lnk mode\n");
+    for (opt = option_table; opt->name; opt++)
+	if (opt->mode == LNK)
+	    printf ("\t   %s\n", opt->usage);
 
     puts ("\n");
     exit (1);
@@ -485,6 +497,11 @@ int   main (int argc, char *argv[])
         if (globals.input_name == NULL)
             fatal("No file name has been given\n");
         dump_emf(globals.input_name);
+        break;
+    case LNK:
+        if (globals.input_name == NULL)
+            fatal("No file name has been given\n");
+        dump_lnk(globals.input_name);
         break;
     }
 
Index: tools/winedump/winedump.h
===================================================================
RCS file: /home/wine/wine/tools/winedump/winedump.h,v
retrieving revision 1.12
diff -u -p -r1.12 winedump.h
--- tools/winedump/winedump.h	4 Jan 2005 20:32:25 -0000	1.12
+++ tools/winedump/winedump.h	17 Feb 2005 06:37:06 -0000
@@ -72,7 +72,7 @@
 #define SYM_THISCALL        0x4
 #define SYM_DATA            0x8 /* Data, not a function */
 
-typedef enum {NONE, DMGL, SPEC, DUMP, EMF} Mode;
+typedef enum {NONE, DMGL, SPEC, DUMP, EMF, LNK} Mode;
 
 /* Structure holding a parsed symbol */
 typedef struct __parsed_symbol
@@ -155,6 +155,9 @@ extern _globals globals;
 
 /* EMF functions */
 int   dump_emf (const char *emf);
+
+/* LNK functions */
+int   dump_lnk (const char *lnk);
 
 /* Image functions */
 void	dump_file(const char* name);
--- /dev/null	2004-12-26 03:00:47.000000000 +0900
+++ tools/winedump/lnk.c	2005-02-17 15:30:37.000000000 +0900
@@ -0,0 +1,313 @@
+/*
+ *  Dump a shortcut (lnk) file
+ *
+ *  Copyright 2005 Mike McCormack
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+
+#include "pshpack1.h"
+
+#define SCF_PIDL 1
+#define SCF_LOCATION 2
+#define SCF_DESCRIPTION 4
+#define SCF_RELATIVE 8
+#define SCF_WORKDIR 0x10
+#define SCF_ARGS 0x20
+#define SCF_CUSTOMICON 0x40
+#define SCF_UNICODE 0x80
+#define SCF_PRODUCT 0x800
+#define SCF_COMPONENT 0x1000
+
+typedef struct _LINK_HEADER
+{
+    DWORD    dwSize;        /* 0x00 size of the header - 0x4c */
+    GUID     MagicGuid;     /* 0x04 is CLSID_ShellLink */
+    DWORD    dwFlags;       /* 0x14 describes elements following */
+    DWORD    dwFileAttr;    /* 0x18 attributes of the target file */
+    FILETIME Time1;         /* 0x1c */
+    FILETIME Time2;         /* 0x24 */
+    FILETIME Time3;         /* 0x2c */
+    DWORD    dwFileLength;  /* 0x34 File length */
+    DWORD    nIcon;         /* 0x38 icon number */
+    DWORD   fStartup;       /* 0x3c startup type */
+    DWORD   wHotKey;        /* 0x40 hotkey */
+    DWORD   Unknown5;       /* 0x44 */
+    DWORD   Unknown6;       /* 0x48 */
+} LINK_HEADER, * PLINK_HEADER;
+
+typedef struct tagLINK_ADVERTISEINFO
+{
+    DWORD size;
+    DWORD magic;
+    CHAR  bufA[MAX_PATH];
+    WCHAR bufW[MAX_PATH];
+} LINK_ADVERTISEINFO;
+
+typedef struct _LOCATION_INFO
+{
+    DWORD  dwTotalSize;
+    DWORD  dwHeaderSize;
+    DWORD  dwFlags;
+    DWORD  dwVolTableOfs;
+    DWORD  dwLocalPathOfs;
+    DWORD  dwNetworkVolTableOfs;
+    DWORD  dwFinalPathOfs;
+} LOCATION_INFO;
+
+typedef struct lnk_string_tag {
+    unsigned short size;
+    union {
+        unsigned short w[1];
+        unsigned char a[1];
+    } str;
+} lnk_string;
+
+#include "poppack.h"
+
+static void guid_to_string(LPGUID guid, char *str)
+{
+    sprintf(str, "{%08lx-%04x-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+            guid->Data1, guid->Data2, guid->Data3,
+            guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+            guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+}
+
+/* the size is a short integer */
+static void* load_pidl(int fd)
+{
+    int r;
+    unsigned char *data;
+    unsigned short size = 0;
+
+    r = read( fd, &size, sizeof size );
+    if (r != sizeof size)
+        return NULL;
+    if (size<sizeof size)
+        return NULL;
+
+    data = malloc(size + sizeof size);
+    memcpy(data, &size, sizeof size);
+    r = read( fd, data + sizeof size, size );
+    if (r != size)
+    {
+        free(data);
+        return NULL;
+    }
+    return (void*)data;
+}
+
+/* size is an integer */
+static void* load_long_section(int fd)
+{
+    int r, size = 0;
+    unsigned char *data;
+
+    r = read( fd, &size, sizeof size );
+    if (r != sizeof size)
+        return NULL;
+    if (size<sizeof size)
+        return NULL;
+
+    data = malloc(size);
+    memcpy(data, &size, sizeof size);
+    r = read( fd, data + sizeof size, size - sizeof size);
+    if (r != (size - sizeof size))
+    {
+        free(data);
+        return NULL;
+    }
+    return (void*)data;
+}
+
+/* the size is a character count in a short integer */
+static lnk_string* load_string(int fd, int unicode)
+{
+    int r;
+    lnk_string *data;
+    unsigned short size = 0, bytesize;
+
+    r = read( fd, &size, sizeof size );
+    if (r != sizeof size)
+        return NULL;
+    if (size < sizeof size)
+        return NULL;
+
+    bytesize = size;
+    if (unicode)
+        bytesize *= sizeof(WCHAR);
+    data = malloc(sizeof *data + bytesize);
+    data->size = size;
+    if (unicode)
+        data->str.w[size] = 0;
+    else
+        data->str.a[size] = 0;
+    r = read(fd, &data->str, bytesize);
+    if (r != bytesize)
+    {
+        free(data);
+        return NULL;
+    }
+    return data;
+}
+
+
+static int dump_pidl(int fd)
+{
+    void *pidl;
+
+    pidl = load_pidl(fd);
+    if (!pidl)
+        return -1;
+
+    printf("PIDL\n");
+    printf("----\n\n");
+
+    free(pidl);
+
+    return 0;
+}
+
+static void print_unicode_string(unsigned short *str)
+{
+    while(*str)
+    {
+        printf("%c", *str);
+        str++;
+    }
+    printf("\n");
+}
+
+static int dump_string(int fd, char *what, int unicode)
+{
+    lnk_string *data;
+
+    data = load_string(fd, unicode);
+    if (!data)
+        return -1;
+    printf("%s : ", what);
+    if (unicode)
+        print_unicode_string(data->str.w);
+    else
+        printf("%s",data->str.a);
+    printf("\n");
+    free(data);
+    return 0;
+}
+
+static int dump_location(int fd)
+{
+    LOCATION_INFO *loc;
+
+    loc = load_long_section(fd);
+    if (!loc)
+        return -1;
+
+    printf("Location\n");
+    printf("--------\n\n");
+    printf("Total size    = %ld\n", loc->dwTotalSize);
+    printf("Header size   = %ld\n", loc->dwHeaderSize);
+    printf("Flags         = %08lx\n", loc->dwFlags);
+    printf("Volume ofs    = %08lx\n", loc->dwVolTableOfs);
+    printf("LocalPath ofs = %08lx\n", loc->dwLocalPathOfs);
+    printf("Net Path ofs  = %08lx\n", loc->dwNetworkVolTableOfs);
+    printf("Final Path    = %08lx\n", loc->dwFinalPathOfs);
+    printf("\n");
+
+    free(loc);
+
+    return 0;
+}
+
+static int dump_advertise_info(int fd, char *type)
+{
+    LINK_ADVERTISEINFO *avt;
+
+    avt = load_long_section(fd);
+    if (!avt)
+        return -1;
+
+    printf("Advertise Info\n");
+    printf("--------------\n\n");
+    printf("magic   = %lx\n", avt->magic);
+    printf("%s = %s\n", type, avt->bufA);
+    printf("\n");
+
+    return 0;
+}
+
+static int dump_lnk_fd(int fd)
+{
+    LINK_HEADER *hdr;
+    char guid[40];
+
+    hdr = load_long_section( fd );
+    if (!hdr)
+        return -1;
+
+    guid_to_string(&hdr->MagicGuid, guid);
+
+    printf("Header\n");
+    printf("------\n\n");
+    printf("Size:    %04lx\n", hdr->dwSize);
+    printf("GUID:    %s\n", guid);
+    printf("Flags:   %04lx\n", hdr->dwFlags);
+    printf("Length:  %04lx\n", hdr->dwFileLength);
+    printf("\n");
+
+    if (hdr->dwFlags & SCF_PIDL)
+        dump_pidl(fd);
+    if (hdr->dwFlags & SCF_LOCATION)
+        dump_location(fd);
+    if (hdr->dwFlags & SCF_DESCRIPTION)
+        dump_string(fd, "Description", hdr->dwFlags & SCF_UNICODE);
+    if (hdr->dwFlags & SCF_RELATIVE)
+        dump_string(fd, "Relative path", hdr->dwFlags & SCF_UNICODE);
+    if (hdr->dwFlags & SCF_WORKDIR)
+        dump_string(fd, "Working directory", hdr->dwFlags & SCF_UNICODE);
+    if (hdr->dwFlags & SCF_ARGS)
+        dump_string(fd, "Arguments", hdr->dwFlags & SCF_UNICODE);
+    if (hdr->dwFlags & SCF_CUSTOMICON)
+        dump_string(fd, "Icon path", hdr->dwFlags & SCF_UNICODE);
+    if (hdr->dwFlags & SCF_PRODUCT)
+        dump_advertise_info(fd, "product");
+    if (hdr->dwFlags & SCF_COMPONENT)
+        dump_advertise_info(fd, "component");
+
+    return 0;
+}
+
+int dump_lnk(const char *emf)
+{
+    int fd;
+
+    fd = open(emf,O_RDONLY);
+    if (fd<0)
+        return -1;
+    dump_lnk_fd(fd);
+    close(fd);
+    return 0;
+}


More information about the wine-patches mailing list