Coverage Report

Created: 2025-06-13 07:22

/src/libwrc/libwrc/libwrc_resource_node_tree.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Resource node tree functions
3
 *
4
 * Copyright (C) 2011-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include "libwrc_definitions.h"
27
#include "libwrc_io_handle.h"
28
#include "libwrc_libbfio.h"
29
#include "libwrc_libcdata.h"
30
#include "libwrc_libcerror.h"
31
#include "libwrc_libcnotify.h"
32
#include "libwrc_resource_node_entry.h"
33
#include "libwrc_resource_node_header.h"
34
#include "libwrc_resource_node_tree.h"
35
36
#include "wrc_resource_node.h"
37
38
const uint8_t libwrc_resource_name_mui[ 6 ] = {
39
  'M', 0, 'U', 0, 'I', 0 };
40
41
const uint8_t libwrc_resource_name_wevt_template[ 26 ] = {
42
  'W', 0, 'E', 0, 'V', 0, 'T', 0, '_', 0, 'T', 0, 'E', 0, 'M', 0,
43
  'P', 0, 'L', 0, 'A', 0, 'T', 0, 'E', 0 };
44
45
/* Reads the node of a resource node tree
46
 * Returns 1 if successful or -1 on error
47
 */
48
int libwrc_resource_node_tree_read_node(
49
     libcdata_tree_node_t *node,
50
     libwrc_io_handle_t *io_handle,
51
     libbfio_handle_t *file_io_handle,
52
     off64_t file_offset,
53
     int node_level,
54
     libcerror_error_t **error )
55
4.02k
{
56
4.02k
  libcdata_tree_node_t *sub_node                        = NULL;
57
4.02k
  libwrc_resource_node_entry_t *resource_node_entry     = NULL;
58
4.02k
  libwrc_resource_node_entry_t *sub_resource_node_entry = NULL;
59
4.02k
  libwrc_resource_node_header_t *resource_node_header   = NULL;
60
4.02k
  static char *function                                 = "libwrc_resource_node_tree_read_node";
61
4.02k
  off64_t resource_node_entry_data_offset               = 0;
62
4.02k
  uint32_t entry_index                                  = 0;
63
4.02k
  uint32_t number_of_entries                            = 0;
64
4.02k
  uint32_t resource_node_entry_offset                   = 0;
65
4.02k
  int number_of_sub_nodes                               = 0;
66
4.02k
  int resource_node_entry_index                         = 0;
67
4.02k
  int result                                            = 0;
68
4.02k
  int sub_node_index                                    = 0;
69
70
4.02k
  if( io_handle == NULL )
71
0
  {
72
0
    libcerror_error_set(
73
0
     error,
74
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
75
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
76
0
     "%s: invalid IO handle.",
77
0
     function );
78
79
0
    return( -1 );
80
0
  }
81
4.02k
  if( ( node_level < 1 )
82
4.02k
   || ( node_level > LIBWRC_MAXIMUM_RESOURCE_NODE_RECURSION_DEPTH ) )
83
19
  {
84
19
    libcerror_error_set(
85
19
     error,
86
19
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
87
19
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
88
19
     "%s: invalid node level value out of bounds.",
89
19
     function );
90
91
19
    return( -1 );
92
19
  }
93
4.00k
  if( node == NULL )
94
0
  {
95
0
    libcerror_error_set(
96
0
     error,
97
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
98
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
99
0
     "%s: invalid node.",
100
0
     function );
101
102
0
    return( -1 );
103
0
  }
104
4.00k
  if( libwrc_resource_node_header_initialize(
105
4.00k
       &resource_node_header,
106
4.00k
       error ) == -1 )
107
0
  {
108
0
    libcerror_error_set(
109
0
     error,
110
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
111
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
112
0
     "%s: unable to create resource node header.",
113
0
     function );
114
115
0
    goto on_error;
116
0
  }
117
4.00k
  if( libwrc_resource_node_header_read_file_io_handle(
118
4.00k
       resource_node_header,
119
4.00k
       file_io_handle,
120
4.00k
       file_offset,
121
4.00k
       error ) != 1 )
122
110
  {
123
110
    libcerror_error_set(
124
110
     error,
125
110
     LIBCERROR_ERROR_DOMAIN_IO,
126
110
     LIBCERROR_IO_ERROR_READ_FAILED,
127
110
     "%s: unable to read resource node header at offset: %" PRIi64 " (0x%08" PRIx64 ").",
128
110
     function,
129
110
     file_offset,
130
110
     file_offset );
131
132
110
    goto on_error;
133
110
  }
134
3.89k
  file_offset += sizeof( wrc_resource_node_header_t );
135
136
3.89k
  number_of_entries = (uint32_t) resource_node_header->number_of_named_entries + (uint32_t) resource_node_header->number_of_unnamed_entries;
137
138
3.89k
  if( libwrc_resource_node_header_free(
139
3.89k
       &resource_node_header,
140
3.89k
       error ) == -1 )
141
0
  {
142
0
    libcerror_error_set(
143
0
     error,
144
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
145
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
146
0
     "%s: unable to free resource node header.",
147
0
     function );
148
149
0
    goto on_error;
150
0
  }
151
3.89k
  resource_node_entry_data_offset = sizeof( wrc_resource_node_header_t ) + ( number_of_entries * sizeof( wrc_resource_node_entry_t ) );
152
153
3.89k
  if( (size64_t) resource_node_entry_data_offset > io_handle->stream_size )
154
25
  {
155
25
    libcerror_error_set(
156
25
     error,
157
25
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
158
25
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
159
25
     "%s: invalid number of entries value out of bounds.",
160
25
     function );
161
162
25
    goto on_error;
163
25
  }
164
3.86k
  for( entry_index = 0;
165
10.9k
       entry_index < number_of_entries;
166
7.10k
       entry_index++ )
167
7.31k
  {
168
7.31k
    if( libwrc_resource_node_entry_initialize(
169
7.31k
         &resource_node_entry,
170
7.31k
         error ) == -1 )
171
0
    {
172
0
      libcerror_error_set(
173
0
       error,
174
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
175
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
176
0
       "%s: unable to create resource node entry: %d.",
177
0
       function,
178
0
       entry_index );
179
180
0
      goto on_error;
181
0
    }
182
7.31k
    if( libwrc_resource_node_entry_read_file_io_handle(
183
7.31k
         resource_node_entry,
184
7.31k
         file_io_handle,
185
7.31k
         file_offset,
186
7.31k
         node_level,
187
7.31k
         error ) != 1 )
188
5
    {
189
5
      libcerror_error_set(
190
5
       error,
191
5
       LIBCERROR_ERROR_DOMAIN_IO,
192
5
       LIBCERROR_IO_ERROR_READ_FAILED,
193
5
       "%s: unable to read resource node entry: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
194
5
       function,
195
5
       entry_index,
196
5
       file_offset,
197
5
       file_offset );
198
199
5
      goto on_error;
200
5
    }
201
7.30k
    file_offset += sizeof( wrc_resource_node_entry_t );
202
203
7.30k
    result = libwrc_resource_node_entry_read_name_file_io_handle(
204
7.30k
              resource_node_entry,
205
7.30k
              file_io_handle,
206
7.30k
              error );
207
208
7.30k
    if( result == -1 )
209
126
    {
210
126
      libcerror_error_set(
211
126
       error,
212
126
       LIBCERROR_ERROR_DOMAIN_IO,
213
126
       LIBCERROR_IO_ERROR_READ_FAILED,
214
126
       "%s: unable to read resource node entry: %d name.",
215
126
       function,
216
126
       entry_index );
217
218
126
      goto on_error;
219
126
    }
220
7.18k
    resource_node_entry_offset = resource_node_entry->offset & 0x7fffffffUL;
221
222
    /* Check the bounds here to fail fast on corrupt data
223
     */
224
7.18k
    if( ( resource_node_entry_offset < resource_node_entry_data_offset )
225
7.18k
     || ( resource_node_entry_offset >= io_handle->stream_size ) )
226
74
    {
227
74
      libcerror_error_set(
228
74
       error,
229
74
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
230
74
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
231
74
       "%s: invalid resource node entry: %d - offset value out of bounds.",
232
74
       function,
233
74
       entry_index );
234
235
74
      goto on_error;
236
74
    }
237
7.10k
    if( node_level == 1 )
238
1.64k
    {
239
1.64k
      if( ( resource_node_entry->identifier & LIBWRC_RESOURCE_IDENTIFIER_FLAG_HAS_NAME ) == 0 )
240
1.02k
      {
241
1.02k
        switch( resource_node_entry->identifier )
242
1.02k
        {
243
7
          case LIBWRC_RESOURCE_IDENTIFIER_CURSOR:
244
7
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_CURSOR;
245
7
            break;
246
247
5
          case LIBWRC_RESOURCE_IDENTIFIER_BITMAP:
248
5
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_BITMAP;
249
5
            break;
250
251
2
          case LIBWRC_RESOURCE_IDENTIFIER_ICON:
252
2
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_ICON;
253
2
            break;
254
255
2
          case LIBWRC_RESOURCE_IDENTIFIER_MENU:
256
2
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_MENU;
257
2
            break;
258
259
5
          case LIBWRC_RESOURCE_IDENTIFIER_DIALOG:
260
5
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_DIALOG;
261
5
            break;
262
263
5
          case LIBWRC_RESOURCE_IDENTIFIER_STRING:
264
5
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_STRING;
265
5
            break;
266
267
1
          case LIBWRC_RESOURCE_IDENTIFIER_FONT_DIRECTORY:
268
1
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_FONT_DIRECTORY;
269
1
            break;
270
271
11
          case LIBWRC_RESOURCE_IDENTIFIER_FONT:
272
11
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_FONT;
273
11
            break;
274
275
4
          case LIBWRC_RESOURCE_IDENTIFIER_ACCELERATOR:
276
4
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_ACCELERATOR;
277
4
            break;
278
279
2
          case LIBWRC_RESOURCE_IDENTIFIER_RAW_DATA:
280
2
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_RAW_DATA;
281
2
            break;
282
283
2
          case LIBWRC_RESOURCE_IDENTIFIER_MESSAGE_TABLE:
284
2
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_MESSAGE_TABLE;
285
2
            break;
286
287
36
          case LIBWRC_RESOURCE_IDENTIFIER_GROUP_CURSOR:
288
36
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_GROUP_CURSOR;
289
36
            break;
290
291
4
          case LIBWRC_RESOURCE_IDENTIFIER_GROUP_ICON:
292
4
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_GROUP_ICON;
293
4
            break;
294
295
19
          case LIBWRC_RESOURCE_IDENTIFIER_VERSION:
296
19
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_VERSION;
297
19
            break;
298
299
7
          case LIBWRC_RESOURCE_IDENTIFIER_DIALOG_INCLUDE:
300
7
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_DIALOG_INCLUDE;
301
7
            break;
302
303
3
          case LIBWRC_RESOURCE_IDENTIFIER_PLUG_AND_PLAY:
304
3
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_PLUG_AND_PLAY;
305
3
            break;
306
307
3
          case LIBWRC_RESOURCE_IDENTIFIER_VXD:
308
3
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_VXD;
309
3
            break;
310
311
2
          case LIBWRC_RESOURCE_IDENTIFIER_ANIMATED_CURSOR:
312
2
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_ANIMATED_CURSOR;
313
2
            break;
314
315
7
          case LIBWRC_RESOURCE_IDENTIFIER_ANIMATED_ICON:
316
7
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_ANIMATED_ICON;
317
7
            break;
318
319
6
          case LIBWRC_RESOURCE_IDENTIFIER_HTML:
320
6
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_HTML;
321
6
            break;
322
323
27
          case LIBWRC_RESOURCE_IDENTIFIER_MANIFEST:
324
27
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_MANIFEST;
325
27
            break;
326
1.02k
        }
327
1.02k
      }
328
626
      else
329
626
      {
330
626
        if( resource_node_entry->name_string_size == 6 )
331
227
        {
332
227
          if( memory_compare(
333
227
               resource_node_entry->name_string,
334
227
               libwrc_resource_name_mui,
335
227
               6 ) == 0 )
336
70
          {
337
70
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_MUI;
338
70
          }
339
227
        }
340
399
        else if( resource_node_entry->name_string_size == 26 )
341
246
        {
342
246
          if( memory_compare(
343
246
               resource_node_entry->name_string,
344
246
               libwrc_resource_name_wevt_template,
345
246
               26 ) == 0 )
346
77
          {
347
77
            resource_node_entry->type = LIBWRC_RESOURCE_TYPE_WEVT_TEMPLATE;
348
77
          }
349
246
        }
350
626
      }
351
1.64k
    }
352
7.10k
    if( libcdata_tree_node_insert_value(
353
7.10k
         node,
354
7.10k
         (intptr_t *) resource_node_entry,
355
7.10k
         (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libwrc_resource_node_entry_compare,
356
7.10k
         LIBCDATA_INSERT_FLAG_NON_UNIQUE_ENTRIES,
357
7.10k
         error ) == -1 )
358
0
    {
359
0
      libcerror_error_set(
360
0
       error,
361
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
362
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
363
0
       "%s: unable to insert resource node: %d.",
364
0
       function,
365
0
       resource_node_entry_index );
366
367
0
      goto on_error;
368
0
    }
369
7.10k
    resource_node_entry = NULL;
370
371
7.10k
    resource_node_entry_index++;
372
373
#if defined( HAVE_DEBUG_OUTPUT )
374
    if( libcnotify_verbose != 0 )
375
    {
376
      libcnotify_printf(
377
       "\n" );
378
    }
379
#endif
380
7.10k
  }
381
3.66k
  if( libcdata_tree_node_get_number_of_sub_nodes(
382
3.66k
       node,
383
3.66k
       &number_of_sub_nodes,
384
3.66k
       error ) != 1 )
385
0
  {
386
0
    libcerror_error_set(
387
0
     error,
388
0
     LIBCERROR_ERROR_DOMAIN_IO,
389
0
     LIBCERROR_IO_ERROR_READ_FAILED,
390
0
     "%s: unable to retrieve number of sub nodes.",
391
0
     function );
392
393
0
    goto on_error;
394
0
  }
395
3.66k
  if( libcdata_tree_node_get_sub_node_by_index(
396
3.66k
       node,
397
3.66k
       0,
398
3.66k
       &sub_node,
399
3.66k
       error ) != 1 )
400
28
  {
401
28
    libcerror_error_set(
402
28
     error,
403
28
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
404
28
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
405
28
     "%s: unable to retrieve first sub node.",
406
28
     function );
407
408
28
    goto on_error;
409
28
  }
410
3.63k
  for( sub_node_index = 0;
411
5.89k
       sub_node_index < number_of_sub_nodes;
412
3.63k
       sub_node_index++ )
413
5.19k
  {
414
5.19k
    if( libcdata_tree_node_get_value(
415
5.19k
         sub_node,
416
5.19k
         (intptr_t **) &sub_resource_node_entry,
417
5.19k
         error ) != 1 )
418
0
    {
419
0
      libcerror_error_set(
420
0
       error,
421
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
422
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
423
0
       "%s: unable to retrieve resource sub node: %d entry.",
424
0
       function,
425
0
       sub_node_index );
426
427
0
      goto on_error;
428
0
    }
429
5.19k
    if( sub_resource_node_entry == NULL )
430
0
    {
431
0
      libcerror_error_set(
432
0
       error,
433
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
434
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
435
0
       "%s: invalid resource sub node: %d entry.",
436
0
       function,
437
0
       sub_node_index );
438
439
0
      goto on_error;
440
0
    }
441
5.19k
    if( ( sub_resource_node_entry->offset & 0x80000000UL ) != 0 )
442
3.26k
    {
443
3.26k
      resource_node_entry_offset = sub_resource_node_entry->offset & 0x7fffffffUL;
444
445
3.26k
      if( libwrc_resource_node_tree_read_node(
446
3.26k
           sub_node,
447
3.26k
           io_handle,
448
3.26k
           file_io_handle,
449
3.26k
           (off64_t) resource_node_entry_offset,
450
3.26k
           node_level + 1,
451
3.26k
           error ) != 1 )
452
2.60k
      {
453
2.60k
        libcerror_error_set(
454
2.60k
         error,
455
2.60k
         LIBCERROR_ERROR_DOMAIN_IO,
456
2.60k
         LIBCERROR_IO_ERROR_READ_FAILED,
457
2.60k
         "%s: unable to read sub resource node: %d at offset: %" PRIu32 " (0x%08" PRIx32 ").",
458
2.60k
         function,
459
2.60k
         sub_node_index,
460
2.60k
         resource_node_entry_offset,
461
2.60k
         resource_node_entry_offset );
462
463
2.60k
        goto on_error;
464
2.60k
      }
465
3.26k
    }
466
1.92k
    else
467
1.92k
    {
468
1.92k
      if( libwrc_data_descriptor_initialize(
469
1.92k
           &( sub_resource_node_entry->data_descriptor ),
470
1.92k
           error ) == -1 )
471
0
      {
472
0
        libcerror_error_set(
473
0
         error,
474
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
475
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
476
0
         "%s: unable to create data descriptor: %d.",
477
0
         function,
478
0
         sub_node_index );
479
480
0
        goto on_error;
481
0
      }
482
1.92k
      if( libwrc_data_descriptor_read_file_io_handle(
483
1.92k
           sub_resource_node_entry->data_descriptor,
484
1.92k
           file_io_handle,
485
1.92k
           (off64_t) sub_resource_node_entry->offset,
486
1.92k
           error ) != 1 )
487
154
      {
488
154
        libcerror_error_set(
489
154
         error,
490
154
         LIBCERROR_ERROR_DOMAIN_IO,
491
154
         LIBCERROR_IO_ERROR_READ_FAILED,
492
154
         "%s: unable to read data descriptor: %d at offset: %" PRIu32 " (0x%08" PRIx32 ").",
493
154
         function,
494
154
         sub_node_index,
495
154
         sub_resource_node_entry->offset,
496
154
         sub_resource_node_entry->offset );
497
498
154
        goto on_error;
499
154
      }
500
1.77k
      if( ( sub_resource_node_entry->data_descriptor->virtual_address < io_handle->virtual_address )
501
1.77k
       || ( (size64_t) sub_resource_node_entry->data_descriptor->virtual_address >= ( io_handle->virtual_address + io_handle->stream_size ) ) )
502
134
      {
503
134
        libcerror_error_set(
504
134
         error,
505
134
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
506
134
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
507
134
         "%s: invalid data descriptor: %d - virtual address value out of bounds.",
508
134
         function,
509
134
         sub_node_index );
510
511
134
        goto on_error;
512
134
      }
513
1.64k
      if( (size64_t) ( sub_resource_node_entry->data_descriptor->virtual_address + sub_resource_node_entry->data_descriptor->size ) > ( io_handle->virtual_address + io_handle->stream_size ) )
514
37
      {
515
37
        libcerror_error_set(
516
37
         error,
517
37
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
518
37
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
519
37
         "%s: invalid data descriptor: %d - size value out of bounds.",
520
37
         function,
521
37
         sub_node_index );
522
523
37
        goto on_error;
524
37
      }
525
1.64k
    }
526
2.26k
    if( libcdata_tree_node_get_next_node(
527
2.26k
         sub_node,
528
2.26k
         &sub_node,
529
2.26k
         error ) != 1 )
530
0
    {
531
0
      libcerror_error_set(
532
0
       error,
533
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
534
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
535
0
       "%s: unable to retrieve next node of sub node: %d.",
536
0
       function,
537
0
       sub_node_index );
538
539
0
      goto on_error;
540
0
    }
541
2.26k
  }
542
706
  return( 1 );
543
544
3.29k
on_error:
545
3.29k
  if( resource_node_entry != NULL )
546
205
  {
547
205
    libwrc_resource_node_entry_free(
548
205
     &resource_node_entry,
549
205
     NULL );
550
205
  }
551
3.29k
  if( resource_node_header != NULL )
552
110
  {
553
110
    libwrc_resource_node_header_free(
554
110
     &resource_node_header,
555
110
     NULL );
556
110
  }
557
3.29k
  return( -1 );
558
3.63k
}
559