Coverage Report

Created: 2025-06-22 07:35

/src/libexe/libexe/libexe_coff_optional_header.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * COFF optional header functions
3
 *
4
 * Copyright (C) 2011-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libexe_coff_optional_header.h"
28
#include "libexe_data_directory_descriptor.h"
29
#include "libexe_debug.h"
30
#include "libexe_definitions.h"
31
#include "libexe_libcerror.h"
32
#include "libexe_libcnotify.h"
33
34
#include "exe_file_header.h"
35
36
/* Creates a COFF optional header
37
 * Make sure the value coff_optional_header is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libexe_coff_optional_header_initialize(
41
     libexe_coff_optional_header_t **coff_optional_header,
42
     libcerror_error_t **error )
43
607
{
44
607
  static char *function = "libexe_coff_optional_header_initialize";
45
46
607
  if( coff_optional_header == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid COFF optional header.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
607
  if( *coff_optional_header != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid COFF optional header value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
607
  *coff_optional_header = memory_allocate_structure(
69
607
                           libexe_coff_optional_header_t );
70
71
607
  if( *coff_optional_header == NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
76
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
77
0
     "%s: unable to create COFF optional header.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
607
  if( memory_set(
83
607
       *coff_optional_header,
84
607
       0,
85
607
       sizeof( libexe_coff_optional_header_t ) ) == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
91
0
     "%s: unable to clear file.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
607
  return( 1 );
97
98
0
on_error:
99
0
  if( *coff_optional_header != NULL )
100
0
  {
101
0
    memory_free(
102
0
     *coff_optional_header );
103
104
0
    *coff_optional_header = NULL;
105
0
  }
106
0
  return( -1 );
107
607
}
108
109
/* Frees a COFF optional header
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libexe_coff_optional_header_free(
113
     libexe_coff_optional_header_t **coff_optional_header,
114
     libcerror_error_t **error )
115
607
{
116
607
  static char *function = "libexe_coff_optional_header_free";
117
118
607
  if( coff_optional_header == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
124
0
     "%s: invalid COFF optional header.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
607
  if( *coff_optional_header != NULL )
130
607
  {
131
607
    memory_free(
132
607
     *coff_optional_header );
133
134
607
    *coff_optional_header = NULL;
135
607
  }
136
607
  return( 1 );
137
607
}
138
139
/* Reads the COFF optional header
140
 * Returns 1 if successful or -1 on error
141
 */
142
int libexe_coff_optional_header_read_data(
143
     libexe_coff_optional_header_t *coff_optional_header,
144
     const uint8_t *data,
145
     size_t data_size,
146
     libcerror_error_t **error )
147
590
{
148
590
  libexe_data_directory_descriptor_t *data_directory_descriptor = NULL;
149
590
  static char *function                                         = "libexe_coff_optional_header_read_data";
150
590
  size_t data_offset                                            = 0;
151
590
  uint32_t number_of_data_directories_entries                   = 0;
152
590
  uint16_t signature                                            = 0;
153
154
#if defined( HAVE_DEBUG_OUTPUT )
155
  uint64_t value_64bit                                          = 0;
156
  uint32_t value_32bit                                          = 0;
157
  uint16_t value_16bit                                          = 0;
158
#endif
159
160
590
  if( coff_optional_header == NULL )
161
0
  {
162
0
    libcerror_error_set(
163
0
     error,
164
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
165
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
166
0
     "%s: invalid COFF optional header.",
167
0
     function );
168
169
0
    return( -1 );
170
0
  }
171
590
  if( data == NULL )
172
0
  {
173
0
    libcerror_error_set(
174
0
     error,
175
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
176
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
177
0
     "%s: invalid data.",
178
0
     function );
179
180
0
    return( -1 );
181
0
  }
182
590
  if( ( data_size < sizeof( exe_coff_optional_header_t ) )
183
590
   || ( data_size > (size_t) SSIZE_MAX ) )
184
5
  {
185
5
    libcerror_error_set(
186
5
     error,
187
5
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
188
5
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
189
5
     "%s: invalid data size value out of bounds.",
190
5
     function );
191
192
5
    return( -1 );
193
5
  }
194
#if defined( HAVE_DEBUG_OUTPUT )
195
  if( libcnotify_verbose != 0 )
196
  {
197
    libcnotify_printf(
198
     "%s: COFF optional header:\n",
199
     function );
200
    libcnotify_print_data(
201
     data,
202
     data_size,
203
     0 );
204
  }
205
#endif
206
585
  byte_stream_copy_to_uint16_little_endian(
207
585
   ( (exe_coff_optional_header_t *) data )->signature,
208
585
   signature );
209
210
#if defined( HAVE_DEBUG_OUTPUT )
211
  if( libcnotify_verbose != 0 )
212
  {
213
    libcnotify_printf(
214
     "%s: signature\t\t\t: 0x%04" PRIx16 "\n",
215
     function,
216
     signature );
217
218
    libcnotify_printf(
219
     "%s: major linker version\t\t: %" PRIu8 "\n",
220
     function,
221
     ( (exe_coff_optional_header_t *) data )->major_linker_version );
222
223
    libcnotify_printf(
224
     "%s: minor linker version\t\t: %" PRIu8 "\n",
225
     function,
226
     ( (exe_coff_optional_header_t *) data )->minor_linker_version );
227
228
    byte_stream_copy_to_uint32_little_endian(
229
     ( (exe_coff_optional_header_t *) data )->text_section_size,
230
     value_32bit );
231
    libcnotify_printf(
232
     "%s: text section size\t\t: %" PRIu32 "\n",
233
     function,
234
     value_32bit );
235
236
    byte_stream_copy_to_uint32_little_endian(
237
     ( (exe_coff_optional_header_t *) data )->initialized_data_section_size,
238
     value_32bit );
239
    libcnotify_printf(
240
     "%s: initialized data section size\t: %" PRIu32 "\n",
241
     function,
242
     value_32bit );
243
244
    byte_stream_copy_to_uint32_little_endian(
245
     ( (exe_coff_optional_header_t *) data )->uninitialized_data_section_size,
246
     value_32bit );
247
    libcnotify_printf(
248
     "%s: uninitialized data section size\t: %" PRIu32 "\n",
249
     function,
250
     value_32bit );
251
252
    byte_stream_copy_to_uint32_little_endian(
253
     ( (exe_coff_optional_header_t *) data )->entry_point_offset,
254
     value_32bit );
255
    libcnotify_printf(
256
     "%s: entry point offset\t\t: 0x%08" PRIx32 "\n",
257
     function,
258
     value_32bit );
259
260
    byte_stream_copy_to_uint32_little_endian(
261
     ( (exe_coff_optional_header_t *) data )->code_base_offset,
262
     value_32bit );
263
    libcnotify_printf(
264
     "%s: code base offset\t\t\t: 0x%08" PRIx32 "\n",
265
     function,
266
     value_32bit );
267
268
    if( signature == LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 )
269
    {
270
      byte_stream_copy_to_uint32_little_endian(
271
       ( (exe_coff_optional_header_t *) data )->data_base_offset,
272
       value_32bit );
273
      libcnotify_printf(
274
       "%s: data base offset\t\t\t: 0x%08" PRIx32 "\n",
275
       function,
276
       value_32bit );
277
    }
278
    libcnotify_printf(
279
     "\n" );
280
  }
281
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
282
283
585
  if( ( signature != LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 )
284
585
   && ( signature != LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32_PLUS ) )
285
32
  {
286
32
    libcerror_error_set(
287
32
     error,
288
32
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
289
32
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
290
32
     "%s: unsupported signature.",
291
32
     function );
292
293
32
    return( -1 );
294
32
  }
295
553
  data_offset = sizeof( exe_coff_optional_header_t );
296
297
553
  if( signature == LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 )
298
546
  {
299
546
    if( sizeof( exe_coff_optional_header_pe32_t ) > ( data_size - data_offset ) )
300
7
    {
301
7
      libcerror_error_set(
302
7
       error,
303
7
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
304
7
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
305
7
       "%s: invalid data size value too small.",
306
7
       function );
307
308
7
      return( -1 );
309
7
    }
310
539
    byte_stream_copy_to_uint32_little_endian(
311
539
     ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->number_of_data_directories_entries,
312
539
     number_of_data_directories_entries );
313
314
#if defined( HAVE_DEBUG_OUTPUT )
315
    if( libcnotify_verbose != 0 )
316
    {
317
      byte_stream_copy_to_uint32_little_endian(
318
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->image_base_offset,
319
       value_32bit );
320
      libcnotify_printf(
321
       "%s: image base offset\t\t: 0x%08" PRIx32 "\n",
322
       function,
323
       value_32bit );
324
325
      byte_stream_copy_to_uint32_little_endian(
326
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->section_alignment_size,
327
       value_32bit );
328
      libcnotify_printf(
329
       "%s: section alignment size\t\t: %" PRIu32 "\n",
330
       function,
331
       value_32bit );
332
333
      byte_stream_copy_to_uint32_little_endian(
334
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->file_alignment_size,
335
       value_32bit );
336
      libcnotify_printf(
337
       "%s: file alignment size\t\t: %" PRIu32 "\n",
338
       function,
339
       value_32bit );
340
341
      byte_stream_copy_to_uint16_little_endian(
342
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->major_operating_system_version,
343
       value_16bit );
344
      libcnotify_printf(
345
       "%s: major operating system version\t: %" PRIu16 "\n",
346
       function,
347
       value_16bit );
348
349
      byte_stream_copy_to_uint16_little_endian(
350
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->minor_operating_system_version,
351
       value_16bit );
352
      libcnotify_printf(
353
       "%s: minor operating system version\t: %" PRIu16 "\n",
354
       function,
355
       value_16bit );
356
357
      byte_stream_copy_to_uint16_little_endian(
358
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->major_image_version,
359
       value_16bit );
360
      libcnotify_printf(
361
       "%s: major image version\t\t: %" PRIu16 "\n",
362
       function,
363
       value_16bit );
364
365
      byte_stream_copy_to_uint16_little_endian(
366
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->minor_image_version,
367
       value_16bit );
368
      libcnotify_printf(
369
       "%s: minor image version\t\t: %" PRIu16 "\n",
370
       function,
371
       value_16bit );
372
373
      byte_stream_copy_to_uint16_little_endian(
374
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->major_subsystem_version,
375
       value_16bit );
376
      libcnotify_printf(
377
       "%s: major subsystem version\t\t: %" PRIu16 "\n",
378
       function,
379
       value_16bit );
380
381
      byte_stream_copy_to_uint16_little_endian(
382
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->minor_subsystem_version,
383
       value_16bit );
384
      libcnotify_printf(
385
       "%s: minor subsystem version\t\t: %" PRIu16 "\n",
386
       function,
387
       value_16bit );
388
389
      byte_stream_copy_to_uint32_little_endian(
390
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->unknown1,
391
       value_32bit );
392
      libcnotify_printf(
393
       "%s: unknown1\t\t\t\t: %" PRIu32 "\n",
394
       function,
395
       value_32bit );
396
397
      byte_stream_copy_to_uint32_little_endian(
398
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->image_size,
399
       value_32bit );
400
      libcnotify_printf(
401
       "%s: image size\t\t\t: %" PRIu32 "\n",
402
       function,
403
       value_32bit );
404
405
      byte_stream_copy_to_uint32_little_endian(
406
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->headers_size,
407
       value_32bit );
408
      libcnotify_printf(
409
       "%s: headers size\t\t\t: %" PRIu32 "\n",
410
       function,
411
       value_32bit );
412
413
      byte_stream_copy_to_uint32_little_endian(
414
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->checksum,
415
       value_32bit );
416
      libcnotify_printf(
417
       "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
418
       function,
419
       value_32bit );
420
421
      byte_stream_copy_to_uint16_little_endian(
422
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->subsystem,
423
       value_16bit );
424
      libcnotify_printf(
425
       "%s: subsystem\t\t\t: 0x%04" PRIx16 "\n",
426
       function,
427
       value_16bit );
428
429
      byte_stream_copy_to_uint16_little_endian(
430
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->dll_characteristic_flags,
431
       value_16bit );
432
      libcnotify_printf(
433
       "%s: DLL characteristic flags\t\t: 0x%04" PRIx16 "\n",
434
       function,
435
       value_16bit );
436
      libexe_debug_print_dll_characteristic_flags(
437
       value_16bit );
438
      libcnotify_printf(
439
       "\n" );
440
441
      byte_stream_copy_to_uint32_little_endian(
442
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->stack_reservation_size,
443
       value_32bit );
444
      libcnotify_printf(
445
       "%s: stack reservation size\t\t: %" PRIu32 "\n",
446
       function,
447
       value_32bit );
448
449
      byte_stream_copy_to_uint32_little_endian(
450
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->stack_commit_size,
451
       value_32bit );
452
      libcnotify_printf(
453
       "%s: stack commit size\t\t: %" PRIu32 "\n",
454
       function,
455
       value_32bit );
456
457
      byte_stream_copy_to_uint32_little_endian(
458
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->heap_reservation_size,
459
       value_32bit );
460
      libcnotify_printf(
461
       "%s: heap reservation size\t\t: %" PRIu32 "\n",
462
       function,
463
       value_32bit );
464
465
      byte_stream_copy_to_uint32_little_endian(
466
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->heap_commit_size,
467
       value_32bit );
468
      libcnotify_printf(
469
       "%s: heap commit size\t\t\t: %" PRIu32 "\n",
470
       function,
471
       value_32bit );
472
473
      byte_stream_copy_to_uint32_little_endian(
474
       ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->unknown2,
475
       value_32bit );
476
      libcnotify_printf(
477
       "%s: unknown2\t\t\t\t: %" PRIu32 "\n",
478
       function,
479
       value_32bit );
480
481
      libcnotify_printf(
482
       "%s: number of data directory entries\t: %" PRIu32 "\n",
483
       function,
484
       number_of_data_directories_entries );
485
    }
486
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
487
488
539
    data_offset += sizeof( exe_coff_optional_header_pe32_t );
489
539
  }
490
7
  else if( signature == LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 )
491
0
  {
492
0
    if( sizeof( exe_coff_optional_header_pe32_plus_t ) > ( data_size - data_offset ) )
493
0
    {
494
0
      libcerror_error_set(
495
0
       error,
496
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
497
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
498
0
       "%s: invalid data size value too small.",
499
0
       function );
500
501
0
      return( -1 );
502
0
    }
503
0
    byte_stream_copy_to_uint32_little_endian(
504
0
     ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->number_of_data_directories_entries,
505
0
     number_of_data_directories_entries );
506
507
#if defined( HAVE_DEBUG_OUTPUT )
508
    if( libcnotify_verbose != 0 )
509
    {
510
      byte_stream_copy_to_uint64_little_endian(
511
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->image_base_offset,
512
       value_64bit );
513
      libcnotify_printf(
514
       "%s: image base offset\t\t: 0x%08" PRIx64 "\n",
515
       function,
516
       value_64bit );
517
518
      byte_stream_copy_to_uint32_little_endian(
519
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->section_alignment_size,
520
       value_32bit );
521
      libcnotify_printf(
522
       "%s: section alignment size\t\t: %" PRIu32 "\n",
523
       function,
524
       value_32bit );
525
526
      byte_stream_copy_to_uint32_little_endian(
527
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->file_alignment_size,
528
       value_32bit );
529
      libcnotify_printf(
530
       "%s: file alignment size\t\t: %" PRIu32 "\n",
531
       function,
532
       value_32bit );
533
534
      byte_stream_copy_to_uint16_little_endian(
535
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->major_operating_system_version,
536
       value_16bit );
537
      libcnotify_printf(
538
       "%s: major operating system version\t: %" PRIu16 "\n",
539
       function,
540
       value_16bit );
541
542
      byte_stream_copy_to_uint16_little_endian(
543
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->minor_operating_system_version,
544
       value_16bit );
545
      libcnotify_printf(
546
       "%s: minor operating system version\t: %" PRIu16 "\n",
547
       function,
548
       value_16bit );
549
550
      byte_stream_copy_to_uint16_little_endian(
551
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->major_image_version,
552
       value_16bit );
553
      libcnotify_printf(
554
       "%s: major image version\t\t: %" PRIu16 "\n",
555
       function,
556
       value_16bit );
557
558
      byte_stream_copy_to_uint16_little_endian(
559
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->minor_image_version,
560
       value_16bit );
561
      libcnotify_printf(
562
       "%s: minor image version\t\t: %" PRIu16 "\n",
563
       function,
564
       value_16bit );
565
566
      byte_stream_copy_to_uint16_little_endian(
567
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->major_subsystem_version,
568
       value_16bit );
569
      libcnotify_printf(
570
       "%s: major subsystem version\t\t: %" PRIu16 "\n",
571
       function,
572
       value_16bit );
573
574
      byte_stream_copy_to_uint16_little_endian(
575
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->minor_subsystem_version,
576
       value_16bit );
577
      libcnotify_printf(
578
       "%s: minor subsystem version\t\t: %" PRIu16 "\n",
579
       function,
580
       value_16bit );
581
582
      byte_stream_copy_to_uint32_little_endian(
583
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->unknown1,
584
       value_32bit );
585
      libcnotify_printf(
586
       "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n",
587
       function,
588
       value_32bit );
589
590
      byte_stream_copy_to_uint32_little_endian(
591
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->image_size,
592
       value_32bit );
593
      libcnotify_printf(
594
       "%s: image size\t\t\t: %" PRIu32 "\n",
595
       function,
596
       value_32bit );
597
598
      byte_stream_copy_to_uint32_little_endian(
599
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->headers_size,
600
       value_32bit );
601
      libcnotify_printf(
602
       "%s: headers size\t\t\t: %" PRIu32 "\n",
603
       function,
604
       value_32bit );
605
606
      byte_stream_copy_to_uint32_little_endian(
607
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->checksum,
608
       value_32bit );
609
      libcnotify_printf(
610
       "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
611
       function,
612
       value_32bit );
613
614
      byte_stream_copy_to_uint16_little_endian(
615
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->subsystem,
616
       value_16bit );
617
      libcnotify_printf(
618
       "%s: subsystem\t\t\t: 0x%04" PRIx16 "\n",
619
       function,
620
       value_16bit );
621
622
      byte_stream_copy_to_uint16_little_endian(
623
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->dll_characteristic_flags,
624
       value_16bit );
625
      libcnotify_printf(
626
       "%s: DLL characteristic flags\t\t: 0x%04" PRIx16 "\n",
627
       function,
628
       value_16bit );
629
      libexe_debug_print_dll_characteristic_flags(
630
       value_16bit );
631
      libcnotify_printf(
632
       "\n" );
633
634
      byte_stream_copy_to_uint64_little_endian(
635
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->stack_reservation_size,
636
       value_64bit );
637
      libcnotify_printf(
638
       "%s: stack reservation size\t\t: %" PRIu64 "\n",
639
       function,
640
       value_64bit );
641
642
      byte_stream_copy_to_uint64_little_endian(
643
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->stack_commit_size,
644
       value_64bit );
645
      libcnotify_printf(
646
       "%s: stack commit size\t\t: %" PRIu64 "\n",
647
       function,
648
       value_64bit );
649
650
      byte_stream_copy_to_uint64_little_endian(
651
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->heap_reservation_size,
652
       value_64bit );
653
      libcnotify_printf(
654
       "%s: heap reservation size\t\t: %" PRIu64 "\n",
655
       function,
656
       value_64bit );
657
658
      byte_stream_copy_to_uint64_little_endian(
659
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->heap_commit_size,
660
       value_64bit );
661
      libcnotify_printf(
662
       "%s: heap commit size\t\t\t: %" PRIu64 "\n",
663
       function,
664
       value_64bit );
665
666
      byte_stream_copy_to_uint32_little_endian(
667
       ( (exe_coff_optional_header_pe32_plus_t *) &( data[ data_offset ] ) )->unknown2,
668
       value_32bit );
669
      libcnotify_printf(
670
       "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n",
671
       function,
672
       value_32bit );
673
674
      libcnotify_printf(
675
       "%s: number of data directory entries\t: %" PRIu32 "\n",
676
       function,
677
       number_of_data_directories_entries );
678
    }
679
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
680
681
0
    data_offset += sizeof( exe_coff_optional_header_pe32_plus_t );
682
0
  }
683
#if defined( HAVE_DEBUG_OUTPUT )
684
  if( libcnotify_verbose != 0 )
685
  {
686
    libcnotify_printf(
687
     "\n" );
688
  }
689
#endif
690
546
  if( number_of_data_directories_entries > 16 )
691
36
  {
692
36
    libcerror_error_set(
693
36
     error,
694
36
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
695
36
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
696
36
     "%s: unsupported number of data directory entries: %" PRIu32 ".",
697
36
     function,
698
36
     number_of_data_directories_entries );
699
700
36
    return( -1 );
701
36
  }
702
510
  if( ( (size_t) number_of_data_directories_entries * 8 ) > ( data_size - data_offset ) )
703
5
  {
704
5
    libcerror_error_set(
705
5
     error,
706
5
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
707
5
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
708
5
     "%s: invalid data size value too small.",
709
5
     function );
710
711
5
    return( -1 );
712
5
  }
713
505
  if( number_of_data_directories_entries > 0 )
714
473
  {
715
473
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_EXPORT_TABLE ] );
716
717
473
    byte_stream_copy_to_uint32_little_endian(
718
473
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->export_table_rva,
719
473
     data_directory_descriptor->virtual_address );
720
721
473
    byte_stream_copy_to_uint32_little_endian(
722
473
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->export_table_size,
723
473
     data_directory_descriptor->size );
724
725
#if defined( HAVE_DEBUG_OUTPUT )
726
    if( libcnotify_verbose != 0 )
727
    {
728
      libcnotify_printf(
729
       "%s: export table RVA\t\t\t: 0x%08" PRIx32 "\n",
730
       function,
731
       data_directory_descriptor->virtual_address );
732
733
      libcnotify_printf(
734
       "%s: export table size\t\t: %" PRIu32 "\n",
735
       function,
736
       data_directory_descriptor->size );
737
    }
738
#endif
739
473
    number_of_data_directories_entries--;
740
473
  }
741
505
  if( number_of_data_directories_entries > 0 )
742
327
  {
743
327
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_IMPORT_TABLE ] );
744
745
327
    byte_stream_copy_to_uint32_little_endian(
746
327
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_table_rva,
747
327
     data_directory_descriptor->virtual_address );
748
749
327
    byte_stream_copy_to_uint32_little_endian(
750
327
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_table_size,
751
327
     data_directory_descriptor->size );
752
753
#if defined( HAVE_DEBUG_OUTPUT )
754
    if( libcnotify_verbose != 0 )
755
    {
756
      libcnotify_printf(
757
       "%s: import table RVA\t\t\t: 0x%08" PRIx32 "\n",
758
       function,
759
       data_directory_descriptor->virtual_address );
760
761
      libcnotify_printf(
762
       "%s: import table size\t\t: %" PRIu32 "\n",
763
       function,
764
       data_directory_descriptor->size );
765
    }
766
#endif
767
327
    number_of_data_directories_entries--;
768
327
  }
769
505
  if( number_of_data_directories_entries > 0 )
770
212
  {
771
212
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_RESOURCE_TABLE ] );
772
773
212
    byte_stream_copy_to_uint32_little_endian(
774
212
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->resource_table_rva,
775
212
     data_directory_descriptor->virtual_address );
776
777
212
    byte_stream_copy_to_uint32_little_endian(
778
212
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->resource_table_size,
779
212
     data_directory_descriptor->size );
780
781
#if defined( HAVE_DEBUG_OUTPUT )
782
    if( libcnotify_verbose != 0 )
783
    {
784
      libcnotify_printf(
785
       "%s: resource table RVA\t\t: 0x%08" PRIx32 "\n",
786
       function,
787
       data_directory_descriptor->virtual_address );
788
789
      libcnotify_printf(
790
       "%s: resource table size\t\t: %" PRIu32 "\n",
791
       function,
792
       data_directory_descriptor->size );
793
    }
794
#endif
795
212
    number_of_data_directories_entries--;
796
212
  }
797
505
  if( number_of_data_directories_entries > 0 )
798
198
  {
799
198
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_EXCEPTION_TABLE ] );
800
801
198
    byte_stream_copy_to_uint32_little_endian(
802
198
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->exception_table_rva,
803
198
     data_directory_descriptor->virtual_address );
804
805
198
    byte_stream_copy_to_uint32_little_endian(
806
198
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->exception_table_size,
807
198
     data_directory_descriptor->size );
808
809
#if defined( HAVE_DEBUG_OUTPUT )
810
    if( libcnotify_verbose != 0 )
811
    {
812
      libcnotify_printf(
813
       "%s: exception table RVA\t\t: 0x%08" PRIx32 "\n",
814
       function,
815
       data_directory_descriptor->virtual_address );
816
817
      libcnotify_printf(
818
       "%s: exception table size\t\t: %" PRIu32 "\n",
819
       function,
820
       data_directory_descriptor->size );
821
    }
822
#endif
823
198
    number_of_data_directories_entries--;
824
198
  }
825
505
  if( number_of_data_directories_entries > 0 )
826
197
  {
827
197
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_CERTIFICATE_TABLE ] );
828
829
197
    byte_stream_copy_to_uint32_little_endian(
830
197
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->certificate_table_rva,
831
197
     data_directory_descriptor->virtual_address );
832
833
197
    byte_stream_copy_to_uint32_little_endian(
834
197
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->certificate_table_size,
835
197
     data_directory_descriptor->size );
836
837
#if defined( HAVE_DEBUG_OUTPUT )
838
    if( libcnotify_verbose != 0 )
839
    {
840
      libcnotify_printf(
841
       "%s: certificate table RVA\t\t: 0x%08" PRIx32 "\n",
842
       function,
843
       value_32bit );
844
845
      libcnotify_printf(
846
       "%s: certificate table size\t\t: %" PRIu32 "\n",
847
       function,
848
       value_32bit );
849
    }
850
#endif
851
197
    number_of_data_directories_entries--;
852
197
  }
853
505
  if( number_of_data_directories_entries > 0 )
854
196
  {
855
196
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_BASE_RELOCATION_TABLE ] );
856
857
196
    byte_stream_copy_to_uint32_little_endian(
858
196
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->base_relocation_table_rva,
859
196
     data_directory_descriptor->virtual_address );
860
861
196
    byte_stream_copy_to_uint32_little_endian(
862
196
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->base_relocation_table_size,
863
196
     data_directory_descriptor->size );
864
865
#if defined( HAVE_DEBUG_OUTPUT )
866
    if( libcnotify_verbose != 0 )
867
    {
868
      libcnotify_printf(
869
       "%s: base relocation table RVA\t: 0x%08" PRIx32 "\n",
870
       function,
871
       value_32bit );
872
873
      libcnotify_printf(
874
       "%s: base relocation table size\t: %" PRIu32 "\n",
875
       function,
876
       value_32bit );
877
    }
878
#endif
879
196
    number_of_data_directories_entries--;
880
196
  }
881
505
  if( number_of_data_directories_entries > 0 )
882
195
  {
883
195
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_DEBUG_DATA ] );
884
885
195
    byte_stream_copy_to_uint32_little_endian(
886
195
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->debug_data_rva,
887
195
     data_directory_descriptor->virtual_address );
888
889
195
    byte_stream_copy_to_uint32_little_endian(
890
195
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->debug_data_size,
891
195
     data_directory_descriptor->size );
892
893
#if defined( HAVE_DEBUG_OUTPUT )
894
    if( libcnotify_verbose != 0 )
895
    {
896
      libcnotify_printf(
897
       "%s: debug data RVA\t\t\t: 0x%08" PRIx32 "\n",
898
       function,
899
       data_directory_descriptor->virtual_address );
900
901
      libcnotify_printf(
902
       "%s: debug data size\t\t\t: %" PRIu32 "\n",
903
       function,
904
       data_directory_descriptor->size );
905
    }
906
#endif
907
195
    number_of_data_directories_entries--;
908
195
  }
909
505
  if( number_of_data_directories_entries > 0 )
910
41
  {
911
#if defined( HAVE_DEBUG_OUTPUT )
912
    if( libcnotify_verbose != 0 )
913
    {
914
      byte_stream_copy_to_uint32_little_endian(
915
       ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->architecture_specific_data_rva,
916
       value_32bit );
917
      libcnotify_printf(
918
       "%s: architecture-specific data RVA\t: 0x%08" PRIx32 "\n",
919
       function,
920
       value_32bit );
921
922
      byte_stream_copy_to_uint32_little_endian(
923
       ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->architecture_specific_data_size,
924
       value_32bit );
925
      libcnotify_printf(
926
       "%s: architecture-specific data size\t: %" PRIu32 "\n",
927
       function,
928
       value_32bit );
929
    }
930
#endif
931
41
    number_of_data_directories_entries--;
932
41
  }
933
505
  if( number_of_data_directories_entries > 0 )
934
40
  {
935
#if defined( HAVE_DEBUG_OUTPUT )
936
    if( libcnotify_verbose != 0 )
937
    {
938
      byte_stream_copy_to_uint32_little_endian(
939
       ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->global_pointer_register,
940
       value_32bit );
941
      libcnotify_printf(
942
       "%s: global pointer register\t\t: 0x%08" PRIx32 "\n",
943
       function,
944
       value_32bit );
945
946
      byte_stream_copy_to_uint32_little_endian(
947
       ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->unknown3,
948
       value_32bit );
949
      libcnotify_printf(
950
       "%s: unknown3\t\t\t\t: 0x%08" PRIx32 "\n",
951
       function,
952
       value_32bit );
953
    }
954
#endif
955
40
    number_of_data_directories_entries--;
956
40
  }
957
505
  if( number_of_data_directories_entries > 0 )
958
39
  {
959
39
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_THREAD_LOCAL_STORAGE_TABLE ] );
960
961
39
    byte_stream_copy_to_uint32_little_endian(
962
39
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->thread_local_storage_table_rva,
963
39
     data_directory_descriptor->virtual_address );
964
965
39
    byte_stream_copy_to_uint32_little_endian(
966
39
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->thread_local_storage_table_size,
967
39
     data_directory_descriptor->size );
968
969
#if defined( HAVE_DEBUG_OUTPUT )
970
    if( libcnotify_verbose != 0 )
971
    {
972
      libcnotify_printf(
973
       "%s: thread local storage table RVA\t: 0x%08" PRIx32 "\n",
974
       function,
975
       data_directory_descriptor->virtual_address );
976
977
      libcnotify_printf(
978
       "%s: thread local storage table size\t: %" PRIu32 "\n",
979
       function,
980
       data_directory_descriptor->size );
981
    }
982
#endif
983
39
    number_of_data_directories_entries--;
984
39
  }
985
505
  if( number_of_data_directories_entries > 0 )
986
38
  {
987
38
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_LOAD_CONFIGURATION_TABLE ] );
988
989
38
    byte_stream_copy_to_uint32_little_endian(
990
38
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->load_configuration_table_rva,
991
38
     data_directory_descriptor->virtual_address );
992
993
38
    byte_stream_copy_to_uint32_little_endian(
994
38
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->load_configuration_table_size,
995
38
     data_directory_descriptor->size );
996
997
#if defined( HAVE_DEBUG_OUTPUT )
998
    if( libcnotify_verbose != 0 )
999
    {
1000
      libcnotify_printf(
1001
       "%s: load configuration table RVA\t: 0x%08" PRIx32 "\n",
1002
       function,
1003
       data_directory_descriptor->virtual_address );
1004
1005
      libcnotify_printf(
1006
       "%s: load configuration table size\t: %" PRIu32 "\n",
1007
       function,
1008
       data_directory_descriptor->size );
1009
    }
1010
#endif
1011
38
    number_of_data_directories_entries--;
1012
38
  }
1013
505
  if( number_of_data_directories_entries > 0 )
1014
37
  {
1015
37
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_BOUND_IMPORT_TABLE ] );
1016
1017
37
    byte_stream_copy_to_uint32_little_endian(
1018
37
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->bound_import_table_rva,
1019
37
     data_directory_descriptor->virtual_address );
1020
1021
37
    byte_stream_copy_to_uint32_little_endian(
1022
37
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->bound_import_table_size,
1023
37
     data_directory_descriptor->size );
1024
1025
#if defined( HAVE_DEBUG_OUTPUT )
1026
    if( libcnotify_verbose != 0 )
1027
    {
1028
      libcnotify_printf(
1029
       "%s: bound import table RVA\t\t: 0x%08" PRIx32 "\n",
1030
       function,
1031
       data_directory_descriptor->virtual_address );
1032
1033
      libcnotify_printf(
1034
       "%s: bound import table size\t\t: %" PRIu32 "\n",
1035
       function,
1036
       data_directory_descriptor->size );
1037
    }
1038
#endif
1039
37
    number_of_data_directories_entries--;
1040
37
  }
1041
505
  if( number_of_data_directories_entries > 0 )
1042
33
  {
1043
33
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_IMPORT_ADDRESS_TABLE ] );
1044
1045
33
    byte_stream_copy_to_uint32_little_endian(
1046
33
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_address_table_rva,
1047
33
     data_directory_descriptor->virtual_address );
1048
1049
33
    byte_stream_copy_to_uint32_little_endian(
1050
33
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_address_table_size,
1051
33
     data_directory_descriptor->size );
1052
1053
#if defined( HAVE_DEBUG_OUTPUT )
1054
    if( libcnotify_verbose != 0 )
1055
    {
1056
      libcnotify_printf(
1057
       "%s: import address table RVA\t\t: 0x%08" PRIx32 "\n",
1058
       function,
1059
       data_directory_descriptor->virtual_address );
1060
1061
      libcnotify_printf(
1062
       "%s: import address table size\t: %" PRIu32 "\n",
1063
       function,
1064
       data_directory_descriptor->size );
1065
    }
1066
#endif
1067
33
    number_of_data_directories_entries--;
1068
33
  }
1069
505
  if( number_of_data_directories_entries > 0 )
1070
30
  {
1071
30
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_DELAY_IMPORT_DESCRIPTOR ] );
1072
1073
30
    byte_stream_copy_to_uint32_little_endian(
1074
30
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->delay_import_descriptor_rva,
1075
30
     data_directory_descriptor->virtual_address );
1076
1077
30
    byte_stream_copy_to_uint32_little_endian(
1078
30
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->delay_import_descriptor_size,
1079
30
     data_directory_descriptor->size );
1080
1081
#if defined( HAVE_DEBUG_OUTPUT )
1082
    if( libcnotify_verbose != 0 )
1083
    {
1084
      libcnotify_printf(
1085
       "%s: delay import descriptor RVA\t: 0x%08" PRIx32 "\n",
1086
       function,
1087
       data_directory_descriptor->virtual_address );
1088
1089
      libcnotify_printf(
1090
       "%s: delay import descriptor size\t: %" PRIu32 "\n",
1091
       function,
1092
       data_directory_descriptor->size );
1093
    }
1094
#endif
1095
30
    number_of_data_directories_entries--;
1096
30
  }
1097
505
  if( number_of_data_directories_entries > 0 )
1098
27
  {
1099
27
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_COM_PLUS_RUNTIME_HEADER ] );
1100
1101
27
    byte_stream_copy_to_uint32_little_endian(
1102
27
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->com_plus_runtime_header_rva,
1103
27
     data_directory_descriptor->virtual_address );
1104
1105
27
    byte_stream_copy_to_uint32_little_endian(
1106
27
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->com_plus_runtime_header_size,
1107
27
     data_directory_descriptor->size );
1108
1109
#if defined( HAVE_DEBUG_OUTPUT )
1110
    if( libcnotify_verbose != 0 )
1111
    {
1112
      libcnotify_printf(
1113
       "%s: COM+ runtime header RVA\t\t: 0x%08" PRIx32 "\n",
1114
       function,
1115
       data_directory_descriptor->virtual_address );
1116
1117
      libcnotify_printf(
1118
       "%s: COM+ runtime header size\t\t: 0x%08" PRIx32 "\n",
1119
       function,
1120
       data_directory_descriptor->size );
1121
    }
1122
#endif
1123
27
    number_of_data_directories_entries--;
1124
27
  }
1125
505
  if( number_of_data_directories_entries > 0 )
1126
14
  {
1127
#if defined( HAVE_DEBUG_OUTPUT )
1128
    if( libcnotify_verbose != 0 )
1129
    {
1130
      byte_stream_copy_to_uint64_little_endian(
1131
       ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->unknown4,
1132
       value_64bit );
1133
      libcnotify_printf(
1134
       "%s: unknown4\t\t\t\t: 0x%08" PRIx64 "\n",
1135
       function,
1136
       value_64bit );
1137
1138
      libcnotify_printf(
1139
       "\n" );
1140
    }
1141
#endif
1142
14
    number_of_data_directories_entries--;
1143
14
  }
1144
505
  return( 1 );
1145
510
}
1146
1147
/* Reads the COFF optional header from a Basic File IO (bfio) handle
1148
 * Returns 1 if successful or -1 on error
1149
 */
1150
int libexe_coff_optional_header_read_file_io_handle(
1151
     libexe_coff_optional_header_t *coff_optional_header,
1152
     libbfio_handle_t *file_io_handle,
1153
     off64_t file_offset,
1154
     uint16_t optional_header_size,
1155
     libcerror_error_t **error )
1156
607
{
1157
607
  uint8_t *data         = NULL;
1158
607
  static char *function = "libexe_coff_optional_header_read_file_io_handle";
1159
607
  ssize_t read_count    = 0;
1160
1161
607
  if( optional_header_size == 0 )
1162
0
  {
1163
0
    libcerror_error_set(
1164
0
     error,
1165
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1166
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1167
0
     "%s: invalid optional header size value out of bounds.",
1168
0
     function );
1169
1170
0
    return( -1 );
1171
0
  }
1172
607
  if( optional_header_size == 0 )
1173
0
  {
1174
0
    libcerror_error_set(
1175
0
     error,
1176
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1177
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1178
0
     "%s: invalid optional header size value out of bounds.",
1179
0
     function );
1180
1181
0
    return( -1 );
1182
0
  }
1183
607
  data = (uint8_t *) memory_allocate(
1184
607
                      sizeof( uint8_t ) * optional_header_size );
1185
1186
607
  if( data == NULL )
1187
0
  {
1188
0
    libcerror_error_set(
1189
0
     error,
1190
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1191
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1192
0
     "%s: unable to create COFF optional header data.",
1193
0
     function );
1194
1195
0
    goto on_error;
1196
0
  }
1197
#if defined( HAVE_DEBUG_OUTPUT )
1198
  if( libcnotify_verbose != 0 )
1199
  {
1200
    libcnotify_printf(
1201
     "%s: reading COFF optional header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
1202
     function,
1203
     file_offset,
1204
     file_offset );
1205
  }
1206
#endif
1207
607
  read_count = libbfio_handle_read_buffer_at_offset(
1208
607
                file_io_handle,
1209
607
                data,
1210
607
                (size_t) optional_header_size,
1211
607
                file_offset,
1212
607
                error );
1213
1214
607
  if( read_count != (ssize_t) optional_header_size )
1215
17
  {
1216
17
    libcerror_error_set(
1217
17
     error,
1218
17
     LIBCERROR_ERROR_DOMAIN_IO,
1219
17
     LIBCERROR_IO_ERROR_READ_FAILED,
1220
17
     "%s: unable to read COFF optional header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1221
17
     function,
1222
17
     file_offset,
1223
17
     file_offset );
1224
1225
17
    goto on_error;
1226
17
  }
1227
590
  if( libexe_coff_optional_header_read_data(
1228
590
       coff_optional_header,
1229
590
       data,
1230
590
       (size_t) optional_header_size,
1231
590
       error ) != 1 )
1232
85
  {
1233
85
    libcerror_error_set(
1234
85
     error,
1235
85
     LIBCERROR_ERROR_DOMAIN_IO,
1236
85
     LIBCERROR_IO_ERROR_READ_FAILED,
1237
85
     "%s: unable to read COFF optional header at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1238
85
     function,
1239
85
     file_offset,
1240
85
     file_offset );
1241
1242
85
    goto on_error;
1243
85
  }
1244
505
  memory_free(
1245
505
   data );
1246
1247
505
  return( 1 );
1248
1249
102
on_error:
1250
102
  if( data != NULL )
1251
102
  {
1252
102
    memory_free(
1253
102
     data );
1254
102
  }
1255
102
  return( -1 );
1256
590
}
1257