Coverage Report

Created: 2025-06-13 07:22

/src/libwrc/libwrc/libwrc_version_information_resource.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * String table (VERSIONINFO) resource 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 "libwrc_debug.h"
28
#include "libwrc_definitions.h"
29
#include "libwrc_libcerror.h"
30
#include "libwrc_libcnotify.h"
31
#include "libwrc_libuna.h"
32
#include "libwrc_version_information_resource.h"
33
34
#include "wrc_version_information_resource.h"
35
36
uint8_t libwrc_version_information_resource_signature[ 32 ] = {
37
  'V', 0, 'S', 0, '_', 0, 'V', 0, 'E', 0, 'R', 0, 'S', 0, 'I', 0,
38
  'O', 0, 'N', 0, '_', 0, 'I', 0, 'N', 0, 'F', 0, 'O', 0, 0, 0 };
39
40
/* Creates a version information resource
41
 * Make sure the value version_information_resource is referencing, is set to NULL
42
 * Returns 1 if successful or -1 on error
43
 */
44
int libwrc_version_information_resource_initialize(
45
     libwrc_version_information_resource_t **version_information_resource,
46
     libcerror_error_t **error )
47
1.06k
{
48
1.06k
  libwrc_internal_version_information_resource_t *internal_version_information_resource = NULL;
49
1.06k
  static char *function                                                                 = "libwrc_version_information_resource_initialize";
50
51
1.06k
  if( version_information_resource == NULL )
52
0
  {
53
0
    libcerror_error_set(
54
0
     error,
55
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
56
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
57
0
     "%s: invalid version information resource.",
58
0
     function );
59
60
0
    return( -1 );
61
0
  }
62
1.06k
  if( *version_information_resource != NULL )
63
0
  {
64
0
    libcerror_error_set(
65
0
     error,
66
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
67
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
68
0
     "%s: invalid version information resource value already set.",
69
0
     function );
70
71
0
    return( -1 );
72
0
  }
73
1.06k
  internal_version_information_resource = memory_allocate_structure(
74
1.06k
                                           libwrc_internal_version_information_resource_t );
75
76
1.06k
  if( internal_version_information_resource == NULL )
77
0
  {
78
0
    libcerror_error_set(
79
0
     error,
80
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
81
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
82
0
     "%s: unable to create version information resource.",
83
0
     function );
84
85
0
    goto on_error;
86
0
  }
87
1.06k
  if( memory_set(
88
1.06k
       internal_version_information_resource,
89
1.06k
       0,
90
1.06k
       sizeof( libwrc_internal_version_information_resource_t ) ) == NULL )
91
0
  {
92
0
    libcerror_error_set(
93
0
     error,
94
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
95
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
96
0
     "%s: unable to clear version information resource.",
97
0
     function );
98
99
0
    goto on_error;
100
0
  }
101
1.06k
  *version_information_resource = (libwrc_version_information_resource_t *) internal_version_information_resource;
102
103
1.06k
  return( 1 );
104
105
0
on_error:
106
0
  if( internal_version_information_resource != NULL )
107
0
  {
108
0
    memory_free(
109
0
     internal_version_information_resource );
110
0
  }
111
0
  return( -1 );
112
1.06k
}
113
114
/* Frees a version information resource
115
 * Returns 1 if successful or -1 on error
116
 */
117
int libwrc_version_information_resource_free(
118
     libwrc_version_information_resource_t **version_information_resource,
119
     libcerror_error_t **error )
120
1.06k
{
121
1.06k
  libwrc_internal_version_information_resource_t *internal_version_information_resource = NULL;
122
1.06k
  static char *function                                                                 = "libwrc_version_information_resource_free";
123
124
1.06k
  if( version_information_resource == NULL )
125
0
  {
126
0
    libcerror_error_set(
127
0
     error,
128
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
129
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
130
0
     "%s: invalid version information resource.",
131
0
     function );
132
133
0
    return( -1 );
134
0
  }
135
1.06k
  if( *version_information_resource != NULL )
136
1.06k
  {
137
1.06k
    internal_version_information_resource = (libwrc_internal_version_information_resource_t *) *version_information_resource;
138
1.06k
    *version_information_resource         = NULL;
139
140
1.06k
    memory_free(
141
1.06k
     internal_version_information_resource );
142
1.06k
  }
143
1.06k
  return( 1 );
144
1.06k
}
145
146
/* Reads the version information resource string file information
147
 * Returns number of bytes read if successful or -1 on error
148
 */
149
ssize_t libwrc_internal_version_information_resource_read_string_file_information(
150
         libwrc_internal_version_information_resource_t *internal_version_information_resource,
151
         const uint8_t *data,
152
         size_t data_size,
153
         size_t data_offset,
154
         libcerror_error_t **error )
155
848
{
156
848
  const uint8_t *value_identifier_string = NULL;
157
848
  static char *function                  = "libwrc_internal_version_information_resource_read_string_file_information";
158
848
  size_t alignment_padding_size          = 0;
159
848
  size_t calculated_value_data_size      = 0;
160
848
  size_t data_start_offset               = 0;
161
848
  size_t trailing_data_size              = 0;
162
848
  size_t value_identifier_string_size    = 0;
163
848
  ssize_t read_count                     = 0;
164
848
  uint16_t string_data_size              = 0;
165
848
  uint16_t value_data_size               = 0;
166
848
  uint16_t value_data_type               = 0;
167
168
848
  if( internal_version_information_resource == NULL )
169
0
  {
170
0
    libcerror_error_set(
171
0
     error,
172
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
173
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
174
0
     "%s: invalid version information resource.",
175
0
     function );
176
177
0
    return( -1 );
178
0
  }
179
848
  if( data == NULL )
180
0
  {
181
0
    libcerror_error_set(
182
0
     error,
183
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
184
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
185
0
     "%s: invalid data.",
186
0
     function );
187
188
0
    return( -1 );
189
0
  }
190
848
  if( data_size > (size_t) SSIZE_MAX )
191
0
  {
192
0
    libcerror_error_set(
193
0
     error,
194
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
195
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
196
0
     "%s: invalid data size value exceeds maximum.",
197
0
     function );
198
199
0
    return( -1 );
200
0
  }
201
848
  if( data_offset >= data_size )
202
4
  {
203
4
    libcerror_error_set(
204
4
     error,
205
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
206
4
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
207
4
     "%s: invalid data offset value out of bounds.",
208
4
     function );
209
210
4
    return( -1 );
211
4
  }
212
844
  if( ( data_offset + 2 ) > data_size )
213
3
  {
214
3
    libcerror_error_set(
215
3
     error,
216
3
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
217
3
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
218
3
     "%s: invalid data value too small.",
219
3
     function );
220
221
3
    return( -1 );
222
3
  }
223
841
  data_start_offset = data_offset;
224
225
841
  byte_stream_copy_to_uint16_little_endian(
226
841
   &( data[ data_offset ] ),
227
841
   string_data_size );
228
229
841
  data_offset += 2;
230
231
#if defined( HAVE_DEBUG_OUTPUT )
232
  if( libcnotify_verbose != 0 )
233
  {
234
    libcnotify_printf(
235
     "%s: data size\t\t: %" PRIu16 "\n",
236
     function,
237
     string_data_size );
238
  }
239
#endif
240
841
  if( string_data_size != 0 )
241
825
  {
242
825
    if( ( string_data_size < 8 )
243
825
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
244
51
    {
245
51
      libcerror_error_set(
246
51
       error,
247
51
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
248
51
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
249
51
       "%s: data size value out of bounds.",
250
51
       function );
251
252
51
      return( -1 );
253
51
    }
254
774
    byte_stream_copy_to_uint16_little_endian(
255
774
     &( data[ data_offset ] ),
256
774
     value_data_size );
257
258
774
    data_offset += 2;
259
260
774
    byte_stream_copy_to_uint16_little_endian(
261
774
     &( data[ data_offset ] ),
262
774
     value_data_type );
263
264
774
    data_offset += 2;
265
266
#if defined( HAVE_DEBUG_OUTPUT )
267
    if( libcnotify_verbose != 0 )
268
    {
269
      libcnotify_printf(
270
       "%s: value data size\t: %" PRIu16 "\n",
271
       function,
272
       value_data_size );
273
274
      libcnotify_printf(
275
       "%s: value data type\t: %" PRIu16 "\n",
276
       function,
277
       value_data_type );
278
    }
279
#endif
280
774
    value_identifier_string      = &( data[ data_offset ] );
281
774
    value_identifier_string_size = 0;
282
283
4.55M
    while( ( data_offset + 2 ) < data_size )
284
4.55M
    {
285
4.55M
      value_identifier_string_size += 2;
286
287
4.55M
      if( ( data[ data_offset ] == 0 )
288
4.55M
       && ( data[ data_offset + 1 ] == 0 ) )
289
681
      {
290
681
        data_offset += 2;
291
292
681
        break;
293
681
      }
294
4.55M
      data_offset += 2;
295
4.55M
    }
296
#if defined( HAVE_DEBUG_OUTPUT )
297
    if( libcnotify_verbose != 0 )
298
    {
299
      libcnotify_printf(
300
       "%s: value identifier string data:\n",
301
       function );
302
      libcnotify_print_data(
303
       value_identifier_string,
304
       value_identifier_string_size,
305
       0 );
306
    }
307
#endif
308
/* TODO convert string */
309
774
    if( ( data_offset % 4 ) != 0 )
310
212
    {
311
212
      alignment_padding_size = 4 - ( data_offset % 4 );
312
313
212
      if( alignment_padding_size > ( data_size - data_offset ) )
314
16
      {
315
16
        libcerror_error_set(
316
16
         error,
317
16
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
318
16
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
319
16
         "%s: invalid data size value too small.",
320
16
         function );
321
322
16
        return( -1 );
323
16
      }
324
#if defined( HAVE_DEBUG_OUTPUT )
325
      if( libcnotify_verbose != 0 )
326
      {
327
        libcnotify_printf(
328
         "%s: alignment padding:\n",
329
         function );
330
        libcnotify_print_data(
331
         &( data[ data_offset ] ),
332
         alignment_padding_size,
333
         0 );
334
      }
335
#endif
336
196
      data_offset += alignment_padding_size;
337
196
    }
338
758
    if( value_data_type == 1 )
339
501
    {
340
/* TODO check value_data_size == 0 ? */
341
501
      read_count = libwrc_internal_version_information_resource_read_string_table(
342
501
              internal_version_information_resource,
343
501
              data,
344
501
              data_size,
345
501
              data_offset,
346
501
              error );
347
348
501
      if( read_count == -1 )
349
145
      {
350
145
        libcerror_error_set(
351
145
         error,
352
145
         LIBCERROR_ERROR_DOMAIN_IO,
353
145
         LIBCERROR_IO_ERROR_READ_FAILED,
354
145
         "%s: unable to read string table.",
355
145
         function );
356
357
145
        return( -1 );
358
145
      }
359
356
      data_offset += read_count;
360
356
    }
361
/* TODO print unsupported type warning */
362
613
    calculated_value_data_size = data_offset - data_start_offset;
363
364
613
    if( calculated_value_data_size < string_data_size )
365
126
    {
366
126
      trailing_data_size = string_data_size - trailing_data_size;
367
368
#if defined( HAVE_DEBUG_OUTPUT )
369
      if( libcnotify_verbose != 0 )
370
      {
371
        libcnotify_printf(
372
         "%s: trailing data:\n",
373
         function );
374
        libcnotify_print_data(
375
         &( data[ data_offset ] ),
376
         trailing_data_size,
377
         0 );
378
      }
379
#endif
380
126
      data_offset += trailing_data_size;
381
126
    }
382
613
  }
383
629
  return( (ssize_t) string_data_size );
384
841
}
385
386
/* Reads the version information resource string table
387
 * Returns number of bytes read if successful or -1 on error
388
 */
389
ssize_t libwrc_internal_version_information_resource_read_string_table(
390
         libwrc_internal_version_information_resource_t *internal_version_information_resource,
391
         const uint8_t *data,
392
         size_t data_size,
393
         size_t data_offset,
394
         libcerror_error_t **error )
395
501
{
396
501
  const uint8_t *value_identifier_string = NULL;
397
501
  static char *function                  = "libwrc_internal_version_information_resource_read_string_table";
398
501
  size_t alignment_padding_size          = 0;
399
501
  size_t calculated_value_data_size      = 0;
400
501
  size_t data_start_offset               = 0;
401
501
  size_t trailing_data_size              = 0;
402
501
  size_t value_identifier_string_size    = 0;
403
501
  ssize_t read_count                     = 0;
404
501
  uint16_t string_data_size              = 0;
405
501
  uint16_t value_data_size               = 0;
406
501
  uint16_t value_data_type               = 0;
407
408
501
  if( internal_version_information_resource == NULL )
409
0
  {
410
0
    libcerror_error_set(
411
0
     error,
412
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
413
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
414
0
     "%s: invalid version information resource.",
415
0
     function );
416
417
0
    return( -1 );
418
0
  }
419
501
  if( data == NULL )
420
0
  {
421
0
    libcerror_error_set(
422
0
     error,
423
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
424
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
425
0
     "%s: invalid data.",
426
0
     function );
427
428
0
    return( -1 );
429
0
  }
430
501
  if( data_size > (size_t) SSIZE_MAX )
431
0
  {
432
0
    libcerror_error_set(
433
0
     error,
434
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
435
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
436
0
     "%s: invalid data size value exceeds maximum.",
437
0
     function );
438
439
0
    return( -1 );
440
0
  }
441
501
  if( data_offset >= data_size )
442
1
  {
443
1
    libcerror_error_set(
444
1
     error,
445
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
446
1
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
447
1
     "%s: invalid data offset value out of bounds.",
448
1
     function );
449
450
1
    return( -1 );
451
1
  }
452
500
  if( ( data_offset + 2 ) > data_size )
453
10
  {
454
10
    libcerror_error_set(
455
10
     error,
456
10
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
457
10
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
458
10
     "%s: invalid data value too small.",
459
10
     function );
460
461
10
    return( -1 );
462
10
  }
463
490
  data_start_offset = data_offset;
464
465
490
  byte_stream_copy_to_uint16_little_endian(
466
490
   &( data[ data_offset ] ),
467
490
   string_data_size );
468
469
490
  data_offset += 2;
470
471
#if defined( HAVE_DEBUG_OUTPUT )
472
  if( libcnotify_verbose != 0 )
473
  {
474
    libcnotify_printf(
475
     "%s: data size\t\t\t: %" PRIu16 "\n",
476
     function,
477
     string_data_size );
478
  }
479
#endif
480
490
  if( string_data_size != 0 )
481
468
  {
482
468
    if( ( string_data_size < 8 )
483
468
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
484
52
    {
485
52
      libcerror_error_set(
486
52
       error,
487
52
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
488
52
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
489
52
       "%s: data size value out of bounds.",
490
52
       function );
491
492
52
      return( -1 );
493
52
    }
494
416
    byte_stream_copy_to_uint16_little_endian(
495
416
     &( data[ data_offset ] ),
496
416
     value_data_size );
497
498
416
    data_offset += 2;
499
500
416
    byte_stream_copy_to_uint16_little_endian(
501
416
     &( data[ data_offset ] ),
502
416
     value_data_type );
503
504
416
    data_offset += 2;
505
506
#if defined( HAVE_DEBUG_OUTPUT )
507
    if( libcnotify_verbose != 0 )
508
    {
509
      libcnotify_printf(
510
       "%s: value data size\t\t\t: %" PRIu16 "\n",
511
       function,
512
       value_data_size );
513
514
      libcnotify_printf(
515
       "%s: value data type\t\t\t: %" PRIu16 "\n",
516
       function,
517
       value_data_type );
518
    }
519
#endif
520
416
    value_identifier_string      = &( data[ data_offset ] );
521
416
    value_identifier_string_size = 0;
522
523
1.71M
    while( ( data_offset + 2 ) < data_size )
524
1.71M
    {
525
1.71M
      value_identifier_string_size += 2;
526
527
1.71M
      if( ( data[ data_offset ] == 0 )
528
1.71M
       && ( data[ data_offset + 1 ] == 0 ) )
529
316
      {
530
316
        data_offset += 2;
531
532
316
        break;
533
316
      }
534
1.71M
      data_offset += 2;
535
1.71M
    }
536
#if defined( HAVE_DEBUG_OUTPUT )
537
    if( libcnotify_verbose != 0 )
538
    {
539
      libcnotify_printf(
540
       "%s: value identifier string data:\n",
541
       function );
542
      libcnotify_print_data(
543
       value_identifier_string,
544
       value_identifier_string_size,
545
       0 );
546
    }
547
#endif
548
/* TODO convert string */
549
416
    if( ( data_offset % 4 ) != 0 )
550
158
    {
551
158
      alignment_padding_size = 4 - ( data_offset % 4 );
552
553
158
      if( alignment_padding_size > ( data_size - data_offset ) )
554
20
      {
555
20
        libcerror_error_set(
556
20
         error,
557
20
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
558
20
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
559
20
         "%s: invalid data size value too small.",
560
20
         function );
561
562
20
        return( -1 );
563
20
      }
564
#if defined( HAVE_DEBUG_OUTPUT )
565
      if( libcnotify_verbose != 0 )
566
      {
567
        libcnotify_printf(
568
         "%s: alignment padding:\n",
569
         function );
570
        libcnotify_print_data(
571
         &( data[ data_offset ] ),
572
         alignment_padding_size,
573
         0 );
574
      }
575
#endif
576
138
      data_offset += alignment_padding_size;
577
138
    }
578
396
    if( value_data_type == 0 )
579
15
    {
580
/* TODO check value data size is in bounds */
581
#if defined( HAVE_DEBUG_OUTPUT )
582
      if( libcnotify_verbose != 0 )
583
      {
584
        libcnotify_printf(
585
         "%s: value data:\n",
586
         function );
587
        libcnotify_print_data(
588
         &( data[ data_offset ] ),
589
         value_data_size,
590
         0 );
591
      }
592
#endif
593
15
      data_offset += value_data_size;
594
15
    }
595
381
    else if( value_data_type == 1 )
596
267
    {
597
/* TODO check value_data_size == 0 ? */
598
1.84k
      while( ( data_offset + 2 ) < ( data_start_offset + string_data_size ) )
599
1.68k
      {
600
1.68k
        read_count = libwrc_internal_version_information_resource_read_string(
601
1.68k
                internal_version_information_resource,
602
1.68k
                data,
603
1.68k
                data_size,
604
1.68k
                data_offset,
605
1.68k
                error );
606
607
1.68k
        if( read_count == -1 )
608
62
        {
609
62
          libcerror_error_set(
610
62
           error,
611
62
           LIBCERROR_ERROR_DOMAIN_IO,
612
62
           LIBCERROR_IO_ERROR_READ_FAILED,
613
62
           "%s: unable to read string.",
614
62
           function );
615
616
62
          return( -1 );
617
62
        }
618
1.61k
        else if( read_count == 0 )
619
42
        {
620
42
          break;
621
42
        }
622
1.57k
        data_offset += read_count;
623
624
1.57k
        if( ( data_offset % 4 ) != 0 )
625
375
        {
626
375
          alignment_padding_size = 4 - ( data_offset % 4 );
627
628
375
          if( ( data_offset + alignment_padding_size ) < ( data_start_offset + string_data_size ) )
629
293
          {
630
293
            if( alignment_padding_size > ( data_size - data_offset ) )
631
0
            {
632
0
              libcerror_error_set(
633
0
               error,
634
0
               LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
635
0
               LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
636
0
               "%s: invalid data size value too small.",
637
0
               function );
638
639
0
              return( -1 );
640
0
            }
641
#if defined( HAVE_DEBUG_OUTPUT )
642
            if( libcnotify_verbose != 0 )
643
            {
644
              libcnotify_printf(
645
               "%s: alignment padding:\n",
646
               function );
647
              libcnotify_print_data(
648
               &( data[ data_offset ] ),
649
               alignment_padding_size,
650
               0 );
651
            }
652
#endif
653
293
            data_offset += alignment_padding_size;
654
293
          }
655
375
        }
656
1.57k
      }
657
267
    }
658
/* TODO print unsupported type warning */
659
334
    calculated_value_data_size = data_offset - data_start_offset;
660
661
334
    if( calculated_value_data_size < string_data_size )
662
135
    {
663
135
      trailing_data_size = string_data_size - calculated_value_data_size;
664
665
#if defined( HAVE_DEBUG_OUTPUT )
666
      if( libcnotify_verbose != 0 )
667
      {
668
        libcnotify_printf(
669
         "%s: trailing data:\n",
670
         function );
671
        libcnotify_print_data(
672
         &( data[ data_offset ] ),
673
         trailing_data_size,
674
         0 );
675
      }
676
#endif
677
135
      data_offset += trailing_data_size;
678
135
    }
679
334
  }
680
356
  return( (ssize_t) string_data_size );
681
490
}
682
683
/* Reads the version information resource string
684
 * Returns number of bytes read if successful or -1 on error
685
 */
686
ssize_t libwrc_internal_version_information_resource_read_string(
687
         libwrc_internal_version_information_resource_t *internal_version_information_resource,
688
         const uint8_t *data,
689
         size_t data_size,
690
         size_t data_offset,
691
         libcerror_error_t **error )
692
1.68k
{
693
1.68k
  static char *function         = "libwrc_internal_version_information_resource_read_string";
694
1.68k
  size_t alignment_padding_size = 0;
695
1.68k
  size_t value_string_size      = 0;
696
1.68k
  uint16_t string_data_size     = 0;
697
1.68k
  uint16_t value_data_size      = 0;
698
1.68k
  uint16_t value_data_type      = 0;
699
700
#if defined( HAVE_DEBUG_OUTPUT )
701
  size_t data_start_offset      = 0;
702
  size_t trailing_data_size     = 0;
703
  size_t value_string_offset    = 0;
704
#endif
705
706
1.68k
  if( internal_version_information_resource == NULL )
707
0
  {
708
0
    libcerror_error_set(
709
0
     error,
710
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
711
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
712
0
     "%s: invalid version information resource.",
713
0
     function );
714
715
0
    return( -1 );
716
0
  }
717
1.68k
  if( data == NULL )
718
0
  {
719
0
    libcerror_error_set(
720
0
     error,
721
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
722
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
723
0
     "%s: invalid data.",
724
0
     function );
725
726
0
    return( -1 );
727
0
  }
728
1.68k
  if( data_size > (size_t) SSIZE_MAX )
729
0
  {
730
0
    libcerror_error_set(
731
0
     error,
732
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
733
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
734
0
     "%s: invalid data size value exceeds maximum.",
735
0
     function );
736
737
0
    return( -1 );
738
0
  }
739
1.68k
  if( data_offset >= data_size )
740
0
  {
741
0
    libcerror_error_set(
742
0
     error,
743
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
744
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
745
0
     "%s: invalid data offset value out of bounds.",
746
0
     function );
747
748
0
    return( -1 );
749
0
  }
750
1.68k
  if( ( data_offset + 2 ) > data_size )
751
0
  {
752
0
    libcerror_error_set(
753
0
     error,
754
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
755
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
756
0
     "%s: invalid data value too small.",
757
0
     function );
758
759
0
    return( -1 );
760
0
  }
761
#if defined( HAVE_DEBUG_OUTPUT )
762
  data_start_offset = data_offset;
763
#endif
764
765
1.68k
  byte_stream_copy_to_uint16_little_endian(
766
1.68k
   &( data[ data_offset ] ),
767
1.68k
   string_data_size );
768
769
1.68k
  data_offset += 2;
770
771
#if defined( HAVE_DEBUG_OUTPUT )
772
  if( libcnotify_verbose != 0 )
773
  {
774
    libcnotify_printf(
775
     "%s: data size\t\t\t\t: %" PRIu16 "\n",
776
     function,
777
     string_data_size );
778
  }
779
#endif
780
1.68k
  if( string_data_size != 0 )
781
1.63k
  {
782
1.63k
    if( ( string_data_size < 8 )
783
1.63k
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
784
62
    {
785
62
      libcerror_error_set(
786
62
       error,
787
62
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
788
62
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
789
62
       "%s: data size value out of bounds.",
790
62
       function );
791
792
62
      return( -1 );
793
62
    }
794
1.57k
    byte_stream_copy_to_uint16_little_endian(
795
1.57k
     &( data[ data_offset ] ),
796
1.57k
     value_data_size );
797
798
1.57k
    data_offset += 2;
799
800
1.57k
    byte_stream_copy_to_uint16_little_endian(
801
1.57k
     &( data[ data_offset ] ),
802
1.57k
     value_data_type );
803
804
1.57k
    data_offset += 2;
805
806
#if defined( HAVE_DEBUG_OUTPUT )
807
    if( libcnotify_verbose != 0 )
808
    {
809
      libcnotify_printf(
810
       "%s: value data size\t\t\t: %" PRIu16 "\n",
811
       function,
812
       value_data_size );
813
814
      libcnotify_printf(
815
       "%s: value data type\t\t\t: %" PRIu16 "\n",
816
       function,
817
       value_data_type );
818
    }
819
#endif
820
/* TODO check value_data_size == 0 ? */
821
/* TODO handle value_data_type != 1 */
822
#if defined( HAVE_DEBUG_OUTPUT )
823
    value_string_offset = data_offset;
824
#endif
825
826
1.57k
    value_string_size = 0;
827
828
800k
    while( ( data_offset + 2 ) < data_size )
829
800k
    {
830
800k
      value_string_size += 2;
831
832
800k
      if( ( data[ data_offset ] == 0 )
833
800k
       && ( data[ data_offset + 1 ] == 0 ) )
834
1.13k
      {
835
1.13k
        data_offset += 2;
836
837
1.13k
        break;
838
1.13k
      }
839
799k
      data_offset += 2;
840
799k
    }
841
#if defined( HAVE_DEBUG_OUTPUT )
842
    if( libcnotify_verbose != 0 )
843
    {
844
      libcnotify_printf(
845
       "%s: value identifier string data:\n",
846
       function );
847
      libcnotify_print_data(
848
       &( data[ value_string_offset ] ),
849
       value_string_size,
850
       0 );
851
    }
852
#endif
853
/* TODO convert string */
854
1.57k
    if( ( data_offset % 4 ) != 0 )
855
833
    {
856
833
      if( alignment_padding_size > ( data_size - data_offset ) )
857
0
      {
858
0
        libcerror_error_set(
859
0
         error,
860
0
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
861
0
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
862
0
         "%s: invalid data size value too small.",
863
0
         function );
864
865
0
        return( -1 );
866
0
      }
867
833
      alignment_padding_size = 4 - ( data_offset % 4 );
868
869
#if defined( HAVE_DEBUG_OUTPUT )
870
      if( libcnotify_verbose != 0 )
871
      {
872
        libcnotify_printf(
873
         "%s: alignment padding:\n",
874
         function );
875
        libcnotify_print_data(
876
         &( data[ data_offset ] ),
877
         alignment_padding_size,
878
         0 );
879
      }
880
#endif
881
833
      data_offset += alignment_padding_size;
882
833
    }
883
#if defined( HAVE_DEBUG_OUTPUT )
884
    value_string_offset = data_offset;
885
    value_string_size   = 0;
886
887
    while( ( data_offset + 2 ) < data_size )
888
    {
889
      value_string_size += 2;
890
891
      if( ( data[ data_offset ] == 0 )
892
       && ( data[ data_offset + 1 ] == 0 ) )
893
      {
894
        data_offset += 2;
895
896
        break;
897
      }
898
      data_offset += 2;
899
    }
900
#endif
901
#if defined( HAVE_DEBUG_OUTPUT )
902
    if( libcnotify_verbose != 0 )
903
    {
904
      libcnotify_printf(
905
       "%s: value string data:\n",
906
       function );
907
      libcnotify_print_data(
908
       &( data[ value_string_offset ] ),
909
       value_string_size,
910
       0 );
911
    }
912
#endif
913
#if defined( HAVE_DEBUG_OUTPUT )
914
    if( libcnotify_verbose != 0 )
915
    {
916
      trailing_data_size = data_offset - data_start_offset;
917
918
      if( trailing_data_size < string_data_size )
919
      {
920
        trailing_data_size = string_data_size - trailing_data_size;
921
922
        libcnotify_printf(
923
         "%s: trailing data:\n",
924
         function );
925
        libcnotify_print_data(
926
         &( data[ data_offset ] ),
927
         trailing_data_size,
928
         0 );
929
      }
930
    }
931
#endif
932
1.57k
  }
933
1.61k
  return( (ssize_t) string_data_size );
934
1.68k
}
935
936
/* Reads the version information resource variable file information
937
 * Returns number of bytes read if successful or -1 on error
938
 */
939
ssize_t libwrc_internal_version_information_resource_read_variable_file_information(
940
         libwrc_internal_version_information_resource_t *internal_version_information_resource,
941
         const uint8_t *data,
942
         size_t data_size,
943
         size_t data_offset,
944
         libcerror_error_t **error )
945
629
{
946
629
  static char *function         = "libwrc_internal_version_information_resource_read_variable_file_information";
947
629
  size_t alignment_padding_size = 0;
948
629
  size_t data_start_offset      = 0;
949
629
  size_t value_string_size      = 0;
950
629
  ssize_t read_count            = 0;
951
629
  uint16_t string_data_size     = 0;
952
629
  uint16_t value_data_size      = 0;
953
629
  uint16_t value_data_type      = 0;
954
955
#if defined( HAVE_DEBUG_OUTPUT )
956
  size_t trailing_data_size     = 0;
957
  size_t value_string_offset    = 0;
958
#endif
959
960
629
  if( internal_version_information_resource == NULL )
961
0
  {
962
0
    libcerror_error_set(
963
0
     error,
964
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
965
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
966
0
     "%s: invalid version information resource.",
967
0
     function );
968
969
0
    return( -1 );
970
0
  }
971
629
  if( data == NULL )
972
0
  {
973
0
    libcerror_error_set(
974
0
     error,
975
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
976
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
977
0
     "%s: invalid data.",
978
0
     function );
979
980
0
    return( -1 );
981
0
  }
982
629
  if( data_size > (size_t) SSIZE_MAX )
983
0
  {
984
0
    libcerror_error_set(
985
0
     error,
986
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
987
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
988
0
     "%s: invalid data size value exceeds maximum.",
989
0
     function );
990
991
0
    return( -1 );
992
0
  }
993
629
  if( data_offset >= data_size )
994
32
  {
995
32
    libcerror_error_set(
996
32
     error,
997
32
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
998
32
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
999
32
     "%s: invalid data offset value out of bounds.",
1000
32
     function );
1001
1002
32
    return( -1 );
1003
32
  }
1004
597
  if( ( data_offset + 2 ) > data_size )
1005
23
  {
1006
23
    libcerror_error_set(
1007
23
     error,
1008
23
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1009
23
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1010
23
     "%s: invalid data value too small.",
1011
23
     function );
1012
1013
23
    return( -1 );
1014
23
  }
1015
574
  data_start_offset = data_offset;
1016
1017
574
  byte_stream_copy_to_uint16_little_endian(
1018
574
   &( data[ data_offset ] ),
1019
574
   string_data_size );
1020
1021
574
  data_offset += 2;
1022
1023
#if defined( HAVE_DEBUG_OUTPUT )
1024
  if( libcnotify_verbose != 0 )
1025
  {
1026
    libcnotify_printf(
1027
     "%s: data size\t\t: %" PRIu16 "\n",
1028
     function,
1029
     string_data_size );
1030
  }
1031
#endif
1032
574
  if( string_data_size != 0 )
1033
528
  {
1034
528
    if( ( string_data_size < 8 )
1035
528
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
1036
83
    {
1037
83
      libcerror_error_set(
1038
83
       error,
1039
83
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1040
83
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1041
83
       "%s: data size value out of bounds.",
1042
83
       function );
1043
1044
83
      return( -1 );
1045
83
    }
1046
445
    byte_stream_copy_to_uint16_little_endian(
1047
445
     &( data[ data_offset ] ),
1048
445
     value_data_size );
1049
1050
445
    data_offset += 2;
1051
1052
445
    byte_stream_copy_to_uint16_little_endian(
1053
445
     &( data[ data_offset ] ),
1054
445
     value_data_type );
1055
1056
445
    data_offset += 2;
1057
1058
#if defined( HAVE_DEBUG_OUTPUT )
1059
    if( libcnotify_verbose != 0 )
1060
    {
1061
      libcnotify_printf(
1062
       "%s: value data size\t: %" PRIu16 "\n",
1063
       function,
1064
       value_data_size );
1065
1066
      libcnotify_printf(
1067
       "%s: value data type\t: %" PRIu16 "\n",
1068
       function,
1069
       value_data_type );
1070
    }
1071
#endif
1072
/* TODO check value_data_size == 0 ? */
1073
/* TODO handle value_data_type != 1 */
1074
#if defined( HAVE_DEBUG_OUTPUT )
1075
    value_string_offset = data_offset;
1076
#endif
1077
1078
445
    value_string_size  = 0;
1079
1080
3.71M
    while( ( data_offset + 2 ) < data_size )
1081
3.71M
    {
1082
3.71M
      value_string_size += 2;
1083
1084
3.71M
      if( ( data[ data_offset ] == 0 )
1085
3.71M
       && ( data[ data_offset + 1 ] == 0 ) )
1086
346
      {
1087
346
        data_offset += 2;
1088
1089
346
        break;
1090
346
      }
1091
3.71M
      data_offset += 2;
1092
3.71M
    }
1093
#if defined( HAVE_DEBUG_OUTPUT )
1094
    if( libcnotify_verbose != 0 )
1095
    {
1096
      libcnotify_printf(
1097
       "%s: value identifier string data:\n",
1098
       function );
1099
      libcnotify_print_data(
1100
       &( data[ value_string_offset ] ),
1101
       value_string_size,
1102
       0 );
1103
    }
1104
#endif
1105
/* TODO convert string */
1106
445
    if( ( data_offset % 4 ) != 0 )
1107
217
    {
1108
217
      alignment_padding_size = 4 - ( data_offset % 4 );
1109
1110
217
      if( alignment_padding_size > ( data_size - data_offset ) )
1111
15
      {
1112
15
        libcerror_error_set(
1113
15
         error,
1114
15
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1115
15
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1116
15
         "%s: invalid data size value too small.",
1117
15
         function );
1118
1119
15
        return( -1 );
1120
15
      }
1121
#if defined( HAVE_DEBUG_OUTPUT )
1122
      if( libcnotify_verbose != 0 )
1123
      {
1124
        libcnotify_printf(
1125
         "%s: alignment padding:\n",
1126
         function );
1127
        libcnotify_print_data(
1128
         &( data[ data_offset ] ),
1129
         alignment_padding_size,
1130
         0 );
1131
      }
1132
#endif
1133
202
      data_offset += alignment_padding_size;
1134
202
    }
1135
2.10k
    while( ( data_offset + 2 ) < ( data_start_offset + string_data_size ) )
1136
1.84k
    {
1137
1.84k
      read_count = libwrc_internal_version_information_resource_read_variable(
1138
1.84k
              internal_version_information_resource,
1139
1.84k
              data,
1140
1.84k
              data_size,
1141
1.84k
              data_offset,
1142
1.84k
              error );
1143
1144
1.84k
      if( read_count == -1 )
1145
93
      {
1146
93
        libcerror_error_set(
1147
93
         error,
1148
93
         LIBCERROR_ERROR_DOMAIN_IO,
1149
93
         LIBCERROR_IO_ERROR_READ_FAILED,
1150
93
         "%s: unable to read variable.",
1151
93
         function );
1152
1153
93
        return( -1 );
1154
93
      }
1155
1.75k
      else if( read_count == 0 )
1156
78
      {
1157
78
        break;
1158
78
      }
1159
1.67k
      data_offset += read_count;
1160
1.67k
    }
1161
#if defined( HAVE_DEBUG_OUTPUT )
1162
    if( libcnotify_verbose != 0 )
1163
    {
1164
      trailing_data_size = data_offset - data_start_offset;
1165
1166
      if( trailing_data_size < string_data_size )
1167
      {
1168
        trailing_data_size = string_data_size - trailing_data_size;
1169
1170
        libcnotify_printf(
1171
         "%s: trailing data:\n",
1172
         function );
1173
        libcnotify_print_data(
1174
         &( data[ data_offset ] ),
1175
         trailing_data_size,
1176
         0 );
1177
      }
1178
    }
1179
#endif
1180
430
  }
1181
383
  return( (ssize_t) string_data_size );
1182
574
}
1183
1184
/* Reads the version information resource variable
1185
 * Returns number of bytes read if successful or -1 on error
1186
 */
1187
ssize_t libwrc_internal_version_information_resource_read_variable(
1188
         libwrc_internal_version_information_resource_t *internal_version_information_resource,
1189
         const uint8_t *data,
1190
         size_t data_size,
1191
         size_t data_offset,
1192
         libcerror_error_t **error )
1193
1.84k
{
1194
1.84k
  static char *function         = "libwrc_internal_version_information_resource_read_variable";
1195
1.84k
  size_t alignment_padding_size = 0;
1196
1.84k
  size_t value_string_size      = 0;
1197
1.84k
  uint16_t string_data_size     = 0;
1198
1.84k
  uint16_t value_data_size      = 0;
1199
1.84k
  uint16_t value_data_type      = 0;
1200
1201
#if defined( HAVE_DEBUG_OUTPUT )
1202
  size_t data_start_offset      = 0;
1203
  size_t trailing_data_size     = 0;
1204
  size_t value_string_offset    = 0;
1205
#endif
1206
1207
1.84k
  if( internal_version_information_resource == NULL )
1208
0
  {
1209
0
    libcerror_error_set(
1210
0
     error,
1211
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1212
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1213
0
     "%s: invalid version information resource.",
1214
0
     function );
1215
1216
0
    return( -1 );
1217
0
  }
1218
1.84k
  if( data == NULL )
1219
0
  {
1220
0
    libcerror_error_set(
1221
0
     error,
1222
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1223
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1224
0
     "%s: invalid data.",
1225
0
     function );
1226
1227
0
    return( -1 );
1228
0
  }
1229
1.84k
  if( data_size > (size_t) SSIZE_MAX )
1230
0
  {
1231
0
    libcerror_error_set(
1232
0
     error,
1233
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1234
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1235
0
     "%s: invalid data size value exceeds maximum.",
1236
0
     function );
1237
1238
0
    return( -1 );
1239
0
  }
1240
1.84k
  if( data_offset >= data_size )
1241
0
  {
1242
0
    libcerror_error_set(
1243
0
     error,
1244
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1245
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1246
0
     "%s: invalid data offset value out of bounds.",
1247
0
     function );
1248
1249
0
    return( -1 );
1250
0
  }
1251
1.84k
  if( ( data_offset + 2 ) > data_size )
1252
0
  {
1253
0
    libcerror_error_set(
1254
0
     error,
1255
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1256
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1257
0
     "%s: invalid data value too small.",
1258
0
     function );
1259
1260
0
    return( -1 );
1261
0
  }
1262
#if defined( HAVE_DEBUG_OUTPUT )
1263
  data_start_offset = data_offset;
1264
#endif
1265
1266
1.84k
  byte_stream_copy_to_uint16_little_endian(
1267
1.84k
   &( data[ data_offset ] ),
1268
1.84k
   string_data_size );
1269
1270
1.84k
  data_offset += 2;
1271
1272
#if defined( HAVE_DEBUG_OUTPUT )
1273
  if( libcnotify_verbose != 0 )
1274
  {
1275
    libcnotify_printf(
1276
     "%s: data size\t\t\t\t: %" PRIu16 "\n",
1277
     function,
1278
     string_data_size );
1279
  }
1280
#endif
1281
1.84k
  if( string_data_size != 0 )
1282
1.76k
  {
1283
1.76k
    if( ( string_data_size < 8 )
1284
1.76k
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
1285
86
    {
1286
86
      libcerror_error_set(
1287
86
       error,
1288
86
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1289
86
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1290
86
       "%s: data size value out of bounds.",
1291
86
       function );
1292
1293
86
      return( -1 );
1294
86
    }
1295
1.68k
    byte_stream_copy_to_uint16_little_endian(
1296
1.68k
     &( data[ data_offset ] ),
1297
1.68k
     value_data_size );
1298
1299
1.68k
    data_offset += 2;
1300
1301
1.68k
    byte_stream_copy_to_uint16_little_endian(
1302
1.68k
     &( data[ data_offset ] ),
1303
1.68k
     value_data_type );
1304
1305
1.68k
    data_offset += 2;
1306
1307
#if defined( HAVE_DEBUG_OUTPUT )
1308
    if( libcnotify_verbose != 0 )
1309
    {
1310
      libcnotify_printf(
1311
       "%s: value data size\t\t\t: %" PRIu16 "\n",
1312
       function,
1313
       value_data_size );
1314
1315
      libcnotify_printf(
1316
       "%s: value data type\t\t\t: %" PRIu16 "\n",
1317
       function,
1318
       value_data_type );
1319
    }
1320
#endif
1321
/* TODO check value_data_size == 0 ? */
1322
/* TODO handle value_data_type != 1 */
1323
#if defined( HAVE_DEBUG_OUTPUT )
1324
    value_string_offset = data_offset;
1325
#endif
1326
1327
1.68k
    value_string_size = 0;
1328
1329
347k
    while( ( data_offset + 2 ) < data_size )
1330
347k
    {
1331
347k
      value_string_size += 2;
1332
1333
347k
      if( ( data[ data_offset ] == 0 )
1334
347k
       && ( data[ data_offset + 1 ] == 0 ) )
1335
1.16k
      {
1336
1.16k
        data_offset += 2;
1337
1338
1.16k
        break;
1339
1.16k
      }
1340
346k
      data_offset += 2;
1341
346k
    }
1342
#if defined( HAVE_DEBUG_OUTPUT )
1343
    if( libcnotify_verbose != 0 )
1344
    {
1345
      libcnotify_printf(
1346
       "%s: value identifier string data:\n",
1347
       function );
1348
      libcnotify_print_data(
1349
       &( data[ value_string_offset ] ),
1350
       value_string_size,
1351
       0 );
1352
    }
1353
#endif
1354
/* TODO convert string */
1355
1.68k
    if( ( data_offset % 4 ) != 0 )
1356
879
    {
1357
879
      alignment_padding_size = 4 - ( data_offset % 4 );
1358
1359
879
      if( alignment_padding_size > ( data_size - data_offset ) )
1360
7
      {
1361
7
        libcerror_error_set(
1362
7
         error,
1363
7
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1364
7
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1365
7
         "%s: invalid data size value too small.",
1366
7
         function );
1367
1368
7
        return( -1 );
1369
7
      }
1370
#if defined( HAVE_DEBUG_OUTPUT )
1371
      if( libcnotify_verbose != 0 )
1372
      {
1373
        libcnotify_printf(
1374
         "%s: alignment padding:\n",
1375
         function );
1376
        libcnotify_print_data(
1377
         &( data[ data_offset ] ),
1378
         alignment_padding_size,
1379
         0 );
1380
      }
1381
#endif
1382
872
      data_offset += alignment_padding_size;
1383
872
    }
1384
/* TODO */
1385
1386
#if defined( HAVE_DEBUG_OUTPUT )
1387
    if( libcnotify_verbose != 0 )
1388
    {
1389
      trailing_data_size = data_offset - data_start_offset;
1390
1391
      if( trailing_data_size < string_data_size )
1392
      {
1393
        trailing_data_size = string_data_size - trailing_data_size;
1394
1395
        libcnotify_printf(
1396
         "%s: trailing data:\n",
1397
         function );
1398
        libcnotify_print_data(
1399
         &( data[ data_offset ] ),
1400
         trailing_data_size,
1401
         0 );
1402
      }
1403
    }
1404
#endif
1405
1.68k
  }
1406
1.75k
  return( (ssize_t) string_data_size );
1407
1.84k
}
1408
1409
/* Reads the version information resource
1410
 * Returns 1 if successful or -1 on error
1411
 */
1412
int libwrc_version_information_resource_read(
1413
     libwrc_version_information_resource_t *version_information_resource,
1414
     const uint8_t *data,
1415
     size_t data_size,
1416
     libcerror_error_t **error )
1417
1.06k
{
1418
1.06k
  libwrc_internal_version_information_resource_t *internal_version_information_resource = NULL;
1419
1.06k
  const uint8_t *value_identifier_string                                                = NULL;
1420
1.06k
  static char *function                                                                 = "libwrc_version_information_resource_read";
1421
1.06k
  size_t alignment_padding_size                                                         = 0;
1422
1.06k
  size_t data_offset                                                                    = 0;
1423
1.06k
  size_t value_identifier_string_size                                                   = 0;
1424
1.06k
  ssize_t read_count                                                                    = 0;
1425
1.06k
  uint32_t value_32bit                                                                  = 0;
1426
1.06k
  uint16_t resource_data_size                                                           = 0;
1427
1.06k
  uint16_t value_data_size                                                              = 0;
1428
1.06k
  uint16_t value_data_type                                                              = 0;
1429
1430
1.06k
  if( version_information_resource == NULL )
1431
0
  {
1432
0
    libcerror_error_set(
1433
0
     error,
1434
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1435
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1436
0
     "%s: invalid version information resource.",
1437
0
     function );
1438
1439
0
    return( -1 );
1440
0
  }
1441
1.06k
  internal_version_information_resource = (libwrc_internal_version_information_resource_t *) version_information_resource;
1442
1443
1.06k
  if( data == NULL )
1444
0
  {
1445
0
    libcerror_error_set(
1446
0
     error,
1447
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1448
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1449
0
     "%s: invalid data.",
1450
0
     function );
1451
1452
0
    return( -1 );
1453
0
  }
1454
1.06k
  if( ( data_size < sizeof( wrc_version_value_header_t ) )
1455
1.06k
   || ( data_size > (size_t) SSIZE_MAX ) )
1456
4
  {
1457
4
    libcerror_error_set(
1458
4
     error,
1459
4
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1460
4
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1461
4
     "%s: invalid data size value out of bounds.",
1462
4
     function );
1463
1464
4
    return( -1 );
1465
4
  }
1466
#if defined( HAVE_DEBUG_OUTPUT )
1467
  if( libcnotify_verbose != 0 )
1468
  {
1469
    libcnotify_printf(
1470
     "%s: data:\n",
1471
     function );
1472
    libcnotify_print_data(
1473
     data,
1474
     data_size,
1475
     0 );
1476
  }
1477
#endif
1478
1.06k
  byte_stream_copy_to_uint16_little_endian(
1479
1.06k
   ( (wrc_version_value_header_t *) data )->size,
1480
1.06k
   resource_data_size );
1481
1482
1.06k
  byte_stream_copy_to_uint16_little_endian(
1483
1.06k
   ( (wrc_version_value_header_t *) data )->value_data_size,
1484
1.06k
   value_data_size );
1485
1486
1.06k
  byte_stream_copy_to_uint16_little_endian(
1487
1.06k
   ( (wrc_version_value_header_t *) data )->value_data_type,
1488
1.06k
   value_data_type );
1489
1490
#if defined( HAVE_DEBUG_OUTPUT )
1491
  if( libcnotify_verbose != 0 )
1492
  {
1493
    libcnotify_printf(
1494
     "%s: size\t\t\t\t: %" PRIu16 "\n",
1495
     function,
1496
     resource_data_size );
1497
1498
    libcnotify_printf(
1499
     "%s: value data size\t\t: %" PRIu16 "\n",
1500
     function,
1501
     value_data_size );
1502
1503
    libcnotify_printf(
1504
     "%s: value data type\t\t: %" PRIu16 "\n",
1505
     function,
1506
     value_data_type );
1507
1508
    libcnotify_printf(
1509
     "\n" );
1510
  }
1511
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1512
1513
1.06k
  data_offset = sizeof( wrc_version_value_header_t );
1514
1515
1.06k
  value_identifier_string      = &( data[ data_offset ] );
1516
1.06k
  value_identifier_string_size = 0;
1517
1518
934k
  while( data_offset < ( data_size - 2 ) )
1519
934k
  {
1520
934k
    value_identifier_string_size += 2;
1521
1522
934k
    if( ( data[ data_offset ] == 0 )
1523
934k
     && ( data[ data_offset + 1 ] == 0 ) )
1524
929
    {
1525
929
      data_offset += 2;
1526
1527
929
      break;
1528
929
    }
1529
933k
    data_offset += 2;
1530
933k
  }
1531
#if defined( HAVE_DEBUG_OUTPUT )
1532
  if( libcnotify_verbose != 0 )
1533
  {
1534
    libcnotify_printf(
1535
     "%s: value identifier string data:\n",
1536
     function );
1537
    libcnotify_print_data(
1538
     value_identifier_string,
1539
     value_identifier_string_size,
1540
     0 );
1541
  }
1542
#endif
1543
1.06k
  if( ( value_identifier_string_size != 32 )
1544
1.06k
   || ( memory_compare(
1545
1.01k
         value_identifier_string,
1546
1.01k
         libwrc_version_information_resource_signature,
1547
1.01k
         32 ) != 0 ) )
1548
182
  {
1549
182
    libcerror_error_set(
1550
182
     error,
1551
182
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1552
182
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1553
182
     "%s: unsupported version resource value signature.",
1554
182
     function );
1555
1556
182
    return( -1 );
1557
182
  }
1558
#if defined( HAVE_DEBUG_OUTPUT )
1559
  if( libcnotify_verbose != 0 )
1560
  {
1561
    if( libwrc_debug_print_utf16_string_value(
1562
         function,
1563
         "value identifier\t\t",
1564
         value_identifier_string,
1565
         value_identifier_string_size,
1566
         LIBUNA_ENDIAN_LITTLE,
1567
         error ) != 1 )
1568
    {
1569
      libcerror_error_set(
1570
       error,
1571
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1572
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
1573
       "%s: unable to print UTF-16 string value.",
1574
       function );
1575
1576
      return( -1 );
1577
    }
1578
  }
1579
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1580
1581
882
  if( ( data_offset % 4 ) != 0 )
1582
882
  {
1583
882
    alignment_padding_size = 4 - ( data_offset % 4 );
1584
1585
882
    if( alignment_padding_size > ( data_size - data_offset ) )
1586
1
    {
1587
1
      libcerror_error_set(
1588
1
       error,
1589
1
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1590
1
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1591
1
       "%s: invalid data size value too small.",
1592
1
       function );
1593
1594
1
      return( -1 );
1595
1
    }
1596
#if defined( HAVE_DEBUG_OUTPUT )
1597
    if( libcnotify_verbose != 0 )
1598
    {
1599
      libcnotify_printf(
1600
       "%s: alignment padding:\n",
1601
       function );
1602
      libcnotify_print_data(
1603
       &( data[ data_offset ] ),
1604
       alignment_padding_size,
1605
       0 );
1606
    }
1607
#endif
1608
881
    data_offset += alignment_padding_size;
1609
881
  }
1610
/* TODO refactor to separate function? */
1611
881
  if( value_data_size > 0 )
1612
248
  {
1613
248
    if( ( value_data_size < 52 )
1614
248
     || ( value_data_size > ( data_size - data_offset ) ) )
1615
26
    {
1616
26
      libcerror_error_set(
1617
26
       error,
1618
26
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1619
26
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1620
26
       "%s: invalid value data size value out of bounds.",
1621
26
       function );
1622
1623
26
      return( -1 );
1624
26
    }
1625
#if defined( HAVE_DEBUG_OUTPUT )
1626
    if( libcnotify_verbose != 0 )
1627
    {
1628
      libcnotify_printf(
1629
       "%s: value data:\n",
1630
       function );
1631
      libcnotify_print_data(
1632
       &( data[ data_offset ] ),
1633
       value_data_size,
1634
       0 );
1635
    }
1636
#endif
1637
222
    byte_stream_copy_to_uint32_little_endian(
1638
222
     &( data[ data_offset + 8 ] ),
1639
222
     internal_version_information_resource->file_version );
1640
1641
222
    byte_stream_copy_to_uint32_little_endian(
1642
222
     &( data[ data_offset + 12 ] ),
1643
222
     value_32bit );
1644
1645
222
    internal_version_information_resource->file_version <<= 32;
1646
222
    internal_version_information_resource->file_version  |= value_32bit;
1647
1648
222
    byte_stream_copy_to_uint32_little_endian(
1649
222
     &( data[ data_offset + 16 ] ),
1650
222
     internal_version_information_resource->product_version );
1651
1652
222
    byte_stream_copy_to_uint32_little_endian(
1653
222
     &( data[ data_offset + 20 ] ),
1654
222
     value_32bit );
1655
1656
222
    internal_version_information_resource->product_version <<= 32;
1657
222
    internal_version_information_resource->product_version  |= value_32bit;
1658
1659
#if defined( HAVE_DEBUG_OUTPUT )
1660
    if( libcnotify_verbose != 0 )
1661
    {
1662
      byte_stream_copy_to_uint32_little_endian(
1663
       &( data[ data_offset ] ),
1664
       value_32bit );
1665
      libcnotify_printf(
1666
       "%s: signature\t\t\t: 0x%08" PRIx32 "\n",
1667
       function,
1668
       value_32bit );
1669
1670
      byte_stream_copy_to_uint32_little_endian(
1671
       &( data[ data_offset + 4 ] ),
1672
       value_32bit );
1673
      libcnotify_printf(
1674
       "%s: version\t\t\t: %" PRIu32 ".%" PRIu32 "\n",
1675
       function,
1676
       value_32bit >> 16,
1677
       value_32bit & 0x0000ffffUL );
1678
1679
      byte_stream_copy_to_uint32_little_endian(
1680
       &( data[ data_offset + 8 ] ),
1681
       value_32bit );
1682
      libcnotify_printf(
1683
       "%s: file version upper\t\t: %" PRIu32 ".%" PRIu32 "\n",
1684
       function,
1685
       value_32bit >> 16,
1686
       value_32bit & 0x0000ffffUL );
1687
1688
      byte_stream_copy_to_uint32_little_endian(
1689
       &( data[ data_offset + 12 ] ),
1690
       value_32bit );
1691
      libcnotify_printf(
1692
       "%s: file version lower\t\t: %" PRIu32 ".%" PRIu32 "\n",
1693
       function,
1694
       value_32bit >> 16,
1695
       value_32bit & 0x0000ffffUL );
1696
1697
      byte_stream_copy_to_uint32_little_endian(
1698
       &( data[ data_offset + 16 ] ),
1699
       value_32bit );
1700
      libcnotify_printf(
1701
       "%s: product version upper\t\t: %" PRIu32 ".%" PRIu32 "\n",
1702
       function,
1703
       value_32bit >> 16,
1704
       value_32bit & 0x0000ffffUL );
1705
1706
      byte_stream_copy_to_uint32_little_endian(
1707
       &( data[ data_offset + 20 ] ),
1708
       value_32bit );
1709
      libcnotify_printf(
1710
       "%s: product version lower\t\t: %" PRIu32 ".%" PRIu32 "\n",
1711
       function,
1712
       value_32bit >> 16,
1713
       value_32bit & 0x0000ffffUL );
1714
1715
      byte_stream_copy_to_uint32_little_endian(
1716
       &( data[ data_offset + 24 ] ),
1717
       value_32bit );
1718
      libcnotify_printf(
1719
       "%s: file flags bitmask\t\t: 0x%08" PRIx32 "\n",
1720
       function,
1721
       value_32bit );
1722
1723
      byte_stream_copy_to_uint32_little_endian(
1724
       &( data[ data_offset + 28 ] ),
1725
       value_32bit );
1726
      libcnotify_printf(
1727
       "%s: file flags\t\t\t: 0x%08" PRIx32 "\n",
1728
       function,
1729
       value_32bit );
1730
1731
      byte_stream_copy_to_uint32_little_endian(
1732
       &( data[ data_offset + 32 ] ),
1733
       value_32bit );
1734
      libcnotify_printf(
1735
       "%s: file operating system\t\t: 0x%08" PRIx32 "\n",
1736
       function,
1737
       value_32bit );
1738
1739
      byte_stream_copy_to_uint32_little_endian(
1740
       &( data[ data_offset + 36 ] ),
1741
       value_32bit );
1742
      libcnotify_printf(
1743
       "%s: file type\t\t\t: 0x%08" PRIx32 "\n",
1744
       function,
1745
       value_32bit );
1746
1747
      byte_stream_copy_to_uint32_little_endian(
1748
       &( data[ data_offset + 40 ] ),
1749
       value_32bit );
1750
      libcnotify_printf(
1751
       "%s: file sub type\t\t\t: 0x%08" PRIx32 "\n",
1752
       function,
1753
       value_32bit );
1754
1755
      byte_stream_copy_to_uint32_little_endian(
1756
       &( data[ data_offset + 44 ] ),
1757
       value_32bit );
1758
      libcnotify_printf(
1759
       "%s: file time upper\t\t: 0x%08" PRIx32 "\n",
1760
       function,
1761
       value_32bit );
1762
1763
      byte_stream_copy_to_uint32_little_endian(
1764
       &( data[ data_offset + 48 ] ),
1765
       value_32bit );
1766
      libcnotify_printf(
1767
       "%s: file time lower\t\t: 0x%08" PRIx32 "\n",
1768
       function,
1769
       value_32bit );
1770
1771
      libcnotify_printf(
1772
       "\n" );
1773
    }
1774
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1775
1776
222
    data_offset += value_data_size;
1777
222
  }
1778
855
  if( ( data_offset % 4 ) != 0 )
1779
148
  {
1780
148
    alignment_padding_size = 4 - ( data_offset % 4 );
1781
1782
148
    if( alignment_padding_size > ( data_size - data_offset ) )
1783
7
    {
1784
7
      libcerror_error_set(
1785
7
       error,
1786
7
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1787
7
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1788
7
       "%s: invalid data size value too small.",
1789
7
       function );
1790
1791
7
      return( -1 );
1792
7
    }
1793
#if defined( HAVE_DEBUG_OUTPUT )
1794
    if( libcnotify_verbose != 0 )
1795
    {
1796
      libcnotify_printf(
1797
       "%s: alignment padding:\n",
1798
       function );
1799
      libcnotify_print_data(
1800
       &( data[ data_offset ] ),
1801
       alignment_padding_size,
1802
       0 );
1803
    }
1804
#endif
1805
141
    data_offset += alignment_padding_size;
1806
141
  }
1807
848
  read_count = libwrc_internal_version_information_resource_read_string_file_information(
1808
848
                internal_version_information_resource,
1809
848
                data,
1810
848
                data_size,
1811
848
                data_offset,
1812
848
                error );
1813
1814
848
  if( read_count == -1 )
1815
219
  {
1816
219
    libcerror_error_set(
1817
219
     error,
1818
219
     LIBCERROR_ERROR_DOMAIN_IO,
1819
219
     LIBCERROR_IO_ERROR_READ_FAILED,
1820
219
     "%s: unable to read string file information.",
1821
219
     function );
1822
1823
219
    return( -1 );
1824
219
  }
1825
629
  data_offset += read_count;
1826
1827
629
  read_count = libwrc_internal_version_information_resource_read_variable_file_information(
1828
629
                internal_version_information_resource,
1829
629
                data,
1830
629
                data_size,
1831
629
                data_offset,
1832
629
                error );
1833
1834
629
  if( read_count == -1 )
1835
246
  {
1836
246
    libcerror_error_set(
1837
246
     error,
1838
246
     LIBCERROR_ERROR_DOMAIN_IO,
1839
246
     LIBCERROR_IO_ERROR_READ_FAILED,
1840
246
     "%s: unable to read variable file information.",
1841
246
     function );
1842
1843
246
    return( -1 );
1844
246
  }
1845
383
  return( 1 );
1846
629
}
1847
1848
/* Retrieves the file version
1849
 * Returns 1 if successful or -1 on error
1850
 */
1851
int libwrc_version_information_resource_get_file_version(
1852
     libwrc_version_information_resource_t *version_information_resource,
1853
     uint64_t *file_version,
1854
     libcerror_error_t **error )
1855
0
{
1856
0
  libwrc_internal_version_information_resource_t *internal_version_information_resource = NULL;
1857
0
  static char *function                                                                 = "libwrc_version_information_resource_get_file_version";
1858
1859
0
  if( version_information_resource == NULL )
1860
0
  {
1861
0
    libcerror_error_set(
1862
0
     error,
1863
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1864
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1865
0
     "%s: invalid version information resource.",
1866
0
     function );
1867
1868
0
    return( -1 );
1869
0
  }
1870
0
  internal_version_information_resource = (libwrc_internal_version_information_resource_t *) version_information_resource;
1871
1872
0
  if( file_version == NULL )
1873
0
  {
1874
0
    libcerror_error_set(
1875
0
     error,
1876
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1877
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1878
0
     "%s: invalid file version.",
1879
0
     function );
1880
1881
0
    return( -1 );
1882
0
  }
1883
0
  *file_version = internal_version_information_resource->file_version;
1884
1885
0
  return( 1 );
1886
0
}
1887
1888
/* Retrieves the product version
1889
 * Returns 1 if successful or -1 on error
1890
 */
1891
int libwrc_version_information_resource_get_product_version(
1892
     libwrc_version_information_resource_t *version_information_resource,
1893
     uint64_t *product_version,
1894
     libcerror_error_t **error )
1895
0
{
1896
0
  libwrc_internal_version_information_resource_t *internal_version_information_resource = NULL;
1897
0
  static char *function                                                                 = "libwrc_version_information_resource_get_product_version";
1898
1899
0
  if( version_information_resource == NULL )
1900
0
  {
1901
0
    libcerror_error_set(
1902
0
     error,
1903
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1904
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1905
0
     "%s: invalid version information resource.",
1906
0
     function );
1907
1908
0
    return( -1 );
1909
0
  }
1910
0
  internal_version_information_resource = (libwrc_internal_version_information_resource_t *) version_information_resource;
1911
1912
0
  if( product_version == NULL )
1913
0
  {
1914
0
    libcerror_error_set(
1915
0
     error,
1916
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1917
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1918
0
     "%s: invalid product version.",
1919
0
     function );
1920
1921
0
    return( -1 );
1922
0
  }
1923
0
  *product_version = internal_version_information_resource->product_version;
1924
1925
0
  return( 1 );
1926
0
}
1927