Coverage Report

Created: 2026-01-13 07:09

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