mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 08:53:37 +00:00
0d9fbc1ad7
This version of SickBeard uses both TVDB and TVRage to search and gather it's series data from allowing you to now have access to and download shows that you couldn't before because of being locked into only what TheTVDB had to offer. Also this edition is based off the code we used in our XEM editon so it does come with scene numbering support as well as all the other features our XEM edition has to offer. Please before using this with your existing database (sickbeard.db) please make a backup copy of it and delete any other database files such as cache.db and failed.db if present, we HIGHLY recommend starting out with no database files at all to make this a fresh start but the choice is at your own risk! Enjoy!
582 lines
23 KiB
Python
582 lines
23 KiB
Python
"""
|
|
Windows Shortcut (.lnk) parser.
|
|
|
|
Documents:
|
|
- The Windows Shortcut File Format (document version 1.0)
|
|
Reverse-engineered by Jesse Hager
|
|
http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf
|
|
- Wine source code:
|
|
http://source.winehq.org/source/include/shlobj.h (SHELL_LINK_DATA_FLAGS enum)
|
|
http://source.winehq.org/source/dlls/shell32/pidl.h
|
|
- Microsoft:
|
|
http://msdn2.microsoft.com/en-us/library/ms538128.aspx
|
|
|
|
Author: Robert Xiao, Victor Stinner
|
|
|
|
Changes:
|
|
2007-06-27 - Robert Xiao
|
|
* Fixes to FileLocationInfo to correctly handle Unicode paths
|
|
2007-06-13 - Robert Xiao
|
|
* ItemID, FileLocationInfo and ExtraInfo structs, correct Unicode string handling
|
|
2007-03-15 - Victor Stinner
|
|
* Creation of the parser
|
|
"""
|
|
|
|
from lib.hachoir_parser import Parser
|
|
from lib.hachoir_core.field import (FieldSet,
|
|
CString, String,
|
|
UInt32, UInt16, UInt8,
|
|
Bit, Bits, PaddingBits,
|
|
TimestampWin64, DateTimeMSDOS32,
|
|
NullBytes, PaddingBytes, RawBytes, Enum)
|
|
from lib.hachoir_core.endian import LITTLE_ENDIAN
|
|
from lib.hachoir_core.text_handler import textHandler, hexadecimal
|
|
from lib.hachoir_parser.common.win32 import GUID
|
|
from lib.hachoir_parser.common.msdos import MSDOSFileAttr16, MSDOSFileAttr32
|
|
from lib.hachoir_core.text_handler import filesizeHandler
|
|
|
|
from lib.hachoir_core.tools import paddingSize
|
|
|
|
class ItemIdList(FieldSet):
|
|
def __init__(self, *args, **kw):
|
|
FieldSet.__init__(self, *args, **kw)
|
|
self._size = (self["size"].value+2) * 8
|
|
|
|
def createFields(self):
|
|
yield UInt16(self, "size", "Size of item ID list")
|
|
while True:
|
|
item = ItemId(self, "itemid[]")
|
|
yield item
|
|
if not item["length"].value:
|
|
break
|
|
|
|
class ItemId(FieldSet):
|
|
ITEM_TYPE = {
|
|
0x1F: "GUID",
|
|
0x23: "Drive",
|
|
0x25: "Drive",
|
|
0x29: "Drive",
|
|
0x2E: "GUID",
|
|
0x2F: "Drive",
|
|
0x30: "Dir/File",
|
|
0x31: "Directory",
|
|
0x32: "File",
|
|
0x34: "File [Unicode Name]",
|
|
0x41: "Workgroup",
|
|
0x42: "Computer",
|
|
0x46: "Net Provider",
|
|
0x47: "Whole Network",
|
|
0x61: "MSITStore",
|
|
0x70: "Printer/RAS Connection",
|
|
0xB1: "History/Favorite",
|
|
0xC3: "Network Share",
|
|
}
|
|
|
|
def __init__(self, *args, **kw):
|
|
FieldSet.__init__(self, *args, **kw)
|
|
if self["length"].value:
|
|
self._size = self["length"].value * 8
|
|
else:
|
|
self._size = 16
|
|
|
|
def createFields(self):
|
|
yield UInt16(self, "length", "Length of Item ID Entry")
|
|
if not self["length"].value:
|
|
return
|
|
|
|
yield Enum(UInt8(self, "type"),self.ITEM_TYPE)
|
|
entrytype=self["type"].value
|
|
if entrytype in (0x1F, 0x2E, 0x70):
|
|
# GUID
|
|
yield RawBytes(self, "dummy", 1, "should be 0x50")
|
|
yield GUID(self, "guid")
|
|
|
|
elif entrytype in (0x23, 0x25, 0x29, 0x2F):
|
|
# Drive
|
|
yield String(self, "drive", self["length"].value-3, strip="\0")
|
|
|
|
elif entrytype in (0x30, 0x31, 0x32):
|
|
yield RawBytes(self, "dummy", 1, "should be 0x00")
|
|
yield UInt32(self, "size", "size of file; 0 for folders")
|
|
yield DateTimeMSDOS32(self, "date_time", "File/folder date and time")
|
|
yield MSDOSFileAttr16(self, "attribs", "File/folder attributes")
|
|
yield CString(self, "name", "File/folder name")
|
|
if self.root.hasUnicodeNames():
|
|
# Align to 2-bytes
|
|
n = paddingSize(self.current_size//8, 2)
|
|
if n:
|
|
yield PaddingBytes(self, "pad", n)
|
|
|
|
yield UInt16(self, "length_w", "Length of wide struct member")
|
|
yield RawBytes(self, "unknown[]", 6)
|
|
yield DateTimeMSDOS32(self, "creation_date_time", "File/folder creation date and time")
|
|
yield DateTimeMSDOS32(self, "access_date_time", "File/folder last access date and time")
|
|
yield RawBytes(self, "unknown[]", 4)
|
|
yield CString(self, "unicode_name", "File/folder name", charset="UTF-16-LE")
|
|
yield RawBytes(self, "unknown[]", 2)
|
|
else:
|
|
yield CString(self, "name_short", "File/folder short name")
|
|
|
|
elif entrytype in (0x41, 0x42, 0x46):
|
|
yield RawBytes(self, "unknown[]", 2)
|
|
yield CString(self, "name")
|
|
yield CString(self, "protocol")
|
|
yield RawBytes(self, "unknown[]", 2)
|
|
|
|
elif entrytype == 0x47:
|
|
# Whole Network
|
|
yield RawBytes(self, "unknown[]", 2)
|
|
yield CString(self, "name")
|
|
|
|
elif entrytype == 0xC3:
|
|
# Network Share
|
|
yield RawBytes(self, "unknown[]", 2)
|
|
yield CString(self, "name")
|
|
yield CString(self, "protocol")
|
|
yield CString(self, "description")
|
|
yield RawBytes(self, "unknown[]", 2)
|
|
|
|
else:
|
|
yield RawBytes(self, "raw", self["length"].value-3)
|
|
|
|
def createDescription(self):
|
|
if self["length"].value:
|
|
return "Item ID Entry: "+self.ITEM_TYPE.get(self["type"].value,"Unknown")
|
|
else:
|
|
return "End of Item ID List"
|
|
|
|
def formatVolumeSerial(field):
|
|
val = field.value
|
|
return '%04X-%04X'%(val>>16, val&0xFFFF)
|
|
|
|
class LocalVolumeTable(FieldSet):
|
|
VOLUME_TYPE={
|
|
1: "No root directory",
|
|
2: "Removable (Floppy, Zip, etc.)",
|
|
3: "Fixed (Hard disk)",
|
|
4: "Remote (Network drive)",
|
|
5: "CD-ROM",
|
|
6: "Ram drive",
|
|
}
|
|
|
|
def createFields(self):
|
|
yield UInt32(self, "length", "Length of this structure")
|
|
yield Enum(UInt32(self, "volume_type", "Volume Type"),self.VOLUME_TYPE)
|
|
yield textHandler(UInt32(self, "volume_serial", "Volume Serial Number"), formatVolumeSerial)
|
|
|
|
yield UInt32(self, "label_offset", "Offset to volume label")
|
|
padding = self.seekByte(self["label_offset"].value)
|
|
if padding:
|
|
yield padding
|
|
yield CString(self, "drive")
|
|
|
|
def hasValue(self):
|
|
return bool(self["drive"].value)
|
|
|
|
def createValue(self):
|
|
return self["drive"].value
|
|
|
|
class NetworkVolumeTable(FieldSet):
|
|
def createFields(self):
|
|
yield UInt32(self, "length", "Length of this structure")
|
|
yield UInt32(self, "unknown[]")
|
|
yield UInt32(self, "share_name_offset", "Offset to share name")
|
|
yield UInt32(self, "unknown[]")
|
|
yield UInt32(self, "unknown[]")
|
|
padding = self.seekByte(self["share_name_offset"].value)
|
|
if padding:
|
|
yield padding
|
|
yield CString(self, "share_name")
|
|
|
|
def createValue(self):
|
|
return self["share_name"].value
|
|
|
|
class FileLocationInfo(FieldSet):
|
|
def createFields(self):
|
|
yield UInt32(self, "length", "Length of this structure")
|
|
if not self["length"].value:
|
|
return
|
|
|
|
yield UInt32(self, "first_offset_pos", "Position of first offset")
|
|
has_unicode_paths = (self["first_offset_pos"].value == 0x24)
|
|
yield Bit(self, "on_local_volume")
|
|
yield Bit(self, "on_network_volume")
|
|
yield PaddingBits(self, "reserved[]", 30)
|
|
yield UInt32(self, "local_info_offset", "Offset to local volume table; only meaningful if on_local_volume = 1")
|
|
yield UInt32(self, "local_pathname_offset", "Offset to local base pathname; only meaningful if on_local_volume = 1")
|
|
yield UInt32(self, "remote_info_offset", "Offset to network volume table; only meaningful if on_network_volume = 1")
|
|
yield UInt32(self, "pathname_offset", "Offset of remaining pathname")
|
|
if has_unicode_paths:
|
|
yield UInt32(self, "local_pathname_unicode_offset", "Offset to Unicode version of local base pathname; only meaningful if on_local_volume = 1")
|
|
yield UInt32(self, "pathname_unicode_offset", "Offset to Unicode version of remaining pathname")
|
|
if self["on_local_volume"].value:
|
|
padding = self.seekByte(self["local_info_offset"].value)
|
|
if padding:
|
|
yield padding
|
|
yield LocalVolumeTable(self, "local_volume_table", "Local Volume Table")
|
|
|
|
padding = self.seekByte(self["local_pathname_offset"].value)
|
|
if padding:
|
|
yield padding
|
|
yield CString(self, "local_base_pathname", "Local Base Pathname")
|
|
if has_unicode_paths:
|
|
padding = self.seekByte(self["local_pathname_unicode_offset"].value)
|
|
if padding:
|
|
yield padding
|
|
yield CString(self, "local_base_pathname_unicode", "Local Base Pathname in Unicode", charset="UTF-16-LE")
|
|
|
|
if self["on_network_volume"].value:
|
|
padding = self.seekByte(self["remote_info_offset"].value)
|
|
if padding:
|
|
yield padding
|
|
yield NetworkVolumeTable(self, "network_volume_table")
|
|
|
|
padding = self.seekByte(self["pathname_offset"].value)
|
|
if padding:
|
|
yield padding
|
|
yield CString(self, "final_pathname", "Final component of the pathname")
|
|
|
|
if has_unicode_paths:
|
|
padding = self.seekByte(self["pathname_unicode_offset"].value)
|
|
if padding:
|
|
yield padding
|
|
yield CString(self, "final_pathname_unicode", "Final component of the pathname in Unicode", charset="UTF-16-LE")
|
|
|
|
padding=self.seekByte(self["length"].value)
|
|
if padding:
|
|
yield padding
|
|
|
|
class LnkString(FieldSet):
|
|
def createFields(self):
|
|
yield UInt16(self, "length", "Length of this string")
|
|
if self.root.hasUnicodeNames():
|
|
yield String(self, "data", self["length"].value*2, charset="UTF-16-LE")
|
|
else:
|
|
yield String(self, "data", self["length"].value, charset="ASCII")
|
|
|
|
def createValue(self):
|
|
return self["data"].value
|
|
|
|
class ColorRef(FieldSet):
|
|
''' COLORREF struct, 0x00bbggrr '''
|
|
static_size=32
|
|
def createFields(self):
|
|
yield UInt8(self, "red", "Red")
|
|
yield UInt8(self, "green", "Green")
|
|
yield UInt8(self, "blue", "Blue")
|
|
yield PaddingBytes(self, "pad", 1, "Padding (must be 0)")
|
|
def createDescription(self):
|
|
rgb = self["red"].value, self["green"].value, self["blue"].value
|
|
return "RGB Color: #%02X%02X%02X" % rgb
|
|
|
|
class ColorTableIndex(Bits):
|
|
def __init__(self, parent, name, size, description=None):
|
|
Bits.__init__(self, parent, name, size, None)
|
|
self.desc=description
|
|
def createDescription(self):
|
|
assert hasattr(self, 'parent') and hasattr(self, 'value')
|
|
return "%s: %s"%(self.desc,
|
|
self.parent["color[%i]"%self.value].description)
|
|
|
|
class ExtraInfo(FieldSet):
|
|
INFO_TYPE={
|
|
0xA0000001: "Link Target Information", # EXP_SZ_LINK_SIG
|
|
0xA0000002: "Console Window Properties", # NT_CONSOLE_PROPS_SIG
|
|
0xA0000003: "Hostname and Other Stuff",
|
|
0xA0000004: "Console Codepage Information", # NT_FE_CONSOLE_PROPS_SIG
|
|
0xA0000005: "Special Folder Info", # EXP_SPECIAL_FOLDER_SIG
|
|
0xA0000006: "DarwinID (Windows Installer ID) Information", # EXP_DARWIN_ID_SIG
|
|
0xA0000007: "Custom Icon Details", # EXP_LOGO3_ID_SIG or EXP_SZ_ICON_SIG
|
|
}
|
|
SPECIAL_FOLDER = {
|
|
0: "DESKTOP",
|
|
1: "INTERNET",
|
|
2: "PROGRAMS",
|
|
3: "CONTROLS",
|
|
4: "PRINTERS",
|
|
5: "PERSONAL",
|
|
6: "FAVORITES",
|
|
7: "STARTUP",
|
|
8: "RECENT",
|
|
9: "SENDTO",
|
|
10: "BITBUCKET",
|
|
11: "STARTMENU",
|
|
16: "DESKTOPDIRECTORY",
|
|
17: "DRIVES",
|
|
18: "NETWORK",
|
|
19: "NETHOOD",
|
|
20: "FONTS",
|
|
21: "TEMPLATES",
|
|
22: "COMMON_STARTMENU",
|
|
23: "COMMON_PROGRAMS",
|
|
24: "COMMON_STARTUP",
|
|
25: "COMMON_DESKTOPDIRECTORY",
|
|
26: "APPDATA",
|
|
27: "PRINTHOOD",
|
|
28: "LOCAL_APPDATA",
|
|
29: "ALTSTARTUP",
|
|
30: "COMMON_ALTSTARTUP",
|
|
31: "COMMON_FAVORITES",
|
|
32: "INTERNET_CACHE",
|
|
33: "COOKIES",
|
|
34: "HISTORY",
|
|
35: "COMMON_APPDATA",
|
|
36: "WINDOWS",
|
|
37: "SYSTEM",
|
|
38: "PROGRAM_FILES",
|
|
39: "MYPICTURES",
|
|
40: "PROFILE",
|
|
41: "SYSTEMX86",
|
|
42: "PROGRAM_FILESX86",
|
|
43: "PROGRAM_FILES_COMMON",
|
|
44: "PROGRAM_FILES_COMMONX86",
|
|
45: "COMMON_TEMPLATES",
|
|
46: "COMMON_DOCUMENTS",
|
|
47: "COMMON_ADMINTOOLS",
|
|
48: "ADMINTOOLS",
|
|
49: "CONNECTIONS",
|
|
53: "COMMON_MUSIC",
|
|
54: "COMMON_PICTURES",
|
|
55: "COMMON_VIDEO",
|
|
56: "RESOURCES",
|
|
57: "RESOURCES_LOCALIZED",
|
|
58: "COMMON_OEM_LINKS",
|
|
59: "CDBURN_AREA",
|
|
61: "COMPUTERSNEARME",
|
|
}
|
|
BOOL_ENUM = {
|
|
0: "False",
|
|
1: "True",
|
|
}
|
|
|
|
def __init__(self, *args, **kw):
|
|
FieldSet.__init__(self, *args, **kw)
|
|
if self["length"].value:
|
|
self._size = self["length"].value * 8
|
|
else:
|
|
self._size = 32
|
|
|
|
def createFields(self):
|
|
yield UInt32(self, "length", "Length of this structure")
|
|
if not self["length"].value:
|
|
return
|
|
|
|
yield Enum(textHandler(UInt32(self, "signature", "Signature determining the function of this structure"),hexadecimal),self.INFO_TYPE)
|
|
|
|
if self["signature"].value == 0xA0000003:
|
|
# Hostname and Other Stuff
|
|
yield UInt32(self, "remaining_length")
|
|
yield UInt32(self, "unknown[]")
|
|
yield String(self, "hostname", 16, "Computer hostname on which shortcut was last modified", strip="\0")
|
|
yield RawBytes(self, "unknown[]", 32)
|
|
yield RawBytes(self, "unknown[]", 32)
|
|
|
|
elif self["signature"].value == 0xA0000005:
|
|
# Special Folder Info
|
|
yield Enum(UInt32(self, "special_folder_id", "ID of the special folder"),self.SPECIAL_FOLDER)
|
|
yield UInt32(self, "offset", "Offset to Item ID entry")
|
|
|
|
elif self["signature"].value in (0xA0000001, 0xA0000006, 0xA0000007):
|
|
if self["signature"].value == 0xA0000001: # Link Target Information
|
|
object_name="target"
|
|
elif self["signature"].value == 0xA0000006: # DarwinID (Windows Installer ID) Information
|
|
object_name="darwinID"
|
|
else: # Custom Icon Details
|
|
object_name="icon_path"
|
|
yield CString(self, object_name, "Data (ASCII format)", charset="ASCII")
|
|
remaining = self["length"].value - self.current_size/8 - 260*2 # 260*2 = size of next part
|
|
if remaining:
|
|
yield RawBytes(self, "slack_space[]", remaining, "Data beyond end of string")
|
|
yield CString(self, object_name+'_unicode', "Data (Unicode format)", charset="UTF-16-LE", truncate="\0")
|
|
remaining = self["length"].value - self.current_size/8
|
|
if remaining:
|
|
yield RawBytes(self, "slack_space[]", remaining, "Data beyond end of string")
|
|
|
|
elif self["signature"].value == 0xA0000002:
|
|
# Console Window Properties
|
|
yield ColorTableIndex(self, "color_text", 4, "Screen text color index")
|
|
yield ColorTableIndex(self, "color_bg", 4, "Screen background color index")
|
|
yield NullBytes(self, "reserved[]", 1)
|
|
yield ColorTableIndex(self, "color_popup_text", 4, "Pop-up text color index")
|
|
yield ColorTableIndex(self, "color_popup_bg", 4, "Pop-up background color index")
|
|
yield NullBytes(self, "reserved[]", 1)
|
|
yield UInt16(self, "buffer_width", "Screen buffer width (character cells)")
|
|
yield UInt16(self, "buffer_height", "Screen buffer height (character cells)")
|
|
yield UInt16(self, "window_width", "Window width (character cells)")
|
|
yield UInt16(self, "window_height", "Window height (character cells)")
|
|
yield UInt16(self, "position_left", "Window distance from left edge (screen coords)")
|
|
yield UInt16(self, "position_top", "Window distance from top edge (screen coords)")
|
|
yield UInt32(self, "font_number")
|
|
yield UInt32(self, "input_buffer_size")
|
|
yield UInt16(self, "font_width", "Font width in pixels; 0 for a non-raster font")
|
|
yield UInt16(self, "font_height", "Font height in pixels; equal to the font size for non-raster fonts")
|
|
yield UInt32(self, "font_family")
|
|
yield UInt32(self, "font_weight")
|
|
yield String(self, "font_name_unicode", 64, "Font Name (Unicode format)", charset="UTF-16-LE", truncate="\0")
|
|
yield UInt32(self, "cursor_size", "Relative size of cursor (% of character size)")
|
|
yield Enum(UInt32(self, "full_screen", "Run console in full screen?"), self.BOOL_ENUM)
|
|
yield Enum(UInt32(self, "quick_edit", "Console uses quick-edit feature (using mouse to cut & paste)?"), self.BOOL_ENUM)
|
|
yield Enum(UInt32(self, "insert_mode", "Console uses insertion mode?"), self.BOOL_ENUM)
|
|
yield Enum(UInt32(self, "auto_position", "System automatically positions window?"), self.BOOL_ENUM)
|
|
yield UInt32(self, "history_size", "Size of the history buffer (in lines)")
|
|
yield UInt32(self, "history_count", "Number of history buffers (each process gets one up to this limit)")
|
|
yield Enum(UInt32(self, "history_no_dup", "Automatically eliminate duplicate lines in the history buffer?"), self.BOOL_ENUM)
|
|
for index in xrange(16):
|
|
yield ColorRef(self, "color[]")
|
|
|
|
elif self["signature"].value == 0xA0000004:
|
|
# Console Codepage Information
|
|
yield UInt32(self, "codepage", "Console's code page")
|
|
|
|
else:
|
|
yield RawBytes(self, "raw", self["length"].value-self.current_size/8)
|
|
|
|
def createDescription(self):
|
|
if self["length"].value:
|
|
return "Extra Info Entry: "+self["signature"].display
|
|
else:
|
|
return "End of Extra Info"
|
|
|
|
HOT_KEYS = {
|
|
0x00: u'None',
|
|
0x13: u'Pause',
|
|
0x14: u'Caps Lock',
|
|
0x21: u'Page Up',
|
|
0x22: u'Page Down',
|
|
0x23: u'End',
|
|
0x24: u'Home',
|
|
0x25: u'Left',
|
|
0x26: u'Up',
|
|
0x27: u'Right',
|
|
0x28: u'Down',
|
|
0x2d: u'Insert',
|
|
0x2e: u'Delete',
|
|
0x6a: u'Num *',
|
|
0x6b: u'Num +',
|
|
0x6d: u'Num -',
|
|
0x6e: u'Num .',
|
|
0x6f: u'Num /',
|
|
0x90: u'Num Lock',
|
|
0x91: u'Scroll Lock',
|
|
0xba: u';',
|
|
0xbb: u'=',
|
|
0xbc: u',',
|
|
0xbd: u'-',
|
|
0xbe: u'.',
|
|
0xbf: u'/',
|
|
0xc0: u'`',
|
|
0xdb: u'[',
|
|
0xdc: u'\\',
|
|
0xdd: u']',
|
|
0xde: u"'",
|
|
}
|
|
|
|
def text_hot_key(field):
|
|
assert hasattr(field, "value")
|
|
val=field.value
|
|
if 0x30 <= val <= 0x39:
|
|
return unichr(val)
|
|
elif 0x41 <= val <= 0x5A:
|
|
return unichr(val)
|
|
elif 0x60 <= val <= 0x69:
|
|
return u'Numpad %c' % unichr(val-0x30)
|
|
elif 0x70 <= val <= 0x87:
|
|
return 'F%i'%(val-0x6F)
|
|
elif val in HOT_KEYS:
|
|
return HOT_KEYS[val]
|
|
return str(val)
|
|
|
|
class LnkFile(Parser):
|
|
MAGIC = "\x4C\0\0\0\x01\x14\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46"
|
|
PARSER_TAGS = {
|
|
"id": "lnk",
|
|
"category": "misc",
|
|
"file_ext": ("lnk",),
|
|
"mime": (u"application/x-ms-shortcut",),
|
|
"magic": ((MAGIC, 0),),
|
|
"min_size": len(MAGIC)*8, # signature + guid = 20 bytes
|
|
"description": "Windows Shortcut (.lnk)",
|
|
}
|
|
endian = LITTLE_ENDIAN
|
|
|
|
SHOW_WINDOW_STATE = {
|
|
0: u"Hide",
|
|
1: u"Show Normal",
|
|
2: u"Show Minimized",
|
|
3: u"Show Maximized",
|
|
4: u"Show Normal, not activated",
|
|
5: u"Show",
|
|
6: u"Minimize",
|
|
7: u"Show Minimized, not activated",
|
|
8: u"Show, not activated",
|
|
9: u"Restore",
|
|
10: u"Show Default",
|
|
}
|
|
|
|
def validate(self):
|
|
if self["signature"].value != 0x0000004C:
|
|
return "Invalid signature"
|
|
if self["guid"].value != "00021401-0000-0000-C000-000000000046":
|
|
return "Invalid GUID"
|
|
return True
|
|
|
|
def hasUnicodeNames(self):
|
|
return self["has_unicode_names"].value
|
|
|
|
def createFields(self):
|
|
yield UInt32(self, "signature", "Shortcut signature (0x0000004C)")
|
|
yield GUID(self, "guid", "Shortcut GUID (00021401-0000-0000-C000-000000000046)")
|
|
|
|
yield Bit(self, "has_shell_id", "Is the Item ID List present?")
|
|
yield Bit(self, "target_is_file", "Is a file or a directory?")
|
|
yield Bit(self, "has_description", "Is the Description field present?")
|
|
yield Bit(self, "has_rel_path", "Is the relative path to the target available?")
|
|
yield Bit(self, "has_working_dir", "Is there a working directory?")
|
|
yield Bit(self, "has_cmd_line_args", "Are there any command line arguments?")
|
|
yield Bit(self, "has_custom_icon", "Is there a custom icon?")
|
|
yield Bit(self, "has_unicode_names", "Are Unicode names used?")
|
|
yield Bit(self, "force_no_linkinfo")
|
|
yield Bit(self, "has_exp_sz")
|
|
yield Bit(self, "run_in_separate")
|
|
yield Bit(self, "has_logo3id", "Is LOGO3 ID info present?")
|
|
yield Bit(self, "has_darwinid", "Is the DarwinID info present?")
|
|
yield Bit(self, "runas_user", "Is the target run as another user?")
|
|
yield Bit(self, "has_exp_icon_sz", "Is custom icon information available?")
|
|
yield Bit(self, "no_pidl_alias")
|
|
yield Bit(self, "force_unc_name")
|
|
yield Bit(self, "run_with_shim_layer")
|
|
yield PaddingBits(self, "reserved[]", 14, "Flag bits reserved for future use")
|
|
|
|
yield MSDOSFileAttr32(self, "target_attr")
|
|
|
|
yield TimestampWin64(self, "creation_time")
|
|
yield TimestampWin64(self, "modification_time")
|
|
yield TimestampWin64(self, "last_access_time")
|
|
yield filesizeHandler(UInt32(self, "target_filesize"))
|
|
yield UInt32(self, "icon_number")
|
|
yield Enum(UInt32(self, "show_window"), self.SHOW_WINDOW_STATE)
|
|
yield textHandler(UInt8(self, "hot_key", "Hot key used for quick access"),text_hot_key)
|
|
yield Bit(self, "hot_key_shift", "Hot key: is Shift used?")
|
|
yield Bit(self, "hot_key_ctrl", "Hot key: is Ctrl used?")
|
|
yield Bit(self, "hot_key_alt", "Hot key: is Alt used?")
|
|
yield PaddingBits(self, "hot_key_reserved", 21, "Hot key: (reserved)")
|
|
yield NullBytes(self, "reserved[]", 8)
|
|
|
|
if self["has_shell_id"].value:
|
|
yield ItemIdList(self, "item_idlist", "Item ID List")
|
|
if self["target_is_file"].value:
|
|
yield FileLocationInfo(self, "file_location_info", "File Location Info")
|
|
if self["has_description"].value:
|
|
yield LnkString(self, "description")
|
|
if self["has_rel_path"].value:
|
|
yield LnkString(self, "relative_path", "Relative path to target")
|
|
if self["has_working_dir"].value:
|
|
yield LnkString(self, "working_dir", "Working directory (dir to start target in)")
|
|
if self["has_cmd_line_args"].value:
|
|
yield LnkString(self, "cmd_line_args", "Command Line Arguments")
|
|
if self["has_custom_icon"].value:
|
|
yield LnkString(self, "custom_icon", "Custom Icon Path")
|
|
|
|
while not self.eof:
|
|
yield ExtraInfo(self, "extra_info[]")
|
|
|