Add dumping of lnk files.
This commit is contained in:
parent
3ab57cfe4d
commit
50e9c0145d
|
@ -12,6 +12,7 @@ C_SRCS = \
|
||||||
debug.c \
|
debug.c \
|
||||||
emf.c \
|
emf.c \
|
||||||
le.c \
|
le.c \
|
||||||
|
lnk.c \
|
||||||
main.c \
|
main.c \
|
||||||
misc.c \
|
misc.c \
|
||||||
msmangle.c \
|
msmangle.c \
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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)
|
static void do_code (void)
|
||||||
{
|
{
|
||||||
globals.do_code = 1;
|
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)"},
|
{"-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"},
|
{"-x", DUMP, 0, do_dumpall, "-x Dumps everything"},
|
||||||
{"emf", EMF, 0, do_dumpemf, "emf Dumps an Enhanced Meta File"},
|
{"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}
|
{NULL, NONE, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -249,6 +257,10 @@ void do_usage (void)
|
||||||
for (opt = option_table; opt->name; opt++)
|
for (opt = option_table; opt->name; opt++)
|
||||||
if (opt->mode == EMF)
|
if (opt->mode == EMF)
|
||||||
printf ("\t %s\n", opt->usage);
|
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");
|
puts ("\n");
|
||||||
exit (1);
|
exit (1);
|
||||||
|
@ -486,6 +498,11 @@ int main (int argc, char *argv[])
|
||||||
fatal("No file name has been given\n");
|
fatal("No file name has been given\n");
|
||||||
dump_emf(globals.input_name);
|
dump_emf(globals.input_name);
|
||||||
break;
|
break;
|
||||||
|
case LNK:
|
||||||
|
if (globals.input_name == NULL)
|
||||||
|
fatal("No file name has been given\n");
|
||||||
|
dump_lnk(globals.input_name);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
#define SYM_THISCALL 0x4
|
#define SYM_THISCALL 0x4
|
||||||
#define SYM_DATA 0x8 /* Data, not a function */
|
#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 */
|
/* Structure holding a parsed symbol */
|
||||||
typedef struct __parsed_symbol
|
typedef struct __parsed_symbol
|
||||||
|
@ -156,6 +156,9 @@ extern _globals globals;
|
||||||
/* EMF functions */
|
/* EMF functions */
|
||||||
int dump_emf (const char *emf);
|
int dump_emf (const char *emf);
|
||||||
|
|
||||||
|
/* LNK functions */
|
||||||
|
int dump_lnk (const char *lnk);
|
||||||
|
|
||||||
/* Image functions */
|
/* Image functions */
|
||||||
void dump_file(const char* name);
|
void dump_file(const char* name);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue