-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathPE.Types.Resources.pas
More file actions
175 lines (129 loc) · 4.82 KB
/
PE.Types.Resources.pas
File metadata and controls
175 lines (129 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
unit PE.Types.Resources;
interface
{$IFDEF DEBUG}
uses
System.SysUtils; // to Raise
{$ENDIF}
// 5.9.1. Resource Directory Table
type
{ TResourceDirectoryTable }
TResourceDirectoryTable = packed record
// Resource flags. This field is reserved for future use.
// It is currently set to zero.
Characteristics: uint32;
// The time that the resource data was created by the resource compiler.
TimeDateStamp: uint32;
// The major version number, set by the user.
MajorVersion: uint16;
// The minor version number, set by the user.
MinorVersion: uint16;
// The number of directory entries immediately following the table that
// use strings to identify Type, Name, or Language entries (depending on
// the level of the table).
NumberOfNameEntries: uint16;
// The number of directory entries immediately following the Name entries
// that use numeric IDs for Type, Name, or Language entries.
NumberOfIDEntries: uint16;
end;
PResourceDirectoryTable = ^TResourceDirectoryTable;
TResourceEntryType = (ResourceEntryById, ResourceEntryByName);
{ TResourceDirectoryEntry }
TResourceDirectoryEntry = packed record
private
// Either Name RVA or Id.
FEntry: uint32;
DataEntryRVAorSubdirectoryRVA: uint32;
function GetDataEntryRVAorSubdirectoryRVA: uint32; inline;
function GetIntegerID: uint32; inline;
function GetNameRVA: uint32; inline;
procedure SetSubDirRVA(const Value: uint32); inline;
procedure SetDataEntryRVA(const Value: uint32); inline;
procedure SetNameRVA(const Value: uint32); inline;
procedure SetIntegerID(const Value: uint32); inline;
function GetResourceEntryType: TResourceEntryType; inline;
public
procedure Clear;
// To check which union select.
function IsDataEntryRVA: boolean; inline;
function IsSubdirectoryRVA: boolean; inline;
// High bit 0. Address of a Resource Data entry (a leaf).
property DataEntryRVA: uint32 read GetDataEntryRVAorSubdirectoryRVA write SetDataEntryRVA;
// High bit 1. The lower 31 bits are the address of another resource
// directory table (the next level down).
property SubdirectoryRVA: uint32 read GetDataEntryRVAorSubdirectoryRVA write SetSubDirRVA;
property EntryType: TResourceEntryType read GetResourceEntryType;
property NameRVA: uint32 read GetNameRVA write SetNameRVA;
property IntegerID: uint32 read GetIntegerID write SetIntegerID;
end;
PResourceDirectoryEntry = ^TResourceDirectoryEntry;
{ TResourceDataEntry }
TResourceDataEntry = packed record
// The address of a unit of resource data in the Resource Data area.
DataRVA: uint32;
// The size, in bytes, of the resource data that is pointed to by the
// Data RVA field.
Size: uint32;
// The code page that is used to decode code point values within the
// resource data. Typically, the code page would be the Unicode code page.
Codepage: uint32;
// Reserved, must be 0.
Reserved: uint32;
end;
implementation
procedure TResourceDirectoryEntry.Clear;
begin
FEntry := 0;
DataEntryRVAorSubdirectoryRVA := 0;
end;
function TResourceDirectoryEntry.GetDataEntryRVAorSubdirectoryRVA: uint32;
begin
Result := DataEntryRVAorSubdirectoryRVA and $7FFFFFFF;
end;
function TResourceDirectoryEntry.GetIntegerID: uint32;
begin
{$IFDEF DEBUG}
if EntryType <> ResourceEntryById then
raise Exception.Create('Attempt to get ID of named-entry.');
{$ENDIF}
Result := FEntry and $FFFF;
end;
function TResourceDirectoryEntry.GetNameRVA: uint32;
begin
{$IFDEF DEBUG}
if EntryType <> ResourceEntryByName then
raise Exception.Create('Attempt to get name RVA of ID-entry.');
{$ENDIF}
Result := FEntry and $7FFFFFFF;
end;
function TResourceDirectoryEntry.GetResourceEntryType: TResourceEntryType;
begin
if (self.FEntry and $80000000) = 0 then
Result := ResourceEntryById
else
Result := ResourceEntryByName;
end;
function TResourceDirectoryEntry.IsDataEntryRVA: boolean;
begin
Result := (DataEntryRVAorSubdirectoryRVA and $80000000) = 0;
end;
function TResourceDirectoryEntry.IsSubdirectoryRVA: boolean;
begin
Result := (DataEntryRVAorSubdirectoryRVA and $80000000) <> 0;
end;
procedure TResourceDirectoryEntry.SetDataEntryRVA(const Value: uint32);
begin
DataEntryRVAorSubdirectoryRVA := Value and $7FFFFFFF;
end;
procedure TResourceDirectoryEntry.SetIntegerID(const Value: uint32);
begin
FEntry := Value and $7FFFFFFF;
end;
procedure TResourceDirectoryEntry.SetNameRVA(const Value: uint32);
begin
FEntry := Value or $80000000;
end;
procedure TResourceDirectoryEntry.SetSubDirRVA(const Value: uint32);
begin
DataEntryRVAorSubdirectoryRVA := Value or $80000000;
end;
end.