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