Coverage Report

Created: 2025-12-05 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libolecf/libolecf/libolecf_directory_tree.c
Line
Count
Source
1
/*
2
 * The directory tree functions
3
 *
4
 * Copyright (C) 2008-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 <types.h>
24
25
#include "libolecf_definitions.h"
26
#include "libolecf_directory_entry.h"
27
#include "libolecf_directory_list.h"
28
#include "libolecf_directory_tree.h"
29
#include "libolecf_libcdata.h"
30
#include "libolecf_libcerror.h"
31
#include "libolecf_libcnotify.h"
32
#include "libolecf_libuna.h"
33
34
#include "olecf_directory.h"
35
36
/* Create the directory tree from the directory entry list
37
 * Returns 1 if succesful, 0 if no directory entries or -1 on error
38
 */
39
int libolecf_directory_tree_create(
40
     libcdata_tree_node_t **directory_tree_root_node,
41
     uint32_t *short_sector_stream_start_sector_identifier,
42
     libolecf_directory_entry_t **document_summary_information_directory_entry,
43
     libolecf_directory_entry_t **summary_information_directory_entry,
44
     libcdata_list_t *directory_entry_list,
45
     uint8_t byte_order,
46
     libcerror_error_t **error )
47
791
{
48
791
  libcdata_list_element_t *list_element       = NULL;
49
791
  libolecf_directory_entry_t *directory_entry = NULL;
50
791
  static char *function                       = "libolecf_directory_tree_create";
51
791
  int element_index                           = 0;
52
791
  int number_of_elements                      = 0;
53
54
791
  if( directory_tree_root_node == NULL )
55
0
  {
56
0
    libcerror_error_set(
57
0
     error,
58
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
59
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
60
0
     "%s: invalid directory tree root node.",
61
0
     function );
62
63
0
    return( -1 );
64
0
  }
65
791
  if( *directory_tree_root_node != NULL )
66
0
  {
67
0
    libcerror_error_set(
68
0
     error,
69
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
70
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
71
0
     "%s: directory tree root node already set.",
72
0
     function );
73
74
0
    return( -1 );
75
0
  }
76
791
  if( short_sector_stream_start_sector_identifier == NULL )
77
0
  {
78
0
    libcerror_error_set(
79
0
     error,
80
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
81
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
82
0
     "%s: invalid short sector stream start sector identifier.",
83
0
     function );
84
85
0
    return( -1 );
86
0
  }
87
791
  if( libcdata_list_get_number_of_elements(
88
791
       directory_entry_list,
89
791
       &number_of_elements,
90
791
       error ) != 1 )
91
0
  {
92
0
    libcerror_error_set(
93
0
     error,
94
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
95
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
96
0
     "%s: unable to retrieve number of elements in directory entry list.",
97
0
     function );
98
99
0
    goto on_error;
100
0
  }
101
791
  if( number_of_elements == 0 )
102
62
  {
103
62
    return( 0 );
104
62
  }
105
729
  if( libcdata_list_get_first_element(
106
729
       directory_entry_list,
107
729
       &list_element,
108
729
       error ) != 1 )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
113
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
114
0
     "%s: unable to retrieve first element of directory entry list.",
115
0
     function );
116
117
0
    goto on_error;
118
0
  }
119
729
  for( element_index = 0;
120
8.37k
       element_index < number_of_elements;
121
7.65k
       element_index++ )
122
8.28k
  {
123
8.28k
    if( libcdata_list_element_get_value(
124
8.28k
         list_element,
125
8.28k
         (intptr_t **) &directory_entry,
126
8.28k
         error ) != 1 )
127
0
    {
128
0
      libcerror_error_set(
129
0
       error,
130
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
131
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
132
0
       "%s: unable to retrieve value from element: %d.",
133
0
       function,
134
0
       element_index );
135
136
0
      goto on_error;
137
0
    }
138
8.28k
    if( directory_entry == NULL )
139
0
    {
140
0
      libcerror_error_set(
141
0
       error,
142
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
143
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
144
0
       "%s: missing directory entry: %d.",
145
0
       function,
146
0
       element_index );
147
148
0
      goto on_error;
149
0
    }
150
8.28k
    if( directory_entry->type == LIBOLECF_ITEM_TYPE_ROOT_STORAGE )
151
637
    {
152
637
      break;
153
637
    }
154
7.65k
    if( libcdata_list_element_get_next_element(
155
7.65k
         list_element,
156
7.65k
         &list_element,
157
7.65k
         error ) != 1 )
158
0
    {
159
0
      libcerror_error_set(
160
0
       error,
161
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
162
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
163
0
       "%s: unable to retrieve next element of element: %d.",
164
0
       function,
165
0
       element_index );
166
167
0
      goto on_error;
168
0
    }
169
7.65k
  }
170
729
  if( list_element == NULL )
171
92
  {
172
92
    libcerror_error_set(
173
92
     error,
174
92
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
175
92
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
176
92
     "%s: unable to find root storage directory entry.",
177
92
     function );
178
179
92
    goto on_error;
180
92
  }
181
#if defined( HAVE_VERBOSE_OUTPUT ) || defined( HAVE_DEBUG_OUTPUT )
182
  if( libcnotify_verbose != 0 )
183
  {
184
    if( element_index != 0 )
185
    {
186
      libcnotify_printf(
187
       "%s: root storage is not first directory entry.\n",
188
       function );
189
    }
190
    if( directory_entry->previous_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
191
    {
192
      libcnotify_printf(
193
       "%s: previous directory identifier in root storage is not unused.\n",
194
       function );
195
    }
196
    if( directory_entry->next_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
197
    {
198
      libcnotify_printf(
199
       "%s: next directory identifier in root storage is not unused.\n",
200
       function );
201
    }
202
  }
203
#endif
204
637
  if( directory_entry->sub_directory_identifier == LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
205
26
  {
206
26
    return( 0 );
207
26
  }
208
611
  if( libcdata_tree_node_initialize(
209
611
       directory_tree_root_node,
210
611
       error ) != 1 )
211
0
  {
212
0
    libcerror_error_set(
213
0
     error,
214
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
215
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
216
0
     "%s: unable to create directory root node.",
217
0
     function );
218
219
0
    goto on_error;
220
0
  }
221
611
  if( libcdata_tree_node_set_value(
222
611
       *directory_tree_root_node,
223
611
       (intptr_t *) directory_entry,
224
611
       error ) != 1 )
225
0
  {
226
0
    libcerror_error_set(
227
0
     error,
228
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
229
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
230
0
     "%s: unable to set directory root node value.",
231
0
     function );
232
233
0
    goto on_error;
234
0
  }
235
611
  *short_sector_stream_start_sector_identifier = directory_entry->sector_identifier;
236
237
611
  if( libolecf_directory_tree_create_process_entry(
238
611
       *directory_tree_root_node,
239
611
       directory_entry,
240
611
       document_summary_information_directory_entry,
241
611
       summary_information_directory_entry,
242
611
       directory_entry_list,
243
611
       directory_entry,
244
611
       byte_order,
245
611
       error ) != 1 )
246
540
  {
247
540
    libcerror_error_set(
248
540
     error,
249
540
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
250
540
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
251
540
     "%s: unable to process sub directory entry.",
252
540
     function );
253
254
540
    goto on_error;
255
540
  }
256
71
  directory_entry->set_in_tree = 1;
257
258
71
  return( 1 );
259
260
632
on_error:
261
632
  if( *directory_tree_root_node != NULL )
262
540
  {
263
    /* The directory entry is managed by the list
264
     */
265
540
    libcdata_tree_node_free(
266
540
     directory_tree_root_node,
267
540
     NULL,
268
540
     NULL );
269
540
  }
270
632
  return( -1 );
271
611
}
272
273
/* Process the directory entry and adds it to the directory tree node
274
 * Returns 1 if succesful or -1 on error
275
 */
276
int libolecf_directory_tree_create_process_entry(
277
     libcdata_tree_node_t *directory_tree_node,
278
     const libolecf_directory_entry_t *root_directory_entry,
279
     libolecf_directory_entry_t **document_summary_information_directory_entry,
280
     libolecf_directory_entry_t **summary_information_directory_entry,
281
     libcdata_list_t *directory_entry_list,
282
     libolecf_directory_entry_t *directory_entry,
283
     uint8_t byte_order,
284
     libcerror_error_t **error )
285
66.5k
{
286
66.5k
  libcdata_tree_node_t *parent_node               = NULL;
287
66.5k
  libolecf_directory_entry_t *sub_directory_entry = NULL;
288
66.5k
  libcdata_tree_node_t *tree_node                 = NULL;
289
66.5k
  static char *function                           = "libolecf_directory_tree_create_process_entry";
290
66.5k
  int result                                      = 0;
291
292
66.5k
  if( directory_tree_node == NULL )
293
0
  {
294
0
    libcerror_error_set(
295
0
     error,
296
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
297
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
298
0
     "%s: invalid directory tree node.",
299
0
     function );
300
301
0
    return( -1 );
302
0
  }
303
66.5k
  if( root_directory_entry == NULL )
304
0
  {
305
0
    libcerror_error_set(
306
0
     error,
307
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
308
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
309
0
     "%s: invalid root directory entry.",
310
0
     function );
311
312
0
    return( -1 );
313
0
  }
314
66.5k
  if( document_summary_information_directory_entry == NULL )
315
0
  {
316
0
    libcerror_error_set(
317
0
     error,
318
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
319
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
320
0
     "%s: invalid document summary information directory entry.",
321
0
     function );
322
323
0
    return( -1 );
324
0
  }
325
66.5k
  if( summary_information_directory_entry == NULL )
326
0
  {
327
0
    libcerror_error_set(
328
0
     error,
329
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
330
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
331
0
     "%s: invalid summary information directory entry.",
332
0
     function );
333
334
0
    return( -1 );
335
0
  }
336
66.5k
  if( directory_entry->name_size == 28 )
337
307
  {
338
307
    result = libuna_utf8_string_compare_with_utf16_stream(
339
307
              (uint8_t *) "\005DocumentSummaryInformation",
340
307
              28,
341
307
              directory_entry->name,
342
307
              directory_entry->name_size,
343
307
              byte_order,
344
307
              error );
345
346
307
    if( result == -1 )
347
33
    {
348
33
      libcerror_error_set(
349
33
       error,
350
33
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
351
33
       LIBCERROR_RUNTIME_ERROR_GENERIC,
352
33
       "%s: unable to compare directory entry name.",
353
33
       function );
354
355
33
      goto on_error;
356
33
    }
357
274
    else if( result == LIBUNA_COMPARE_EQUAL )
358
0
    {
359
0
      *document_summary_information_directory_entry = directory_entry;
360
0
    }
361
307
  }
362
66.2k
  else if( directory_entry->name_size == 20 )
363
308
  {
364
308
    result = libuna_utf8_string_compare_with_utf16_stream(
365
308
              (uint8_t *) "\005SummaryInformation",
366
308
              20,
367
308
              directory_entry->name,
368
308
              directory_entry->name_size,
369
308
              byte_order,
370
308
              error );
371
372
308
    if( result == -1 )
373
33
    {
374
33
      libcerror_error_set(
375
33
       error,
376
33
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
377
33
       LIBCERROR_RUNTIME_ERROR_GENERIC,
378
33
       "%s: unable to compare directory entry name.",
379
33
       function );
380
381
33
      goto on_error;
382
33
    }
383
275
    else if( result == LIBUNA_COMPARE_EQUAL )
384
0
    {
385
0
      *summary_information_directory_entry = directory_entry;
386
0
    }
387
308
  }
388
  /* Process sub directory identifier
389
   */
390
66.4k
  if( ( directory_entry->sub_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
391
46.9k
   && ( directory_entry->sub_directory_identifier != 0 )
392
46.6k
   && ( root_directory_entry->directory_identifier == 0 ) )
393
46.5k
  {
394
46.5k
    result = libolecf_directory_list_get_element_by_identifier(
395
46.5k
              directory_entry_list,
396
46.5k
              directory_entry->sub_directory_identifier,
397
46.5k
              &sub_directory_entry,
398
46.5k
              error );
399
400
46.5k
    if( result == -1 )
401
0
    {
402
0
      libcerror_error_set(
403
0
       error,
404
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
405
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
406
0
       "%s: unable to retrieve sub directory entry list element: %" PRIu32 ".",
407
0
       function,
408
0
       directory_entry->sub_directory_identifier );
409
410
0
      goto on_error;
411
0
    }
412
46.5k
    else if( result != 0 )
413
1.66k
    {
414
1.66k
      if( sub_directory_entry == NULL )
415
0
      {
416
0
        libcerror_error_set(
417
0
         error,
418
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
419
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
420
0
         "%s: missing sub directory entry: %" PRIu32 ".",
421
0
         function,
422
0
         directory_entry->sub_directory_identifier );
423
424
0
        goto on_error;
425
0
      }
426
1.66k
      if( sub_directory_entry->set_in_tree != 0 )
427
122
      {
428
122
        libcerror_error_set(
429
122
         error,
430
122
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
431
122
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
432
122
         "%s: directory entry tree node already set.",
433
122
         function );
434
435
122
        goto on_error;
436
122
      }
437
1.54k
      if( libcdata_tree_node_initialize(
438
1.54k
           &tree_node,
439
1.54k
           error ) != 1 )
440
0
      {
441
0
        libcerror_error_set(
442
0
         error,
443
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
444
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
445
0
         "%s: unable to create directory tree node.",
446
0
         function );
447
448
0
        goto on_error;
449
0
      }
450
1.54k
      if( libcdata_tree_node_set_value(
451
1.54k
           tree_node,
452
1.54k
           (intptr_t *) sub_directory_entry,
453
1.54k
           error ) != 1 )
454
0
      {
455
0
        libcerror_error_set(
456
0
         error,
457
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
458
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
459
0
         "%s: unable to set directory tree node value.",
460
0
         function );
461
462
0
        goto on_error;
463
0
      }
464
1.54k
      if( libcdata_tree_node_insert_node(
465
1.54k
           directory_tree_node,
466
1.54k
           tree_node,
467
1.54k
           (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libolecf_directory_entry_compare,
468
1.54k
           LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES,
469
1.54k
           error ) != 1 )
470
0
      {
471
0
        libcerror_error_set(
472
0
         error,
473
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
474
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
475
0
         "%s: unable to insert sub directory tree node.",
476
0
         function );
477
478
0
        goto on_error;
479
0
      }
480
1.54k
      sub_directory_entry->set_in_tree = 1;
481
482
1.54k
      if( libolecf_directory_tree_create_process_entry(
483
1.54k
           tree_node,
484
1.54k
           root_directory_entry,
485
1.54k
           document_summary_information_directory_entry,
486
1.54k
           summary_information_directory_entry,
487
1.54k
           directory_entry_list,
488
1.54k
           sub_directory_entry,
489
1.54k
           byte_order,
490
1.54k
           error ) != 1 )
491
496
      {
492
496
        libcerror_error_set(
493
496
         error,
494
496
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
495
496
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
496
496
         "%s: unable to process sub directory entry.",
497
496
         function );
498
499
496
        tree_node = NULL;
500
501
496
        goto on_error;
502
496
      }
503
1.04k
      tree_node = NULL;
504
1.04k
    }
505
46.5k
  }
506
  /* Process previous directory identifier
507
   */
508
65.8k
  if( directory_entry->previous_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
509
35.3k
  {
510
35.3k
    result = libolecf_directory_list_get_element_by_identifier(
511
35.3k
              directory_entry_list,
512
35.3k
              (int) directory_entry->previous_directory_identifier,
513
35.3k
              &sub_directory_entry,
514
35.3k
              error );
515
516
35.3k
    if( result == -1 )
517
0
    {
518
0
      libcerror_error_set(
519
0
       error,
520
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
521
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
522
0
       "%s: unable to retrieve previous directory entry: 0x%08" PRIx32 ".",
523
0
       function,
524
0
       directory_entry->previous_directory_identifier );
525
526
0
      goto on_error;
527
0
    }
528
35.3k
    else if( result != 0 )
529
33.8k
    {
530
33.8k
      if( sub_directory_entry == NULL )
531
0
      {
532
0
        libcerror_error_set(
533
0
         error,
534
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
535
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
536
0
         "%s: missing previous directory entry: %" PRIu32 ".",
537
0
         function,
538
0
         directory_entry->previous_directory_identifier );
539
540
0
        goto on_error;
541
0
      }
542
33.8k
      if( sub_directory_entry->set_in_tree != 0 )
543
20
      {
544
20
        libcerror_error_set(
545
20
         error,
546
20
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
547
20
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
548
20
         "%s: directory entry tree node already set.",
549
20
         function );
550
551
20
        goto on_error;
552
20
      }
553
33.8k
      if( libcdata_tree_node_initialize(
554
33.8k
           &tree_node,
555
33.8k
           error ) != 1 )
556
0
      {
557
0
        libcerror_error_set(
558
0
         error,
559
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
560
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
561
0
         "%s: unable to create directory tree node.",
562
0
         function );
563
564
0
        goto on_error;
565
0
      }
566
33.8k
      if( libcdata_tree_node_set_value(
567
33.8k
           tree_node,
568
33.8k
           (intptr_t *) sub_directory_entry,
569
33.8k
           error ) != 1 )
570
0
      {
571
0
        libcerror_error_set(
572
0
         error,
573
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
574
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
575
0
         "%s: unable to set directory tree node value.",
576
0
         function );
577
578
0
        goto on_error;
579
0
      }
580
33.8k
      if( libcdata_tree_node_get_parent_node(
581
33.8k
           directory_tree_node,
582
33.8k
           &parent_node,
583
33.8k
           error ) != 1 )
584
0
      {
585
0
        libcerror_error_set(
586
0
         error,
587
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
588
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
589
0
         "%s: unable to retrieve parent node.",
590
0
         function );
591
592
0
        goto on_error;
593
0
      }
594
33.8k
      if( libcdata_tree_node_insert_node(
595
33.8k
           parent_node,
596
33.8k
           tree_node,
597
33.8k
           (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libolecf_directory_entry_compare,
598
33.8k
           LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES,
599
33.8k
           error ) != 1 )
600
14
      {
601
14
        libcerror_error_set(
602
14
         error,
603
14
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
604
14
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
605
14
         "%s: unable to insert previous directory tree node.",
606
14
         function );
607
608
14
        goto on_error;
609
14
      }
610
33.7k
      sub_directory_entry->set_in_tree = 1;
611
612
33.7k
      if( libolecf_directory_tree_create_process_entry(
613
33.7k
           tree_node,
614
33.7k
           root_directory_entry,
615
33.7k
           document_summary_information_directory_entry,
616
33.7k
           summary_information_directory_entry,
617
33.7k
           directory_entry_list,
618
33.7k
           sub_directory_entry,
619
33.7k
           byte_order,
620
33.7k
           error ) != 1 )
621
3.87k
      {
622
3.87k
        libcerror_error_set(
623
3.87k
         error,
624
3.87k
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
625
3.87k
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
626
3.87k
         "%s: unable to process previous directory entry.",
627
3.87k
         function );
628
629
3.87k
        tree_node = NULL;
630
631
3.87k
        goto on_error;
632
3.87k
      }
633
29.9k
      tree_node = NULL;
634
29.9k
    }
635
35.3k
  }
636
  /* Process next directory identifier
637
   */
638
61.9k
  if( directory_entry->next_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
639
30.9k
  {
640
30.9k
    result = libolecf_directory_list_get_element_by_identifier(
641
30.9k
              directory_entry_list,
642
30.9k
              (int) directory_entry->next_directory_identifier,
643
30.9k
              &sub_directory_entry,
644
30.9k
              error );
645
646
30.9k
    if( result != 1 )
647
282
    {
648
282
      libcerror_error_set(
649
282
       error,
650
282
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
651
282
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
652
282
       "%s: unable to retrieve next directory entry: 0x%08" PRIx32 ".",
653
282
       function,
654
282
       directory_entry->next_directory_identifier );
655
656
282
      goto on_error;
657
282
    }
658
30.6k
    else if( result != 0 )
659
30.6k
    {
660
30.6k
      if( sub_directory_entry == NULL )
661
0
      {
662
0
        libcerror_error_set(
663
0
         error,
664
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
665
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
666
0
         "%s: missing next directory entry: %" PRIu32 ".",
667
0
         function,
668
0
         directory_entry->sub_directory_identifier );
669
670
0
        goto on_error;
671
0
      }
672
30.6k
      if( sub_directory_entry->set_in_tree != 0 )
673
21
      {
674
21
        libcerror_error_set(
675
21
         error,
676
21
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
677
21
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
678
21
         "%s: directory entry tree node already set.",
679
21
         function );
680
681
21
        goto on_error;
682
21
      }
683
30.6k
      if( libcdata_tree_node_initialize(
684
30.6k
           &tree_node,
685
30.6k
           error ) != 1 )
686
0
      {
687
0
        libcerror_error_set(
688
0
         error,
689
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
690
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
691
0
         "%s: unable to create directory tree node.",
692
0
         function );
693
694
0
        goto on_error;
695
0
      }
696
30.6k
      if( libcdata_tree_node_set_value(
697
30.6k
           tree_node,
698
30.6k
           (intptr_t *) sub_directory_entry,
699
30.6k
           error ) != 1 )
700
0
      {
701
0
        libcerror_error_set(
702
0
         error,
703
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
704
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
705
0
         "%s: unable to set directory tree node value.",
706
0
         function );
707
708
0
        goto on_error;
709
0
      }
710
30.6k
      if( libcdata_tree_node_get_parent_node(
711
30.6k
           directory_tree_node,
712
30.6k
           &parent_node,
713
30.6k
           error ) != 1 )
714
0
      {
715
0
        libcerror_error_set(
716
0
         error,
717
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
718
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
719
0
         "%s: unable to retrieve parent node.",
720
0
         function );
721
722
0
        goto on_error;
723
0
      }
724
30.6k
      if( libcdata_tree_node_insert_node(
725
30.6k
           parent_node,
726
30.6k
           tree_node,
727
30.6k
           (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libolecf_directory_entry_compare,
728
30.6k
           LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES,
729
30.6k
           error ) != 1 )
730
15
      {
731
15
        libcerror_error_set(
732
15
         error,
733
15
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
734
15
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
735
15
         "%s: unable to insert next directory tree node.",
736
15
         function );
737
738
15
        goto on_error;
739
15
      }
740
30.5k
      sub_directory_entry->set_in_tree = 1;
741
742
30.5k
      if( libolecf_directory_tree_create_process_entry(
743
30.5k
           tree_node,
744
30.5k
           root_directory_entry,
745
30.5k
           document_summary_information_directory_entry,
746
30.5k
           summary_information_directory_entry,
747
30.5k
           directory_entry_list,
748
30.5k
           sub_directory_entry,
749
30.5k
           byte_order,
750
30.5k
           error ) != 1 )
751
3.87k
      {
752
3.87k
        libcerror_error_set(
753
3.87k
         error,
754
3.87k
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
755
3.87k
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
756
3.87k
         "%s: unable to process next directory entry.",
757
3.87k
         function );
758
759
3.87k
        tree_node = NULL;
760
761
3.87k
        goto on_error;
762
3.87k
      }
763
26.7k
      tree_node = NULL;
764
26.7k
    }
765
30.9k
  }
766
57.7k
  return( 1 );
767
768
8.78k
on_error:
769
8.78k
  if( tree_node != NULL )
770
29
  {
771
29
    libcdata_tree_node_free(
772
29
     &tree_node,
773
29
     NULL,
774
29
     NULL );
775
29
  }
776
8.78k
  return( -1 );
777
61.9k
}
778
779
/* Retrieves the sub node for the specific UTF-8 formatted name
780
 * Returns 1 if successful, 0 if no such sub node or -1 on error
781
 */
782
int libolecf_directory_tree_get_sub_node_by_utf8_name(
783
     libcdata_tree_node_t *directory_tree_node,
784
     const uint8_t *utf8_string,
785
     size_t utf8_string_length,
786
     uint8_t byte_order,
787
     libcdata_tree_node_t **sub_directory_tree_node,
788
     libcerror_error_t **error )
789
0
{
790
0
  libcdata_tree_node_t *safe_sub_directory_tree_node = NULL;
791
0
  libolecf_directory_entry_t *sub_directory_entry    = NULL;
792
0
  static char *function                              = "libolecf_directory_tree_get_sub_node_by_utf8_name";
793
0
  int number_of_sub_nodex                            = 0;
794
0
  int result                                         = 0;
795
0
  int sub_node_index                                 = 0;
796
797
0
  if( directory_tree_node == NULL )
798
0
  {
799
0
    libcerror_error_set(
800
0
     error,
801
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
802
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
803
0
     "%s: invalid directory tree node.",
804
0
     function );
805
806
0
    return( -1 );
807
0
  }
808
0
  if( sub_directory_tree_node == NULL )
809
0
  {
810
0
    libcerror_error_set(
811
0
     error,
812
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
813
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
814
0
     "%s: invalid sub directory tree node.",
815
0
     function );
816
817
0
    return( -1 );
818
0
  }
819
0
  *sub_directory_tree_node = NULL;
820
821
0
  if( libcdata_tree_node_get_number_of_sub_nodes(
822
0
       directory_tree_node,
823
0
       &number_of_sub_nodex,
824
0
       error ) != 1 )
825
0
  {
826
0
    libcerror_error_set(
827
0
     error,
828
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
829
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
830
0
     "%s: unable to retrieve number of sub nodex.",
831
0
     function );
832
833
0
    return( -1 );
834
0
  }
835
0
  for( sub_node_index = 0;
836
0
       sub_node_index < number_of_sub_nodex;
837
0
       sub_node_index++ )
838
0
        {
839
0
    if( libcdata_tree_node_get_sub_node_by_index(
840
0
         directory_tree_node,
841
0
         sub_node_index,
842
0
         &safe_sub_directory_tree_node,
843
0
         error ) != 1 )
844
0
    {
845
0
      libcerror_error_set(
846
0
       error,
847
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
848
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
849
0
       "%s: unable to retrieve number of sub nodex: %d.",
850
0
       function,
851
0
       sub_node_index );
852
853
0
      return( -1 );
854
0
    }
855
0
    if( libcdata_tree_node_get_value(
856
0
         safe_sub_directory_tree_node,
857
0
         (intptr_t **) &sub_directory_entry,
858
0
         error ) != 1 )
859
0
    {
860
0
      libcerror_error_set(
861
0
       error,
862
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
863
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
864
0
       "%s: unable to retrieve value from sub directory tree node: %d.",
865
0
       function,
866
0
       sub_node_index );
867
868
0
      return( -1 );
869
0
    }
870
0
    if( sub_directory_entry == NULL )
871
0
    {
872
0
      libcerror_error_set(
873
0
       error,
874
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
875
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
876
0
       "%s: missing sub directory entry: %d.",
877
0
       function,
878
0
       sub_node_index );
879
880
0
      return( -1 );
881
0
    }
882
0
    result = libuna_utf8_string_compare_with_utf16_stream(
883
0
              utf8_string,
884
0
              utf8_string_length,
885
0
              sub_directory_entry->name,
886
0
              sub_directory_entry->name_size,
887
0
              byte_order,
888
0
              error );
889
890
0
    if( result == -1 )
891
0
    {
892
0
      libcerror_error_set(
893
0
       error,
894
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
895
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
896
0
       "%s: unable to compare sub directory entry: %d name.",
897
0
       function,
898
0
       sub_node_index );
899
900
0
      return( -1 );
901
0
    }
902
0
    else if( result == LIBUNA_COMPARE_EQUAL )
903
0
    {
904
0
      *sub_directory_tree_node = safe_sub_directory_tree_node;
905
906
0
      return( 1 );
907
0
    }
908
0
  }
909
0
  return( 0 );
910
0
}
911
912
/* Retrieves the sub node for the specific UTF-16 formatted name
913
 * Returns 1 if successful, 0 if no such sub node or -1 on error
914
 */
915
int libolecf_directory_tree_get_sub_node_by_utf16_name(
916
     libcdata_tree_node_t *directory_tree_node,
917
     const uint16_t *utf16_string,
918
     size_t utf16_string_length,
919
     uint8_t byte_order,
920
     libcdata_tree_node_t **sub_directory_tree_node,
921
     libcerror_error_t **error )
922
0
{
923
0
  libcdata_tree_node_t *safe_sub_directory_tree_node = NULL;
924
0
  libolecf_directory_entry_t *sub_directory_entry    = NULL;
925
0
  static char *function                              = "libolecf_directory_tree_get_sub_node_by_utf16_name";
926
0
  int number_of_sub_nodex                            = 0;
927
0
  int result                                         = 0;
928
0
  int sub_node_index                                 = 0;
929
930
0
  if( directory_tree_node == NULL )
931
0
  {
932
0
    libcerror_error_set(
933
0
     error,
934
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
935
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
936
0
     "%s: invalid directory tree node.",
937
0
     function );
938
939
0
    return( -1 );
940
0
  }
941
0
  if( sub_directory_tree_node == NULL )
942
0
  {
943
0
    libcerror_error_set(
944
0
     error,
945
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
946
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
947
0
     "%s: invalid sub directory tree node.",
948
0
     function );
949
950
0
    return( -1 );
951
0
  }
952
0
  *sub_directory_tree_node = NULL;
953
954
0
  if( libcdata_tree_node_get_number_of_sub_nodes(
955
0
       directory_tree_node,
956
0
       &number_of_sub_nodex,
957
0
       error ) != 1 )
958
0
  {
959
0
    libcerror_error_set(
960
0
     error,
961
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
962
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
963
0
     "%s: unable to retrieve number of sub nodex.",
964
0
     function );
965
966
0
    return( -1 );
967
0
  }
968
0
  for( sub_node_index = 0;
969
0
       sub_node_index < number_of_sub_nodex;
970
0
       sub_node_index++ )
971
0
        {
972
0
    if( libcdata_tree_node_get_sub_node_by_index(
973
0
         directory_tree_node,
974
0
         sub_node_index,
975
0
         &safe_sub_directory_tree_node,
976
0
         error ) != 1 )
977
0
    {
978
0
      libcerror_error_set(
979
0
       error,
980
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
981
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
982
0
       "%s: unable to retrieve number of sub nodex: %d.",
983
0
       function,
984
0
       sub_node_index );
985
986
0
      return( -1 );
987
0
    }
988
0
    if( libcdata_tree_node_get_value(
989
0
         safe_sub_directory_tree_node,
990
0
         (intptr_t **) &sub_directory_entry,
991
0
         error ) != 1 )
992
0
    {
993
0
      libcerror_error_set(
994
0
       error,
995
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
996
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
997
0
       "%s: unable to retrieve value from sub directory tree node: %d.",
998
0
       function,
999
0
       sub_node_index );
1000
1001
0
      return( -1 );
1002
0
    }
1003
0
    if( sub_directory_entry == NULL )
1004
0
    {
1005
0
      libcerror_error_set(
1006
0
       error,
1007
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1008
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1009
0
       "%s: missing sub directory entry: %d.",
1010
0
       function,
1011
0
       sub_node_index );
1012
1013
0
      return( -1 );
1014
0
    }
1015
0
    result = libuna_utf16_string_compare_with_utf16_stream(
1016
0
              utf16_string,
1017
0
              utf16_string_length,
1018
0
              sub_directory_entry->name,
1019
0
              sub_directory_entry->name_size,
1020
0
              byte_order,
1021
0
              error );
1022
1023
0
    if( result == -1 )
1024
0
    {
1025
0
      libcerror_error_set(
1026
0
       error,
1027
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1028
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1029
0
       "%s: unable to compare sub directory entry: %d name.",
1030
0
       function,
1031
0
       sub_node_index );
1032
1033
0
      return( -1 );
1034
0
    }
1035
0
    else if( result == LIBUNA_COMPARE_EQUAL )
1036
0
    {
1037
0
      *sub_directory_tree_node = safe_sub_directory_tree_node;
1038
1039
0
      return( 1 );
1040
0
    }
1041
0
  }
1042
0
  return( 0 );
1043
0
}
1044