Coverage Report

Created: 2023-06-07 06:53

/src/libmsiecf/libmsiecf/libmsiecf_file.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File functions
3
 *
4
 * Copyright (C) 2009-2023, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <narrow_string.h>
25
#include <types.h>
26
#include <wide_string.h>
27
28
#include "libmsiecf_allocation_table.h"
29
#include "libmsiecf_cache_directory_table.h"
30
#include "libmsiecf_codepage.h"
31
#include "libmsiecf_debug.h"
32
#include "libmsiecf_definitions.h"
33
#include "libmsiecf_file_header.h"
34
#include "libmsiecf_io_handle.h"
35
#include "libmsiecf_item.h"
36
#include "libmsiecf_item_descriptor.h"
37
#include "libmsiecf_file.h"
38
#include "libmsiecf_libbfio.h"
39
#include "libmsiecf_libcdata.h"
40
#include "libmsiecf_libcerror.h"
41
#include "libmsiecf_libcnotify.h"
42
#include "libmsiecf_libcthreads.h"
43
44
#include "msiecf_file_header.h"
45
46
/* Creates a file
47
 * Make sure the value file is referencing, is set to NULL
48
 * Returns 1 if successful or -1 on error
49
 */
50
int libmsiecf_file_initialize(
51
     libmsiecf_file_t **file,
52
     libcerror_error_t **error )
53
3.48k
{
54
3.48k
  libmsiecf_internal_file_t *internal_file = NULL;
55
3.48k
  static char *function                    = "libmsiecf_file_initialize";
56
57
3.48k
  if( file == NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
63
0
     "%s: invalid file.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
3.48k
  if( *file != NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
73
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
74
0
     "%s: invalid file value already set.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
3.48k
  internal_file = memory_allocate_structure(
80
3.48k
                   libmsiecf_internal_file_t );
81
82
3.48k
  if( internal_file == NULL )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
87
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
88
0
     "%s: unable to create file.",
89
0
     function );
90
91
0
    goto on_error;
92
0
  }
93
3.48k
  if( memory_set(
94
3.48k
       internal_file,
95
3.48k
       0,
96
3.48k
       sizeof( libmsiecf_internal_file_t ) ) == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
101
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
102
0
     "%s: unable to clear file.",
103
0
     function );
104
105
0
    memory_free(
106
0
     internal_file );
107
108
0
    return( -1 );
109
0
  }
110
3.48k
  if( libmsiecf_io_handle_initialize(
111
3.48k
       &( internal_file->io_handle ),
112
3.48k
       error ) != 1 )
113
0
  {
114
0
    libcerror_error_set(
115
0
     error,
116
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
117
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
118
0
     "%s: unable to create IO handle.",
119
0
     function );
120
121
0
    goto on_error;
122
0
  }
123
3.48k
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
124
3.48k
  if( libcthreads_read_write_lock_initialize(
125
3.48k
       &( internal_file->read_write_lock ),
126
3.48k
       error ) != 1 )
127
0
  {
128
0
    libcerror_error_set(
129
0
     error,
130
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
131
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
132
0
     "%s: unable to initialize read/write lock.",
133
0
     function );
134
135
0
    goto on_error;
136
0
  }
137
3.48k
#endif
138
3.48k
  *file = (libmsiecf_file_t *) internal_file;
139
140
3.48k
  return( 1 );
141
142
0
on_error:
143
0
  if( internal_file != NULL )
144
0
  {
145
0
    if( internal_file->io_handle != NULL )
146
0
    {
147
0
      libmsiecf_io_handle_free(
148
0
       &( internal_file->io_handle ),
149
0
       NULL );
150
0
    }
151
0
    memory_free(
152
0
     internal_file );
153
0
  }
154
0
  return( -1 );
155
3.48k
}
156
157
/* Frees a file
158
 * Returns 1 if successful or -1 on error
159
 */
160
int libmsiecf_file_free(
161
     libmsiecf_file_t **file,
162
     libcerror_error_t **error )
163
3.48k
{
164
3.48k
  libmsiecf_internal_file_t *internal_file = NULL;
165
3.48k
  static char *function                    = "libmsiecf_file_free";
166
3.48k
  int result                               = 1;
167
168
3.48k
  if( file == 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 file.",
175
0
     function );
176
177
0
    return( -1 );
178
0
  }
179
3.48k
  if( *file != NULL )
180
3.48k
  {
181
3.48k
    internal_file = (libmsiecf_internal_file_t *) *file;
182
183
3.48k
    if( internal_file->file_io_handle != NULL )
184
0
    {
185
0
      if( libmsiecf_file_close(
186
0
           *file,
187
0
           error ) != 0 )
188
0
      {
189
0
        libcerror_error_set(
190
0
         error,
191
0
         LIBCERROR_ERROR_DOMAIN_IO,
192
0
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
193
0
         "%s: unable to close file.",
194
0
         function );
195
196
0
        result = -1;
197
0
      }
198
0
    }
199
3.48k
    *file = NULL;
200
201
3.48k
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
202
3.48k
    if( libcthreads_read_write_lock_free(
203
3.48k
         &( internal_file->read_write_lock ),
204
3.48k
         error ) != 1 )
205
0
    {
206
0
      libcerror_error_set(
207
0
       error,
208
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
209
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
210
0
       "%s: unable to free read/write lock.",
211
0
       function );
212
213
0
      result = -1;
214
0
    }
215
3.48k
#endif
216
3.48k
    if( libmsiecf_io_handle_free(
217
3.48k
         &( internal_file->io_handle ),
218
3.48k
         error ) != 1 )
219
0
    {
220
0
      libcerror_error_set(
221
0
       error,
222
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
223
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
224
0
       "%s: unable to free IO handle.",
225
0
       function );
226
227
0
      result = -1;
228
0
    }
229
3.48k
    memory_free(
230
3.48k
     internal_file );
231
3.48k
  }
232
3.48k
  return( result );
233
3.48k
}
234
235
/* Signals the libmsiecf file to abort its current activity
236
 * Returns 1 if successful or -1 on error
237
 */
238
int libmsiecf_file_signal_abort(
239
     libmsiecf_file_t *file,
240
     libcerror_error_t **error )
241
0
{
242
0
  libmsiecf_internal_file_t *internal_file = NULL;
243
0
  static char *function                    = "libmsiecf_file_signal_abort";
244
245
0
  if( file == NULL )
246
0
  {
247
0
    libcerror_error_set(
248
0
     error,
249
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
250
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
251
0
     "%s: invalid file.",
252
0
     function );
253
254
0
    return( -1 );
255
0
  }
256
0
  internal_file = (libmsiecf_internal_file_t *) file;
257
258
0
  if( internal_file->io_handle == NULL )
259
0
  {
260
0
    libcerror_error_set(
261
0
     error,
262
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
263
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
264
0
     "%s: invalid file - missing IO handle.",
265
0
     function );
266
267
0
    return( -1 );
268
0
  }
269
0
  internal_file->io_handle->abort = 1;
270
271
0
  return( 1 );
272
0
}
273
274
/* Opens a file
275
 * Returns 1 if successful or -1 on error
276
 */
277
int libmsiecf_file_open(
278
     libmsiecf_file_t *file,
279
     const char *filename,
280
     int access_flags,
281
     libcerror_error_t **error )
282
0
{
283
0
  libbfio_handle_t *file_io_handle         = NULL;
284
0
  libmsiecf_internal_file_t *internal_file = NULL;
285
0
  static char *function                    = "libmsiecf_file_open";
286
0
  size_t filename_length                   = 0;
287
288
0
  if( file == NULL )
289
0
  {
290
0
    libcerror_error_set(
291
0
     error,
292
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
293
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
294
0
     "%s: invalid file.",
295
0
     function );
296
297
0
    return( -1 );
298
0
  }
299
0
  internal_file = (libmsiecf_internal_file_t *) file;
300
301
0
  if( filename == NULL )
302
0
  {
303
0
    libcerror_error_set(
304
0
     error,
305
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
306
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
307
0
     "%s: invalid filename.",
308
0
     function );
309
310
0
    return( -1 );
311
0
  }
312
0
  if( ( ( access_flags & LIBMSIECF_ACCESS_FLAG_READ ) == 0 )
313
0
   && ( ( access_flags & LIBMSIECF_ACCESS_FLAG_WRITE ) == 0 ) )
314
0
  {
315
0
    libcerror_error_set(
316
0
     error,
317
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
318
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
319
0
     "%s: unsupported access flags.",
320
0
     function );
321
322
0
    return( -1 );
323
0
  }
324
0
  if( ( access_flags & LIBMSIECF_ACCESS_FLAG_WRITE ) != 0 )
325
0
  {
326
0
    libcerror_error_set(
327
0
     error,
328
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
329
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
330
0
     "%s: write access currently not supported.",
331
0
     function );
332
333
0
    return( -1 );
334
0
  }
335
0
  if( libbfio_file_initialize(
336
0
       &file_io_handle,
337
0
       error ) != 1 )
338
0
  {
339
0
    libcerror_error_set(
340
0
     error,
341
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
342
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
343
0
     "%s: unable to create file IO handle.",
344
0
     function );
345
346
0
    goto on_error;
347
0
  }
348
#if defined( HAVE_DEBUG_OUTPUT )
349
  if( libbfio_handle_set_track_offsets_read(
350
       file_io_handle,
351
       1,
352
       error ) != 1 )
353
  {
354
                libcerror_error_set(
355
                 error,
356
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
357
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
358
                 "%s: unable to set track offsets read in file IO handle.",
359
                 function );
360
361
    goto on_error;
362
  }
363
#endif
364
0
  filename_length = narrow_string_length(
365
0
                     filename );
366
367
0
  if( libbfio_file_set_name(
368
0
       file_io_handle,
369
0
       filename,
370
0
       filename_length + 1,
371
0
       error ) != 1 )
372
0
  {
373
0
                libcerror_error_set(
374
0
                 error,
375
0
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
376
0
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
377
0
                 "%s: unable to set filename in file IO handle.",
378
0
                 function );
379
380
0
    goto on_error;
381
0
  }
382
0
  if( libmsiecf_file_open_file_io_handle(
383
0
       file,
384
0
       file_io_handle,
385
0
       access_flags,
386
0
       error ) != 1 )
387
0
  {
388
0
    libcerror_error_set(
389
0
     error,
390
0
     LIBCERROR_ERROR_DOMAIN_IO,
391
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
392
0
     "%s: unable to open file: %s.",
393
0
     function,
394
0
     filename );
395
396
0
    goto on_error;
397
0
  }
398
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
399
0
  if( libcthreads_read_write_lock_grab_for_write(
400
0
       internal_file->read_write_lock,
401
0
       error ) != 1 )
402
0
  {
403
0
    libcerror_error_set(
404
0
     error,
405
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
406
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
407
0
     "%s: unable to grab read/write lock for writing.",
408
0
     function );
409
410
0
    goto on_error;
411
0
  }
412
0
#endif
413
0
  internal_file->file_io_handle_created_in_library = 1;
414
415
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
416
0
  if( libcthreads_read_write_lock_release_for_write(
417
0
       internal_file->read_write_lock,
418
0
       error ) != 1 )
419
0
  {
420
0
    libcerror_error_set(
421
0
     error,
422
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
423
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
424
0
     "%s: unable to release read/write lock for writing.",
425
0
     function );
426
427
0
    internal_file->file_io_handle_created_in_library = 0;
428
429
0
    goto on_error;
430
0
  }
431
0
#endif
432
0
  return( 1 );
433
434
0
on_error:
435
0
  if( file_io_handle != NULL )
436
0
  {
437
0
    libbfio_handle_free(
438
0
     &file_io_handle,
439
0
     NULL );
440
0
  }
441
0
  return( -1 );
442
0
}
443
444
#if defined( HAVE_WIDE_CHARACTER_TYPE )
445
446
/* Opens a file
447
 * Returns 1 if successful or -1 on error
448
 */
449
int libmsiecf_file_open_wide(
450
     libmsiecf_file_t *file,
451
     const wchar_t *filename,
452
     int access_flags,
453
     libcerror_error_t **error )
454
{
455
  libbfio_handle_t *file_io_handle         = NULL;
456
  libmsiecf_internal_file_t *internal_file = NULL;
457
  static char *function                    = "libmsiecf_file_open_wide";
458
  size_t filename_length                   = 0;
459
460
  if( file == NULL )
461
  {
462
    libcerror_error_set(
463
     error,
464
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
465
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
466
     "%s: invalid file.",
467
     function );
468
469
    return( -1 );
470
  }
471
  internal_file = (libmsiecf_internal_file_t *) file;
472
473
  if( filename == NULL )
474
  {
475
    libcerror_error_set(
476
     error,
477
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
478
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
479
     "%s: invalid filename.",
480
     function );
481
482
    return( -1 );
483
  }
484
  if( ( ( access_flags & LIBMSIECF_ACCESS_FLAG_READ ) == 0 )
485
   && ( ( access_flags & LIBMSIECF_ACCESS_FLAG_WRITE ) == 0 ) )
486
  {
487
    libcerror_error_set(
488
     error,
489
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
490
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
491
     "%s: unsupported access flags.",
492
     function );
493
494
    return( -1 );
495
  }
496
  if( ( access_flags & LIBMSIECF_ACCESS_FLAG_WRITE ) != 0 )
497
  {
498
    libcerror_error_set(
499
     error,
500
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
501
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
502
     "%s: write access currently not supported.",
503
     function );
504
505
    return( -1 );
506
  }
507
  if( libbfio_file_initialize(
508
       &file_io_handle,
509
       error ) != 1 )
510
  {
511
    libcerror_error_set(
512
     error,
513
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
514
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
515
     "%s: unable to create file IO handle.",
516
     function );
517
518
    goto on_error;
519
  }
520
#if defined( HAVE_DEBUG_OUTPUT )
521
  if( libbfio_handle_set_track_offsets_read(
522
       file_io_handle,
523
       1,
524
       error ) != 1 )
525
  {
526
                libcerror_error_set(
527
                 error,
528
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
529
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
530
                 "%s: unable to set track offsets read in file IO handle.",
531
                 function );
532
533
    goto on_error;
534
  }
535
#endif
536
  filename_length = wide_string_length(
537
                     filename );
538
539
  if( libbfio_file_set_name_wide(
540
       file_io_handle,
541
       filename,
542
       filename_length + 1,
543
       error ) != 1 )
544
  {
545
                libcerror_error_set(
546
                 error,
547
                 LIBCERROR_ERROR_DOMAIN_RUNTIME,
548
                 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
549
                 "%s: unable to set filename in file IO handle.",
550
                 function );
551
552
    goto on_error;
553
  }
554
  if( libmsiecf_file_open_file_io_handle(
555
       file,
556
       file_io_handle,
557
       access_flags,
558
       error ) != 1 )
559
  {
560
    libcerror_error_set(
561
     error,
562
     LIBCERROR_ERROR_DOMAIN_IO,
563
     LIBCERROR_IO_ERROR_OPEN_FAILED,
564
     "%s: unable to open file: %ls.",
565
     function,
566
     filename );
567
568
    goto on_error;
569
  }
570
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
571
  if( libcthreads_read_write_lock_grab_for_write(
572
       internal_file->read_write_lock,
573
       error ) != 1 )
574
  {
575
    libcerror_error_set(
576
     error,
577
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
578
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
579
     "%s: unable to grab read/write lock for writing.",
580
     function );
581
582
    goto on_error;
583
  }
584
#endif
585
  internal_file->file_io_handle_created_in_library = 1;
586
587
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
588
  if( libcthreads_read_write_lock_release_for_write(
589
       internal_file->read_write_lock,
590
       error ) != 1 )
591
  {
592
    libcerror_error_set(
593
     error,
594
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
595
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
596
     "%s: unable to release read/write lock for writing.",
597
     function );
598
599
    internal_file->file_io_handle_created_in_library = 0;
600
601
    goto on_error;
602
  }
603
#endif
604
  return( 1 );
605
606
on_error:
607
  if( file_io_handle != NULL )
608
  {
609
    libbfio_handle_free(
610
     &file_io_handle,
611
     NULL );
612
  }
613
  return( -1 );
614
}
615
616
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
617
618
/* Opens a file using a Basic File IO (bfio) handle
619
 * Returns 1 if successful or -1 on error
620
 */
621
int libmsiecf_file_open_file_io_handle(
622
     libmsiecf_file_t *file,
623
     libbfio_handle_t *file_io_handle,
624
     int access_flags,
625
     libcerror_error_t **error )
626
3.48k
{
627
3.48k
  libmsiecf_internal_file_t *internal_file = NULL;
628
3.48k
  static char *function                    = "libmsiecf_file_open_file_io_handle";
629
3.48k
  uint8_t file_io_handle_opened_in_library = 0;
630
3.48k
  int bfio_access_flags                    = 0;
631
3.48k
  int file_io_handle_is_open               = 0;
632
633
3.48k
  if( file == NULL )
634
0
  {
635
0
    libcerror_error_set(
636
0
     error,
637
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
638
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
639
0
     "%s: invalid file.",
640
0
     function );
641
642
0
    return( -1 );
643
0
  }
644
3.48k
  internal_file = (libmsiecf_internal_file_t *) file;
645
646
3.48k
  if( internal_file->file_io_handle != NULL )
647
0
  {
648
0
    libcerror_error_set(
649
0
     error,
650
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
651
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
652
0
     "%s: invalid file - file IO handle already set.",
653
0
     function );
654
655
0
    return( -1 );
656
0
  }
657
3.48k
  if( file_io_handle == NULL )
658
0
  {
659
0
    libcerror_error_set(
660
0
     error,
661
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
662
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
663
0
     "%s: invalid file IO handle.",
664
0
     function );
665
666
0
    return( -1 );
667
0
  }
668
3.48k
  if( ( ( access_flags & LIBMSIECF_ACCESS_FLAG_READ ) == 0 )
669
3.48k
   && ( ( access_flags & LIBMSIECF_ACCESS_FLAG_WRITE ) == 0 ) )
670
0
  {
671
0
    libcerror_error_set(
672
0
     error,
673
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
674
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
675
0
     "%s: unsupported access flags.",
676
0
     function );
677
678
0
    return( -1 );
679
0
  }
680
3.48k
  if( ( access_flags & LIBMSIECF_ACCESS_FLAG_WRITE ) != 0 )
681
0
  {
682
0
    libcerror_error_set(
683
0
     error,
684
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
685
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
686
0
     "%s: write access currently not supported.",
687
0
     function );
688
689
0
    return( -1 );
690
0
  }
691
3.48k
  if( ( access_flags & LIBMSIECF_ACCESS_FLAG_READ ) != 0 )
692
3.48k
  {
693
3.48k
    bfio_access_flags = LIBBFIO_ACCESS_FLAG_READ;
694
3.48k
  }
695
3.48k
  file_io_handle_is_open = libbfio_handle_is_open(
696
3.48k
                            file_io_handle,
697
3.48k
                            error );
698
699
3.48k
  if( file_io_handle_is_open == -1 )
700
0
  {
701
0
    libcerror_error_set(
702
0
     error,
703
0
     LIBCERROR_ERROR_DOMAIN_IO,
704
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
705
0
     "%s: unable to open file.",
706
0
     function );
707
708
0
    goto on_error;
709
0
  }
710
3.48k
  else if( file_io_handle_is_open == 0 )
711
3.48k
  {
712
3.48k
    if( libbfio_handle_open(
713
3.48k
         file_io_handle,
714
3.48k
         bfio_access_flags,
715
3.48k
         error ) != 1 )
716
0
    {
717
0
      libcerror_error_set(
718
0
       error,
719
0
       LIBCERROR_ERROR_DOMAIN_IO,
720
0
       LIBCERROR_IO_ERROR_OPEN_FAILED,
721
0
       "%s: unable to open file IO handle.",
722
0
       function );
723
724
0
      goto on_error;
725
0
    }
726
3.48k
    file_io_handle_opened_in_library = 1;
727
3.48k
  }
728
3.48k
  if( libmsiecf_internal_file_open_read(
729
3.48k
       internal_file,
730
3.48k
       file_io_handle,
731
3.48k
       error ) != 1 )
732
2.61k
  {
733
2.61k
    libcerror_error_set(
734
2.61k
     error,
735
2.61k
     LIBCERROR_ERROR_DOMAIN_IO,
736
2.61k
     LIBCERROR_IO_ERROR_READ_FAILED,
737
2.61k
     "%s: unable to read from file handle.",
738
2.61k
     function );
739
740
2.61k
    goto on_error;
741
2.61k
  }
742
874
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
743
874
  if( libcthreads_read_write_lock_grab_for_write(
744
874
       internal_file->read_write_lock,
745
874
       error ) != 1 )
746
0
  {
747
0
    libcerror_error_set(
748
0
     error,
749
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
750
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
751
0
     "%s: unable to grab read/write lock for writing.",
752
0
     function );
753
754
0
    goto on_error;
755
0
  }
756
874
#endif
757
874
  internal_file->file_io_handle                   = file_io_handle;
758
874
  internal_file->file_io_handle_opened_in_library = file_io_handle_opened_in_library;
759
760
874
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
761
874
  if( libcthreads_read_write_lock_release_for_write(
762
874
       internal_file->read_write_lock,
763
874
       error ) != 1 )
764
0
  {
765
0
    libcerror_error_set(
766
0
     error,
767
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
768
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
769
0
     "%s: unable to release read/write lock for writing.",
770
0
     function );
771
772
0
    internal_file->file_io_handle                   = NULL;
773
0
    internal_file->file_io_handle_opened_in_library = 0;
774
775
0
    goto on_error;
776
0
  }
777
874
#endif
778
874
  return( 1 );
779
780
2.61k
on_error:
781
2.61k
  if( file_io_handle_opened_in_library != 0 )
782
2.61k
  {
783
2.61k
    libbfio_handle_close(
784
2.61k
     file_io_handle,
785
2.61k
     error );
786
2.61k
  }
787
2.61k
  return( -1 );
788
874
}
789
790
/* Closes a file
791
 * Returns 0 if successful or -1 on error
792
 */
793
int libmsiecf_file_close(
794
     libmsiecf_file_t *file,
795
     libcerror_error_t **error )
796
874
{
797
874
  libmsiecf_internal_file_t *internal_file = NULL;
798
874
  static char *function                    = "libmsiecf_file_close";
799
874
  int result                               = 0;
800
801
874
  if( file == NULL )
802
0
  {
803
0
    libcerror_error_set(
804
0
     error,
805
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
806
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
807
0
     "%s: invalid file.",
808
0
     function );
809
810
0
    return( -1 );
811
0
  }
812
874
  internal_file = (libmsiecf_internal_file_t *) file;
813
814
874
  if( internal_file->file_io_handle == NULL )
815
0
  {
816
0
    libcerror_error_set(
817
0
     error,
818
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
819
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
820
0
     "%s: invalid file - missing file IO handle.",
821
0
     function );
822
823
0
    return( -1 );
824
0
  }
825
874
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
826
874
  if( libcthreads_read_write_lock_grab_for_write(
827
874
       internal_file->read_write_lock,
828
874
       error ) != 1 )
829
0
  {
830
0
    libcerror_error_set(
831
0
     error,
832
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
833
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
834
0
     "%s: unable to grab read/write lock for writing.",
835
0
     function );
836
837
0
    return( -1 );
838
0
  }
839
874
#endif
840
#if defined( HAVE_DEBUG_OUTPUT )
841
  if( libcnotify_verbose != 0 )
842
  {
843
    if( internal_file->file_io_handle_created_in_library != 0 )
844
    {
845
      if( libmsiecf_debug_print_read_offsets(
846
           internal_file->file_io_handle,
847
           error ) != 1 )
848
      {
849
        libcerror_error_set(
850
         error,
851
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
852
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
853
         "%s: unable to print the read offsets.",
854
         function );
855
      }
856
    }
857
  }
858
#endif
859
874
  if( internal_file->file_io_handle_opened_in_library != 0 )
860
874
  {
861
874
    if( libbfio_handle_close(
862
874
         internal_file->file_io_handle,
863
874
         error ) != 0 )
864
0
    {
865
0
      libcerror_error_set(
866
0
       error,
867
0
       LIBCERROR_ERROR_DOMAIN_IO,
868
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
869
0
       "%s: unable to close file IO handle.",
870
0
       function );
871
872
0
      result = -1;
873
0
    }
874
874
    internal_file->file_io_handle_opened_in_library = 0;
875
874
  }
876
874
  if( internal_file->file_io_handle_created_in_library != 0 )
877
0
  {
878
0
    if( libbfio_handle_free(
879
0
         &( internal_file->file_io_handle ),
880
0
         error ) != 1 )
881
0
    {
882
0
      libcerror_error_set(
883
0
       error,
884
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
885
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
886
0
       "%s: unable to free file IO handle.",
887
0
       function );
888
889
0
      result = -1;
890
0
    }
891
0
    internal_file->file_io_handle_created_in_library = 0;
892
0
  }
893
874
  internal_file->file_io_handle = NULL;
894
895
874
  if( libmsiecf_io_handle_clear(
896
874
       internal_file->io_handle,
897
874
       error ) != 1 )
898
0
  {
899
0
    libcerror_error_set(
900
0
     error,
901
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
902
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
903
0
     "%s: unable to clear IO handle.",
904
0
     function );
905
906
0
    result = -1;
907
0
  }
908
874
  if( internal_file->file_header != NULL )
909
874
  {
910
874
    if( libmsiecf_file_header_free(
911
874
         &( internal_file->file_header ),
912
874
         error ) != 1 )
913
0
    {
914
0
      libcerror_error_set(
915
0
       error,
916
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
917
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
918
0
       "%s: unable to free file header.",
919
0
       function );
920
921
0
      result = -1;
922
0
    }
923
874
  }
924
874
  if( internal_file->cache_directory_table != NULL )
925
874
  {
926
874
    if( libmsiecf_cache_directory_table_free(
927
874
         &( internal_file->cache_directory_table ),
928
874
         error ) != 1 )
929
0
    {
930
0
      libcerror_error_set(
931
0
       error,
932
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
933
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
934
0
       "%s: unable to free cache directory table.",
935
0
       function );
936
937
0
      result = -1;
938
0
    }
939
874
  }
940
874
  if( internal_file->item_array != NULL )
941
874
  {
942
874
    if( libcdata_array_free(
943
874
         &( internal_file->item_array ),
944
874
         (int (*)(intptr_t **, libcerror_error_t **)) &libmsiecf_item_descriptor_free,
945
874
         error ) != 1 )
946
0
    {
947
0
      libcerror_error_set(
948
0
       error,
949
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
950
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
951
0
       "%s: unable to free item array.",
952
0
       function );
953
954
0
      result = -1;
955
0
    }
956
874
  }
957
874
  if( internal_file->recovered_item_array != NULL )
958
874
  {
959
874
    if( libcdata_array_free(
960
874
         &( internal_file->recovered_item_array ),
961
874
         (int (*)(intptr_t **, libcerror_error_t **)) &libmsiecf_item_descriptor_free,
962
874
         error ) != 1 )
963
0
    {
964
0
      libcerror_error_set(
965
0
       error,
966
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
967
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
968
0
       "%s: unable to free recovered item array.",
969
0
       function );
970
971
0
      result = -1;
972
0
    }
973
874
  }
974
874
  if( internal_file->unallocated_block_list != NULL )
975
874
  {
976
874
    if( libcdata_range_list_free(
977
874
         &( internal_file->unallocated_block_list ),
978
874
         NULL,
979
874
         error ) != 1 )
980
0
    {
981
0
      libcerror_error_set(
982
0
       error,
983
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
984
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
985
0
       "%s: unable to free unallocated block list.",
986
0
       function );
987
988
0
      result = -1;
989
0
    }
990
874
  }
991
874
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
992
874
  if( libcthreads_read_write_lock_release_for_write(
993
874
       internal_file->read_write_lock,
994
874
       error ) != 1 )
995
0
  {
996
0
    libcerror_error_set(
997
0
     error,
998
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
999
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1000
0
     "%s: unable to release read/write lock for writing.",
1001
0
     function );
1002
1003
0
    return( -1 );
1004
0
  }
1005
874
#endif
1006
874
  return( result );
1007
874
}
1008
1009
/* Opens a file for reading
1010
 * Returns 1 if successful or -1 on error
1011
 */
1012
int libmsiecf_internal_file_open_read(
1013
     libmsiecf_internal_file_t *internal_file,
1014
     libbfio_handle_t *file_io_handle,
1015
     libcerror_error_t **error )
1016
3.48k
{
1017
3.48k
  static char *function = "libmsiecf_internal_file_open_read";
1018
1019
3.48k
  if( internal_file == NULL )
1020
0
  {
1021
0
    libcerror_error_set(
1022
0
     error,
1023
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1024
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1025
0
     "%s: invalid file.",
1026
0
     function );
1027
1028
0
    return( -1 );
1029
0
  }
1030
3.48k
  if( internal_file->io_handle == NULL )
1031
0
  {
1032
0
    libcerror_error_set(
1033
0
     error,
1034
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1035
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1036
0
     "%s: invalid file - missing IO handle.",
1037
0
     function );
1038
1039
0
    return( -1 );
1040
0
  }
1041
3.48k
  if( internal_file->file_header != NULL )
1042
0
  {
1043
0
    libcerror_error_set(
1044
0
     error,
1045
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1046
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1047
0
     "%s: invalid file - file header already set.",
1048
0
     function );
1049
1050
0
    return( -1 );
1051
0
  }
1052
3.48k
  if( internal_file->cache_directory_table != NULL )
1053
0
  {
1054
0
    libcerror_error_set(
1055
0
     error,
1056
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1057
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1058
0
     "%s: invalid file - cache directory table value already set.",
1059
0
     function );
1060
1061
0
    return( -1 );
1062
0
  }
1063
3.48k
  if( internal_file->item_array != NULL )
1064
0
  {
1065
0
    libcerror_error_set(
1066
0
     error,
1067
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1068
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1069
0
     "%s: invalid file - item array already set.",
1070
0
     function );
1071
1072
0
    return( -1 );
1073
0
  }
1074
3.48k
  if( internal_file->recovered_item_array != NULL )
1075
0
  {
1076
0
    libcerror_error_set(
1077
0
     error,
1078
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1079
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1080
0
     "%s: invalid file - recovered item array already set.",
1081
0
     function );
1082
1083
0
    return( -1 );
1084
0
  }
1085
3.48k
  if( internal_file->unallocated_block_list != NULL )
1086
0
  {
1087
0
    libcerror_error_set(
1088
0
     error,
1089
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1090
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1091
0
     "%s: invalid file - unallocated block list already set.",
1092
0
     function );
1093
1094
0
    return( -1 );
1095
0
  }
1096
#if defined( HAVE_DEBUG_OUTPUT )
1097
  if( libcnotify_verbose != 0 )
1098
  {
1099
    libcnotify_printf(
1100
     "Reading file header:\n" );
1101
  }
1102
#endif
1103
3.48k
  if( libmsiecf_file_header_initialize(
1104
3.48k
       &( internal_file->file_header ),
1105
3.48k
       error ) != 1 )
1106
0
  {
1107
0
    libcerror_error_set(
1108
0
     error,
1109
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1110
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1111
0
     "%s: unable to create file handle.",
1112
0
     function );
1113
1114
0
    goto on_error;
1115
0
  }
1116
3.48k
  if( libmsiecf_file_header_read_file_io_handle(
1117
3.48k
       internal_file->file_header,
1118
3.48k
       file_io_handle,
1119
3.48k
       0,
1120
3.48k
       error ) != 1 )
1121
411
  {
1122
411
    libcerror_error_set(
1123
411
     error,
1124
411
     LIBCERROR_ERROR_DOMAIN_IO,
1125
411
     LIBCERROR_IO_ERROR_READ_FAILED,
1126
411
     "%s: unable to read file header.",
1127
411
     function );
1128
1129
411
    goto on_error;
1130
411
  }
1131
3.07k
  internal_file->io_handle->major_version = internal_file->file_header->major_version;
1132
3.07k
  internal_file->io_handle->minor_version = internal_file->file_header->minor_version;
1133
3.07k
  internal_file->io_handle->file_size     = internal_file->file_header->file_size;
1134
1135
#if defined( HAVE_DEBUG_OUTPUT )
1136
  if( libcnotify_verbose != 0 )
1137
  {
1138
    libcnotify_printf(
1139
     "Reading cache directory table:\n" );
1140
  }
1141
#endif
1142
3.07k
  if( libmsiecf_cache_directory_table_initialize(
1143
3.07k
       &( internal_file->cache_directory_table ),
1144
3.07k
       error ) != 1 )
1145
0
  {
1146
0
    libcerror_error_set(
1147
0
     error,
1148
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1149
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1150
0
     "%s: unable to create cache directory table.",
1151
0
     function );
1152
1153
0
    goto on_error;
1154
0
  }
1155
3.07k
  if( libmsiecf_cache_directory_table_read_file_io_handle(
1156
3.07k
       internal_file->cache_directory_table,
1157
3.07k
       file_io_handle,
1158
3.07k
       sizeof( msiecf_file_header_t ),
1159
3.07k
       error ) != 1 )
1160
98
  {
1161
98
    libcerror_error_set(
1162
98
     error,
1163
98
     LIBCERROR_ERROR_DOMAIN_IO,
1164
98
     LIBCERROR_IO_ERROR_READ_FAILED,
1165
98
     "%s: unable to read cache directory table.",
1166
98
     function );
1167
1168
98
    goto on_error;
1169
98
  }
1170
#if defined( HAVE_DEBUG_OUTPUT )
1171
  if( libcnotify_verbose != 0 )
1172
  {
1173
    libcnotify_printf(
1174
     "Reading allocation table:\n" );
1175
  }
1176
#endif
1177
2.97k
  if( libcdata_range_list_initialize(
1178
2.97k
       &( internal_file->unallocated_block_list ),
1179
2.97k
       error ) != 1 )
1180
0
  {
1181
0
    libcerror_error_set(
1182
0
     error,
1183
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1184
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1185
0
     "%s: unable to create unallocated data block list.",
1186
0
     function );
1187
1188
0
    goto on_error;
1189
0
  }
1190
2.97k
  if( libmsiecf_allocation_table_read_file_io_handle(
1191
2.97k
       internal_file->unallocated_block_list,
1192
2.97k
       file_io_handle,
1193
2.97k
       0x250,
1194
2.97k
       internal_file->file_header->file_size,
1195
2.97k
       0x4000,
1196
2.97k
       internal_file->io_handle->block_size,
1197
2.97k
       internal_file->file_header->number_of_blocks,
1198
2.97k
       internal_file->file_header->number_of_allocated_blocks,
1199
2.97k
       error ) != 1 )
1200
290
  {
1201
290
    libcerror_error_set(
1202
290
     error,
1203
290
     LIBCERROR_ERROR_DOMAIN_IO,
1204
290
     LIBCERROR_IO_ERROR_READ_FAILED,
1205
290
     "%s: unable to read allocation table.",
1206
290
     function );
1207
1208
290
    goto on_error;
1209
290
  }
1210
#if defined( HAVE_DEBUG_OUTPUT )
1211
  if( libcnotify_verbose != 0 )
1212
  {
1213
    libcnotify_printf(
1214
     "Reading hash table:\n" );
1215
  }
1216
#endif
1217
2.68k
  if( libcdata_array_initialize(
1218
2.68k
       &( internal_file->item_array ),
1219
2.68k
       0,
1220
2.68k
       error ) != 1 )
1221
0
  {
1222
0
    libcerror_error_set(
1223
0
     error,
1224
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1225
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1226
0
     "%s: unable to create item array.",
1227
0
     function );
1228
1229
0
    goto on_error;
1230
0
  }
1231
2.68k
  if( libmsiecf_io_handle_read_hash_table(
1232
2.68k
       internal_file->item_array,
1233
2.68k
       internal_file->io_handle,
1234
2.68k
       file_io_handle,
1235
2.68k
       internal_file->file_header->hash_table_offset,
1236
2.68k
       error ) != 1 )
1237
411
  {
1238
411
    libcerror_error_set(
1239
411
     error,
1240
411
     LIBCERROR_ERROR_DOMAIN_IO,
1241
411
     LIBCERROR_IO_ERROR_READ_FAILED,
1242
411
     "%s: unable to read hash table.",
1243
411
     function );
1244
1245
411
    goto on_error;
1246
411
  }
1247
#if defined( HAVE_DEBUG_OUTPUT )
1248
  if( libcnotify_verbose != 0 )
1249
  {
1250
    libcnotify_printf(
1251
     "Scanning for records:\n" );
1252
  }
1253
#endif
1254
2.27k
  if( libcdata_array_initialize(
1255
2.27k
       &( internal_file->recovered_item_array ),
1256
2.27k
       0,
1257
2.27k
       error ) != 1 )
1258
0
  {
1259
0
    libcerror_error_set(
1260
0
     error,
1261
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1262
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1263
0
     "%s: unable to create recovered item array.",
1264
0
     function );
1265
1266
0
    goto on_error;
1267
0
  }
1268
2.27k
  if( libmsiecf_io_handle_read_record_scan(
1269
2.27k
       internal_file->item_array,
1270
2.27k
       internal_file->recovered_item_array,
1271
2.27k
       internal_file->io_handle,
1272
2.27k
       file_io_handle,
1273
2.27k
       internal_file->file_header->hash_table_offset,
1274
2.27k
       internal_file->unallocated_block_list,
1275
2.27k
       error ) != 1 )
1276
1.40k
  {
1277
1.40k
    libcerror_error_set(
1278
1.40k
     error,
1279
1.40k
     LIBCERROR_ERROR_DOMAIN_IO,
1280
1.40k
     LIBCERROR_IO_ERROR_READ_FAILED,
1281
1.40k
     "%s: unable to perform record scan.",
1282
1.40k
     function );
1283
1284
1.40k
    goto on_error;
1285
1.40k
  }
1286
874
  return( 1 );
1287
1288
2.61k
on_error:
1289
2.61k
  if( internal_file->recovered_item_array != NULL )
1290
1.40k
  {
1291
1.40k
    libcdata_array_free(
1292
1.40k
     &( internal_file->recovered_item_array ),
1293
1.40k
     (int (*)(intptr_t **, libcerror_error_t **)) &libmsiecf_item_descriptor_free,
1294
1.40k
     NULL );
1295
1.40k
  }
1296
2.61k
  if( internal_file->item_array != NULL )
1297
1.81k
  {
1298
1.81k
    libcdata_array_free(
1299
1.81k
     &( internal_file->item_array ),
1300
1.81k
     (int (*)(intptr_t **, libcerror_error_t **)) &libmsiecf_item_descriptor_free,
1301
1.81k
     NULL );
1302
1.81k
  }
1303
2.61k
  if( internal_file->unallocated_block_list != NULL )
1304
2.10k
  {
1305
2.10k
    libcdata_range_list_free(
1306
2.10k
     &( internal_file->unallocated_block_list ),
1307
2.10k
     NULL,
1308
2.10k
     NULL );
1309
2.10k
  }
1310
2.61k
  if( internal_file->cache_directory_table != NULL )
1311
2.19k
  {
1312
2.19k
    libmsiecf_cache_directory_table_free(
1313
2.19k
     &( internal_file->cache_directory_table ),
1314
2.19k
     NULL );
1315
2.19k
  }
1316
2.61k
  if( internal_file->file_header != NULL )
1317
2.61k
  {
1318
2.61k
    libmsiecf_file_header_free(
1319
2.61k
     &( internal_file->file_header ),
1320
2.61k
     NULL );
1321
2.61k
  }
1322
2.61k
  return( -1 );
1323
2.27k
}
1324
1325
/* Retrieves the file size
1326
 * Returns 1 if successful or -1 on error
1327
 */
1328
int libmsiecf_file_get_size(
1329
     libmsiecf_file_t *file,
1330
     size64_t *size,
1331
     libcerror_error_t **error )
1332
0
{
1333
0
  libmsiecf_internal_file_t *internal_file = NULL;
1334
0
  static char *function                    = "libmsiecf_file_get_size";
1335
1336
0
  if( file == NULL )
1337
0
  {
1338
0
    libcerror_error_set(
1339
0
     error,
1340
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1341
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1342
0
     "%s: invalid file.",
1343
0
     function );
1344
1345
0
    return( -1 );
1346
0
  }
1347
0
  internal_file = (libmsiecf_internal_file_t *) file;
1348
1349
0
  if( internal_file->file_header == NULL )
1350
0
  {
1351
0
    libcerror_error_set(
1352
0
     error,
1353
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1354
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1355
0
     "%s: invalid file - missing file header.",
1356
0
     function );
1357
1358
0
    return( -1 );
1359
0
  }
1360
0
  if( size == NULL )
1361
0
  {
1362
0
    libcerror_error_set(
1363
0
     error,
1364
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1365
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1366
0
     "%s: invalid size.",
1367
0
     function );
1368
1369
0
    return( -1 );
1370
0
  }
1371
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1372
0
  if( libcthreads_read_write_lock_grab_for_read(
1373
0
       internal_file->read_write_lock,
1374
0
       error ) != 1 )
1375
0
  {
1376
0
    libcerror_error_set(
1377
0
     error,
1378
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1379
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1380
0
     "%s: unable to grab read/write lock for reading.",
1381
0
     function );
1382
1383
0
    return( -1 );
1384
0
  }
1385
0
#endif
1386
0
  *size = internal_file->file_header->file_size;
1387
1388
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1389
0
  if( libcthreads_read_write_lock_release_for_read(
1390
0
       internal_file->read_write_lock,
1391
0
       error ) != 1 )
1392
0
  {
1393
0
    libcerror_error_set(
1394
0
     error,
1395
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1396
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1397
0
     "%s: unable to release read/write lock for reading.",
1398
0
     function );
1399
1400
0
    return( -1 );
1401
0
  }
1402
0
#endif
1403
0
  return( 1 );
1404
0
}
1405
1406
/* Retrieves the file ASCII codepage
1407
 * Returns 1 if successful or -1 on error
1408
 */
1409
int libmsiecf_file_get_ascii_codepage(
1410
     libmsiecf_file_t *file,
1411
     int *ascii_codepage,
1412
     libcerror_error_t **error )
1413
0
{
1414
0
  libmsiecf_internal_file_t *internal_file = NULL;
1415
0
  static char *function                    = "libmsiecf_file_get_ascii_codepage";
1416
1417
0
  if( file == NULL )
1418
0
  {
1419
0
    libcerror_error_set(
1420
0
     error,
1421
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1422
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1423
0
     "%s: invalid file.",
1424
0
     function );
1425
1426
0
    return( -1 );
1427
0
  }
1428
0
  internal_file = (libmsiecf_internal_file_t *) file;
1429
1430
0
  if( internal_file->io_handle == NULL )
1431
0
  {
1432
0
    libcerror_error_set(
1433
0
     error,
1434
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1435
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1436
0
     "%s: invalid file - missing IO handle.",
1437
0
     function );
1438
1439
0
    return( -1 );
1440
0
  }
1441
0
  if( ascii_codepage == NULL )
1442
0
  {
1443
0
    libcerror_error_set(
1444
0
     error,
1445
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1446
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1447
0
     "%s: invalid ASCII codepage.",
1448
0
     function );
1449
1450
0
    return( -1 );
1451
0
  }
1452
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1453
0
  if( libcthreads_read_write_lock_grab_for_read(
1454
0
       internal_file->read_write_lock,
1455
0
       error ) != 1 )
1456
0
  {
1457
0
    libcerror_error_set(
1458
0
     error,
1459
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1460
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1461
0
     "%s: unable to grab read/write lock for reading.",
1462
0
     function );
1463
1464
0
    return( -1 );
1465
0
  }
1466
0
#endif
1467
0
  *ascii_codepage = internal_file->io_handle->ascii_codepage;
1468
1469
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1470
0
  if( libcthreads_read_write_lock_release_for_read(
1471
0
       internal_file->read_write_lock,
1472
0
       error ) != 1 )
1473
0
  {
1474
0
    libcerror_error_set(
1475
0
     error,
1476
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1477
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1478
0
     "%s: unable to release read/write lock for reading.",
1479
0
     function );
1480
1481
0
    return( -1 );
1482
0
  }
1483
0
#endif
1484
0
  return( 1 );
1485
0
}
1486
1487
/* Sets the file ASCII codepage
1488
 * Returns 1 if successful or -1 on error
1489
 */
1490
int libmsiecf_file_set_ascii_codepage(
1491
     libmsiecf_file_t *file,
1492
     int ascii_codepage,
1493
     libcerror_error_t **error )
1494
0
{
1495
0
  libmsiecf_internal_file_t *internal_file = NULL;
1496
0
  static char *function                    = "libmsiecf_file_set_ascii_codepage";
1497
1498
0
  if( file == NULL )
1499
0
  {
1500
0
    libcerror_error_set(
1501
0
     error,
1502
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1503
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1504
0
     "%s: invalid file.",
1505
0
     function );
1506
1507
0
    return( -1 );
1508
0
  }
1509
0
  internal_file = (libmsiecf_internal_file_t *) file;
1510
1511
0
  if( internal_file->io_handle == NULL )
1512
0
  {
1513
0
    libcerror_error_set(
1514
0
     error,
1515
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1516
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1517
0
     "%s: invalid file - missing IO handle.",
1518
0
     function );
1519
1520
0
    return( -1 );
1521
0
  }
1522
0
  if( ( ascii_codepage != LIBMSIECF_CODEPAGE_ASCII )
1523
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_874 )
1524
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_932 )
1525
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_936 )
1526
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_949 )
1527
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_950 )
1528
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_1250 )
1529
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_1251 )
1530
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_1252 )
1531
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_1253 )
1532
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_1254 )
1533
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_1255 )
1534
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_1256 )
1535
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_1257 )
1536
0
   && ( ascii_codepage != LIBMSIECF_CODEPAGE_WINDOWS_1258 ) )
1537
0
  {
1538
0
    libcerror_error_set(
1539
0
     error,
1540
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1541
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1542
0
     "%s: unsupported ASCII codepage.",
1543
0
     function );
1544
1545
0
    return( -1 );
1546
0
  }
1547
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1548
0
  if( libcthreads_read_write_lock_grab_for_write(
1549
0
       internal_file->read_write_lock,
1550
0
       error ) != 1 )
1551
0
  {
1552
0
    libcerror_error_set(
1553
0
     error,
1554
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1555
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1556
0
     "%s: unable to grab read/write lock for writing.",
1557
0
     function );
1558
1559
0
    return( -1 );
1560
0
  }
1561
0
#endif
1562
0
  internal_file->io_handle->ascii_codepage = ascii_codepage;
1563
1564
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1565
0
  if( libcthreads_read_write_lock_release_for_write(
1566
0
       internal_file->read_write_lock,
1567
0
       error ) != 1 )
1568
0
  {
1569
0
    libcerror_error_set(
1570
0
     error,
1571
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1572
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1573
0
     "%s: unable to release read/write lock for writing.",
1574
0
     function );
1575
1576
0
    return( -1 );
1577
0
  }
1578
0
#endif
1579
0
  return( 1 );
1580
0
}
1581
1582
/* Retrieves the format version
1583
 * Returns 1 if successful or -1 on error
1584
 */
1585
int libmsiecf_file_get_format_version(
1586
     libmsiecf_file_t *file,
1587
     uint8_t *major_version,
1588
     uint8_t *minor_version,
1589
     libcerror_error_t **error )
1590
0
{
1591
0
  libmsiecf_internal_file_t *internal_file = NULL;
1592
0
  static char *function                    = "libmsiecf_file_get_format_version";
1593
1594
0
  if( file == NULL )
1595
0
  {
1596
0
    libcerror_error_set(
1597
0
     error,
1598
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1599
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1600
0
     "%s: invalid file.",
1601
0
     function );
1602
1603
0
    return( -1 );
1604
0
  }
1605
0
  internal_file = (libmsiecf_internal_file_t *) file;
1606
1607
0
  if( internal_file->file_header == NULL )
1608
0
  {
1609
0
    libcerror_error_set(
1610
0
     error,
1611
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1612
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1613
0
     "%s: invalid file - missing file header.",
1614
0
     function );
1615
1616
0
    return( -1 );
1617
0
  }
1618
0
  if( major_version == NULL )
1619
0
  {
1620
0
    libcerror_error_set(
1621
0
     error,
1622
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1623
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1624
0
     "%s: invalid major version.",
1625
0
     function );
1626
1627
0
    return( -1 );
1628
0
  }
1629
0
  if( minor_version == NULL )
1630
0
  {
1631
0
    libcerror_error_set(
1632
0
     error,
1633
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1634
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1635
0
     "%s: invalid minor version.",
1636
0
     function );
1637
1638
0
    return( -1 );
1639
0
  }
1640
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1641
0
  if( libcthreads_read_write_lock_grab_for_read(
1642
0
       internal_file->read_write_lock,
1643
0
       error ) != 1 )
1644
0
  {
1645
0
    libcerror_error_set(
1646
0
     error,
1647
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1648
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1649
0
     "%s: unable to grab read/write lock for reading.",
1650
0
     function );
1651
1652
0
    return( -1 );
1653
0
  }
1654
0
#endif
1655
0
  *major_version = internal_file->file_header->major_version;
1656
0
  *minor_version = internal_file->file_header->minor_version;
1657
1658
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1659
0
  if( libcthreads_read_write_lock_release_for_read(
1660
0
       internal_file->read_write_lock,
1661
0
       error ) != 1 )
1662
0
  {
1663
0
    libcerror_error_set(
1664
0
     error,
1665
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1666
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1667
0
     "%s: unable to release read/write lock for reading.",
1668
0
     function );
1669
1670
0
    return( -1 );
1671
0
  }
1672
0
#endif
1673
0
  return( 1 );
1674
0
}
1675
1676
/* Retrieves the number of unallocated blocks
1677
 * Returns 1 if successful or -1 on error
1678
 */
1679
int libmsiecf_file_get_number_of_unallocated_blocks(
1680
     libmsiecf_file_t *file,
1681
     int *number_of_unallocated_blocks,
1682
     libcerror_error_t **error )
1683
0
{
1684
0
  libmsiecf_internal_file_t *internal_file = NULL;
1685
0
  static char *function                    = "libmsiecf_file_get_number_of_unallocated_blocks";
1686
0
  int result                               = 1;
1687
1688
0
  if( file == NULL )
1689
0
  {
1690
0
    libcerror_error_set(
1691
0
     error,
1692
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1693
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1694
0
     "%s: invalid file.",
1695
0
     function );
1696
1697
0
    return( -1 );
1698
0
  }
1699
0
  internal_file = (libmsiecf_internal_file_t *) file;
1700
1701
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1702
0
  if( libcthreads_read_write_lock_grab_for_read(
1703
0
       internal_file->read_write_lock,
1704
0
       error ) != 1 )
1705
0
  {
1706
0
    libcerror_error_set(
1707
0
     error,
1708
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1709
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1710
0
     "%s: unable to grab read/write lock for reading.",
1711
0
     function );
1712
1713
0
    return( -1 );
1714
0
  }
1715
0
#endif
1716
0
  result = libcdata_range_list_get_number_of_elements(
1717
0
            internal_file->unallocated_block_list,
1718
0
            number_of_unallocated_blocks,
1719
0
            error );
1720
1721
0
  if( result != 1 )
1722
0
  {
1723
0
    libcerror_error_set(
1724
0
     error,
1725
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1726
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1727
0
     "%s: unable to retrieve number of elements.",
1728
0
     function );
1729
1730
0
    result = -1;
1731
0
  }
1732
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1733
0
  if( libcthreads_read_write_lock_release_for_read(
1734
0
       internal_file->read_write_lock,
1735
0
       error ) != 1 )
1736
0
  {
1737
0
    libcerror_error_set(
1738
0
     error,
1739
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1740
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1741
0
     "%s: unable to release read/write lock for reading.",
1742
0
     function );
1743
1744
0
    return( -1 );
1745
0
  }
1746
0
#endif
1747
0
  return( result );
1748
0
}
1749
1750
/* Retrieves a specific unallocated block
1751
 * Returns 1 if successful or -1 on error
1752
 */
1753
int libmsiecf_file_get_unallocated_block(
1754
     libmsiecf_file_t *file,
1755
     int unallocated_block_index,
1756
     off64_t *offset,
1757
     size64_t *size,
1758
     libcerror_error_t **error )
1759
0
{
1760
0
  libmsiecf_internal_file_t *internal_file = NULL;
1761
0
  intptr_t *value                          = NULL;
1762
0
  static char *function                    = "libmsiecf_file_get_unallocated_block";
1763
0
  int result                               = 1;
1764
1765
0
  if( file == NULL )
1766
0
  {
1767
0
    libcerror_error_set(
1768
0
     error,
1769
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1770
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1771
0
     "%s: invalid file.",
1772
0
     function );
1773
1774
0
    return( -1 );
1775
0
  }
1776
0
  internal_file = (libmsiecf_internal_file_t *) file;
1777
1778
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1779
0
  if( libcthreads_read_write_lock_grab_for_read(
1780
0
       internal_file->read_write_lock,
1781
0
       error ) != 1 )
1782
0
  {
1783
0
    libcerror_error_set(
1784
0
     error,
1785
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1786
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1787
0
     "%s: unable to grab read/write lock for reading.",
1788
0
     function );
1789
1790
0
    return( -1 );
1791
0
  }
1792
0
#endif
1793
0
  result = libcdata_range_list_get_range_by_index(
1794
0
            internal_file->unallocated_block_list,
1795
0
            unallocated_block_index,
1796
0
            (uint64_t *) offset,
1797
0
            (uint64_t *) size,
1798
0
            &value,
1799
0
            error );
1800
1801
0
  if( result != 1 )
1802
0
  {
1803
0
    libcerror_error_set(
1804
0
     error,
1805
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1806
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1807
0
     "%s: unable to retrieve unallocated block range: %d.",
1808
0
     function,
1809
0
     unallocated_block_index );
1810
1811
0
    result = -1;
1812
0
  }
1813
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1814
0
  if( libcthreads_read_write_lock_release_for_read(
1815
0
       internal_file->read_write_lock,
1816
0
       error ) != 1 )
1817
0
  {
1818
0
    libcerror_error_set(
1819
0
     error,
1820
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1821
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1822
0
     "%s: unable to release read/write lock for reading.",
1823
0
     function );
1824
1825
0
    return( -1 );
1826
0
  }
1827
0
#endif
1828
0
  return( result );
1829
0
}
1830
1831
/* Retrieves the number of cache directories
1832
 * Returns 1 if successful or -1 on error
1833
 */
1834
int libmsiecf_file_get_number_of_cache_directories(
1835
     libmsiecf_file_t *file,
1836
     int *number_of_cache_directories,
1837
     libcerror_error_t **error )
1838
0
{
1839
0
  libmsiecf_internal_file_t *internal_file = NULL;
1840
0
  static char *function                    = "libmsiecf_file_get_number_of_cache_directories";
1841
0
  int result                               = 1;
1842
1843
0
  if( file == NULL )
1844
0
  {
1845
0
    libcerror_error_set(
1846
0
     error,
1847
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1848
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1849
0
     "%s: invalid file.",
1850
0
     function );
1851
1852
0
    return( -1 );
1853
0
  }
1854
0
  internal_file = (libmsiecf_internal_file_t *) file;
1855
1856
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1857
0
  if( libcthreads_read_write_lock_grab_for_read(
1858
0
       internal_file->read_write_lock,
1859
0
       error ) != 1 )
1860
0
  {
1861
0
    libcerror_error_set(
1862
0
     error,
1863
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1864
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1865
0
     "%s: unable to grab read/write lock for reading.",
1866
0
     function );
1867
1868
0
    return( -1 );
1869
0
  }
1870
0
#endif
1871
0
  result = libmsiecf_cache_directory_table_get_number_of_cache_directories(
1872
0
            internal_file->cache_directory_table,
1873
0
            number_of_cache_directories,
1874
0
            error );
1875
1876
0
  if( result != 1 )
1877
0
  {
1878
0
    libcerror_error_set(
1879
0
     error,
1880
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1881
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1882
0
     "%s: unable to retrieve number of elements from directory array.",
1883
0
     function );
1884
1885
0
    result = -1;
1886
0
  }
1887
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1888
0
  if( libcthreads_read_write_lock_release_for_read(
1889
0
       internal_file->read_write_lock,
1890
0
       error ) != 1 )
1891
0
  {
1892
0
    libcerror_error_set(
1893
0
     error,
1894
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1895
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1896
0
     "%s: unable to release read/write lock for reading.",
1897
0
     function );
1898
1899
0
    return( -1 );
1900
0
  }
1901
0
#endif
1902
0
  return( result );
1903
0
}
1904
1905
/* Retrieves the extended ASCII encoded name of a certain cache directory
1906
 * The size should include the end of string character
1907
 * The cache directory name consists of 8 characters + end of string character
1908
 * Returns 1 if successful or -1 on error
1909
 */
1910
int libmsiecf_file_get_cache_directory_name(
1911
     libmsiecf_file_t *file,
1912
     int cache_directory_index,
1913
     char *string,
1914
     size_t string_size,
1915
     libcerror_error_t **error )
1916
0
{
1917
0
  libmsiecf_internal_file_t *internal_file = NULL;
1918
0
  static char *function                    = "libmsiecf_file_get_cache_directory_name";
1919
0
  int result                               = 1;
1920
1921
0
  if( file == NULL )
1922
0
  {
1923
0
    libcerror_error_set(
1924
0
     error,
1925
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1926
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1927
0
     "%s: invalid file.",
1928
0
     function );
1929
1930
0
    return( -1 );
1931
0
  }
1932
0
  internal_file = (libmsiecf_internal_file_t *) file;
1933
1934
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1935
0
  if( libcthreads_read_write_lock_grab_for_read(
1936
0
       internal_file->read_write_lock,
1937
0
       error ) != 1 )
1938
0
  {
1939
0
    libcerror_error_set(
1940
0
     error,
1941
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1942
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1943
0
     "%s: unable to grab read/write lock for reading.",
1944
0
     function );
1945
1946
0
    return( -1 );
1947
0
  }
1948
0
#endif
1949
0
  result = libmsiecf_cache_directory_table_get_directory_name_by_index(
1950
0
            internal_file->cache_directory_table,
1951
0
            cache_directory_index,
1952
0
            string,
1953
0
            string_size,
1954
0
            error );
1955
1956
0
  if( result != 1 )
1957
0
  {
1958
0
    libcerror_error_set(
1959
0
     error,
1960
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1961
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1962
0
     "%s: unable to retrieve cache directory: %d name.",
1963
0
     function,
1964
0
     cache_directory_index );
1965
1966
0
    result = -1;
1967
0
  }
1968
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
1969
0
  if( libcthreads_read_write_lock_release_for_read(
1970
0
       internal_file->read_write_lock,
1971
0
       error ) != 1 )
1972
0
  {
1973
0
    libcerror_error_set(
1974
0
     error,
1975
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1976
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1977
0
     "%s: unable to release read/write lock for reading.",
1978
0
     function );
1979
1980
0
    return( -1 );
1981
0
  }
1982
0
#endif
1983
0
  return( result );
1984
0
}
1985
1986
/* Retrieves the number of items
1987
 * Returns 1 if successful or -1 on error
1988
 */
1989
int libmsiecf_file_get_number_of_items(
1990
     libmsiecf_file_t *file,
1991
     int *number_of_items,
1992
     libcerror_error_t **error )
1993
862
{
1994
862
  libmsiecf_internal_file_t *internal_file = NULL;
1995
862
  static char *function                    = "libmsiecf_file_get_number_of_items";
1996
862
  int result                               = 1;
1997
1998
862
  if( file == NULL )
1999
0
  {
2000
0
    libcerror_error_set(
2001
0
     error,
2002
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2003
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2004
0
     "%s: invalid file.",
2005
0
     function );
2006
2007
0
    return( -1 );
2008
0
  }
2009
862
  internal_file = (libmsiecf_internal_file_t *) file;
2010
2011
862
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
2012
862
  if( libcthreads_read_write_lock_grab_for_read(
2013
862
       internal_file->read_write_lock,
2014
862
       error ) != 1 )
2015
0
  {
2016
0
    libcerror_error_set(
2017
0
     error,
2018
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2019
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2020
0
     "%s: unable to grab read/write lock for reading.",
2021
0
     function );
2022
2023
0
    return( -1 );
2024
0
  }
2025
862
#endif
2026
862
  result = libcdata_array_get_number_of_entries(
2027
862
            internal_file->item_array,
2028
862
            number_of_items,
2029
862
            error );
2030
2031
862
  if( result != 1 )
2032
0
  {
2033
0
    libcerror_error_set(
2034
0
     error,
2035
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2036
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2037
0
     "%s: unable to retrieve number of elements from item array.",
2038
0
     function );
2039
2040
0
    result = -1;
2041
0
  }
2042
862
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
2043
862
  if( libcthreads_read_write_lock_release_for_read(
2044
862
       internal_file->read_write_lock,
2045
862
       error ) != 1 )
2046
0
  {
2047
0
    libcerror_error_set(
2048
0
     error,
2049
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2050
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2051
0
     "%s: unable to release read/write lock for reading.",
2052
0
     function );
2053
2054
0
    return( -1 );
2055
0
  }
2056
862
#endif
2057
862
  return( result );
2058
862
}
2059
2060
/* Retrieves the item for the specific index
2061
 * Returns 1 if successful or -1 on error
2062
 */
2063
int libmsiecf_file_get_item_by_index(
2064
     libmsiecf_file_t *file,
2065
     int item_index,
2066
     libmsiecf_item_t **item,
2067
     libcerror_error_t **error )
2068
858
{
2069
858
  libmsiecf_internal_file_t *internal_file     = NULL;
2070
858
  libmsiecf_item_descriptor_t *item_descriptor = NULL;
2071
858
  static char *function                        = "libmsiecf_file_get_item_by_index";
2072
858
  int result                               = 1;
2073
2074
858
  if( file == NULL )
2075
0
  {
2076
0
    libcerror_error_set(
2077
0
     error,
2078
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2079
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2080
0
     "%s: invalid file.",
2081
0
     function );
2082
2083
0
    return( -1 );
2084
0
  }
2085
858
  internal_file = (libmsiecf_internal_file_t *) file;
2086
2087
858
  if( internal_file->item_array == NULL )
2088
0
  {
2089
0
    libcerror_error_set(
2090
0
     error,
2091
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2092
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2093
0
     "%s: invalid file - missing item array.",
2094
0
     function );
2095
2096
0
    return( -1 );
2097
0
  }
2098
858
  if( item == NULL )
2099
0
  {
2100
0
    libcerror_error_set(
2101
0
     error,
2102
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2103
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2104
0
     "%s: invalid item.",
2105
0
     function );
2106
2107
0
    return( -1 );
2108
0
  }
2109
858
  if( *item != NULL )
2110
0
  {
2111
0
    libcerror_error_set(
2112
0
     error,
2113
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2114
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2115
0
     "%s: item already set.",
2116
0
     function );
2117
2118
0
    return( -1 );
2119
0
  }
2120
858
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
2121
858
  if( libcthreads_read_write_lock_grab_for_read(
2122
858
       internal_file->read_write_lock,
2123
858
       error ) != 1 )
2124
0
  {
2125
0
    libcerror_error_set(
2126
0
     error,
2127
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2128
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2129
0
     "%s: unable to grab read/write lock for reading.",
2130
0
     function );
2131
2132
0
    return( -1 );
2133
0
  }
2134
858
#endif
2135
858
  if( libcdata_array_get_entry_by_index(
2136
858
       internal_file->item_array,
2137
858
       item_index,
2138
858
       (intptr_t **) &item_descriptor,
2139
858
       error ) != 1 )
2140
0
  {
2141
0
    libcerror_error_set(
2142
0
     error,
2143
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2144
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2145
0
     "%s: unable to retrieve item descriptor.",
2146
0
     function );
2147
2148
0
    result = -1;
2149
0
  }
2150
858
  else if( libmsiecf_item_initialize(
2151
858
            item,
2152
858
            item_descriptor,
2153
858
            error ) != 1 )
2154
0
  {
2155
0
    libcerror_error_set(
2156
0
     error,
2157
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2158
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2159
0
     "%s: unable to create item.",
2160
0
     function );
2161
2162
0
    result = -1;
2163
0
  }
2164
/* TODO make more error tollerant for corrupt items */
2165
858
  else if( libmsiecf_internal_item_read_values(
2166
858
            (libmsiecf_internal_item_t *) *item,
2167
858
            internal_file->io_handle,
2168
858
            internal_file->file_io_handle,
2169
858
            error ) != 1 )
2170
705
  {
2171
705
    libcerror_error_set(
2172
705
     error,
2173
705
     LIBCERROR_ERROR_DOMAIN_IO,
2174
705
     LIBCERROR_IO_ERROR_READ_FAILED,
2175
705
     "%s: unable to read item values.",
2176
705
     function );
2177
2178
705
    libmsiecf_item_free(
2179
705
     item,
2180
705
     NULL );
2181
2182
705
    result = -1;
2183
705
  }
2184
858
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
2185
858
  if( libcthreads_read_write_lock_release_for_read(
2186
858
       internal_file->read_write_lock,
2187
858
       error ) != 1 )
2188
0
  {
2189
0
    libcerror_error_set(
2190
0
     error,
2191
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2192
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2193
0
     "%s: unable to release read/write lock for reading.",
2194
0
     function );
2195
2196
0
    return( -1 );
2197
0
  }
2198
858
#endif
2199
858
  return( result );
2200
858
}
2201
2202
/* Retrieves the number of recovered items
2203
 * Returns 1 if successful or -1 on error
2204
 */
2205
int libmsiecf_file_get_number_of_recovered_items(
2206
     libmsiecf_file_t *file,
2207
     int *number_of_recovered_items,
2208
     libcerror_error_t **error )
2209
0
{
2210
0
  libmsiecf_internal_file_t *internal_file = NULL;
2211
0
  static char *function                    = "libmsiecf_file_get_number_of_recovered_items";
2212
0
  int result                               = 1;
2213
2214
0
  if( file == NULL )
2215
0
  {
2216
0
    libcerror_error_set(
2217
0
     error,
2218
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2219
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2220
0
     "%s: invalid file.",
2221
0
     function );
2222
2223
0
    return( -1 );
2224
0
  }
2225
0
  internal_file = (libmsiecf_internal_file_t *) file;
2226
2227
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
2228
0
  if( libcthreads_read_write_lock_grab_for_read(
2229
0
       internal_file->read_write_lock,
2230
0
       error ) != 1 )
2231
0
  {
2232
0
    libcerror_error_set(
2233
0
     error,
2234
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2235
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2236
0
     "%s: unable to grab read/write lock for reading.",
2237
0
     function );
2238
2239
0
    return( -1 );
2240
0
  }
2241
0
#endif
2242
0
  result = libcdata_array_get_number_of_entries(
2243
0
            internal_file->recovered_item_array,
2244
0
            number_of_recovered_items,
2245
0
            error );
2246
2247
0
  if( result != 1 )
2248
0
  {
2249
0
    libcerror_error_set(
2250
0
     error,
2251
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2252
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2253
0
     "%s: unable to retrieve number of elements from recovered item array.",
2254
0
     function );
2255
2256
0
    result = -1;
2257
0
  }
2258
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
2259
0
  if( libcthreads_read_write_lock_release_for_read(
2260
0
       internal_file->read_write_lock,
2261
0
       error ) != 1 )
2262
0
  {
2263
0
    libcerror_error_set(
2264
0
     error,
2265
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2266
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2267
0
     "%s: unable to release read/write lock for reading.",
2268
0
     function );
2269
2270
0
    return( -1 );
2271
0
  }
2272
0
#endif
2273
0
  return( result );
2274
0
}
2275
2276
/* Retrieves the recovered item for the specific index
2277
 * Returns 1 if successful or -1 on error
2278
 */
2279
int libmsiecf_file_get_recovered_item_by_index(
2280
     libmsiecf_file_t *file,
2281
     int recovered_item_index,
2282
     libmsiecf_item_t **recovered_item,
2283
     libcerror_error_t **error )
2284
0
{
2285
0
  libmsiecf_internal_file_t *internal_file     = NULL;
2286
0
  libmsiecf_item_descriptor_t *item_descriptor = NULL;
2287
0
  static char *function                        = "libmsiecf_file_get_recovered_item_by_index";
2288
0
  int result                               = 1;
2289
2290
0
  if( file == NULL )
2291
0
  {
2292
0
    libcerror_error_set(
2293
0
     error,
2294
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2295
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2296
0
     "%s: invalid file.",
2297
0
     function );
2298
2299
0
    return( -1 );
2300
0
  }
2301
0
  internal_file = (libmsiecf_internal_file_t *) file;
2302
2303
0
  if( internal_file->recovered_item_array == NULL )
2304
0
  {
2305
0
    libcerror_error_set(
2306
0
     error,
2307
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2308
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2309
0
     "%s: invalid file - missing recovered item array.",
2310
0
     function );
2311
2312
0
    return( -1 );
2313
0
  }
2314
0
  if( recovered_item == NULL )
2315
0
  {
2316
0
    libcerror_error_set(
2317
0
     error,
2318
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2319
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2320
0
     "%s: invalid recovered item.",
2321
0
     function );
2322
2323
0
    return( -1 );
2324
0
  }
2325
0
  if( *recovered_item != NULL )
2326
0
  {
2327
0
    libcerror_error_set(
2328
0
     error,
2329
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2330
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2331
0
     "%s: recovered item already set.",
2332
0
     function );
2333
2334
0
    return( -1 );
2335
0
  }
2336
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
2337
0
  if( libcthreads_read_write_lock_grab_for_read(
2338
0
       internal_file->read_write_lock,
2339
0
       error ) != 1 )
2340
0
  {
2341
0
    libcerror_error_set(
2342
0
     error,
2343
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2344
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2345
0
     "%s: unable to grab read/write lock for reading.",
2346
0
     function );
2347
2348
0
    return( -1 );
2349
0
  }
2350
0
#endif
2351
0
  if( libcdata_array_get_entry_by_index(
2352
0
       internal_file->recovered_item_array,
2353
0
       recovered_item_index,
2354
0
       (intptr_t **) &item_descriptor,
2355
0
       error ) != 1 )
2356
0
  {
2357
0
    libcerror_error_set(
2358
0
     error,
2359
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2360
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2361
0
     "%s: unable to retrieve recovered item descriptor.",
2362
0
     function );
2363
2364
0
    result = -1;
2365
0
  }
2366
0
  else if( libmsiecf_item_initialize(
2367
0
            recovered_item,
2368
0
            item_descriptor,
2369
0
            error ) != 1 )
2370
0
  {
2371
0
    libcerror_error_set(
2372
0
     error,
2373
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2374
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2375
0
     "%s: unable to create recovered item.",
2376
0
     function );
2377
2378
0
    result = -1;
2379
0
  }
2380
/* TODO make more error tollerant for corrupt items */
2381
0
  else if( libmsiecf_internal_item_read_values(
2382
0
            (libmsiecf_internal_item_t *) *recovered_item,
2383
0
            internal_file->io_handle,
2384
0
            internal_file->file_io_handle,
2385
0
            error ) != 1 )
2386
0
  {
2387
0
    libcerror_error_set(
2388
0
     error,
2389
0
     LIBCERROR_ERROR_DOMAIN_IO,
2390
0
     LIBCERROR_IO_ERROR_READ_FAILED,
2391
0
     "%s: unable to read recovered item values.",
2392
0
     function );
2393
2394
0
    libmsiecf_item_free(
2395
0
     recovered_item,
2396
0
     NULL );
2397
2398
0
    result = -1;
2399
0
  }
2400
0
#if defined( HAVE_LIBMSIECF_MULTI_THREAD_SUPPORT )
2401
0
  if( libcthreads_read_write_lock_release_for_read(
2402
0
       internal_file->read_write_lock,
2403
0
       error ) != 1 )
2404
0
  {
2405
0
    libcerror_error_set(
2406
0
     error,
2407
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2408
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2409
0
     "%s: unable to release read/write lock for reading.",
2410
0
     function );
2411
2412
0
    return( -1 );
2413
0
  }
2414
0
#endif
2415
0
  return( result );
2416
0
}
2417