Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
454355ec
Commit
454355ec
authored
Oct 02, 2000
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert NtQueryKey and NtEnumerateKey to the new request mechanism.
Fixed a few bugs.
parent
1871e660
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
631 additions
and
477 deletions
+631
-477
registry.c
dlls/advapi32/registry.c
+197
-92
reg.c
dlls/ntdll/reg.c
+126
-151
ntddk.h
include/ntddk.h
+1
-7
server.h
include/server.h
+7
-19
registry.c
memory/registry.c
+197
-92
registry.c
server/registry.c
+94
-88
request.h
server/request.h
+0
-2
trace.c
server/trace.c
+9
-26
No files found.
dlls/advapi32/registry.c
View file @
454355ec
...
...
@@ -289,32 +289,58 @@ DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
DWORD
WINAPI
RegEnumKeyExW
(
HKEY
hkey
,
DWORD
index
,
LPWSTR
name
,
LPDWORD
name_len
,
LPDWORD
reserved
,
LPWSTR
class
,
LPDWORD
class_len
,
FILETIME
*
ft
)
{
DWORD
ret
,
len
,
cls_len
;
struct
enum_key_request
*
req
=
get_req_buffer
();
NTSTATUS
status
;
char
buffer
[
256
],
*
buf_ptr
=
buffer
;
KEY_NODE_INFORMATION
*
info
=
(
KEY_NODE_INFORMATION
*
)
buffer
;
DWORD
total_size
;
TRACE
(
"(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)
\n
"
,
hkey
,
index
,
name
,
name_len
,
name_len
?
*
name_len
:
-
1
,
reserved
,
class
,
class_len
,
ft
);
if
(
reserved
)
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
req
->
index
=
index
;
if
((
ret
=
reg_server_call
(
REQ_ENUM_KEY
))
!=
ERROR_SUCCESS
)
return
ret
;
status
=
NtEnumerateKey
(
hkey
,
index
,
KeyNodeInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
len
=
strlenW
(
req
->
name
)
+
1
;
cls_len
=
strlenW
(
req
->
class
)
+
1
;
if
(
len
>
*
name_len
)
return
ERROR_MORE_DATA
;
if
(
class_len
&&
(
cls_len
>
*
class_len
))
return
ERROR_MORE_DATA
;
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
/* retry with a dynamically allocated buffer */
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
info
=
(
KEY_NODE_INFORMATION
*
)
buf_ptr
;
status
=
NtEnumerateKey
(
hkey
,
index
,
KeyNodeInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
memcpy
(
name
,
req
->
name
,
len
*
sizeof
(
WCHAR
)
);
*
name_len
=
len
-
1
;
if
(
class_len
)
if
(
!
status
)
{
if
(
class
)
memcpy
(
class
,
req
->
class
,
cls_len
*
sizeof
(
WCHAR
)
);
*
class_len
=
cls_len
-
1
;
DWORD
len
=
info
->
NameLength
/
sizeof
(
WCHAR
);
DWORD
cls_len
=
info
->
ClassLength
/
sizeof
(
WCHAR
);
if
(
ft
)
*
ft
=
info
->
LastWriteTime
;
if
(
len
>=
*
name_len
||
(
class_len
&&
(
cls_len
>=
*
class_len
)))
status
=
STATUS_BUFFER_OVERFLOW
;
else
{
*
name_len
=
len
;
memcpy
(
name
,
info
->
Name
,
info
->
NameLength
);
name
[
len
]
=
0
;
if
(
class_len
)
{
*
class_len
=
cls_len
;
if
(
class
)
{
memcpy
(
class
,
buf_ptr
+
info
->
ClassOffset
,
info
->
ClassLength
);
class
[
cls_len
]
=
0
;
}
}
}
}
if
(
ft
)
RtlSecondsSince1970ToTime
(
req
->
modif
,
ft
);
return
ERROR_SUCCESS
;
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -324,32 +350,64 @@ DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_le
DWORD
WINAPI
RegEnumKeyExA
(
HKEY
hkey
,
DWORD
index
,
LPSTR
name
,
LPDWORD
name_len
,
LPDWORD
reserved
,
LPSTR
class
,
LPDWORD
class_len
,
FILETIME
*
ft
)
{
DWORD
ret
,
len
,
cls_len
;
struct
enum_key_request
*
req
=
get_req_buffer
();
NTSTATUS
status
;
char
buffer
[
256
],
*
buf_ptr
=
buffer
;
KEY_NODE_INFORMATION
*
info
=
(
KEY_NODE_INFORMATION
*
)
buffer
;
DWORD
total_size
;
TRACE
(
"(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)
\n
"
,
hkey
,
index
,
name
,
name_len
,
name_len
?
*
name_len
:
-
1
,
reserved
,
class
,
class_len
,
ft
);
if
(
reserved
)
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
req
->
index
=
index
;
if
((
ret
=
reg_server_call
(
REQ_ENUM_KEY
))
!=
ERROR_SUCCESS
)
return
ret
;
status
=
NtEnumerateKey
(
hkey
,
index
,
KeyNodeInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
len
=
strlenW
(
req
->
name
)
+
1
;
cls_len
=
strlenW
(
req
->
class
)
+
1
;
if
(
len
>
*
name_len
)
return
ERROR_MORE_DATA
;
if
(
class_len
&&
(
cls_len
>
*
class_len
))
return
ERROR_MORE_DATA
;
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
/* retry with a dynamically allocated buffer */
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
info
=
(
KEY_NODE_INFORMATION
*
)
buf_ptr
;
status
=
NtEnumerateKey
(
hkey
,
index
,
KeyNodeInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
memcpyWtoA
(
name
,
req
->
name
,
len
);
*
name_len
=
len
-
1
;
if
(
class_len
)
if
(
!
status
)
{
if
(
class
)
memcpyWtoA
(
class
,
req
->
class
,
cls_len
);
*
class_len
=
cls_len
-
1
;
DWORD
len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
info
->
Name
,
info
->
NameLength
/
sizeof
(
WCHAR
),
NULL
,
0
,
NULL
,
NULL
);
DWORD
cls_len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
(
WCHAR
*
)(
buf_ptr
+
info
->
ClassOffset
),
info
->
ClassLength
/
sizeof
(
WCHAR
),
NULL
,
0
,
NULL
,
NULL
);
if
(
ft
)
*
ft
=
info
->
LastWriteTime
;
if
(
len
>=
*
name_len
||
(
class_len
&&
(
cls_len
>=
*
class_len
)))
status
=
STATUS_BUFFER_OVERFLOW
;
else
{
*
name_len
=
len
;
WideCharToMultiByte
(
CP_ACP
,
0
,
info
->
Name
,
info
->
NameLength
/
sizeof
(
WCHAR
),
name
,
len
,
NULL
,
NULL
);
name
[
len
]
=
0
;
if
(
class_len
)
{
*
class_len
=
cls_len
;
if
(
class
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
(
WCHAR
*
)(
buf_ptr
+
info
->
ClassOffset
),
info
->
ClassLength
/
sizeof
(
WCHAR
),
class
,
cls_len
,
NULL
,
NULL
);
class
[
cls_len
]
=
0
;
}
}
}
}
if
(
ft
)
RtlSecondsSince1970ToTime
(
req
->
modif
,
ft
);
return
ERROR_SUCCESS
;
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -398,9 +456,10 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
LPDWORD
values
,
LPDWORD
max_value
,
LPDWORD
max_data
,
LPDWORD
security
,
FILETIME
*
modif
)
{
DWORD
ret
;
struct
query_key_info_request
*
req
=
get_req_buffer
();
NTSTATUS
status
;
char
buffer
[
256
],
*
buf_ptr
=
buffer
;
KEY_FULL_INFORMATION
*
info
=
(
KEY_FULL_INFORMATION
*
)
buffer
;
DWORD
total_size
;
TRACE
(
"(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
class
,
class_len
?
*
class_len
:
0
,
reserved
,
subkeys
,
max_subkey
,
values
,
max_value
,
max_data
,
security
,
modif
);
...
...
@@ -408,27 +467,48 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
if
(
class
&&
!
class_len
&&
!
(
GetVersion
()
&
0x80000000
/*NT*/
))
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
if
((
ret
=
reg_server_call
(
REQ_QUERY_KEY_INFO
))
!=
ERROR_SUCCESS
)
return
ret
;
status
=
NtQueryKey
(
hkey
,
KeyFullInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
if
(
class
)
{
if
(
class_len
&&
(
strlenW
(
req
->
class
)
+
1
>
*
class_len
))
/* retry with a dynamically allocated buffer */
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
*
class_len
=
strlenW
(
req
->
class
);
return
ERROR_MORE_DATA
;
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
info
=
(
KEY_FULL_INFORMATION
*
)
buf_ptr
;
status
=
NtQueryKey
(
hkey
,
KeyFullInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
if
(
!
status
)
{
if
(
class_len
&&
(
info
->
ClassLength
/
sizeof
(
WCHAR
)
+
1
>
*
class_len
))
{
status
=
STATUS_BUFFER_OVERFLOW
;
}
else
{
memcpy
(
class
,
buf_ptr
+
info
->
ClassOffset
,
info
->
ClassLength
);
class
[
info
->
ClassLength
/
sizeof
(
WCHAR
)]
=
0
;
}
}
strcpyW
(
class
,
req
->
class
);
}
if
(
class_len
)
*
class_len
=
strlenW
(
req
->
class
);
if
(
subkeys
)
*
subkeys
=
req
->
subkeys
;
if
(
max_subkey
)
*
max_subkey
=
req
->
max_subkey
;
if
(
max_class
)
*
max_class
=
req
->
max_class
;
if
(
values
)
*
values
=
req
->
values
;
if
(
max_value
)
*
max_value
=
req
->
max_value
;
if
(
max_data
)
*
max_data
=
req
->
max_data
;
if
(
modif
)
RtlSecondsSince1970ToTime
(
req
->
modif
,
modif
);
return
ERROR_SUCCESS
;
if
(
!
status
||
status
==
STATUS_BUFFER_OVERFLOW
)
{
if
(
class_len
)
*
class_len
=
info
->
ClassLength
/
sizeof
(
WCHAR
);
if
(
subkeys
)
*
subkeys
=
info
->
SubKeys
;
if
(
max_subkey
)
*
max_subkey
=
info
->
MaxNameLen
;
if
(
max_class
)
*
max_class
=
info
->
MaxClassLen
;
if
(
values
)
*
values
=
info
->
Values
;
if
(
max_value
)
*
max_value
=
info
->
MaxValueNameLen
;
if
(
max_data
)
*
max_data
=
info
->
MaxValueDataLen
;
if
(
modif
)
*
modif
=
info
->
LastWriteTime
;
}
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -440,9 +520,10 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
LPDWORD
values
,
LPDWORD
max_value
,
LPDWORD
max_data
,
LPDWORD
security
,
FILETIME
*
modif
)
{
DWORD
ret
;
struct
query_key_info_request
*
req
=
get_req_buffer
();
NTSTATUS
status
;
char
buffer
[
256
],
*
buf_ptr
=
buffer
;
KEY_FULL_INFORMATION
*
info
=
(
KEY_FULL_INFORMATION
*
)
buffer
;
DWORD
total_size
;
TRACE
(
"(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
class
,
class_len
?
*
class_len
:
0
,
reserved
,
subkeys
,
max_subkey
,
values
,
max_value
,
max_data
,
security
,
modif
);
...
...
@@ -450,27 +531,55 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
if
(
class
&&
!
class_len
&&
!
(
GetVersion
()
&
0x80000000
/*NT*/
))
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
if
((
ret
=
reg_server_call
(
REQ_QUERY_KEY_INFO
))
!=
ERROR_SUCCESS
)
return
ret
;
status
=
NtQueryKey
(
hkey
,
KeyFullInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
if
(
class
)
if
(
class
||
class_len
)
{
if
(
class_len
&&
(
strlenW
(
req
->
class
)
+
1
>
*
class_len
))
/* retry with a dynamically allocated buffer */
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
*
class_len
=
strlenW
(
req
->
class
);
return
ERROR_MORE_DATA
;
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
info
=
(
KEY_FULL_INFORMATION
*
)
buf_ptr
;
status
=
NtQueryKey
(
hkey
,
KeyFullInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
if
(
!
status
)
{
DWORD
len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
(
WCHAR
*
)(
buf_ptr
+
info
->
ClassOffset
),
info
->
ClassLength
/
sizeof
(
WCHAR
),
NULL
,
0
,
NULL
,
NULL
);
if
(
class_len
)
{
if
(
len
+
1
>
*
class_len
)
status
=
STATUS_BUFFER_OVERFLOW
;
*
class_len
=
len
;
}
if
(
class
&&
!
status
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
(
WCHAR
*
)(
buf_ptr
+
info
->
ClassOffset
),
info
->
ClassLength
/
sizeof
(
WCHAR
),
class
,
len
,
NULL
,
NULL
);
class
[
len
]
=
0
;
}
}
lstrcpyWtoA
(
class
,
req
->
class
);
}
if
(
class_len
)
*
class_len
=
strlenW
(
req
->
class
);
if
(
subkeys
)
*
subkeys
=
req
->
subkeys
;
if
(
max_subkey
)
*
max_subkey
=
req
->
max_subkey
;
if
(
max_class
)
*
max_class
=
req
->
max_class
;
if
(
values
)
*
values
=
req
->
values
;
if
(
max_value
)
*
max_value
=
req
->
max_value
;
if
(
max_data
)
*
max_data
=
req
->
max_data
;
if
(
modif
)
RtlSecondsSince1970ToTime
(
req
->
modif
,
modif
);
return
ERROR_SUCCESS
;
if
(
!
status
||
status
==
STATUS_BUFFER_OVERFLOW
)
{
if
(
subkeys
)
*
subkeys
=
info
->
SubKeys
;
if
(
max_subkey
)
*
max_subkey
=
info
->
MaxNameLen
;
if
(
max_class
)
*
max_class
=
info
->
MaxClassLen
;
if
(
values
)
*
values
=
info
->
Values
;
if
(
max_value
)
*
max_value
=
info
->
MaxValueNameLen
;
if
(
max_data
)
*
max_data
=
info
->
MaxValueDataLen
;
if
(
modif
)
*
modif
=
info
->
LastWriteTime
;
}
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -689,7 +798,7 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
NTSTATUS
status
;
UNICODE_STRING
name_str
;
DWORD
total_size
;
char
buffer
[
256
];
char
buffer
[
256
]
,
*
buf_ptr
=
buffer
;
KEY_VALUE_PARTIAL_INFORMATION
*
info
=
(
KEY_VALUE_PARTIAL_INFORMATION
*
)
buffer
;
static
const
int
info_size
=
sizeof
(
*
info
)
-
sizeof
(
info
->
Data
);
...
...
@@ -709,16 +818,15 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
if
(
data
)
{
char
*
buf_ptr
=
buffer
;
/* retry with a dynamically allocated buffer */
while
(
status
==
STATUS_BUFFER_OVERFLOW
&&
total_size
-
info_size
<=
*
count
)
{
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
status
=
STATUS_NO
_MEMORY
;
else
status
=
NtQueryValueKey
(
hkey
,
&
name_str
,
KeyValuePartialInformation
,
buf_ptr
,
total_size
,
&
total_size
);
return
ERROR_NOT_ENOUGH
_MEMORY
;
info
=
(
KEY_VALUE_PARTIAL_INFORMATION
*
)
buf_ptr
;
status
=
NtQueryValueKey
(
hkey
,
&
name_str
,
KeyValuePartialInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
if
(
!
status
)
...
...
@@ -732,13 +840,14 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
if
(
ptr
>
(
WCHAR
*
)
data
&&
ptr
[
-
1
])
*
ptr
=
0
;
}
}
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
)
;
else
if
(
status
!=
STATUS_BUFFER_OVERFLOW
)
goto
done
;
}
if
(
type
)
*
type
=
info
->
Type
;
if
(
count
)
*
count
=
total_size
-
info_size
;
done:
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -756,7 +865,7 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
ANSI_STRING
nameA
;
UNICODE_STRING
nameW
;
DWORD
total_size
;
char
buffer
[
256
];
char
buffer
[
256
]
,
*
buf_ptr
=
buffer
;
KEY_VALUE_PARTIAL_INFORMATION
*
info
=
(
KEY_VALUE_PARTIAL_INFORMATION
*
)
buffer
;
static
const
int
info_size
=
sizeof
(
*
info
)
-
sizeof
(
info
->
Data
);
...
...
@@ -767,7 +876,8 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
RtlInitAnsiString
(
&
nameA
,
name
);
/* FIXME: should use Unicode buffer in TEB */
if
((
status
=
RtlAnsiStringToUnicodeString
(
&
nameW
,
&
nameA
,
TRUE
)))
goto
done
;
if
((
status
=
RtlAnsiStringToUnicodeString
(
&
nameW
,
&
nameA
,
TRUE
)))
return
RtlNtStatusToDosError
(
status
);
status
=
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
...
...
@@ -777,16 +887,18 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
* because we need to compute the length of the ASCII string. */
if
(
data
||
is_string
(
info
->
Type
))
{
char
*
buf_ptr
=
buffer
;
/* retry with a dynamically allocated buffer */
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
{
status
=
STATUS_NO_MEMORY
;
else
status
=
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
buf_ptr
,
total_size
,
&
total_size
);
goto
done
;
}
info
=
(
KEY_VALUE_PARTIAL_INFORMATION
*
)
buf_ptr
;
status
=
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
if
(
!
status
)
...
...
@@ -812,23 +924,16 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
total_size
=
len
+
info_size
;
}
else
if
(
data
)
memcpy
(
data
,
buf_ptr
+
info_size
,
total_size
-
info_size
);
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if
(
total_size
-
info_size
<=
*
count
-
sizeof
(
WCHAR
)
&&
is_string
(
info
->
Type
))
{
WCHAR
*
ptr
=
(
WCHAR
*
)(
data
+
total_size
-
info_size
);
if
(
ptr
>
(
WCHAR
*
)
data
&&
ptr
[
-
1
])
*
ptr
=
0
;
}
}
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
)
;
else
if
(
status
!=
STATUS_BUFFER_OVERFLOW
)
goto
done
;
}
if
(
type
)
*
type
=
info
->
Type
;
if
(
count
)
*
count
=
total_size
-
info_size
;
RtlFreeUnicodeString
(
&
nameW
);
done:
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
RtlFreeUnicodeString
(
&
nameW
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
dlls/ntdll/reg.c
View file @
454355ec
...
...
@@ -168,170 +168,147 @@ NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
/******************************************************************************
* fill_key_info
*
* Helper function for NtQueryKey and NtEnumerateKey
*/
static
NTSTATUS
fill_key_info
(
KEY_INFORMATION_CLASS
info_class
,
void
*
info
,
DWORD
length
,
DWORD
*
result_len
,
const
struct
enum_key_request
*
req
)
{
WCHAR
*
name_ptr
=
server_data_ptr
(
req
);
int
name_size
=
*
name_ptr
++
;
WCHAR
*
class_ptr
=
(
WCHAR
*
)((
char
*
)
name_ptr
+
name_size
);
int
class_size
=
server_data_size
(
req
)
-
sizeof
(
WCHAR
)
-
name_size
;
int
fixed_size
;
FILETIME
modif
;
RtlSecondsSince1970ToTime
(
req
->
modif
,
&
modif
);
switch
(
info_class
)
{
case
KeyBasicInformation
:
{
KEY_BASIC_INFORMATION
keyinfo
;
fixed_size
=
sizeof
(
keyinfo
)
-
sizeof
(
keyinfo
.
Name
);
keyinfo
.
LastWriteTime
=
modif
;
keyinfo
.
TitleIndex
=
0
;
keyinfo
.
NameLength
=
name_size
;
memcpy
(
info
,
&
keyinfo
,
min
(
length
,
fixed_size
)
);
class_size
=
0
;
}
break
;
case
KeyFullInformation
:
{
KEY_FULL_INFORMATION
keyinfo
;
fixed_size
=
sizeof
(
keyinfo
)
-
sizeof
(
keyinfo
.
Class
);
keyinfo
.
LastWriteTime
=
modif
;
keyinfo
.
TitleIndex
=
0
;
keyinfo
.
ClassLength
=
class_size
;
keyinfo
.
ClassOffset
=
keyinfo
.
ClassLength
?
fixed_size
:
-
1
;
keyinfo
.
SubKeys
=
req
->
subkeys
;
keyinfo
.
MaxNameLen
=
req
->
max_subkey
;
keyinfo
.
MaxClassLen
=
req
->
max_class
;
keyinfo
.
Values
=
req
->
values
;
keyinfo
.
MaxValueNameLen
=
req
->
max_value
;
keyinfo
.
MaxValueDataLen
=
req
->
max_data
;
memcpy
(
info
,
&
keyinfo
,
min
(
length
,
fixed_size
)
);
name_size
=
0
;
}
break
;
case
KeyNodeInformation
:
{
KEY_NODE_INFORMATION
keyinfo
;
fixed_size
=
sizeof
(
keyinfo
)
-
sizeof
(
keyinfo
.
Name
);
keyinfo
.
LastWriteTime
=
modif
;
keyinfo
.
TitleIndex
=
0
;
keyinfo
.
ClassLength
=
class_size
;
keyinfo
.
ClassOffset
=
fixed_size
+
name_size
;
if
(
!
keyinfo
.
ClassLength
||
keyinfo
.
ClassOffset
>
length
)
keyinfo
.
ClassOffset
=
-
1
;
keyinfo
.
NameLength
=
name_size
;
memcpy
(
info
,
&
keyinfo
,
min
(
length
,
fixed_size
)
);
}
break
;
default:
FIXME
(
"Information class not implemented
\n
"
);
return
STATUS_INVALID_PARAMETER
;
}
*
result_len
=
fixed_size
+
name_size
+
class_size
;
if
(
length
<=
fixed_size
)
return
STATUS_BUFFER_OVERFLOW
;
length
-=
fixed_size
;
/* copy the name */
if
(
name_size
)
{
memcpy
(
(
char
*
)
info
+
fixed_size
,
name_ptr
,
min
(
length
,
name_size
)
);
if
(
length
<
name_size
)
return
STATUS_BUFFER_OVERFLOW
;
length
-=
name_size
;
}
/* copy the class */
if
(
class_size
)
{
memcpy
(
(
char
*
)
info
+
fixed_size
+
name_size
,
class_ptr
,
min
(
length
,
class_size
)
);
if
(
length
<
class_size
)
return
STATUS_BUFFER_OVERFLOW
;
}
return
STATUS_SUCCESS
;
}
/******************************************************************************
* NtEnumerateKey [NTDLL]
* ZwEnumerateKey
*
* NOTES
* the name copied into the buffer is NOT 0-terminated
*/
NTSTATUS
WINAPI
NtEnumerateKey
(
HANDLE
KeyHandle
,
ULONG
Index
,
KEY_INFORMATION_CLASS
KeyInformationClass
,
PVOID
KeyInformation
,
ULONG
Length
,
PULONG
ResultLength
)
NTSTATUS
WINAPI
NtEnumerateKey
(
HANDLE
handle
,
ULONG
index
,
KEY_INFORMATION_CLASS
info_class
,
void
*
info
,
DWORD
length
,
DWORD
*
result_len
)
{
struct
enum_key_request
*
req
=
get_req_buffer
();
NTSTATUS
ret
;
NTSTATUS
ret
;
TRACE
(
"(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p)
\n
"
,
KeyHandle
,
Index
,
KeyInformationClass
,
KeyInformation
,
Length
,
ResultLength
)
;
/* -1 means query key, so avoid it here */
if
(
index
==
(
ULONG
)
-
1
)
return
STATUS_NO_MORE_ENTRIES
;
req
->
hkey
=
KeyHandle
;
req
->
index
=
Index
;
if
((
ret
=
server_call_noerr
(
REQ_ENUM_KEY
))
!=
STATUS_SUCCESS
)
return
ret
;
switch
(
KeyInformationClass
)
{
case
KeyBasicInformation
:
{
PKEY_BASIC_INFORMATION
kbi
=
KeyInformation
;
UINT
NameLength
=
strlenW
(
req
->
name
)
*
sizeof
(
WCHAR
);
*
ResultLength
=
sizeof
(
KEY_BASIC_INFORMATION
)
-
sizeof
(
WCHAR
)
+
NameLength
;
if
(
Length
<
*
ResultLength
)
return
STATUS_BUFFER_OVERFLOW
;
RtlSecondsSince1970ToTime
(
req
->
modif
,
&
kbi
->
LastWriteTime
);
kbi
->
TitleIndex
=
0
;
kbi
->
NameLength
=
NameLength
;
memcpy
(
kbi
->
Name
,
req
->
name
,
NameLength
);
}
break
;
case
KeyFullInformation
:
{
PKEY_FULL_INFORMATION
kfi
=
KeyInformation
;
kfi
->
ClassLength
=
strlenW
(
req
->
class
)
*
sizeof
(
WCHAR
);
kfi
->
ClassOffset
=
(
kfi
->
ClassLength
)
?
sizeof
(
KEY_FULL_INFORMATION
)
-
sizeof
(
WCHAR
)
:
0xffffffff
;
*
ResultLength
=
sizeof
(
KEY_FULL_INFORMATION
)
-
sizeof
(
WCHAR
)
+
kfi
->
ClassLength
;
if
(
Length
<
*
ResultLength
)
return
STATUS_BUFFER_OVERFLOW
;
RtlSecondsSince1970ToTime
(
req
->
modif
,
&
kfi
->
LastWriteTime
);
kfi
->
TitleIndex
=
0
;
/* kfi->SubKeys = req->subkeys;
kfi->MaxNameLength = req->max_subkey;
kfi->MaxClassLength = req->max_class;
kfi->Values = req->values;
kfi->MaxValueNameLen = req->max_value;
kfi->MaxValueDataLen = req->max_data;
*/
FIXME
(
"incomplete
\n
"
);
if
(
kfi
->
ClassLength
)
memcpy
(
kfi
->
Class
,
req
->
class
,
kfi
->
ClassLength
);
}
break
;
case
KeyNodeInformation
:
{
PKEY_NODE_INFORMATION
kni
=
KeyInformation
;
kni
->
ClassLength
=
strlenW
(
req
->
class
)
*
sizeof
(
WCHAR
);
kni
->
NameLength
=
strlenW
(
req
->
name
)
*
sizeof
(
WCHAR
);
kni
->
ClassOffset
=
(
kni
->
ClassLength
)
?
sizeof
(
KEY_NODE_INFORMATION
)
-
sizeof
(
WCHAR
)
+
kni
->
NameLength
:
0xffffffff
;
*
ResultLength
=
sizeof
(
KEY_NODE_INFORMATION
)
-
sizeof
(
WCHAR
)
+
kni
->
NameLength
+
kni
->
ClassLength
;
if
(
Length
<
*
ResultLength
)
return
STATUS_BUFFER_OVERFLOW
;
RtlSecondsSince1970ToTime
(
req
->
modif
,
&
kni
->
LastWriteTime
);
kni
->
TitleIndex
=
0
;
memcpy
(
kni
->
Name
,
req
->
name
,
kni
->
NameLength
);
if
(
kni
->
ClassLength
)
memcpy
((
char
*
)
KeyInformation
+
kni
->
ClassOffset
,
req
->
class
,
kni
->
ClassLength
);
}
break
;
default:
FIXME
(
"KeyInformationClass not implemented
\n
"
);
return
STATUS_UNSUCCESSFUL
;
}
TRACE
(
"buf=%lu len=%lu
\n
"
,
Length
,
*
ResultLength
);
return
ret
;
SERVER_START_REQ
{
struct
enum_key_request
*
req
=
server_alloc_req
(
sizeof
(
*
req
),
REQUEST_MAX_VAR_SIZE
);
req
->
hkey
=
handle
;
req
->
index
=
index
;
req
->
full
=
(
info_class
==
KeyFullInformation
);
if
(
!
(
ret
=
server_call_noerr
(
REQ_ENUM_KEY
)))
{
ret
=
fill_key_info
(
info_class
,
info
,
length
,
result_len
,
req
);
}
}
SERVER_END_REQ
;
return
ret
;
}
/******************************************************************************
* NtQueryKey [NTDLL]
* ZwQueryKey
*/
NTSTATUS
WINAPI
NtQueryKey
(
HANDLE
KeyHandle
,
KEY_INFORMATION_CLASS
KeyInformationClass
,
PVOID
KeyInformation
,
ULONG
Length
,
PULONG
ResultLength
)
NTSTATUS
WINAPI
NtQueryKey
(
HANDLE
handle
,
KEY_INFORMATION_CLASS
info_class
,
void
*
info
,
DWORD
length
,
DWORD
*
result_len
)
{
struct
query_key_info_request
*
req
=
get_req_buffer
();
NTSTATUS
ret
;
TRACE
(
"(0x%08x,0x%08x,%p,0x%08lx,%p) stub
\n
"
,
KeyHandle
,
KeyInformationClass
,
KeyInformation
,
Length
,
ResultLength
);
req
->
hkey
=
KeyHandle
;
if
((
ret
=
server_call_noerr
(
REQ_QUERY_KEY_INFO
))
!=
STATUS_SUCCESS
)
return
ret
;
switch
(
KeyInformationClass
)
{
case
KeyBasicInformation
:
{
PKEY_BASIC_INFORMATION
kbi
=
KeyInformation
;
UINT
NameLength
=
strlenW
(
req
->
name
)
*
sizeof
(
WCHAR
);
*
ResultLength
=
sizeof
(
KEY_BASIC_INFORMATION
)
-
sizeof
(
WCHAR
)
+
NameLength
;
if
(
Length
<
*
ResultLength
)
return
STATUS_BUFFER_OVERFLOW
;
NTSTATUS
ret
;
RtlSecondsSince1970ToTime
(
req
->
modif
,
&
kbi
->
LastWriteTime
);
kbi
->
TitleIndex
=
0
;
kbi
->
NameLength
=
NameLength
;
memcpy
(
kbi
->
Name
,
req
->
name
,
NameLength
);
}
break
;
case
KeyFullInformation
:
{
PKEY_FULL_INFORMATION
kfi
=
KeyInformation
;
kfi
->
ClassLength
=
strlenW
(
req
->
class
)
*
sizeof
(
WCHAR
);
kfi
->
ClassOffset
=
(
kfi
->
ClassLength
)
?
sizeof
(
KEY_FULL_INFORMATION
)
-
sizeof
(
WCHAR
)
:
0xffffffff
;
*
ResultLength
=
sizeof
(
KEY_FULL_INFORMATION
)
-
sizeof
(
WCHAR
)
+
kfi
->
ClassLength
;
if
(
Length
<
*
ResultLength
)
return
STATUS_BUFFER_OVERFLOW
;
RtlSecondsSince1970ToTime
(
req
->
modif
,
&
kfi
->
LastWriteTime
);
kfi
->
TitleIndex
=
0
;
kfi
->
SubKeys
=
req
->
subkeys
;
kfi
->
MaxNameLen
=
req
->
max_subkey
;
kfi
->
MaxClassLen
=
req
->
max_class
;
kfi
->
Values
=
req
->
values
;
kfi
->
MaxValueNameLen
=
req
->
max_value
;
kfi
->
MaxValueDataLen
=
req
->
max_data
;
if
(
kfi
->
ClassLength
)
memcpy
((
char
*
)
KeyInformation
+
kfi
->
ClassOffset
,
req
->
class
,
kfi
->
ClassLength
);
}
break
;
case
KeyNodeInformation
:
{
PKEY_NODE_INFORMATION
kni
=
KeyInformation
;
kni
->
ClassLength
=
strlenW
(
req
->
class
)
*
sizeof
(
WCHAR
);
kni
->
NameLength
=
strlenW
(
req
->
name
)
*
sizeof
(
WCHAR
);
kni
->
ClassOffset
=
(
kni
->
ClassLength
)
?
sizeof
(
KEY_NODE_INFORMATION
)
-
sizeof
(
WCHAR
)
+
kni
->
NameLength
:
0xffffffff
;
*
ResultLength
=
sizeof
(
KEY_NODE_INFORMATION
)
-
sizeof
(
WCHAR
)
+
kni
->
NameLength
+
kni
->
ClassLength
;
if
(
Length
<
*
ResultLength
)
return
STATUS_BUFFER_OVERFLOW
;
RtlSecondsSince1970ToTime
(
req
->
modif
,
&
kni
->
LastWriteTime
);
kni
->
TitleIndex
=
0
;
memcpy
(
kni
->
Name
,
req
->
name
,
kni
->
NameLength
);
if
(
kni
->
ClassLength
)
memcpy
((
char
*
)
KeyInformation
+
kni
->
ClassOffset
,
req
->
class
,
kni
->
ClassLength
);
}
break
;
default:
FIXME
(
"KeyInformationClass not implemented
\n
"
);
return
STATUS_UNSUCCESSFUL
;
}
return
ret
;
SERVER_START_REQ
{
struct
enum_key_request
*
req
=
server_alloc_req
(
sizeof
(
*
req
),
REQUEST_MAX_VAR_SIZE
);
req
->
hkey
=
handle
;
req
->
index
=
-
1
;
req
->
full
=
(
info_class
==
KeyFullInformation
);
if
(
!
(
ret
=
server_call_noerr
(
REQ_ENUM_KEY
)))
{
ret
=
fill_key_info
(
info_class
,
info
,
length
,
result_len
,
req
);
}
}
SERVER_END_REQ
;
return
ret
;
}
/******************************************************************************
...
...
@@ -489,8 +466,6 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
KEY_VALUE_INFORMATION_CLASS
info_class
,
void
*
info
,
DWORD
length
,
DWORD
*
result_len
)
{
NTSTATUS
ret
;
char
*
data_ptr
;
int
fixed_size
=
0
,
data_len
=
0
,
offset
=
0
,
type
=
0
,
total_len
=
0
;
...
...
@@ -523,7 +498,7 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
do
{
size_t
reqlen
=
min
(
data_len
,
REQUEST_MAX_VAR_SIZE
);
reqlen
=
max
(
reqlen
,
name
->
Length
);
reqlen
=
max
(
reqlen
,
name
->
Length
+
sizeof
(
WCHAR
)
);
SERVER_START_REQ
{
...
...
@@ -554,7 +529,7 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
*
result_len
=
total_len
+
fixed_size
;
if
(
!
data
_len
)
ret
=
STATUS_BUFFER_OVERFLOW
;
if
(
offset
<
total
_len
)
ret
=
STATUS_BUFFER_OVERFLOW
;
if
(
length
<
fixed_size
)
ret
=
STATUS_BUFFER_OVERFLOW
;
switch
(
info_class
)
...
...
include/ntddk.h
View file @
454355ec
...
...
@@ -821,17 +821,11 @@ NTSTATUS WINAPI NtDeleteKey(HANDLE);
NTSTATUS
WINAPI
NtDeleteValueKey
(
HANDLE
,
const
UNICODE_STRING
*
);
NTSTATUS
WINAPI
NtOpenKey
(
PHANDLE
,
ACCESS_MASK
,
const
OBJECT_ATTRIBUTES
*
);
NTSTATUS
WINAPI
NtSetValueKey
(
HANDLE
,
const
UNICODE_STRING
*
,
ULONG
,
ULONG
,
const
void
*
,
ULONG
);
NTSTATUS
WINAPI
NtEnumerateKey
(
HANDLE
,
ULONG
,
KEY_INFORMATION_CLASS
,
void
*
,
DWORD
,
DWORD
*
);
NTSTATUS
WINAPI
NtQueryValueKey
(
HANDLE
,
const
UNICODE_STRING
*
,
KEY_VALUE_INFORMATION_CLASS
,
void
*
,
DWORD
,
DWORD
*
);
NTSTATUS
WINAPI
NtEnumerateKey
(
HANDLE
KeyHandle
,
ULONG
Index
,
KEY_INFORMATION_CLASS
KeyInformationClass
,
PVOID
KeyInformation
,
ULONG
Length
,
PULONG
ResultLength
);
NTSTATUS
WINAPI
NtQueryKey
(
HANDLE
KeyHandle
,
...
...
include/server.h
View file @
454355ec
...
...
@@ -1046,18 +1046,8 @@ struct enum_key_request
{
REQUEST_HEADER
;
/* request header */
IN
int
hkey
;
/* handle to registry key */
IN
int
index
;
/* index of subkey */
OUT
time_t
modif
;
/* last modification time */
OUT
path_t
name
;
/* subkey name */
OUT
WCHAR
class
[
1
];
/* class name */
};
/* Query information about a registry key */
struct
query_key_info_request
{
REQUEST_HEADER
;
/* request header */
IN
int
hkey
;
/* handle to registry key */
IN
int
index
;
/* index of subkey (or -1 for current key) */
IN
int
full
;
/* return the full info? */
OUT
int
subkeys
;
/* number of subkeys */
OUT
int
max_subkey
;
/* longest subkey name */
OUT
int
max_class
;
/* longest class name */
...
...
@@ -1065,8 +1055,8 @@ struct query_key_info_request
OUT
int
max_value
;
/* longest value name */
OUT
int
max_data
;
/* longest value data */
OUT
time_t
modif
;
/* last modification time */
OUT
path_t
name
;
/* key name */
OUT
WCHAR
class
[
1
]
;
/* class name */
OUT
VARARG
(
name
,
unicode_len_str
);
/* key name */
OUT
VARARG
(
class
,
unicode_str
)
;
/* class name */
};
...
...
@@ -1429,7 +1419,6 @@ enum request
REQ_OPEN_KEY
,
REQ_DELETE_KEY
,
REQ_ENUM_KEY
,
REQ_QUERY_KEY_INFO
,
REQ_SET_KEY_VALUE
,
REQ_GET_KEY_VALUE
,
REQ_ENUM_KEY_VALUE
,
...
...
@@ -1545,7 +1534,6 @@ union generic_request
struct
open_key_request
open_key
;
struct
delete_key_request
delete_key
;
struct
enum_key_request
enum_key
;
struct
query_key_info_request
query_key_info
;
struct
set_key_value_request
set_key_value
;
struct
get_key_value_request
get_key_value
;
struct
enum_key_value_request
enum_key_value
;
...
...
@@ -1574,7 +1562,7 @@ union generic_request
struct
set_serial_info_request
set_serial_info
;
};
#define SERVER_PROTOCOL_VERSION 2
4
#define SERVER_PROTOCOL_VERSION 2
5
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
...
...
@@ -1648,13 +1636,13 @@ static inline void server_strcpyAtoW( WCHAR *dst, const char *src )
}
/* get a pointer to the variable part of the request */
inline
static
void
*
server_data_ptr
(
void
*
req
)
inline
static
void
*
server_data_ptr
(
const
void
*
req
)
{
return
(
union
generic_request
*
)
req
+
1
;
}
/* get the size of the variable part of the request */
inline
static
size_t
server_data_size
(
void
*
req
)
inline
static
size_t
server_data_size
(
const
void
*
req
)
{
return
((
struct
request_header
*
)
req
)
->
var_size
;
}
...
...
memory/registry.c
View file @
454355ec
...
...
@@ -289,32 +289,58 @@ DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
DWORD
WINAPI
RegEnumKeyExW
(
HKEY
hkey
,
DWORD
index
,
LPWSTR
name
,
LPDWORD
name_len
,
LPDWORD
reserved
,
LPWSTR
class
,
LPDWORD
class_len
,
FILETIME
*
ft
)
{
DWORD
ret
,
len
,
cls_len
;
struct
enum_key_request
*
req
=
get_req_buffer
();
NTSTATUS
status
;
char
buffer
[
256
],
*
buf_ptr
=
buffer
;
KEY_NODE_INFORMATION
*
info
=
(
KEY_NODE_INFORMATION
*
)
buffer
;
DWORD
total_size
;
TRACE
(
"(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)
\n
"
,
hkey
,
index
,
name
,
name_len
,
name_len
?
*
name_len
:
-
1
,
reserved
,
class
,
class_len
,
ft
);
if
(
reserved
)
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
req
->
index
=
index
;
if
((
ret
=
reg_server_call
(
REQ_ENUM_KEY
))
!=
ERROR_SUCCESS
)
return
ret
;
status
=
NtEnumerateKey
(
hkey
,
index
,
KeyNodeInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
len
=
strlenW
(
req
->
name
)
+
1
;
cls_len
=
strlenW
(
req
->
class
)
+
1
;
if
(
len
>
*
name_len
)
return
ERROR_MORE_DATA
;
if
(
class_len
&&
(
cls_len
>
*
class_len
))
return
ERROR_MORE_DATA
;
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
/* retry with a dynamically allocated buffer */
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
info
=
(
KEY_NODE_INFORMATION
*
)
buf_ptr
;
status
=
NtEnumerateKey
(
hkey
,
index
,
KeyNodeInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
memcpy
(
name
,
req
->
name
,
len
*
sizeof
(
WCHAR
)
);
*
name_len
=
len
-
1
;
if
(
class_len
)
if
(
!
status
)
{
if
(
class
)
memcpy
(
class
,
req
->
class
,
cls_len
*
sizeof
(
WCHAR
)
);
*
class_len
=
cls_len
-
1
;
DWORD
len
=
info
->
NameLength
/
sizeof
(
WCHAR
);
DWORD
cls_len
=
info
->
ClassLength
/
sizeof
(
WCHAR
);
if
(
ft
)
*
ft
=
info
->
LastWriteTime
;
if
(
len
>=
*
name_len
||
(
class_len
&&
(
cls_len
>=
*
class_len
)))
status
=
STATUS_BUFFER_OVERFLOW
;
else
{
*
name_len
=
len
;
memcpy
(
name
,
info
->
Name
,
info
->
NameLength
);
name
[
len
]
=
0
;
if
(
class_len
)
{
*
class_len
=
cls_len
;
if
(
class
)
{
memcpy
(
class
,
buf_ptr
+
info
->
ClassOffset
,
info
->
ClassLength
);
class
[
cls_len
]
=
0
;
}
}
}
}
if
(
ft
)
RtlSecondsSince1970ToTime
(
req
->
modif
,
ft
);
return
ERROR_SUCCESS
;
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -324,32 +350,64 @@ DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_le
DWORD
WINAPI
RegEnumKeyExA
(
HKEY
hkey
,
DWORD
index
,
LPSTR
name
,
LPDWORD
name_len
,
LPDWORD
reserved
,
LPSTR
class
,
LPDWORD
class_len
,
FILETIME
*
ft
)
{
DWORD
ret
,
len
,
cls_len
;
struct
enum_key_request
*
req
=
get_req_buffer
();
NTSTATUS
status
;
char
buffer
[
256
],
*
buf_ptr
=
buffer
;
KEY_NODE_INFORMATION
*
info
=
(
KEY_NODE_INFORMATION
*
)
buffer
;
DWORD
total_size
;
TRACE
(
"(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)
\n
"
,
hkey
,
index
,
name
,
name_len
,
name_len
?
*
name_len
:
-
1
,
reserved
,
class
,
class_len
,
ft
);
if
(
reserved
)
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
req
->
index
=
index
;
if
((
ret
=
reg_server_call
(
REQ_ENUM_KEY
))
!=
ERROR_SUCCESS
)
return
ret
;
status
=
NtEnumerateKey
(
hkey
,
index
,
KeyNodeInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
len
=
strlenW
(
req
->
name
)
+
1
;
cls_len
=
strlenW
(
req
->
class
)
+
1
;
if
(
len
>
*
name_len
)
return
ERROR_MORE_DATA
;
if
(
class_len
&&
(
cls_len
>
*
class_len
))
return
ERROR_MORE_DATA
;
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
/* retry with a dynamically allocated buffer */
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
info
=
(
KEY_NODE_INFORMATION
*
)
buf_ptr
;
status
=
NtEnumerateKey
(
hkey
,
index
,
KeyNodeInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
memcpyWtoA
(
name
,
req
->
name
,
len
);
*
name_len
=
len
-
1
;
if
(
class_len
)
if
(
!
status
)
{
if
(
class
)
memcpyWtoA
(
class
,
req
->
class
,
cls_len
);
*
class_len
=
cls_len
-
1
;
DWORD
len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
info
->
Name
,
info
->
NameLength
/
sizeof
(
WCHAR
),
NULL
,
0
,
NULL
,
NULL
);
DWORD
cls_len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
(
WCHAR
*
)(
buf_ptr
+
info
->
ClassOffset
),
info
->
ClassLength
/
sizeof
(
WCHAR
),
NULL
,
0
,
NULL
,
NULL
);
if
(
ft
)
*
ft
=
info
->
LastWriteTime
;
if
(
len
>=
*
name_len
||
(
class_len
&&
(
cls_len
>=
*
class_len
)))
status
=
STATUS_BUFFER_OVERFLOW
;
else
{
*
name_len
=
len
;
WideCharToMultiByte
(
CP_ACP
,
0
,
info
->
Name
,
info
->
NameLength
/
sizeof
(
WCHAR
),
name
,
len
,
NULL
,
NULL
);
name
[
len
]
=
0
;
if
(
class_len
)
{
*
class_len
=
cls_len
;
if
(
class
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
(
WCHAR
*
)(
buf_ptr
+
info
->
ClassOffset
),
info
->
ClassLength
/
sizeof
(
WCHAR
),
class
,
cls_len
,
NULL
,
NULL
);
class
[
cls_len
]
=
0
;
}
}
}
}
if
(
ft
)
RtlSecondsSince1970ToTime
(
req
->
modif
,
ft
);
return
ERROR_SUCCESS
;
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -398,9 +456,10 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
LPDWORD
values
,
LPDWORD
max_value
,
LPDWORD
max_data
,
LPDWORD
security
,
FILETIME
*
modif
)
{
DWORD
ret
;
struct
query_key_info_request
*
req
=
get_req_buffer
();
NTSTATUS
status
;
char
buffer
[
256
],
*
buf_ptr
=
buffer
;
KEY_FULL_INFORMATION
*
info
=
(
KEY_FULL_INFORMATION
*
)
buffer
;
DWORD
total_size
;
TRACE
(
"(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
class
,
class_len
?
*
class_len
:
0
,
reserved
,
subkeys
,
max_subkey
,
values
,
max_value
,
max_data
,
security
,
modif
);
...
...
@@ -408,27 +467,48 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
if
(
class
&&
!
class_len
&&
!
(
GetVersion
()
&
0x80000000
/*NT*/
))
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
if
((
ret
=
reg_server_call
(
REQ_QUERY_KEY_INFO
))
!=
ERROR_SUCCESS
)
return
ret
;
status
=
NtQueryKey
(
hkey
,
KeyFullInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
if
(
class
)
{
if
(
class_len
&&
(
strlenW
(
req
->
class
)
+
1
>
*
class_len
))
/* retry with a dynamically allocated buffer */
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
*
class_len
=
strlenW
(
req
->
class
);
return
ERROR_MORE_DATA
;
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
info
=
(
KEY_FULL_INFORMATION
*
)
buf_ptr
;
status
=
NtQueryKey
(
hkey
,
KeyFullInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
if
(
!
status
)
{
if
(
class_len
&&
(
info
->
ClassLength
/
sizeof
(
WCHAR
)
+
1
>
*
class_len
))
{
status
=
STATUS_BUFFER_OVERFLOW
;
}
else
{
memcpy
(
class
,
buf_ptr
+
info
->
ClassOffset
,
info
->
ClassLength
);
class
[
info
->
ClassLength
/
sizeof
(
WCHAR
)]
=
0
;
}
}
strcpyW
(
class
,
req
->
class
);
}
if
(
class_len
)
*
class_len
=
strlenW
(
req
->
class
);
if
(
subkeys
)
*
subkeys
=
req
->
subkeys
;
if
(
max_subkey
)
*
max_subkey
=
req
->
max_subkey
;
if
(
max_class
)
*
max_class
=
req
->
max_class
;
if
(
values
)
*
values
=
req
->
values
;
if
(
max_value
)
*
max_value
=
req
->
max_value
;
if
(
max_data
)
*
max_data
=
req
->
max_data
;
if
(
modif
)
RtlSecondsSince1970ToTime
(
req
->
modif
,
modif
);
return
ERROR_SUCCESS
;
if
(
!
status
||
status
==
STATUS_BUFFER_OVERFLOW
)
{
if
(
class_len
)
*
class_len
=
info
->
ClassLength
/
sizeof
(
WCHAR
);
if
(
subkeys
)
*
subkeys
=
info
->
SubKeys
;
if
(
max_subkey
)
*
max_subkey
=
info
->
MaxNameLen
;
if
(
max_class
)
*
max_class
=
info
->
MaxClassLen
;
if
(
values
)
*
values
=
info
->
Values
;
if
(
max_value
)
*
max_value
=
info
->
MaxValueNameLen
;
if
(
max_data
)
*
max_data
=
info
->
MaxValueDataLen
;
if
(
modif
)
*
modif
=
info
->
LastWriteTime
;
}
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -440,9 +520,10 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
LPDWORD
values
,
LPDWORD
max_value
,
LPDWORD
max_data
,
LPDWORD
security
,
FILETIME
*
modif
)
{
DWORD
ret
;
struct
query_key_info_request
*
req
=
get_req_buffer
();
NTSTATUS
status
;
char
buffer
[
256
],
*
buf_ptr
=
buffer
;
KEY_FULL_INFORMATION
*
info
=
(
KEY_FULL_INFORMATION
*
)
buffer
;
DWORD
total_size
;
TRACE
(
"(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
class
,
class_len
?
*
class_len
:
0
,
reserved
,
subkeys
,
max_subkey
,
values
,
max_value
,
max_data
,
security
,
modif
);
...
...
@@ -450,27 +531,55 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
if
(
class
&&
!
class_len
&&
!
(
GetVersion
()
&
0x80000000
/*NT*/
))
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
if
((
ret
=
reg_server_call
(
REQ_QUERY_KEY_INFO
))
!=
ERROR_SUCCESS
)
return
ret
;
status
=
NtQueryKey
(
hkey
,
KeyFullInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
if
(
class
)
if
(
class
||
class_len
)
{
if
(
class_len
&&
(
strlenW
(
req
->
class
)
+
1
>
*
class_len
))
/* retry with a dynamically allocated buffer */
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
*
class_len
=
strlenW
(
req
->
class
);
return
ERROR_MORE_DATA
;
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
return
ERROR_NOT_ENOUGH_MEMORY
;
info
=
(
KEY_FULL_INFORMATION
*
)
buf_ptr
;
status
=
NtQueryKey
(
hkey
,
KeyFullInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
if
(
!
status
)
{
DWORD
len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
(
WCHAR
*
)(
buf_ptr
+
info
->
ClassOffset
),
info
->
ClassLength
/
sizeof
(
WCHAR
),
NULL
,
0
,
NULL
,
NULL
);
if
(
class_len
)
{
if
(
len
+
1
>
*
class_len
)
status
=
STATUS_BUFFER_OVERFLOW
;
*
class_len
=
len
;
}
if
(
class
&&
!
status
)
{
WideCharToMultiByte
(
CP_ACP
,
0
,
(
WCHAR
*
)(
buf_ptr
+
info
->
ClassOffset
),
info
->
ClassLength
/
sizeof
(
WCHAR
),
class
,
len
,
NULL
,
NULL
);
class
[
len
]
=
0
;
}
}
lstrcpyWtoA
(
class
,
req
->
class
);
}
if
(
class_len
)
*
class_len
=
strlenW
(
req
->
class
);
if
(
subkeys
)
*
subkeys
=
req
->
subkeys
;
if
(
max_subkey
)
*
max_subkey
=
req
->
max_subkey
;
if
(
max_class
)
*
max_class
=
req
->
max_class
;
if
(
values
)
*
values
=
req
->
values
;
if
(
max_value
)
*
max_value
=
req
->
max_value
;
if
(
max_data
)
*
max_data
=
req
->
max_data
;
if
(
modif
)
RtlSecondsSince1970ToTime
(
req
->
modif
,
modif
);
return
ERROR_SUCCESS
;
if
(
!
status
||
status
==
STATUS_BUFFER_OVERFLOW
)
{
if
(
subkeys
)
*
subkeys
=
info
->
SubKeys
;
if
(
max_subkey
)
*
max_subkey
=
info
->
MaxNameLen
;
if
(
max_class
)
*
max_class
=
info
->
MaxClassLen
;
if
(
values
)
*
values
=
info
->
Values
;
if
(
max_value
)
*
max_value
=
info
->
MaxValueNameLen
;
if
(
max_data
)
*
max_data
=
info
->
MaxValueDataLen
;
if
(
modif
)
*
modif
=
info
->
LastWriteTime
;
}
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -689,7 +798,7 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
NTSTATUS
status
;
UNICODE_STRING
name_str
;
DWORD
total_size
;
char
buffer
[
256
];
char
buffer
[
256
]
,
*
buf_ptr
=
buffer
;
KEY_VALUE_PARTIAL_INFORMATION
*
info
=
(
KEY_VALUE_PARTIAL_INFORMATION
*
)
buffer
;
static
const
int
info_size
=
sizeof
(
*
info
)
-
sizeof
(
info
->
Data
);
...
...
@@ -709,16 +818,15 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
if
(
data
)
{
char
*
buf_ptr
=
buffer
;
/* retry with a dynamically allocated buffer */
while
(
status
==
STATUS_BUFFER_OVERFLOW
&&
total_size
-
info_size
<=
*
count
)
{
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
status
=
STATUS_NO
_MEMORY
;
else
status
=
NtQueryValueKey
(
hkey
,
&
name_str
,
KeyValuePartialInformation
,
buf_ptr
,
total_size
,
&
total_size
);
return
ERROR_NOT_ENOUGH
_MEMORY
;
info
=
(
KEY_VALUE_PARTIAL_INFORMATION
*
)
buf_ptr
;
status
=
NtQueryValueKey
(
hkey
,
&
name_str
,
KeyValuePartialInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
if
(
!
status
)
...
...
@@ -732,13 +840,14 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
if
(
ptr
>
(
WCHAR
*
)
data
&&
ptr
[
-
1
])
*
ptr
=
0
;
}
}
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
)
;
else
if
(
status
!=
STATUS_BUFFER_OVERFLOW
)
goto
done
;
}
if
(
type
)
*
type
=
info
->
Type
;
if
(
count
)
*
count
=
total_size
-
info_size
;
done:
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
@@ -756,7 +865,7 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
ANSI_STRING
nameA
;
UNICODE_STRING
nameW
;
DWORD
total_size
;
char
buffer
[
256
];
char
buffer
[
256
]
,
*
buf_ptr
=
buffer
;
KEY_VALUE_PARTIAL_INFORMATION
*
info
=
(
KEY_VALUE_PARTIAL_INFORMATION
*
)
buffer
;
static
const
int
info_size
=
sizeof
(
*
info
)
-
sizeof
(
info
->
Data
);
...
...
@@ -767,7 +876,8 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
RtlInitAnsiString
(
&
nameA
,
name
);
/* FIXME: should use Unicode buffer in TEB */
if
((
status
=
RtlAnsiStringToUnicodeString
(
&
nameW
,
&
nameA
,
TRUE
)))
goto
done
;
if
((
status
=
RtlAnsiStringToUnicodeString
(
&
nameW
,
&
nameA
,
TRUE
)))
return
RtlNtStatusToDosError
(
status
);
status
=
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
buffer
,
sizeof
(
buffer
),
&
total_size
);
...
...
@@ -777,16 +887,18 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
* because we need to compute the length of the ASCII string. */
if
(
data
||
is_string
(
info
->
Type
))
{
char
*
buf_ptr
=
buffer
;
/* retry with a dynamically allocated buffer */
while
(
status
==
STATUS_BUFFER_OVERFLOW
)
{
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
if
(
!
(
buf_ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
total_size
)))
{
status
=
STATUS_NO_MEMORY
;
else
status
=
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
buf_ptr
,
total_size
,
&
total_size
);
goto
done
;
}
info
=
(
KEY_VALUE_PARTIAL_INFORMATION
*
)
buf_ptr
;
status
=
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
buf_ptr
,
total_size
,
&
total_size
);
}
if
(
!
status
)
...
...
@@ -812,23 +924,16 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
total_size
=
len
+
info_size
;
}
else
if
(
data
)
memcpy
(
data
,
buf_ptr
+
info_size
,
total_size
-
info_size
);
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if
(
total_size
-
info_size
<=
*
count
-
sizeof
(
WCHAR
)
&&
is_string
(
info
->
Type
))
{
WCHAR
*
ptr
=
(
WCHAR
*
)(
data
+
total_size
-
info_size
);
if
(
ptr
>
(
WCHAR
*
)
data
&&
ptr
[
-
1
])
*
ptr
=
0
;
}
}
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
)
;
else
if
(
status
!=
STATUS_BUFFER_OVERFLOW
)
goto
done
;
}
if
(
type
)
*
type
=
info
->
Type
;
if
(
count
)
*
count
=
total_size
-
info_size
;
RtlFreeUnicodeString
(
&
nameW
);
done:
if
(
buf_ptr
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
buf_ptr
);
RtlFreeUnicodeString
(
&
nameW
);
return
RtlNtStatusToDosError
(
status
);
}
...
...
server/registry.c
View file @
454355ec
...
...
@@ -560,57 +560,80 @@ static struct key *create_key( struct key *key, WCHAR *name, WCHAR *class,
return
key
;
}
/*
find a subkey of a given key by its index
*/
static
void
enum_key
(
struct
key
*
parent
,
int
index
,
WCHAR
*
name
,
WCHAR
*
class
,
time_t
*
modif
)
/*
query information about a key or a subkey
*/
static
size_t
enum_key
(
struct
key
*
key
,
int
index
,
struct
enum_key_request
*
req
)
{
struct
key
*
key
;
int
i
;
size_t
len
,
namelen
,
classlen
;
int
max_subkey
=
0
,
max_class
=
0
;
int
max_value
=
0
,
max_data
=
0
;
WCHAR
*
data
=
get_req_data
(
req
);
if
((
index
<
0
)
||
(
index
>
parent
->
last_subkey
))
set_error
(
STATUS_NO_MORE_ENTRIES
);
if
(
index
!=
-
1
)
/* -1 means use the specified key directly */
{
if
((
index
<
0
)
||
(
index
>
key
->
last_subkey
))
{
set_error
(
STATUS_NO_MORE_ENTRIES
);
return
0
;
}
key
=
key
->
subkeys
[
index
];
}
if
(
req
->
full
)
{
for
(
i
=
0
;
i
<=
key
->
last_subkey
;
i
++
)
{
struct
key
*
subkey
=
key
->
subkeys
[
i
];
len
=
strlenW
(
subkey
->
name
);
if
(
len
>
max_subkey
)
max_subkey
=
len
;
if
(
!
subkey
->
class
)
continue
;
len
=
strlenW
(
subkey
->
class
);
if
(
len
>
max_class
)
max_class
=
len
;
}
for
(
i
=
0
;
i
<=
key
->
last_value
;
i
++
)
{
len
=
strlenW
(
key
->
values
[
i
].
name
);
if
(
len
>
max_value
)
max_value
=
len
;
len
=
key
->
values
[
i
].
len
;
if
(
len
>
max_data
)
max_data
=
len
;
}
req
->
max_subkey
=
max_subkey
;
req
->
max_class
=
max_class
;
req
->
max_value
=
max_value
;
req
->
max_data
=
max_data
;
}
else
{
key
=
parent
->
subkeys
[
index
];
*
modif
=
key
->
modif
;
strcpyW
(
name
,
key
->
name
);
if
(
key
->
class
)
strcpyW
(
class
,
key
->
class
);
/* FIXME: length */
else
*
class
=
0
;
if
(
debug_level
>
1
)
dump_operation
(
key
,
NULL
,
"Enum"
);
req
->
max_subkey
=
0
;
req
->
max_class
=
0
;
req
->
max_value
=
0
;
req
->
max_data
=
0
;
}
}
req
->
subkeys
=
key
->
last_subkey
+
1
;
req
->
values
=
key
->
last_value
+
1
;
req
->
modif
=
key
->
modif
;
/* query information about a key */
static
void
query_key
(
struct
key
*
key
,
struct
query_key_info_request
*
req
)
{
int
i
,
len
;
int
max_subkey
=
0
,
max_class
=
0
;
int
max_value
=
0
,
max_data
=
0
;
namelen
=
strlenW
(
key
->
name
)
*
sizeof
(
WCHAR
);
classlen
=
key
->
class
?
strlenW
(
key
->
class
)
*
sizeof
(
WCHAR
)
:
0
;
for
(
i
=
0
;
i
<=
key
->
last_subkey
;
i
++
)
len
=
namelen
+
classlen
+
sizeof
(
WCHAR
);
if
(
len
>
get_req_data_size
(
req
))
{
struct
key
*
subkey
=
key
->
subkeys
[
i
];
len
=
strlenW
(
subkey
->
name
);
if
(
len
>
max_subkey
)
max_subkey
=
len
;
if
(
!
subkey
->
class
)
continue
;
len
=
strlenW
(
subkey
->
class
);
if
(
len
>
max_class
)
max_class
=
len
;
len
=
get_req_data_size
(
req
);
if
(
len
<
sizeof
(
WCHAR
))
return
0
;
}
for
(
i
=
0
;
i
<=
key
->
last_value
;
i
++
)
*
data
++
=
namelen
;
len
-=
sizeof
(
WCHAR
);
if
(
len
>
namelen
)
{
len
=
strlenW
(
key
->
values
[
i
].
name
);
if
(
len
>
max_value
)
max_value
=
len
;
len
=
key
->
values
[
i
].
len
;
if
(
len
>
max_data
)
max_data
=
len
;
}
req
->
subkeys
=
key
->
last_subkey
+
1
;
req
->
max_subkey
=
max_subkey
;
req
->
max_class
=
max_class
;
req
->
values
=
key
->
last_value
+
1
;
req
->
max_value
=
max_value
;
req
->
max_data
=
max_data
;
req
->
modif
=
key
->
modif
;
strcpyW
(
req
->
name
,
key
->
name
);
if
(
key
->
class
)
strcpyW
(
req
->
class
,
key
->
class
);
/* FIXME: length */
else
req
->
class
[
0
]
=
0
;
if
(
debug_level
>
1
)
dump_operation
(
key
,
NULL
,
"Query"
);
memcpy
(
data
,
key
->
name
,
namelen
);
memcpy
(
(
char
*
)
data
+
namelen
,
key
->
class
,
min
(
classlen
,
len
-
namelen
)
);
}
else
memcpy
(
data
,
key
->
name
,
len
);
if
(
debug_level
>
1
)
dump_operation
(
key
,
NULL
,
"Enum"
);
return
len
+
sizeof
(
WCHAR
);
}
/* delete a key and its values */
...
...
@@ -1537,31 +1560,29 @@ DECL_HANDLER(create_key)
if
(
access
&
MAXIMUM_ALLOWED
)
access
=
KEY_ALL_ACCESS
;
/* FIXME: needs general solution */
req
->
hkey
=
-
1
;
if
(
!
(
name
=
copy_req_path
(
req
,
&
len
)))
return
;
if
((
parent
=
get_hkey_obj
(
req
->
parent
,
0
/*FIXME*/
)))
{
if
(
(
name
=
copy_req_path
(
req
,
&
len
)))
if
(
len
==
get_req_data_size
(
req
))
/* no class specified */
{
if
(
len
==
get_req_data_size
(
req
))
/* no class specified */
{
key
=
create_key
(
parent
,
name
,
NULL
,
req
->
options
,
req
->
modif
,
&
req
->
created
);
}
else
{
const
WCHAR
*
class_ptr
=
(
WCHAR
*
)((
char
*
)
get_req_data
(
req
)
+
len
);
key
=
create_key
(
parent
,
name
,
NULL
,
req
->
options
,
req
->
modif
,
&
req
->
created
);
}
else
{
const
WCHAR
*
class_ptr
=
(
WCHAR
*
)((
char
*
)
get_req_data
(
req
)
+
len
);
if
((
class
=
req_strdupW
(
req
,
class_ptr
,
get_req_data_size
(
req
)
-
len
)))
{
key
=
create_key
(
parent
,
name
,
class
,
req
->
options
,
req
->
modif
,
&
req
->
created
);
free
(
class
);
}
}
if
(
key
)
if
((
class
=
req_strdupW
(
req
,
class_ptr
,
get_req_data_size
(
req
)
-
len
)))
{
req
->
hkey
=
alloc_handle
(
current
->
process
,
key
,
access
,
0
);
release_object
(
key
);
key
=
create_key
(
parent
,
name
,
class
,
req
->
options
,
req
->
modif
,
&
req
->
created
);
free
(
class
);
}
}
if
(
key
)
{
req
->
hkey
=
alloc_handle
(
current
->
process
,
key
,
access
,
0
);
release_object
(
key
);
}
release_object
(
parent
);
}
}
...
...
@@ -1602,26 +1623,15 @@ DECL_HANDLER(delete_key)
DECL_HANDLER
(
enum_key
)
{
struct
key
*
key
;
size_t
len
=
0
;
req
->
name
[
0
]
=
req
->
class
[
0
]
=
0
;
if
((
key
=
get_hkey_obj
(
req
->
hkey
,
KEY_ENUMERATE_SUB_KEYS
)))
{
enum_key
(
key
,
req
->
index
,
req
->
name
,
req
->
class
,
&
req
->
modif
);
release_object
(
key
);
}
}
/* query information about a registry key */
DECL_HANDLER
(
query_key_info
)
{
struct
key
*
key
;
req
->
name
[
0
]
=
req
->
class
[
0
]
=
0
;
if
((
key
=
get_hkey_obj
(
req
->
hkey
,
KEY_QUERY_VALUE
)))
if
((
key
=
get_hkey_obj
(
req
->
hkey
,
req
->
index
==
-
1
?
KEY_QUERY_VALUE
:
KEY_ENUMERATE_SUB_KEYS
)))
{
query_key
(
key
,
req
);
len
=
enum_key
(
key
,
req
->
index
,
req
);
release_object
(
key
);
}
set_req_data_size
(
req
,
len
);
}
/* set a value of a registry key */
...
...
@@ -1631,15 +1641,13 @@ DECL_HANDLER(set_key_value)
WCHAR
*
name
;
size_t
len
;
if
(
!
(
name
=
copy_req_path
(
req
,
&
len
)))
return
;
if
((
key
=
get_hkey_obj
(
req
->
hkey
,
KEY_SET_VALUE
)))
{
if
((
name
=
copy_req_path
(
req
,
&
len
)))
{
size_t
datalen
=
get_req_data_size
(
req
)
-
len
;
const
char
*
data
=
(
char
*
)
get_req_data
(
req
)
+
len
;
size_t
datalen
=
get_req_data_size
(
req
)
-
len
;
const
char
*
data
=
(
char
*
)
get_req_data
(
req
)
+
len
;
set_value
(
key
,
name
,
req
->
type
,
req
->
total
,
req
->
offset
,
datalen
,
data
);
}
set_value
(
key
,
name
,
req
->
type
,
req
->
total
,
req
->
offset
,
datalen
,
data
);
release_object
(
key
);
}
}
...
...
@@ -1649,19 +1657,17 @@ DECL_HANDLER(get_key_value)
{
struct
key
*
key
;
WCHAR
*
name
;
size_t
len
;
size_t
len
=
0
,
tmp
;
req
->
len
=
0
;
if
(
!
(
name
=
copy_req_path
(
req
,
&
tmp
)))
return
;
if
((
key
=
get_hkey_obj
(
req
->
hkey
,
KEY_QUERY_VALUE
)))
{
if
((
name
=
copy_req_path
(
req
,
&
len
)))
{
len
=
get_value
(
key
,
name
,
req
->
offset
,
get_req_data_size
(
req
),
&
req
->
type
,
&
req
->
len
,
get_req_data
(
req
)
);
set_req_data_size
(
req
,
len
);
}
len
=
get_value
(
key
,
name
,
req
->
offset
,
get_req_data_size
(
req
),
&
req
->
type
,
&
req
->
len
,
get_req_data
(
req
)
);
release_object
(
key
);
}
set_req_data_size
(
req
,
len
);
}
/* enumerate the value of a registry key */
...
...
server/request.h
View file @
454355ec
...
...
@@ -176,7 +176,6 @@ DECL_HANDLER(create_key);
DECL_HANDLER
(
open_key
);
DECL_HANDLER
(
delete_key
);
DECL_HANDLER
(
enum_key
);
DECL_HANDLER
(
query_key_info
);
DECL_HANDLER
(
set_key_value
);
DECL_HANDLER
(
get_key_value
);
DECL_HANDLER
(
enum_key_value
);
...
...
@@ -291,7 +290,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_open_key
,
(
req_handler
)
req_delete_key
,
(
req_handler
)
req_enum_key
,
(
req_handler
)
req_query_key_info
,
(
req_handler
)
req_set_key_value
,
(
req_handler
)
req_get_key_value
,
(
req_handler
)
req_enum_key_value
,
...
...
server/trace.c
View file @
454355ec
...
...
@@ -94,7 +94,7 @@ static void dump_exc_record( const EXCEPTION_RECORD *rec )
fprintf
(
stderr
,
"{code=%lx,flags=%lx,rec=%p,addr=%p,params={"
,
rec
->
ExceptionCode
,
rec
->
ExceptionFlags
,
rec
->
ExceptionRecord
,
rec
->
ExceptionAddress
);
for
(
i
=
0
;
i
<
rec
->
NumberParameters
;
i
++
)
for
(
i
=
0
;
i
<
min
(
rec
->
NumberParameters
,
EXCEPTION_MAXIMUM_PARAMETERS
)
;
i
++
)
{
if
(
i
)
fputc
(
','
,
stderr
);
fprintf
(
stderr
,
"%lx"
,
rec
->
ExceptionInformation
[
i
]
);
...
...
@@ -156,12 +156,12 @@ static size_t dump_varargs_string( const void *req )
static
size_t
dump_varargs_unicode_len_str
(
const
void
*
req
)
{
const
WCHAR
*
str
=
get_data
(
req
);
WCHAR
len
=
*
str
++
;
int
len
=
*
str
++
+
sizeof
(
WCHAR
)
;
len
=
min
(
len
,
get_size
(
req
)
);
fprintf
(
stderr
,
"L
\"
"
);
dump_strW
(
str
,
len
/
sizeof
(
WCHAR
)
,
stderr
,
"
\"\"
"
);
if
(
len
>=
sizeof
(
WCHAR
))
dump_strW
(
str
,
(
len
/
sizeof
(
WCHAR
))
-
1
,
stderr
,
"
\"\"
"
);
fputc
(
'\"'
,
stderr
);
return
len
+
sizeof
(
WCHAR
)
;
return
len
;
}
static
size_t
dump_varargs_unicode_str
(
const
void
*
req
)
...
...
@@ -1184,26 +1184,12 @@ static void dump_delete_key_request( const struct delete_key_request *req )
static
void
dump_enum_key_request
(
const
struct
enum_key_request
*
req
)
{
fprintf
(
stderr
,
" hkey=%d,"
,
req
->
hkey
);
fprintf
(
stderr
,
" index=%d"
,
req
->
index
);
fprintf
(
stderr
,
" index=%d,"
,
req
->
index
);
fprintf
(
stderr
,
" full=%d"
,
req
->
full
);
}
static
void
dump_enum_key_reply
(
const
struct
enum_key_request
*
req
)
{
fprintf
(
stderr
,
" modif=%ld,"
,
req
->
modif
);
fprintf
(
stderr
,
" name="
);
dump_path_t
(
req
,
&
req
->
name
);
fprintf
(
stderr
,
","
);
fprintf
(
stderr
,
" class="
);
dump_unicode_string
(
req
,
req
->
class
);
}
static
void
dump_query_key_info_request
(
const
struct
query_key_info_request
*
req
)
{
fprintf
(
stderr
,
" hkey=%d"
,
req
->
hkey
);
}
static
void
dump_query_key_info_reply
(
const
struct
query_key_info_request
*
req
)
{
fprintf
(
stderr
,
" subkeys=%d,"
,
req
->
subkeys
);
fprintf
(
stderr
,
" max_subkey=%d,"
,
req
->
max_subkey
);
fprintf
(
stderr
,
" max_class=%d,"
,
req
->
max_class
);
...
...
@@ -1212,10 +1198,10 @@ static void dump_query_key_info_reply( const struct query_key_info_request *req
fprintf
(
stderr
,
" max_data=%d,"
,
req
->
max_data
);
fprintf
(
stderr
,
" modif=%ld,"
,
req
->
modif
);
fprintf
(
stderr
,
" name="
);
dump_path_t
(
req
,
&
req
->
name
);
fp
rintf
(
stderr
,
","
);
cur_pos
+=
dump_varargs_unicode_len_str
(
req
);
fp
utc
(
','
,
stderr
);
fprintf
(
stderr
,
" class="
);
dump_unicode_string
(
req
,
req
->
class
);
cur_pos
+=
dump_varargs_unicode_str
(
req
);
}
static
void
dump_set_key_value_request
(
const
struct
set_key_value_request
*
req
)
...
...
@@ -1574,7 +1560,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_open_key_request
,
(
dump_func
)
dump_delete_key_request
,
(
dump_func
)
dump_enum_key_request
,
(
dump_func
)
dump_query_key_info_request
,
(
dump_func
)
dump_set_key_value_request
,
(
dump_func
)
dump_get_key_value_request
,
(
dump_func
)
dump_enum_key_value_request
,
...
...
@@ -1686,7 +1671,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_open_key_reply
,
(
dump_func
)
0
,
(
dump_func
)
dump_enum_key_reply
,
(
dump_func
)
dump_query_key_info_reply
,
(
dump_func
)
0
,
(
dump_func
)
dump_get_key_value_reply
,
(
dump_func
)
dump_enum_key_value_reply
,
...
...
@@ -1798,7 +1782,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"open_key"
,
"delete_key"
,
"enum_key"
,
"query_key_info"
,
"set_key_value"
,
"get_key_value"
,
"enum_key_value"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment