Coverage Report

Created: 2025-06-22 07:35

/src/libfmapi/libfmapi/libfmapi_entry_identifier.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Entry identifier (ENTRYID) functions
3
 *
4
 * Copyright (C) 2009-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 <system_string.h>
25
#include <types.h>
26
27
#include "libfmapi_definitions.h"
28
#include "libfmapi_entry_identifier.h"
29
#include "libfmapi_libcerror.h"
30
#include "libfmapi_libcnotify.h"
31
#include "libfmapi_libfguid.h"
32
#include "libfmapi_service_provider_identifier.h"
33
34
/* Creates an entry identifier
35
 * Make sure the value entry_identifier is referencing, is set to NULL
36
 * Returns 1 if successful or -1 on error
37
 */
38
int libfmapi_entry_identifier_initialize(
39
     libfmapi_entry_identifier_t **entry_identifier,
40
     libcerror_error_t **error )
41
47
{
42
47
  libfmapi_internal_entry_identifier_t *internal_entry_identifier = NULL;
43
47
  static char *function                                           = "libfmapi_entry_identifier_initialize";
44
45
47
  if( entry_identifier == NULL )
46
0
  {
47
0
    libcerror_error_set(
48
0
     error,
49
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
50
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
51
0
     "%s: invalid entry identifier.",
52
0
     function );
53
54
0
    return( -1 );
55
0
  }
56
47
  if( *entry_identifier != NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
61
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
62
0
     "%s: invalid entry identifier value already set.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
47
  internal_entry_identifier = memory_allocate_structure(
68
47
                               libfmapi_internal_entry_identifier_t );
69
70
47
  if( internal_entry_identifier == NULL )
71
0
  {
72
0
    libcerror_error_set(
73
0
     error,
74
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
75
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
76
0
     "%s: unable to create entry identifier.",
77
0
     function );
78
79
0
    goto on_error;
80
0
  }
81
47
  if( memory_set(
82
47
       internal_entry_identifier,
83
47
       0,
84
47
       sizeof( libfmapi_internal_entry_identifier_t ) ) == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
89
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
90
0
     "%s: unable to clear entry identifier.",
91
0
     function );
92
93
0
    goto on_error;
94
0
  }
95
47
  *entry_identifier = (libfmapi_entry_identifier_t *) internal_entry_identifier;
96
97
47
  return( 1 );
98
99
0
on_error:
100
0
  if( internal_entry_identifier != NULL )
101
0
  {
102
0
    memory_free(
103
0
     internal_entry_identifier );
104
0
  }
105
0
  return( -1 );
106
47
}
107
108
/* Frees an entry identifier
109
 * Returns 1 if successful or -1 on error
110
 */
111
int libfmapi_entry_identifier_free(
112
     libfmapi_entry_identifier_t **entry_identifier,
113
     libcerror_error_t **error )
114
47
{
115
47
  libfmapi_internal_entry_identifier_t *internal_entry_identifier = NULL;
116
47
  static char *function                                           = "libfmapi_entry_identifier_free";
117
118
47
  if( entry_identifier == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
124
0
     "%s: invalid entry identifier.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
47
  if( *entry_identifier != NULL )
130
47
  {
131
47
    internal_entry_identifier = (libfmapi_internal_entry_identifier_t *) *entry_identifier;
132
47
    *entry_identifier         = NULL;
133
134
47
    memory_free(
135
47
     internal_entry_identifier );
136
47
  }
137
47
  return( 1 );
138
47
}
139
140
/* Converts a byte stream into an entry identifier
141
 * Returns 1 if successful or -1 on error
142
 */
143
int libfmapi_entry_identifier_copy_from_byte_stream(
144
     libfmapi_entry_identifier_t *entry_identifier,
145
     const uint8_t *byte_stream,
146
     size_t byte_stream_size,
147
     libcerror_error_t **error )
148
47
{
149
47
  libfmapi_internal_entry_identifier_t *internal_entry_identifier = NULL;
150
47
  static char *function                                           = "libfmapi_entry_identifier_copy_from_byte_stream";
151
152
#if defined( HAVE_DEBUG_OUTPUT )
153
  system_character_t guid_string[ 48 ];
154
155
  libfguid_identifier_t *guid                                     = NULL;
156
  int result                                                      = 0;
157
#endif
158
159
47
  if( entry_identifier == NULL )
160
0
  {
161
0
    libcerror_error_set(
162
0
     error,
163
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
164
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
165
0
     "%s: invalid entry identifier.",
166
0
     function );
167
168
0
    return( -1 );
169
0
  }
170
47
  internal_entry_identifier = (libfmapi_internal_entry_identifier_t *) entry_identifier;
171
172
47
  if( byte_stream == NULL )
173
0
  {
174
0
    libcerror_error_set(
175
0
     error,
176
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
177
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
178
0
     "%s: invalid byte stream.",
179
0
     function );
180
181
0
    return( -1 );
182
0
  }
183
47
  if( ( byte_stream_size < 20 )
184
47
   || ( byte_stream_size > (size_t) SSIZE_MAX ) )
185
8
  {
186
8
    libcerror_error_set(
187
8
     error,
188
8
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
189
8
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
190
8
     "%s: invalid byte stream size value out of bounds.",
191
8
     function );
192
193
8
    return( -1 );
194
8
  }
195
#if defined( HAVE_DEBUG_OUTPUT )
196
  if( libcnotify_verbose != 0 )
197
  {
198
    libcnotify_printf(
199
     "%s: entry identifier data:\n",
200
     function );
201
    libcnotify_print_data(
202
     byte_stream,
203
     20,
204
     0 );
205
  }
206
#endif
207
39
  if( memory_copy(
208
39
       internal_entry_identifier->flags,
209
39
       &( byte_stream[ 0 ] ),
210
39
       4 ) == NULL )
211
0
  {
212
0
    libcerror_error_set(
213
0
     error,
214
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
215
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
216
0
     "%s: unable to copy flags.",
217
0
     function );
218
219
0
    goto on_error;
220
0
  }
221
39
  if( memory_copy(
222
39
       internal_entry_identifier->service_provider_identifier,
223
39
       &( byte_stream[ 4 ] ),
224
39
       16 ) == NULL )
225
0
  {
226
0
    libcerror_error_set(
227
0
     error,
228
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
229
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
230
0
     "%s: unable to copy service provider identifier.",
231
0
     function );
232
233
0
    goto on_error;
234
0
  }
235
#if defined( HAVE_DEBUG_OUTPUT )
236
  if( libcnotify_verbose != 0 )
237
  {
238
    if( libfguid_identifier_initialize(
239
         &guid,
240
         error ) != 1 )
241
    {
242
      libcerror_error_set(
243
       error,
244
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
245
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
246
       "%s: unable to create service provider identifier.",
247
       function );
248
249
      goto on_error;
250
    }
251
    libcnotify_printf(
252
     "%s: flags\t\t\t\t: 0x%02" PRIx8 ", 0x%02" PRIx8 ", 0x%02" PRIx8 ", 0x%02" PRIx8 "\n",
253
     function,
254
     internal_entry_identifier->flags[ 0 ],
255
     internal_entry_identifier->flags[ 1 ],
256
     internal_entry_identifier->flags[ 2 ],
257
     internal_entry_identifier->flags[ 3 ] );
258
259
    if( libfguid_identifier_copy_from_byte_stream(
260
         guid,
261
         internal_entry_identifier->service_provider_identifier,
262
         16,
263
         LIBFGUID_ENDIAN_LITTLE,
264
         error ) != 1 )
265
    {
266
      libcerror_error_set(
267
       error,
268
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
269
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
270
       "%s: unable to copy service provider identifier from byte stream.",
271
       function );
272
273
      goto on_error;
274
    }
275
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
276
    result = libfguid_identifier_copy_to_utf16_string(
277
        guid,
278
        (uint16_t *) guid_string,
279
        48,
280
        LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
281
        error );
282
#else
283
    result = libfguid_identifier_copy_to_utf8_string(
284
        guid,
285
        (uint8_t *) guid_string,
286
        48,
287
        LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
288
        error );
289
#endif
290
    if( result != 1 )
291
    {
292
      libcerror_error_set(
293
       error,
294
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
295
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
296
       "%s: unable to copy GUID to string.",
297
       function );
298
299
      goto on_error;
300
    }
301
    libcnotify_printf(
302
     "%s: service provider identifier\t: %" PRIs_SYSTEM " (%s)\n",
303
     function,
304
     guid_string,
305
     libfmapi_service_provider_identifier_get_name(
306
      internal_entry_identifier->service_provider_identifier ) );
307
  
308
    if( libfguid_identifier_free(
309
         &guid,
310
         error ) != 1 )
311
    {
312
      libcerror_error_set(
313
       error,
314
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
315
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
316
       "%s: unable to free service provider identifier.",
317
       function );
318
319
      goto on_error;
320
    }
321
    libcnotify_printf(
322
     "\n" );
323
  }
324
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
325
326
39
  return( 1 );
327
328
0
on_error:
329
#if defined( HAVE_DEBUG_OUTPUT )
330
  if( guid != NULL )
331
  {
332
    libfguid_identifier_free(
333
     &guid,
334
     NULL );
335
  }
336
#endif
337
0
  return( -1 );
338
39
}
339
340
/* Retrieves the service provider identifier
341
 * Returns 1 if successful or -1 on error
342
 */
343
int libfmapi_entry_identifier_get_service_provider_identifier(
344
     libfmapi_entry_identifier_t *entry_identifier,
345
     uint8_t *guid_data,
346
     size_t guid_data_size,
347
     libcerror_error_t **error )
348
0
{
349
0
  libfmapi_internal_entry_identifier_t *internal_entry_identifier = NULL;
350
0
  static char *function                                           = "libfmapi_entry_identifier_get_service_provider_identifier";
351
352
0
  if( entry_identifier == NULL )
353
0
  {
354
0
    libcerror_error_set(
355
0
     error,
356
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
357
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
358
0
     "%s: invalid entry identifier.",
359
0
     function );
360
361
0
    return( -1 );
362
0
  }
363
0
  internal_entry_identifier = (libfmapi_internal_entry_identifier_t *) entry_identifier;
364
365
0
  if( guid_data == NULL )
366
0
  {
367
0
    libcerror_error_set(
368
0
     error,
369
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
370
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
371
0
     "%s: invalid GUID data.",
372
0
     function );
373
374
0
    return( -1 );
375
0
  }
376
0
  if( guid_data_size > (size_t) SSIZE_MAX )
377
0
  {
378
0
    libcerror_error_set(
379
0
     error,
380
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
381
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
382
0
     "%s: GUID data size value exceeds maximum.",
383
0
     function );
384
385
0
    return( -1 );
386
0
  }
387
0
  if( guid_data_size < 16 )
388
0
  {
389
0
    libcerror_error_set(
390
0
     error,
391
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
392
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
393
0
     "%s: GUID data size value too small.",
394
0
     function );
395
396
0
    return( -1 );
397
0
  }
398
0
  if( memory_copy(
399
0
       guid_data,
400
0
       internal_entry_identifier->service_provider_identifier,
401
0
       16 ) == NULL )
402
0
  {
403
0
    libcerror_error_set(
404
0
     error,
405
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
406
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
407
0
     "%s: unable to copy service provider identifier.",
408
0
     function );
409
410
0
    return( -1 );
411
0
  }
412
0
  return( 1 );
413
0
}
414