Coverage Report

Created: 2026-07-25 07:30

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