4 * Copyright (C) 1999 Juergen Schmied
5 * Copyright (C) 2000 Alexandre Julliard
8 * HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE
9 * HKEY_USERS \\REGISTRY\\USER
10 * HKEY_CURRENT_CONFIG \\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT
11 * HKEY_CLASSES \\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES
15 #include "debugtools.h"
18 #include "wine/unicode.h"
21 #include "ntdll_misc.h"
23 DEFAULT_DEBUG_CHANNEL(reg
);
25 static const WCHAR root_name
[] = { '\\','R','e','g','i','s','t','r','y','\\',0 };
26 static const UNICODE_STRING root_path
=
28 sizeof(root_name
)-sizeof(WCHAR
), /* Length */
29 sizeof(root_name
), /* MaximumLength */
30 (LPWSTR
)root_name
/* Buffer */
33 /* maximum length of a key/value name in bytes (without terminating null) */
34 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
37 /* copy a key name into the request buffer */
38 static inline NTSTATUS
copy_nameU( LPWSTR Dest
, const UNICODE_STRING
*name
, UINT max
)
40 if (name
->Length
>= max
) return STATUS_BUFFER_OVERFLOW
;
41 if (name
->Length
) memcpy( Dest
, name
->Buffer
, name
->Length
);
42 Dest
[name
->Length
/ sizeof(WCHAR
)] = 0;
43 return STATUS_SUCCESS
;
47 /******************************************************************************
51 NTSTATUS WINAPI
NtCreateKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
52 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
56 DWORD len
= attr
->ObjectName
->Length
;
58 TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
59 debugstr_us(class), options
, access
, retkey
);
61 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
62 len
+= sizeof(WCHAR
); /* for storing name length */
66 if (len
> REQUEST_MAX_VAR_SIZE
) return STATUS_BUFFER_OVERFLOW
;
68 if (!retkey
) return STATUS_INVALID_PARAMETER
;
72 struct create_key_request
*req
= server_alloc_req( sizeof(*req
), len
);
73 WCHAR
*data
= server_data_ptr(req
);
75 req
->parent
= attr
->RootDirectory
;
77 req
->options
= options
;
80 *data
++ = attr
->ObjectName
->Length
;
81 memcpy( data
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
82 if (class) memcpy( (char *)data
+ attr
->ObjectName
->Length
, class->Buffer
, class->Length
);
83 if (!(ret
= server_call_noerr( REQ_CREATE_KEY
)))
86 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
94 /******************************************************************************
95 * NtOpenKey [NTDLL.129]
97 * OUT PHANDLE retkey (returns 0 when failure)
98 * IN ACCESS_MASK access
99 * IN POBJECT_ATTRIBUTES attr
101 NTSTATUS WINAPI
NtOpenKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
104 DWORD len
= attr
->ObjectName
->Length
;
106 TRACE( "(0x%x,%s,%lx,%p)\n", attr
->RootDirectory
,
107 debugstr_us(attr
->ObjectName
), access
, retkey
);
109 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
110 if (!retkey
) return STATUS_INVALID_PARAMETER
;
114 struct open_key_request
*req
= server_alloc_req( sizeof(*req
), len
);
115 req
->parent
= attr
->RootDirectory
;
116 req
->access
= access
;
117 memcpy( server_data_ptr(req
), attr
->ObjectName
->Buffer
, len
);
118 ret
= server_call_noerr( REQ_OPEN_KEY
);
126 /******************************************************************************
127 * NtDeleteKey [NTDLL]
130 NTSTATUS WINAPI
NtDeleteKey( HANDLE hkey
)
134 TRACE( "(%x)\n", hkey
);
138 struct delete_key_request
*req
= server_alloc_req( sizeof(*req
), 0 );
140 ret
= server_call_noerr( REQ_DELETE_KEY
);
147 /******************************************************************************
148 * NtDeleteValueKey [NTDLL]
151 NTSTATUS WINAPI
NtDeleteValueKey( HANDLE hkey
, const UNICODE_STRING
*name
)
155 TRACE( "(0x%x,%s)\n", hkey
, debugstr_us(name
) );
156 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
160 struct delete_key_value_request
*req
= server_alloc_req( sizeof(*req
), name
->Length
);
163 memcpy( server_data_ptr(req
), name
->Buffer
, name
->Length
);
164 ret
= server_call_noerr( REQ_DELETE_KEY_VALUE
);
171 /******************************************************************************
174 * Helper function for NtQueryKey and NtEnumerateKey
176 static NTSTATUS
fill_key_info( KEY_INFORMATION_CLASS info_class
, void *info
, DWORD length
,
177 DWORD
*result_len
, const struct enum_key_request
*req
)
179 WCHAR
*name_ptr
= server_data_ptr(req
);
180 int name_size
= *name_ptr
++;
181 WCHAR
*class_ptr
= (WCHAR
*)((char *)name_ptr
+ name_size
);
182 int class_size
= server_data_size(req
) - sizeof(WCHAR
) - name_size
;
186 RtlSecondsSince1970ToTime( req
->modif
, &modif
);
190 case KeyBasicInformation
:
192 KEY_BASIC_INFORMATION keyinfo
;
193 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
);
194 keyinfo
.LastWriteTime
= modif
;
195 keyinfo
.TitleIndex
= 0;
196 keyinfo
.NameLength
= name_size
;
197 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
201 case KeyFullInformation
:
203 KEY_FULL_INFORMATION keyinfo
;
204 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Class
);
205 keyinfo
.LastWriteTime
= modif
;
206 keyinfo
.TitleIndex
= 0;
207 keyinfo
.ClassLength
= class_size
;
208 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
: -1;
209 keyinfo
.SubKeys
= req
->subkeys
;
210 keyinfo
.MaxNameLen
= req
->max_subkey
;
211 keyinfo
.MaxClassLen
= req
->max_class
;
212 keyinfo
.Values
= req
->values
;
213 keyinfo
.MaxValueNameLen
= req
->max_value
;
214 keyinfo
.MaxValueDataLen
= req
->max_data
;
215 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
219 case KeyNodeInformation
:
221 KEY_NODE_INFORMATION keyinfo
;
222 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
);
223 keyinfo
.LastWriteTime
= modif
;
224 keyinfo
.TitleIndex
= 0;
225 keyinfo
.ClassLength
= class_size
;
226 keyinfo
.ClassOffset
= fixed_size
+ name_size
;
227 if (!keyinfo
.ClassLength
|| keyinfo
.ClassOffset
> length
) keyinfo
.ClassOffset
= -1;
228 keyinfo
.NameLength
= name_size
;
229 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
233 FIXME("Information class not implemented\n");
234 return STATUS_INVALID_PARAMETER
;
237 *result_len
= fixed_size
+ name_size
+ class_size
;
238 if (length
<= fixed_size
) return STATUS_BUFFER_OVERFLOW
;
239 length
-= fixed_size
;
244 memcpy( (char *)info
+ fixed_size
, name_ptr
, min(length
,name_size
) );
245 if (length
< name_size
) return STATUS_BUFFER_OVERFLOW
;
252 memcpy( (char *)info
+ fixed_size
+ name_size
, class_ptr
, min(length
,class_size
) );
253 if (length
< class_size
) return STATUS_BUFFER_OVERFLOW
;
255 return STATUS_SUCCESS
;
260 /******************************************************************************
261 * NtEnumerateKey [NTDLL]
265 * the name copied into the buffer is NOT 0-terminated
267 NTSTATUS WINAPI
NtEnumerateKey( HANDLE handle
, ULONG index
, KEY_INFORMATION_CLASS info_class
,
268 void *info
, DWORD length
, DWORD
*result_len
)
272 /* -1 means query key, so avoid it here */
273 if (index
== (ULONG
)-1) return STATUS_NO_MORE_ENTRIES
;
277 struct enum_key_request
*req
= server_alloc_req( sizeof(*req
), REQUEST_MAX_VAR_SIZE
);
280 req
->full
= (info_class
== KeyFullInformation
);
281 if (!(ret
= server_call_noerr( REQ_ENUM_KEY
)))
283 ret
= fill_key_info( info_class
, info
, length
, result_len
, req
);
291 /******************************************************************************
295 NTSTATUS WINAPI
NtQueryKey( HANDLE handle
, KEY_INFORMATION_CLASS info_class
,
296 void *info
, DWORD length
, DWORD
*result_len
)
302 struct enum_key_request
*req
= server_alloc_req( sizeof(*req
), REQUEST_MAX_VAR_SIZE
);
305 req
->full
= (info_class
== KeyFullInformation
);
306 if (!(ret
= server_call_noerr( REQ_ENUM_KEY
)))
308 ret
= fill_key_info( info_class
, info
, length
, result_len
, req
);
316 /* fill the key value info structure for a specific info class */
317 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class
, void *info
,
318 DWORD length
, int type
, int name_len
, int data_len
)
322 case KeyValueBasicInformation
:
324 KEY_VALUE_BASIC_INFORMATION keyinfo
;
325 keyinfo
.TitleIndex
= 0;
327 keyinfo
.NameLength
= name_len
;
328 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Name
) );
329 memcpy( info
, &keyinfo
, length
);
332 case KeyValueFullInformation
:
334 KEY_VALUE_FULL_INFORMATION keyinfo
;
335 keyinfo
.TitleIndex
= 0;
337 keyinfo
.DataOffset
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
) + name_len
;
338 keyinfo
.DataLength
= data_len
;
339 keyinfo
.NameLength
= name_len
;
340 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Name
) );
341 memcpy( info
, &keyinfo
, length
);
344 case KeyValuePartialInformation
:
346 KEY_VALUE_PARTIAL_INFORMATION keyinfo
;
347 keyinfo
.TitleIndex
= 0;
349 keyinfo
.DataLength
= data_len
;
350 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Data
) );
351 memcpy( info
, &keyinfo
, length
);
360 /******************************************************************************
361 * NtEnumerateValueKey [NTDLL]
362 * ZwEnumerateValueKey
364 NTSTATUS WINAPI
NtEnumerateValueKey( HANDLE handle
, ULONG index
,
365 KEY_VALUE_INFORMATION_CLASS info_class
,
366 void *info
, DWORD length
, DWORD
*result_len
)
369 char *data_ptr
, *name_ptr
;
370 int fixed_size
= 0, name_len
= 0, data_len
= 0, offset
= 0, type
= 0, total_len
= 0;
372 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle
, index
, info_class
, info
, length
);
374 /* compute the length we want to retrieve */
377 case KeyValueBasicInformation
:
378 fixed_size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) - sizeof(WCHAR
);
379 name_ptr
= (char *)info
+ fixed_size
;
382 case KeyValueFullInformation
:
383 fixed_size
= sizeof(KEY_VALUE_FULL_INFORMATION
) - sizeof(WCHAR
);
384 name_ptr
= data_ptr
= (char *)info
+ fixed_size
;
386 case KeyValuePartialInformation
:
387 fixed_size
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) - sizeof(UCHAR
);
389 data_ptr
= (char *)info
+ fixed_size
;
392 FIXME( "Information class %d not implemented\n", info_class
);
393 return STATUS_INVALID_PARAMETER
;
395 if (length
> fixed_size
) data_len
= length
- fixed_size
;
399 size_t reqlen
= data_len
+ sizeof(WCHAR
);
400 if (name_ptr
&& !offset
) reqlen
+= MAX_PATH
*sizeof(WCHAR
);
401 reqlen
= min( reqlen
, REQUEST_MAX_VAR_SIZE
);
405 struct enum_key_value_request
*req
= server_alloc_req( sizeof(*req
), reqlen
);
409 req
->offset
= offset
;
411 if (!(ret
= server_call_noerr( REQ_ENUM_KEY_VALUE
)))
413 size_t size
= server_data_size(req
) - sizeof(WCHAR
);
414 WCHAR
*name
= server_data_ptr(req
);
415 if (!offset
) /* name is only present on the first request */
421 if (name_len
> data_len
) /* overflow */
423 memcpy( name_ptr
, name
, data_len
);
425 ret
= STATUS_BUFFER_OVERFLOW
;
429 memcpy( name_ptr
, name
, name_len
);
430 data_len
-= name_len
;
431 if (data_ptr
) data_ptr
+= name_len
;
434 name
+= name_len
/ sizeof(WCHAR
);
436 else name
++; /* skip 0 length */
440 size
= min( size
, data_len
);
441 memcpy( data_ptr
+ offset
, name
, size
);
446 total_len
= req
->len
;
451 } while (data_len
&& data_ptr
&& offset
< total_len
);
453 *result_len
= total_len
+ fixed_size
+ (name_ptr
? name_len
: 0);
455 if (data_ptr
&& offset
< total_len
) ret
= STATUS_BUFFER_OVERFLOW
;
456 if (length
< fixed_size
) ret
= STATUS_BUFFER_OVERFLOW
;
458 copy_key_value_info( info_class
, info
, length
, type
, name_len
, total_len
);
464 /******************************************************************************
465 * NtQueryValueKey [NTDLL]
469 * the name in the KeyValueInformation is never set
471 NTSTATUS WINAPI
NtQueryValueKey( HANDLE handle
, const UNICODE_STRING
*name
,
472 KEY_VALUE_INFORMATION_CLASS info_class
,
473 void *info
, DWORD length
, DWORD
*result_len
)
477 int fixed_size
= 0, data_len
= 0, offset
= 0, type
= 0, total_len
= 0;
479 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle
, debugstr_us(name
), info_class
, info
, length
);
481 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
483 /* compute the length we want to retrieve */
486 case KeyValueBasicInformation
:
487 fixed_size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) - sizeof(WCHAR
);
490 case KeyValueFullInformation
:
491 fixed_size
= sizeof(KEY_VALUE_FULL_INFORMATION
) - sizeof(WCHAR
);
492 data_ptr
= (char *)info
+ fixed_size
;
494 case KeyValuePartialInformation
:
495 fixed_size
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) - sizeof(UCHAR
);
496 data_ptr
= (char *)info
+ fixed_size
;
499 FIXME( "Information class %d not implemented\n", info_class
);
500 return STATUS_INVALID_PARAMETER
;
502 if (data_ptr
&& length
> fixed_size
) data_len
= length
- fixed_size
;
506 size_t reqlen
= min( data_len
, REQUEST_MAX_VAR_SIZE
);
507 reqlen
= max( reqlen
, name
->Length
+ sizeof(WCHAR
) );
511 struct get_key_value_request
*req
= server_alloc_req( sizeof(*req
), reqlen
);
512 WCHAR
*nameptr
= server_data_ptr(req
);
515 req
->offset
= offset
;
516 *nameptr
++ = name
->Length
;
517 memcpy( nameptr
, name
->Buffer
, name
->Length
);
519 if (!(ret
= server_call_noerr( REQ_GET_KEY_VALUE
)))
521 size_t size
= min( server_data_size(req
), data_len
);
523 total_len
= req
->len
;
526 memcpy( data_ptr
+ offset
, server_data_ptr(req
), size
);
534 } while (data_len
&& offset
< total_len
);
536 *result_len
= total_len
+ fixed_size
;
538 if (offset
< total_len
) ret
= STATUS_BUFFER_OVERFLOW
;
539 if (length
< fixed_size
) ret
= STATUS_BUFFER_OVERFLOW
;
541 copy_key_value_info( info_class
, info
, length
, type
, 0, total_len
);
546 /******************************************************************************
550 NTSTATUS WINAPI
NtFlushKey(HANDLE KeyHandle
)
552 FIXME("(0x%08x) stub!\n",
557 /******************************************************************************
561 NTSTATUS WINAPI
NtLoadKey( const OBJECT_ATTRIBUTES
*attr
, const OBJECT_ATTRIBUTES
*file
)
564 dump_ObjectAttributes(attr
);
565 dump_ObjectAttributes(file
);
566 return STATUS_SUCCESS
;
569 /******************************************************************************
570 * NtNotifyChangeKey [NTDLL]
573 NTSTATUS WINAPI
NtNotifyChangeKey(
576 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
577 IN PVOID ApcContext OPTIONAL
,
578 OUT PIO_STATUS_BLOCK IoStatusBlock
,
579 IN ULONG CompletionFilter
,
580 IN BOOLEAN Asynchroneous
,
581 OUT PVOID ChangeBuffer
,
583 IN BOOLEAN WatchSubtree
)
585 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
586 KeyHandle
, Event
, ApcRoutine
, ApcContext
, IoStatusBlock
, CompletionFilter
,
587 Asynchroneous
, ChangeBuffer
, Length
, WatchSubtree
);
588 return STATUS_SUCCESS
;
591 /******************************************************************************
592 * NtQueryMultipleValueKey [NTDLL]
593 * ZwQueryMultipleValueKey
596 NTSTATUS WINAPI
NtQueryMultipleValueKey(
598 PVALENTW ListOfValuesToQuery
,
600 PVOID MultipleValueInformation
,
604 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
605 KeyHandle
, ListOfValuesToQuery
, NumberOfItems
, MultipleValueInformation
,
606 Length
,ReturnLength
);
607 return STATUS_SUCCESS
;
610 /******************************************************************************
611 * NtReplaceKey [NTDLL]
614 NTSTATUS WINAPI
NtReplaceKey(
615 IN POBJECT_ATTRIBUTES ObjectAttributes
,
617 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
619 FIXME("(0x%08x),stub!\n", Key
);
620 dump_ObjectAttributes(ObjectAttributes
);
621 dump_ObjectAttributes(ReplacedObjectAttributes
);
622 return STATUS_SUCCESS
;
624 /******************************************************************************
625 * NtRestoreKey [NTDLL]
628 NTSTATUS WINAPI
NtRestoreKey(
633 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
634 KeyHandle
, FileHandle
, RestoreFlags
);
635 return STATUS_SUCCESS
;
637 /******************************************************************************
641 NTSTATUS WINAPI
NtSaveKey(
643 IN HANDLE FileHandle
)
645 FIXME("(0x%08x,0x%08x) stub\n",
646 KeyHandle
, FileHandle
);
647 return STATUS_SUCCESS
;
649 /******************************************************************************
650 * NtSetInformationKey [NTDLL]
651 * ZwSetInformationKey
653 NTSTATUS WINAPI
NtSetInformationKey(
655 IN
const int KeyInformationClass
,
656 IN PVOID KeyInformation
,
657 IN ULONG KeyInformationLength
)
659 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
660 KeyHandle
, KeyInformationClass
, KeyInformation
, KeyInformationLength
);
661 return STATUS_SUCCESS
;
665 /******************************************************************************
666 * NtSetValueKey [NTDLL]
670 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
671 * NT does definitely care (aj)
673 NTSTATUS WINAPI
NtSetValueKey( HANDLE hkey
, const UNICODE_STRING
*name
, ULONG TitleIndex
,
674 ULONG type
, const void *data
, ULONG count
)
679 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey
, debugstr_us(name
), type
, data
, count
);
681 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
683 namelen
= name
->Length
+ sizeof(WCHAR
); /* for storing length */
688 ULONG len
= count
- pos
;
689 if (len
> REQUEST_MAX_VAR_SIZE
- namelen
) len
= REQUEST_MAX_VAR_SIZE
- namelen
;
693 struct set_key_value_request
*req
= server_alloc_req( sizeof(*req
), namelen
+ len
);
694 WCHAR
*name_ptr
= server_data_ptr(req
);
700 *name_ptr
++ = name
->Length
;
701 memcpy( name_ptr
, name
->Buffer
, name
->Length
);
702 memcpy( (char *)name_ptr
+ name
->Length
, (char *)data
+ pos
, len
);
704 ret
= server_call_noerr( REQ_SET_KEY_VALUE
);
707 } while (!ret
&& pos
< count
);
711 /******************************************************************************
712 * NtUnloadKey [NTDLL]
715 NTSTATUS WINAPI
NtUnloadKey(
718 FIXME("(0x%08x) stub\n",
720 return STATUS_SUCCESS
;
723 /******************************************************************************
724 * RtlFormatCurrentUserKeyPath [NTDLL.371]
726 NTSTATUS WINAPI
RtlFormatCurrentUserKeyPath(
727 IN OUT PUNICODE_STRING KeyPath
)
729 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
730 LPSTR Path
= "\\REGISTRY\\USER\\.DEFAULT";
731 ANSI_STRING AnsiPath
;
733 FIXME("(%p) stub\n",KeyPath
);
734 RtlInitAnsiString(&AnsiPath
, Path
);
735 return RtlAnsiStringToUnicodeString(KeyPath
, &AnsiPath
, TRUE
);
738 /******************************************************************************
739 * RtlOpenCurrentUser [NTDLL]
741 * if we return just HKEY_CURRENT_USER the advapi try's to find a remote
742 * registry (odd handle) and fails
745 DWORD WINAPI
RtlOpenCurrentUser(
746 IN ACCESS_MASK DesiredAccess
, /* [in] */
747 OUT PHANDLE KeyHandle
) /* [out] handle of HKEY_CURRENT_USER */
749 OBJECT_ATTRIBUTES ObjectAttributes
;
750 UNICODE_STRING ObjectName
;
753 TRACE("(0x%08lx, %p) stub\n",DesiredAccess
, KeyHandle
);
755 RtlFormatCurrentUserKeyPath(&ObjectName
);
756 InitializeObjectAttributes(&ObjectAttributes
,&ObjectName
,OBJ_CASE_INSENSITIVE
,0, NULL
);
757 ret
= NtOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
758 RtlFreeUnicodeString(&ObjectName
);