Coverage Report

Created: 2025-10-14 07:00

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-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.05k
{
48
1.05k
  libwrc_internal_version_information_resource_t *internal_version_information_resource = NULL;
49
1.05k
  static char *function                                                                 = "libwrc_version_information_resource_initialize";
50
51
1.05k
  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.05k
  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.05k
  internal_version_information_resource = memory_allocate_structure(
74
1.05k
                                           libwrc_internal_version_information_resource_t );
75
76
1.05k
  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.05k
  if( memory_set(
88
1.05k
       internal_version_information_resource,
89
1.05k
       0,
90
1.05k
       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.05k
  *version_information_resource = (libwrc_version_information_resource_t *) internal_version_information_resource;
102
103
1.05k
  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.05k
}
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.05k
{
121
1.05k
  libwrc_internal_version_information_resource_t *internal_version_information_resource = NULL;
122
1.05k
  static char *function                                                                 = "libwrc_version_information_resource_free";
123
124
1.05k
  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.05k
  if( *version_information_resource != NULL )
136
1.05k
  {
137
1.05k
    internal_version_information_resource = (libwrc_internal_version_information_resource_t *) *version_information_resource;
138
1.05k
    *version_information_resource         = NULL;
139
140
1.05k
    memory_free(
141
1.05k
     internal_version_information_resource );
142
1.05k
  }
143
1.05k
  return( 1 );
144
1.05k
}
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
824
{
156
824
  const uint8_t *value_identifier_string = NULL;
157
824
  static char *function                  = "libwrc_internal_version_information_resource_read_string_file_information";
158
824
  size_t alignment_padding_size          = 0;
159
824
  size_t calculated_value_data_size      = 0;
160
824
  size_t data_start_offset               = 0;
161
824
  size_t trailing_data_size              = 0;
162
824
  size_t value_identifier_string_size    = 0;
163
824
  ssize_t read_count                     = 0;
164
824
  uint16_t string_data_size              = 0;
165
824
  uint16_t value_data_size               = 0;
166
824
  uint16_t value_data_type               = 0;
167
168
824
  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
824
  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
824
  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
824
  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
820
  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
817
  data_start_offset = data_offset;
224
225
817
  byte_stream_copy_to_uint16_little_endian(
226
817
   &( data[ data_offset ] ),
227
817
   string_data_size );
228
229
817
  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
817
  if( string_data_size != 0 )
241
801
  {
242
801
    if( ( string_data_size < 8 )
243
798
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
244
45
    {
245
45
      libcerror_error_set(
246
45
       error,
247
45
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
248
45
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
249
45
       "%s: data size value out of bounds.",
250
45
       function );
251
252
45
      return( -1 );
253
45
    }
254
756
    byte_stream_copy_to_uint16_little_endian(
255
756
     &( data[ data_offset ] ),
256
756
     value_data_size );
257
258
756
    data_offset += 2;
259
260
756
    byte_stream_copy_to_uint16_little_endian(
261
756
     &( data[ data_offset ] ),
262
756
     value_data_type );
263
264
756
    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
756
    value_identifier_string      = &( data[ data_offset ] );
281
756
    value_identifier_string_size = 0;
282
283
4.73M
    while( ( data_offset + 2 ) < data_size )
284
4.73M
    {
285
4.73M
      value_identifier_string_size += 2;
286
287
4.73M
      if( ( data[ data_offset ] == 0 )
288
18.9k
       && ( data[ data_offset + 1 ] == 0 ) )
289
665
      {
290
665
        data_offset += 2;
291
292
665
        break;
293
665
      }
294
4.72M
      data_offset += 2;
295
4.72M
    }
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
756
    if( ( data_offset % 4 ) != 0 )
310
207
    {
311
207
      alignment_padding_size = 4 - ( data_offset % 4 );
312
313
207
      if( alignment_padding_size > ( data_size - data_offset ) )
314
15
      {
315
15
        libcerror_error_set(
316
15
         error,
317
15
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
318
15
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
319
15
         "%s: invalid data size value too small.",
320
15
         function );
321
322
15
        return( -1 );
323
15
      }
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
192
      data_offset += alignment_padding_size;
337
192
    }
338
741
    if( value_data_type == 1 )
339
497
    {
340
/* TODO check value_data_size == 0 ? */
341
497
      read_count = libwrc_internal_version_information_resource_read_string_table(
342
497
              internal_version_information_resource,
343
497
              data,
344
497
              data_size,
345
497
              data_offset,
346
497
              error );
347
348
497
      if( read_count == -1 )
349
143
      {
350
143
        libcerror_error_set(
351
143
         error,
352
143
         LIBCERROR_ERROR_DOMAIN_IO,
353
143
         LIBCERROR_IO_ERROR_READ_FAILED,
354
143
         "%s: unable to read string table.",
355
143
         function );
356
357
143
        return( -1 );
358
143
      }
359
354
      data_offset += read_count;
360
354
    }
361
/* TODO print unsupported type warning */
362
598
    calculated_value_data_size = data_offset - data_start_offset;
363
364
598
    if( calculated_value_data_size < string_data_size )
365
121
    {
366
121
      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
121
      data_offset += trailing_data_size;
381
121
    }
382
598
  }
383
614
  return( (ssize_t) string_data_size );
384
817
}
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
497
{
396
497
  const uint8_t *value_identifier_string = NULL;
397
497
  static char *function                  = "libwrc_internal_version_information_resource_read_string_table";
398
497
  size_t alignment_padding_size          = 0;
399
497
  size_t calculated_value_data_size      = 0;
400
497
  size_t data_start_offset               = 0;
401
497
  size_t trailing_data_size              = 0;
402
497
  size_t value_identifier_string_size    = 0;
403
497
  ssize_t read_count                     = 0;
404
497
  uint16_t string_data_size              = 0;
405
497
  uint16_t value_data_size               = 0;
406
497
  uint16_t value_data_type               = 0;
407
408
497
  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
497
  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
497
  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
497
  if( data_offset >= data_size )
442
3
  {
443
3
    libcerror_error_set(
444
3
     error,
445
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
446
3
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
447
3
     "%s: invalid data offset value out of bounds.",
448
3
     function );
449
450
3
    return( -1 );
451
3
  }
452
494
  if( ( data_offset + 2 ) > data_size )
453
8
  {
454
8
    libcerror_error_set(
455
8
     error,
456
8
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
457
8
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
458
8
     "%s: invalid data value too small.",
459
8
     function );
460
461
8
    return( -1 );
462
8
  }
463
486
  data_start_offset = data_offset;
464
465
486
  byte_stream_copy_to_uint16_little_endian(
466
486
   &( data[ data_offset ] ),
467
486
   string_data_size );
468
469
486
  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
486
  if( string_data_size != 0 )
481
472
  {
482
472
    if( ( string_data_size < 8 )
483
466
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
484
46
    {
485
46
      libcerror_error_set(
486
46
       error,
487
46
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
488
46
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
489
46
       "%s: data size value out of bounds.",
490
46
       function );
491
492
46
      return( -1 );
493
46
    }
494
426
    byte_stream_copy_to_uint16_little_endian(
495
426
     &( data[ data_offset ] ),
496
426
     value_data_size );
497
498
426
    data_offset += 2;
499
500
426
    byte_stream_copy_to_uint16_little_endian(
501
426
     &( data[ data_offset ] ),
502
426
     value_data_type );
503
504
426
    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
426
    value_identifier_string      = &( data[ data_offset ] );
521
426
    value_identifier_string_size = 0;
522
523
1.77M
    while( ( data_offset + 2 ) < data_size )
524
1.77M
    {
525
1.77M
      value_identifier_string_size += 2;
526
527
1.77M
      if( ( data[ data_offset ] == 0 )
528
6.94k
       && ( data[ data_offset + 1 ] == 0 ) )
529
325
      {
530
325
        data_offset += 2;
531
532
325
        break;
533
325
      }
534
1.77M
      data_offset += 2;
535
1.77M
    }
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
426
    if( ( data_offset % 4 ) != 0 )
550
163
    {
551
163
      alignment_padding_size = 4 - ( data_offset % 4 );
552
553
163
      if( alignment_padding_size > ( data_size - data_offset ) )
554
19
      {
555
19
        libcerror_error_set(
556
19
         error,
557
19
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
558
19
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
559
19
         "%s: invalid data size value too small.",
560
19
         function );
561
562
19
        return( -1 );
563
19
      }
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
144
      data_offset += alignment_padding_size;
577
144
    }
578
407
    if( value_data_type == 0 )
579
19
    {
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
19
      data_offset += value_data_size;
594
19
    }
595
388
    else if( value_data_type == 1 )
596
281
    {
597
/* TODO check value_data_size == 0 ? */
598
1.79k
      while( ( data_offset + 2 ) < ( data_start_offset + string_data_size ) )
599
1.61k
      {
600
1.61k
        read_count = libwrc_internal_version_information_resource_read_string(
601
1.61k
                internal_version_information_resource,
602
1.61k
                data,
603
1.61k
                data_size,
604
1.61k
                data_offset,
605
1.61k
                error );
606
607
1.61k
        if( read_count == -1 )
608
67
        {
609
67
          libcerror_error_set(
610
67
           error,
611
67
           LIBCERROR_ERROR_DOMAIN_IO,
612
67
           LIBCERROR_IO_ERROR_READ_FAILED,
613
67
           "%s: unable to read string.",
614
67
           function );
615
616
67
          return( -1 );
617
67
        }
618
1.55k
        else if( read_count == 0 )
619
39
        {
620
39
          break;
621
39
        }
622
1.51k
        data_offset += read_count;
623
624
1.51k
        if( ( data_offset % 4 ) != 0 )
625
418
        {
626
418
          alignment_padding_size = 4 - ( data_offset % 4 );
627
628
418
          if( ( data_offset + alignment_padding_size ) < ( data_start_offset + string_data_size ) )
629
328
          {
630
328
            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
328
            data_offset += alignment_padding_size;
654
328
          }
655
418
        }
656
1.51k
      }
657
281
    }
658
/* TODO print unsupported type warning */
659
340
    calculated_value_data_size = data_offset - data_start_offset;
660
661
340
    if( calculated_value_data_size < string_data_size )
662
128
    {
663
128
      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
128
      data_offset += trailing_data_size;
678
128
    }
679
340
  }
680
354
  return( (ssize_t) string_data_size );
681
486
}
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.61k
{
693
1.61k
  static char *function         = "libwrc_internal_version_information_resource_read_string";
694
1.61k
  size_t alignment_padding_size = 0;
695
1.61k
  size_t value_string_size      = 0;
696
1.61k
  uint16_t string_data_size     = 0;
697
1.61k
  uint16_t value_data_size      = 0;
698
1.61k
  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.61k
  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.61k
  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.61k
  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.61k
  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.61k
  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.61k
  byte_stream_copy_to_uint16_little_endian(
766
1.61k
   &( data[ data_offset ] ),
767
1.61k
   string_data_size );
768
769
1.61k
  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.61k
  if( string_data_size != 0 )
781
1.58k
  {
782
1.58k
    if( ( string_data_size < 8 )
783
1.57k
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
784
67
    {
785
67
      libcerror_error_set(
786
67
       error,
787
67
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
788
67
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
789
67
       "%s: data size value out of bounds.",
790
67
       function );
791
792
67
      return( -1 );
793
67
    }
794
1.51k
    byte_stream_copy_to_uint16_little_endian(
795
1.51k
     &( data[ data_offset ] ),
796
1.51k
     value_data_size );
797
798
1.51k
    data_offset += 2;
799
800
1.51k
    byte_stream_copy_to_uint16_little_endian(
801
1.51k
     &( data[ data_offset ] ),
802
1.51k
     value_data_type );
803
804
1.51k
    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.51k
    value_string_size = 0;
827
828
778k
    while( ( data_offset + 2 ) < data_size )
829
777k
    {
830
777k
      value_string_size += 2;
831
832
777k
      if( ( data[ data_offset ] == 0 )
833
12.9k
       && ( data[ data_offset + 1 ] == 0 ) )
834
1.16k
      {
835
1.16k
        data_offset += 2;
836
837
1.16k
        break;
838
1.16k
      }
839
776k
      data_offset += 2;
840
776k
    }
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.51k
    if( ( data_offset % 4 ) != 0 )
855
764
    {
856
764
      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
764
      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
764
      data_offset += alignment_padding_size;
882
764
    }
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.51k
  }
933
1.55k
  return( (ssize_t) string_data_size );
934
1.61k
}
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
614
{
946
614
  static char *function         = "libwrc_internal_version_information_resource_read_variable_file_information";
947
614
  size_t alignment_padding_size = 0;
948
614
  size_t data_start_offset      = 0;
949
614
  size_t value_string_size      = 0;
950
614
  ssize_t read_count            = 0;
951
614
  uint16_t string_data_size     = 0;
952
614
  uint16_t value_data_size      = 0;
953
614
  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
614
  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
614
  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
614
  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
614
  if( data_offset >= data_size )
994
35
  {
995
35
    libcerror_error_set(
996
35
     error,
997
35
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
998
35
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
999
35
     "%s: invalid data offset value out of bounds.",
1000
35
     function );
1001
1002
35
    return( -1 );
1003
35
  }
1004
579
  if( ( data_offset + 2 ) > data_size )
1005
24
  {
1006
24
    libcerror_error_set(
1007
24
     error,
1008
24
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1009
24
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1010
24
     "%s: invalid data value too small.",
1011
24
     function );
1012
1013
24
    return( -1 );
1014
24
  }
1015
555
  data_start_offset = data_offset;
1016
1017
555
  byte_stream_copy_to_uint16_little_endian(
1018
555
   &( data[ data_offset ] ),
1019
555
   string_data_size );
1020
1021
555
  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
555
  if( string_data_size != 0 )
1033
514
  {
1034
514
    if( ( string_data_size < 8 )
1035
510
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
1036
75
    {
1037
75
      libcerror_error_set(
1038
75
       error,
1039
75
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1040
75
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1041
75
       "%s: data size value out of bounds.",
1042
75
       function );
1043
1044
75
      return( -1 );
1045
75
    }
1046
439
    byte_stream_copy_to_uint16_little_endian(
1047
439
     &( data[ data_offset ] ),
1048
439
     value_data_size );
1049
1050
439
    data_offset += 2;
1051
1052
439
    byte_stream_copy_to_uint16_little_endian(
1053
439
     &( data[ data_offset ] ),
1054
439
     value_data_type );
1055
1056
439
    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
439
    value_string_size  = 0;
1079
1080
3.85M
    while( ( data_offset + 2 ) < data_size )
1081
3.85M
    {
1082
3.85M
      value_string_size += 2;
1083
1084
3.85M
      if( ( data[ data_offset ] == 0 )
1085
15.0k
       && ( data[ data_offset + 1 ] == 0 ) )
1086
345
      {
1087
345
        data_offset += 2;
1088
1089
345
        break;
1090
345
      }
1091
3.84M
      data_offset += 2;
1092
3.84M
    }
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
439
    if( ( data_offset % 4 ) != 0 )
1107
216
    {
1108
216
      alignment_padding_size = 4 - ( data_offset % 4 );
1109
1110
216
      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
201
      data_offset += alignment_padding_size;
1134
201
    }
1135
2.05k
    while( ( data_offset + 2 ) < ( data_start_offset + string_data_size ) )
1136
1.79k
    {
1137
1.79k
      read_count = libwrc_internal_version_information_resource_read_variable(
1138
1.79k
              internal_version_information_resource,
1139
1.79k
              data,
1140
1.79k
              data_size,
1141
1.79k
              data_offset,
1142
1.79k
              error );
1143
1144
1.79k
      if( read_count == -1 )
1145
87
      {
1146
87
        libcerror_error_set(
1147
87
         error,
1148
87
         LIBCERROR_ERROR_DOMAIN_IO,
1149
87
         LIBCERROR_IO_ERROR_READ_FAILED,
1150
87
         "%s: unable to read variable.",
1151
87
         function );
1152
1153
87
        return( -1 );
1154
87
      }
1155
1.70k
      else if( read_count == 0 )
1156
76
      {
1157
76
        break;
1158
76
      }
1159
1.62k
      data_offset += read_count;
1160
1.62k
    }
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
424
  }
1181
378
  return( (ssize_t) string_data_size );
1182
555
}
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.79k
{
1194
1.79k
  static char *function         = "libwrc_internal_version_information_resource_read_variable";
1195
1.79k
  size_t alignment_padding_size = 0;
1196
1.79k
  size_t value_string_size      = 0;
1197
1.79k
  uint16_t string_data_size     = 0;
1198
1.79k
  uint16_t value_data_size      = 0;
1199
1.79k
  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.79k
  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.79k
  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.79k
  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.79k
  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.79k
  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.79k
  byte_stream_copy_to_uint16_little_endian(
1267
1.79k
   &( data[ data_offset ] ),
1268
1.79k
   string_data_size );
1269
1270
1.79k
  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.79k
  if( string_data_size != 0 )
1282
1.71k
  {
1283
1.71k
    if( ( string_data_size < 8 )
1284
1.71k
     || ( string_data_size > ( data_size - ( data_offset - 2 ) ) ) )
1285
80
    {
1286
80
      libcerror_error_set(
1287
80
       error,
1288
80
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1289
80
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1290
80
       "%s: data size value out of bounds.",
1291
80
       function );
1292
1293
80
      return( -1 );
1294
80
    }
1295
1.63k
    byte_stream_copy_to_uint16_little_endian(
1296
1.63k
     &( data[ data_offset ] ),
1297
1.63k
     value_data_size );
1298
1299
1.63k
    data_offset += 2;
1300
1301
1.63k
    byte_stream_copy_to_uint16_little_endian(
1302
1.63k
     &( data[ data_offset ] ),
1303
1.63k
     value_data_type );
1304
1305
1.63k
    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.63k
    value_string_size = 0;
1328
1329
460k
    while( ( data_offset + 2 ) < data_size )
1330
460k
    {
1331
460k
      value_string_size += 2;
1332
1333
460k
      if( ( data[ data_offset ] == 0 )
1334
13.0k
       && ( data[ data_offset + 1 ] == 0 ) )
1335
1.20k
      {
1336
1.20k
        data_offset += 2;
1337
1338
1.20k
        break;
1339
1.20k
      }
1340
458k
      data_offset += 2;
1341
458k
    }
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.63k
    if( ( data_offset % 4 ) != 0 )
1356
836
    {
1357
836
      alignment_padding_size = 4 - ( data_offset % 4 );
1358
1359
836
      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
829
      data_offset += alignment_padding_size;
1383
829
    }
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.63k
  }
1406
1.70k
  return( (ssize_t) string_data_size );
1407
1.79k
}
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.05k
{
1418
1.05k
  libwrc_internal_version_information_resource_t *internal_version_information_resource = NULL;
1419
1.05k
  const uint8_t *value_identifier_string                                                = NULL;
1420
1.05k
  static char *function                                                                 = "libwrc_version_information_resource_read";
1421
1.05k
  size_t alignment_padding_size                                                         = 0;
1422
1.05k
  size_t data_offset                                                                    = 0;
1423
1.05k
  size_t value_identifier_string_size                                                   = 0;
1424
1.05k
  ssize_t read_count                                                                    = 0;
1425
1.05k
  uint32_t value_32bit                                                                  = 0;
1426
1.05k
  uint16_t resource_data_size                                                           = 0;
1427
1.05k
  uint16_t value_data_size                                                              = 0;
1428
1.05k
  uint16_t value_data_type                                                              = 0;
1429
1430
1.05k
  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.05k
  internal_version_information_resource = (libwrc_internal_version_information_resource_t *) version_information_resource;
1442
1443
1.05k
  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.05k
  if( ( data_size < sizeof( wrc_version_value_header_t ) )
1455
1.05k
   || ( 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.05k
  byte_stream_copy_to_uint16_little_endian(
1479
1.05k
   ( (wrc_version_value_header_t *) data )->size,
1480
1.05k
   resource_data_size );
1481
1482
1.05k
  byte_stream_copy_to_uint16_little_endian(
1483
1.05k
   ( (wrc_version_value_header_t *) data )->value_data_size,
1484
1.05k
   value_data_size );
1485
1486
1.05k
  byte_stream_copy_to_uint16_little_endian(
1487
1.05k
   ( (wrc_version_value_header_t *) data )->value_data_type,
1488
1.05k
   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.05k
  data_offset = sizeof( wrc_version_value_header_t );
1514
1515
1.05k
  value_identifier_string      = &( data[ data_offset ] );
1516
1.05k
  value_identifier_string_size = 0;
1517
1518
2.22M
  while( data_offset < ( data_size - 2 ) )
1519
2.22M
  {
1520
2.22M
    value_identifier_string_size += 2;
1521
1522
2.22M
    if( ( data[ data_offset ] == 0 )
1523
19.2k
     && ( data[ data_offset + 1 ] == 0 ) )
1524
910
    {
1525
910
      data_offset += 2;
1526
1527
910
      break;
1528
910
    }
1529
2.22M
    data_offset += 2;
1530
2.22M
  }
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.05k
  if( ( value_identifier_string_size != 32 )
1544
985
   || ( memory_compare(
1545
985
         value_identifier_string,
1546
985
         libwrc_version_information_resource_signature,
1547
985
         32 ) != 0 ) )
1548
198
  {
1549
198
    libcerror_error_set(
1550
198
     error,
1551
198
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1552
198
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1553
198
     "%s: unsupported version resource value signature.",
1554
198
     function );
1555
1556
198
    return( -1 );
1557
198
  }
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
856
  if( ( data_offset % 4 ) != 0 )
1582
856
  {
1583
856
    alignment_padding_size = 4 - ( data_offset % 4 );
1584
1585
856
    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
855
    data_offset += alignment_padding_size;
1609
855
  }
1610
/* TODO refactor to separate function? */
1611
855
  if( value_data_size > 0 )
1612
223
  {
1613
223
    if( ( value_data_size < 52 )
1614
217
     || ( value_data_size > ( data_size - data_offset ) ) )
1615
24
    {
1616
24
      libcerror_error_set(
1617
24
       error,
1618
24
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1619
24
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1620
24
       "%s: invalid value data size value out of bounds.",
1621
24
       function );
1622
1623
24
      return( -1 );
1624
24
    }
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
199
    byte_stream_copy_to_uint32_little_endian(
1638
199
     &( data[ data_offset + 8 ] ),
1639
199
     internal_version_information_resource->file_version );
1640
1641
199
    byte_stream_copy_to_uint32_little_endian(
1642
199
     &( data[ data_offset + 12 ] ),
1643
199
     value_32bit );
1644
1645
199
    internal_version_information_resource->file_version <<= 32;
1646
199
    internal_version_information_resource->file_version  |= value_32bit;
1647
1648
199
    byte_stream_copy_to_uint32_little_endian(
1649
199
     &( data[ data_offset + 16 ] ),
1650
199
     internal_version_information_resource->product_version );
1651
1652
199
    byte_stream_copy_to_uint32_little_endian(
1653
199
     &( data[ data_offset + 20 ] ),
1654
199
     value_32bit );
1655
1656
199
    internal_version_information_resource->product_version <<= 32;
1657
199
    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
199
    data_offset += value_data_size;
1777
199
  }
1778
831
  if( ( data_offset % 4 ) != 0 )
1779
137
  {
1780
137
    alignment_padding_size = 4 - ( data_offset % 4 );
1781
1782
137
    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
130
    data_offset += alignment_padding_size;
1806
130
  }
1807
824
  read_count = libwrc_internal_version_information_resource_read_string_file_information(
1808
824
                internal_version_information_resource,
1809
824
                data,
1810
824
                data_size,
1811
824
                data_offset,
1812
824
                error );
1813
1814
824
  if( read_count == -1 )
1815
210
  {
1816
210
    libcerror_error_set(
1817
210
     error,
1818
210
     LIBCERROR_ERROR_DOMAIN_IO,
1819
210
     LIBCERROR_IO_ERROR_READ_FAILED,
1820
210
     "%s: unable to read string file information.",
1821
210
     function );
1822
1823
210
    return( -1 );
1824
210
  }
1825
614
  data_offset += read_count;
1826
1827
614
  read_count = libwrc_internal_version_information_resource_read_variable_file_information(
1828
614
                internal_version_information_resource,
1829
614
                data,
1830
614
                data_size,
1831
614
                data_offset,
1832
614
                error );
1833
1834
614
  if( read_count == -1 )
1835
236
  {
1836
236
    libcerror_error_set(
1837
236
     error,
1838
236
     LIBCERROR_ERROR_DOMAIN_IO,
1839
236
     LIBCERROR_IO_ERROR_READ_FAILED,
1840
236
     "%s: unable to read variable file information.",
1841
236
     function );
1842
1843
236
    return( -1 );
1844
236
  }
1845
378
  return( 1 );
1846
614
}
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