Add dumping of lnk files.
This commit is contained in:
parent
3ab57cfe4d
commit
50e9c0145d
|
@ -12,6 +12,7 @@ C_SRCS = \
|
|||
debug.c \
|
||||
emf.c \
|
||||
le.c \
|
||||
lnk.c \
|
||||
main.c \
|
||||
misc.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)
|
||||
{
|
||||
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);
|
||||
|
@ -486,6 +498,11 @@ int main (int argc, char *argv[])
|
|||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -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
|
||||
|
@ -156,6 +156,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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue