Coverage Report

Created: 2023-06-07 06:53

/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-2023, 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
650
{
44
650
  static char *function = "libexe_coff_optional_header_initialize";
45
46
650
  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
650
  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
650
  *coff_optional_header = memory_allocate_structure(
69
650
                           libexe_coff_optional_header_t );
70
71
650
  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
650
  if( memory_set(
83
650
       *coff_optional_header,
84
650
       0,
85
650
       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
650
  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
650
}
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
650
{
116
650
  static char *function = "libexe_coff_optional_header_free";
117
118
650
  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
650
  if( *coff_optional_header != NULL )
130
650
  {
131
650
    memory_free(
132
650
     *coff_optional_header );
133
134
650
    *coff_optional_header = NULL;
135
650
  }
136
650
  return( 1 );
137
650
}
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
633
{
148
633
  libexe_data_directory_descriptor_t *data_directory_descriptor = NULL;
149
633
  static char *function                                         = "libexe_coff_optional_header_read_data";
150
633
  size_t data_offset                                            = 0;
151
633
  uint32_t number_of_data_directories_entries                   = 0;
152
633
  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
633
  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
633
  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
633
  if( ( data_size < sizeof( exe_coff_optional_header_t ) )
183
633
   || ( data_size > (size_t) SSIZE_MAX ) )
184
4
  {
185
4
    libcerror_error_set(
186
4
     error,
187
4
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
188
4
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
189
4
     "%s: invalid data size value out of bounds.",
190
4
     function );
191
192
4
    return( -1 );
193
4
  }
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
629
  byte_stream_copy_to_uint16_little_endian(
207
629
   ( (exe_coff_optional_header_t *) data )->signature,
208
629
   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
629
  if( ( signature != LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 )
284
629
   && ( 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
597
  data_offset = sizeof( exe_coff_optional_header_t );
296
297
597
  if( signature == LIBEXE_COFF_OPTIONAL_HEADER_SIGNATURE_PE32 )
298
591
  {
299
591
    if( sizeof( exe_coff_optional_header_pe32_t ) > ( data_size - data_offset ) )
300
8
    {
301
8
      libcerror_error_set(
302
8
       error,
303
8
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
304
8
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
305
8
       "%s: invalid data size value too small.",
306
8
       function );
307
308
8
      return( -1 );
309
8
    }
310
583
    byte_stream_copy_to_uint32_little_endian(
311
583
     ( (exe_coff_optional_header_pe32_t *) &( data[ data_offset ] ) )->number_of_data_directories_entries,
312
583
     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
583
    data_offset += sizeof( exe_coff_optional_header_pe32_t );
489
583
  }
490
6
  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
589
  if( number_of_data_directories_entries > 16 )
691
39
  {
692
39
    libcerror_error_set(
693
39
     error,
694
39
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
695
39
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
696
39
     "%s: unsupported number of data directory entries: %" PRIu32 ".",
697
39
     function,
698
39
     number_of_data_directories_entries );
699
700
39
    return( -1 );
701
39
  }
702
550
  if( ( (size_t) number_of_data_directories_entries * 8 ) > ( data_size - data_offset ) )
703
12
  {
704
12
    libcerror_error_set(
705
12
     error,
706
12
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
707
12
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
708
12
     "%s: invalid data size value too small.",
709
12
     function );
710
711
12
    return( -1 );
712
12
  }
713
538
  if( number_of_data_directories_entries > 0 )
714
513
  {
715
513
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_EXPORT_TABLE ] );
716
717
513
    byte_stream_copy_to_uint32_little_endian(
718
513
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->export_table_rva,
719
513
     data_directory_descriptor->virtual_address );
720
721
513
    byte_stream_copy_to_uint32_little_endian(
722
513
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->export_table_size,
723
513
     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
513
    number_of_data_directories_entries--;
740
513
  }
741
538
  if( number_of_data_directories_entries > 0 )
742
359
  {
743
359
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_IMPORT_TABLE ] );
744
745
359
    byte_stream_copy_to_uint32_little_endian(
746
359
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_table_rva,
747
359
     data_directory_descriptor->virtual_address );
748
749
359
    byte_stream_copy_to_uint32_little_endian(
750
359
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_table_size,
751
359
     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
359
    number_of_data_directories_entries--;
768
359
  }
769
538
  if( number_of_data_directories_entries > 0 )
770
242
  {
771
242
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_RESOURCE_TABLE ] );
772
773
242
    byte_stream_copy_to_uint32_little_endian(
774
242
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->resource_table_rva,
775
242
     data_directory_descriptor->virtual_address );
776
777
242
    byte_stream_copy_to_uint32_little_endian(
778
242
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->resource_table_size,
779
242
     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
242
    number_of_data_directories_entries--;
796
242
  }
797
538
  if( number_of_data_directories_entries > 0 )
798
217
  {
799
217
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_EXCEPTION_TABLE ] );
800
801
217
    byte_stream_copy_to_uint32_little_endian(
802
217
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->exception_table_rva,
803
217
     data_directory_descriptor->virtual_address );
804
805
217
    byte_stream_copy_to_uint32_little_endian(
806
217
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->exception_table_size,
807
217
     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
217
    number_of_data_directories_entries--;
824
217
  }
825
538
  if( number_of_data_directories_entries > 0 )
826
207
  {
827
207
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_CERTIFICATE_TABLE ] );
828
829
207
    byte_stream_copy_to_uint32_little_endian(
830
207
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->certificate_table_rva,
831
207
     data_directory_descriptor->virtual_address );
832
833
207
    byte_stream_copy_to_uint32_little_endian(
834
207
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->certificate_table_size,
835
207
     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
207
    number_of_data_directories_entries--;
852
207
  }
853
538
  if( number_of_data_directories_entries > 0 )
854
206
  {
855
206
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_BASE_RELOCATION_TABLE ] );
856
857
206
    byte_stream_copy_to_uint32_little_endian(
858
206
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->base_relocation_table_rva,
859
206
     data_directory_descriptor->virtual_address );
860
861
206
    byte_stream_copy_to_uint32_little_endian(
862
206
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->base_relocation_table_size,
863
206
     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
206
    number_of_data_directories_entries--;
880
206
  }
881
538
  if( number_of_data_directories_entries > 0 )
882
204
  {
883
204
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_DEBUG_DATA ] );
884
885
204
    byte_stream_copy_to_uint32_little_endian(
886
204
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->debug_data_rva,
887
204
     data_directory_descriptor->virtual_address );
888
889
204
    byte_stream_copy_to_uint32_little_endian(
890
204
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->debug_data_size,
891
204
     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
204
    number_of_data_directories_entries--;
908
204
  }
909
538
  if( number_of_data_directories_entries > 0 )
910
50
  {
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
50
    number_of_data_directories_entries--;
932
50
  }
933
538
  if( number_of_data_directories_entries > 0 )
934
48
  {
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
48
    number_of_data_directories_entries--;
956
48
  }
957
538
  if( number_of_data_directories_entries > 0 )
958
47
  {
959
47
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_THREAD_LOCAL_STORAGE_TABLE ] );
960
961
47
    byte_stream_copy_to_uint32_little_endian(
962
47
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->thread_local_storage_table_rva,
963
47
     data_directory_descriptor->virtual_address );
964
965
47
    byte_stream_copy_to_uint32_little_endian(
966
47
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->thread_local_storage_table_size,
967
47
     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
47
    number_of_data_directories_entries--;
984
47
  }
985
538
  if( number_of_data_directories_entries > 0 )
986
46
  {
987
46
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_LOAD_CONFIGURATION_TABLE ] );
988
989
46
    byte_stream_copy_to_uint32_little_endian(
990
46
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->load_configuration_table_rva,
991
46
     data_directory_descriptor->virtual_address );
992
993
46
    byte_stream_copy_to_uint32_little_endian(
994
46
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->load_configuration_table_size,
995
46
     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
46
    number_of_data_directories_entries--;
1012
46
  }
1013
538
  if( number_of_data_directories_entries > 0 )
1014
45
  {
1015
45
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_BOUND_IMPORT_TABLE ] );
1016
1017
45
    byte_stream_copy_to_uint32_little_endian(
1018
45
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->bound_import_table_rva,
1019
45
     data_directory_descriptor->virtual_address );
1020
1021
45
    byte_stream_copy_to_uint32_little_endian(
1022
45
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->bound_import_table_size,
1023
45
     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
45
    number_of_data_directories_entries--;
1040
45
  }
1041
538
  if( number_of_data_directories_entries > 0 )
1042
40
  {
1043
40
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_IMPORT_ADDRESS_TABLE ] );
1044
1045
40
    byte_stream_copy_to_uint32_little_endian(
1046
40
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_address_table_rva,
1047
40
     data_directory_descriptor->virtual_address );
1048
1049
40
    byte_stream_copy_to_uint32_little_endian(
1050
40
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->import_address_table_size,
1051
40
     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
40
    number_of_data_directories_entries--;
1068
40
  }
1069
538
  if( number_of_data_directories_entries > 0 )
1070
39
  {
1071
39
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_DELAY_IMPORT_DESCRIPTOR ] );
1072
1073
39
    byte_stream_copy_to_uint32_little_endian(
1074
39
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->delay_import_descriptor_rva,
1075
39
     data_directory_descriptor->virtual_address );
1076
1077
39
    byte_stream_copy_to_uint32_little_endian(
1078
39
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->delay_import_descriptor_size,
1079
39
     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
39
    number_of_data_directories_entries--;
1096
39
  }
1097
538
  if( number_of_data_directories_entries > 0 )
1098
37
  {
1099
37
    data_directory_descriptor = &( coff_optional_header->data_directories[ LIBEXE_DATA_DIRECTORY_COM_PLUS_RUNTIME_HEADER ] );
1100
1101
37
    byte_stream_copy_to_uint32_little_endian(
1102
37
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->com_plus_runtime_header_rva,
1103
37
     data_directory_descriptor->virtual_address );
1104
1105
37
    byte_stream_copy_to_uint32_little_endian(
1106
37
     ( (exe_coff_optional_header_data_directories_t *) &( data[ data_offset ] ) )->com_plus_runtime_header_size,
1107
37
     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
37
    number_of_data_directories_entries--;
1124
37
  }
1125
538
  if( number_of_data_directories_entries > 0 )
1126
18
  {
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
18
    number_of_data_directories_entries--;
1143
18
  }
1144
538
  return( 1 );
1145
550
}
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
650
{
1157
650
  uint8_t *data         = NULL;
1158
650
  static char *function = "libexe_coff_optional_header_read_file_io_handle";
1159
650
  ssize_t read_count    = 0;
1160
1161
650
  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
650
  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
650
  data = (uint8_t *) memory_allocate(
1184
650
                      sizeof( uint8_t ) * optional_header_size );
1185
1186
650
  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
650
  read_count = libbfio_handle_read_buffer_at_offset(
1208
650
                file_io_handle,
1209
650
                data,
1210
650
                (size_t) optional_header_size,
1211
650
                file_offset,
1212
650
                error );
1213
1214
650
  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
633
  if( libexe_coff_optional_header_read_data(
1228
633
       coff_optional_header,
1229
633
       data,
1230
633
       (size_t) optional_header_size,
1231
633
       error ) != 1 )
1232
95
  {
1233
95
    libcerror_error_set(
1234
95
     error,
1235
95
     LIBCERROR_ERROR_DOMAIN_IO,
1236
95
     LIBCERROR_IO_ERROR_READ_FAILED,
1237
95
     "%s: unable to read COFF optional header at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1238
95
     function,
1239
95
     file_offset,
1240
95
     file_offset );
1241
1242
95
    goto on_error;
1243
95
  }
1244
538
  memory_free(
1245
538
   data );
1246
1247
538
  return( 1 );
1248
1249
112
on_error:
1250
112
  if( data != NULL )
1251
112
  {
1252
112
    memory_free(
1253
112
     data );
1254
112
  }
1255
112
  return( -1 );
1256
633
}
1257