Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
2fab2ef1
Commit
2fab2ef1
authored
Nov 23, 1999
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Changed to use new server-side registry support.
parent
d7e85d66
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1358 additions
and
2581 deletions
+1358
-2581
Makefile.in
dlls/advapi32/Makefile.in
+1
-0
registry.c
dlls/advapi32/registry.c
+1065
-0
shell.spec
dlls/shell32/shell.spec
+1
-1
kernel.spec
if1632/kernel.spec
+1
-1
winbase16.h
include/wine/winbase16.h
+4
-3
winnt.h
include/winnt.h
+3
-0
winreg.h
include/winreg.h
+0
-1
registry.c
misc/registry.c
+283
-2575
No files found.
dlls/advapi32/Makefile.in
View file @
2fab2ef1
...
...
@@ -11,6 +11,7 @@ C_SRCS = \
advapi.c
\
crypt.c
\
eventlog.c
\
registry.c
\
security.c
\
service.c
...
...
dlls/advapi32/registry.c
0 → 100644
View file @
2fab2ef1
/*
* Registry management
*
* Copyright (C) 1999 Alexandre Julliard
*
* Based on misc/registry.c code
* Copyright (C) 1996 Marcus Meissner
* Copyright (C) 1998 Matthew Becker
* Copyright (C) 1999 Sylvain St-Germain
*
* This file is concerned about handle management and interaction with the Wine server.
* Registry file I/O is in misc/registry.c.
*/
#include <stdlib.h>
#include <unistd.h>
#include "winbase.h"
#include "winreg.h"
#include "winerror.h"
#include "wine/winbase16.h"
#include "winversion.h"
#include "file.h"
#include "heap.h"
#include "server.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL
(
reg
)
/* Ansi->Unicode conversion without string delimiters */
static
LPWSTR
memcpyAtoW
(
LPWSTR
dst
,
LPCSTR
src
,
INT
n
)
{
LPWSTR
p
=
dst
;
while
(
n
--
>
0
)
*
p
++
=
(
WCHAR
)
*
src
++
;
return
dst
;
}
/* Unicode->Ansi conversion without string delimiters */
static
LPSTR
memcpyWtoA
(
LPSTR
dst
,
LPCWSTR
src
,
INT
n
)
{
LPSTR
p
=
dst
;
while
(
n
--
>
0
)
*
p
++
=
(
CHAR
)
*
src
++
;
return
dst
;
}
/* check if value type needs string conversion (Ansi<->Unicode) */
static
inline
int
is_string
(
DWORD
type
)
{
return
(
type
==
REG_SZ
)
||
(
type
==
REG_EXPAND_SZ
)
||
(
type
==
REG_MULTI_SZ
);
}
/* copy key value data into a user-specified buffer
*
* 'len' is the total length of the data
* 'count' is the size of the user-specified buffer
* and is updated to reflect the length copied
*/
static
DWORD
copy_data
(
void
*
data
,
const
void
*
src
,
DWORD
len
,
DWORD
*
count
)
{
DWORD
ret
=
ERROR_SUCCESS
;
if
(
data
)
{
if
(
*
count
<
len
)
ret
=
ERROR_MORE_DATA
;
else
memcpy
(
data
,
src
,
len
);
}
*
count
=
len
;
return
ret
;
}
/* same as copy_data but with optional Unicode->Ascii conversion depending on the type */
static
DWORD
copy_data_WtoA
(
void
*
data
,
const
void
*
src
,
DWORD
len
,
DWORD
*
count
,
DWORD
type
)
{
DWORD
ret
=
ERROR_SUCCESS
;
if
(
is_string
(
type
))
{
/* need to convert from Unicode */
len
/=
sizeof
(
WCHAR
);
if
(
data
)
{
if
(
*
count
<
len
)
ret
=
ERROR_MORE_DATA
;
else
memcpyWtoA
(
data
,
src
,
len
);
}
}
else
if
(
data
)
{
if
(
*
count
<
len
)
ret
=
ERROR_MORE_DATA
;
else
memcpy
(
data
,
src
,
len
);
}
*
count
=
len
;
return
ret
;
}
/* copy a key name into the request buffer */
static
inline
DWORD
copy_nameW
(
LPWSTR
dest
,
LPCWSTR
name
)
{
if
(
name
)
{
if
(
lstrlenW
(
name
)
>
MAX_PATH
)
return
ERROR_MORE_DATA
;
lstrcpyW
(
dest
,
name
);
}
else
dest
[
0
]
=
0
;
return
ERROR_SUCCESS
;
}
/* copy a key name into the request buffer */
static
inline
DWORD
copy_nameAtoW
(
LPWSTR
dest
,
LPCSTR
name
)
{
if
(
name
)
{
if
(
strlen
(
name
)
>
MAX_PATH
)
return
ERROR_MORE_DATA
;
lstrcpyAtoW
(
dest
,
name
);
}
else
dest
[
0
]
=
0
;
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegCreateKeyExW [ADVAPI32.131]
*
* PARAMS
* hkey [I] Handle of an open key
* name [I] Address of subkey name
* reserved [I] Reserved - must be 0
* class [I] Address of class string
* options [I] Special options flag
* access [I] Desired security access
* sa [I] Address of key security structure
* retkey [O] Address of buffer for opened handle
* dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
*/
DWORD
WINAPI
RegCreateKeyExW
(
HKEY
hkey
,
LPCWSTR
name
,
DWORD
reserved
,
LPWSTR
class
,
DWORD
options
,
REGSAM
access
,
SECURITY_ATTRIBUTES
*
sa
,
LPHKEY
retkey
,
LPDWORD
dispos
)
{
DWORD
ret
;
struct
create_key_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)
\n
"
,
hkey
,
debugstr_w
(
name
),
reserved
,
debugstr_w
(
class
),
options
,
access
,
sa
,
retkey
,
dispos
);
if
(
reserved
)
return
ERROR_INVALID_PARAMETER
;
if
(
!
(
access
&
KEY_ALL_ACCESS
)
||
(
access
&
~
KEY_ALL_ACCESS
))
return
ERROR_ACCESS_DENIED
;
req
->
parent
=
hkey
;
req
->
access
=
access
;
req
->
options
=
options
;
req
->
modif
=
time
(
NULL
);
if
((
ret
=
copy_nameW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
if
(
req
->
name
[
0
]
==
'\\'
)
return
ERROR_BAD_PATHNAME
;
lstrcpynW
(
req
->
class
,
class
?
class
:
(
LPWSTR
)
"
\0\0
"
,
server_remaining
(
req
->
class
)
/
sizeof
(
WCHAR
)
);
if
((
ret
=
server_call_noerr
(
REQ_CREATE_KEY
))
==
ERROR_SUCCESS
)
{
*
retkey
=
req
->
hkey
;
if
(
dispos
)
*
dispos
=
req
->
created
?
REG_CREATED_NEW_KEY
:
REG_OPENED_EXISTING_KEY
;
}
return
ret
;
}
/******************************************************************************
* RegCreateKeyExA [ADVAPI32.130]
*/
DWORD
WINAPI
RegCreateKeyExA
(
HKEY
hkey
,
LPCSTR
name
,
DWORD
reserved
,
LPSTR
class
,
DWORD
options
,
REGSAM
access
,
SECURITY_ATTRIBUTES
*
sa
,
LPHKEY
retkey
,
LPDWORD
dispos
)
{
DWORD
ret
;
struct
create_key_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)
\n
"
,
hkey
,
debugstr_a
(
name
),
reserved
,
debugstr_a
(
class
),
options
,
access
,
sa
,
retkey
,
dispos
);
if
(
reserved
)
return
ERROR_INVALID_PARAMETER
;
if
(
!
(
access
&
KEY_ALL_ACCESS
)
||
(
access
&
~
KEY_ALL_ACCESS
))
return
ERROR_ACCESS_DENIED
;
req
->
parent
=
hkey
;
req
->
access
=
access
;
req
->
options
=
options
;
req
->
modif
=
time
(
NULL
);
if
((
ret
=
copy_nameAtoW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
if
(
req
->
name
[
0
]
==
'\\'
)
return
ERROR_BAD_PATHNAME
;
lstrcpynAtoW
(
req
->
class
,
class
?
class
:
""
,
server_remaining
(
req
->
class
)
/
sizeof
(
WCHAR
)
);
if
((
ret
=
server_call_noerr
(
REQ_CREATE_KEY
))
==
ERROR_SUCCESS
)
{
*
retkey
=
req
->
hkey
;
if
(
dispos
)
*
dispos
=
req
->
created
?
REG_CREATED_NEW_KEY
:
REG_OPENED_EXISTING_KEY
;
}
return
ret
;
}
/******************************************************************************
* RegCreateKeyW [ADVAPI32.132]
*/
DWORD
WINAPI
RegCreateKeyW
(
HKEY
hkey
,
LPCWSTR
name
,
LPHKEY
retkey
)
{
/* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
/* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
return
RegCreateKeyExW
(
hkey
,
name
,
0
,
NULL
,
REG_OPTION_NON_VOLATILE
,
KEY_ALL_ACCESS
,
NULL
,
retkey
,
NULL
);
}
/******************************************************************************
* RegCreateKeyA [ADVAPI32.129]
*/
DWORD
WINAPI
RegCreateKeyA
(
HKEY
hkey
,
LPCSTR
name
,
LPHKEY
retkey
)
{
return
RegCreateKeyExA
(
hkey
,
name
,
0
,
NULL
,
REG_OPTION_NON_VOLATILE
,
KEY_ALL_ACCESS
,
NULL
,
retkey
,
NULL
);
}
/******************************************************************************
* RegOpenKeyExW [ADVAPI32.150]
*
* Opens the specified key
*
* Unlike RegCreateKeyEx, this does not create the key if it does not exist.
*
* PARAMS
* hkey [I] Handle of open key
* name [I] Name of subkey to open
* reserved [I] Reserved - must be zero
* access [I] Security access mask
* retkey [O] Handle to open key
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD
WINAPI
RegOpenKeyExW
(
HKEY
hkey
,
LPCWSTR
name
,
DWORD
reserved
,
REGSAM
access
,
LPHKEY
retkey
)
{
DWORD
ret
;
struct
open_key_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s,%ld,%lx,%p)
\n
"
,
hkey
,
debugstr_w
(
name
),
reserved
,
access
,
retkey
);
if
(
!
retkey
)
return
ERROR_INVALID_PARAMETER
;
req
->
parent
=
hkey
;
req
->
access
=
access
;
if
((
ret
=
copy_nameW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
if
(
req
->
name
[
0
]
==
'\\'
)
return
ERROR_BAD_PATHNAME
;
if
((
ret
=
server_call_noerr
(
REQ_OPEN_KEY
))
==
ERROR_SUCCESS
)
*
retkey
=
req
->
hkey
;
return
ret
;
}
/******************************************************************************
* RegOpenKeyExA [ADVAPI32.149]
*/
DWORD
WINAPI
RegOpenKeyExA
(
HKEY
hkey
,
LPCSTR
name
,
DWORD
reserved
,
REGSAM
access
,
LPHKEY
retkey
)
{
DWORD
ret
;
struct
open_key_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s,%ld,%lx,%p)
\n
"
,
hkey
,
debugstr_a
(
name
),
reserved
,
access
,
retkey
);
if
(
!
retkey
)
return
ERROR_INVALID_PARAMETER
;
req
->
parent
=
hkey
;
req
->
access
=
access
;
if
((
ret
=
copy_nameAtoW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
if
(
req
->
name
[
0
]
==
'\\'
)
return
ERROR_BAD_PATHNAME
;
if
((
ret
=
server_call_noerr
(
REQ_OPEN_KEY
))
==
ERROR_SUCCESS
)
*
retkey
=
req
->
hkey
;
return
ret
;
}
/******************************************************************************
* RegOpenKeyW [ADVAPI32.151]
*
* PARAMS
* hkey [I] Handle of open key
* name [I] Address of name of subkey to open
* retkey [O] Handle to open key
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD
WINAPI
RegOpenKeyW
(
HKEY
hkey
,
LPCWSTR
name
,
LPHKEY
retkey
)
{
return
RegOpenKeyExW
(
hkey
,
name
,
0
,
KEY_ALL_ACCESS
,
retkey
);
}
/******************************************************************************
* RegOpenKeyA [ADVAPI32.148]
*/
DWORD
WINAPI
RegOpenKeyA
(
HKEY
hkey
,
LPCSTR
name
,
LPHKEY
retkey
)
{
return
RegOpenKeyExA
(
hkey
,
name
,
0
,
KEY_ALL_ACCESS
,
retkey
);
}
/******************************************************************************
* RegEnumKeyExW [ADVAPI32.139]
*
* PARAMS
* hkey [I] Handle to key to enumerate
* index [I] Index of subkey to enumerate
* name [O] Buffer for subkey name
* name_len [O] Size of subkey buffer
* reserved [I] Reserved
* class [O] Buffer for class string
* class_len [O] Size of class buffer
* ft [O] Time key last written to
*/
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
();
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
=
server_call_noerr
(
REQ_ENUM_KEY
))
!=
ERROR_SUCCESS
)
return
ret
;
len
=
lstrlenW
(
req
->
name
)
+
1
;
cls_len
=
lstrlenW
(
req
->
class
)
+
1
;
if
(
len
>
*
name_len
)
return
ERROR_MORE_DATA
;
if
(
class_len
&&
(
cls_len
>
*
class_len
))
return
ERROR_MORE_DATA
;
memcpy
(
name
,
req
->
name
,
len
*
sizeof
(
WCHAR
)
);
*
name_len
=
len
-
1
;
if
(
class_len
)
{
if
(
class
)
memcpy
(
class
,
req
->
class
,
cls_len
*
sizeof
(
WCHAR
)
);
*
class_len
=
cls_len
-
1
;
}
if
(
ft
)
DOSFS_UnixTimeToFileTime
(
req
->
modif
,
ft
,
0
);
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegEnumKeyExA [ADVAPI32.138]
*/
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
();
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
=
server_call_noerr
(
REQ_ENUM_KEY
))
!=
ERROR_SUCCESS
)
return
ret
;
len
=
lstrlenW
(
req
->
name
)
+
1
;
cls_len
=
lstrlenW
(
req
->
class
)
+
1
;
if
(
len
>
*
name_len
)
return
ERROR_MORE_DATA
;
if
(
class_len
&&
(
cls_len
>
*
class_len
))
return
ERROR_MORE_DATA
;
memcpyWtoA
(
name
,
req
->
name
,
len
);
*
name_len
=
len
-
1
;
if
(
class_len
)
{
if
(
class
)
memcpyWtoA
(
class
,
req
->
class
,
cls_len
);
*
class_len
=
cls_len
-
1
;
}
if
(
ft
)
DOSFS_UnixTimeToFileTime
(
req
->
modif
,
ft
,
0
);
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegEnumKeyW [ADVAPI32.140]
*/
DWORD
WINAPI
RegEnumKeyW
(
HKEY
hkey
,
DWORD
index
,
LPWSTR
name
,
DWORD
name_len
)
{
return
RegEnumKeyExW
(
hkey
,
index
,
name
,
&
name_len
,
NULL
,
NULL
,
NULL
,
NULL
);
}
/******************************************************************************
* RegEnumKeyA [ADVAPI32.137]
*/
DWORD
WINAPI
RegEnumKeyA
(
HKEY
hkey
,
DWORD
index
,
LPSTR
name
,
DWORD
name_len
)
{
return
RegEnumKeyExA
(
hkey
,
index
,
name
,
&
name_len
,
NULL
,
NULL
,
NULL
,
NULL
);
}
/******************************************************************************
* RegQueryInfoKeyW [ADVAPI32.153]
*
* PARAMS
* hkey [I] Handle to key to query
* class [O] Buffer for class string
* class_len [O] Size of class string buffer
* reserved [I] Reserved
* subkeys [O] Buffer for number of subkeys
* max_subkey [O] Buffer for longest subkey name length
* max_class [O] Buffer for longest class string length
* values [O] Buffer for number of value entries
* max_value [O] Buffer for longest value name length
* max_data [O] Buffer for longest value data length
* security [O] Buffer for security descriptor length
* modif [O] Modification time
*
* - win95 allows class to be valid and class_len to be NULL
* - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
* - both allow class to be NULL and class_len to be NULL
* (it's hard to test validity, so test !NULL instead)
*/
DWORD
WINAPI
RegQueryInfoKeyW
(
HKEY
hkey
,
LPWSTR
class
,
LPDWORD
class_len
,
LPDWORD
reserved
,
LPDWORD
subkeys
,
LPDWORD
max_subkey
,
LPDWORD
max_class
,
LPDWORD
values
,
LPDWORD
max_value
,
LPDWORD
max_data
,
LPDWORD
security
,
FILETIME
*
modif
)
{
DWORD
ret
;
struct
query_key_info_request
*
req
=
get_req_buffer
();
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
);
if
(
class
&&
!
class_len
&&
(
VERSION_GetVersion
()
==
NT40
))
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
if
((
ret
=
server_call_noerr
(
REQ_QUERY_KEY_INFO
))
!=
ERROR_SUCCESS
)
return
ret
;
if
(
class
)
{
if
(
class_len
&&
(
lstrlenW
(
req
->
class
)
+
1
>
*
class_len
))
{
*
class_len
=
lstrlenW
(
req
->
class
);
return
ERROR_MORE_DATA
;
}
lstrcpyW
(
class
,
req
->
class
);
}
if
(
class_len
)
*
class_len
=
lstrlenW
(
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
)
DOSFS_UnixTimeToFileTime
(
req
->
modif
,
modif
,
0
);
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegQueryInfoKeyA [ADVAPI32.152]
*/
DWORD
WINAPI
RegQueryInfoKeyA
(
HKEY
hkey
,
LPSTR
class
,
LPDWORD
class_len
,
LPDWORD
reserved
,
LPDWORD
subkeys
,
LPDWORD
max_subkey
,
LPDWORD
max_class
,
LPDWORD
values
,
LPDWORD
max_value
,
LPDWORD
max_data
,
LPDWORD
security
,
FILETIME
*
modif
)
{
DWORD
ret
;
struct
query_key_info_request
*
req
=
get_req_buffer
();
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
);
if
(
class
&&
!
class_len
&&
(
VERSION_GetVersion
()
==
NT40
))
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
if
((
ret
=
server_call_noerr
(
REQ_QUERY_KEY_INFO
))
!=
ERROR_SUCCESS
)
return
ret
;
if
(
class
)
{
if
(
class_len
&&
(
lstrlenW
(
req
->
class
)
+
1
>
*
class_len
))
{
*
class_len
=
lstrlenW
(
req
->
class
);
return
ERROR_MORE_DATA
;
}
lstrcpyWtoA
(
class
,
req
->
class
);
}
if
(
class_len
)
*
class_len
=
lstrlenW
(
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
)
DOSFS_UnixTimeToFileTime
(
req
->
modif
,
modif
,
0
);
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegCloseKey [ADVAPI32.126]
*
* Releases the handle of the specified key
*
* PARAMS
* hkey [I] Handle of key to close
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD
WINAPI
RegCloseKey
(
HKEY
hkey
)
{
struct
close_key_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x)
\n
"
,
hkey
);
req
->
hkey
=
hkey
;
return
server_call_noerr
(
REQ_CLOSE_KEY
);
}
/******************************************************************************
* RegDeleteKeyW [ADVAPI32.134]
*
* PARAMS
* hkey [I] Handle to open key
* name [I] Name of subkey to delete
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD
WINAPI
RegDeleteKeyW
(
HKEY
hkey
,
LPCWSTR
name
)
{
DWORD
ret
;
struct
delete_key_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s)
\n
"
,
hkey
,
debugstr_w
(
name
)
);
req
->
hkey
=
hkey
;
if
((
ret
=
copy_nameW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
if
(
req
->
name
[
0
]
==
'\\'
)
return
ERROR_BAD_PATHNAME
;
return
server_call_noerr
(
REQ_DELETE_KEY
);
}
/******************************************************************************
* RegDeleteKeyA [ADVAPI32.133]
*/
DWORD
WINAPI
RegDeleteKeyA
(
HKEY
hkey
,
LPCSTR
name
)
{
DWORD
ret
;
struct
delete_key_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s)
\n
"
,
hkey
,
debugstr_a
(
name
)
);
req
->
hkey
=
hkey
;
if
((
ret
=
copy_nameAtoW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
if
(
req
->
name
[
0
]
==
'\\'
)
return
ERROR_BAD_PATHNAME
;
return
server_call_noerr
(
REQ_DELETE_KEY
);
}
/******************************************************************************
* RegSetValueExW [ADVAPI32.170]
*
* Sets the data and type of a value under a register key
*
* PARAMS
* hkey [I] Handle of key to set value for
* name [I] Name of value to set
* reserved [I] Reserved - must be zero
* type [I] Flag for value type
* data [I] Address of value data
* count [I] Size of value data
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*
* NOTES
* win95 does not care about count for REG_SZ and finds out the len by itself (js)
* NT does definitely care (aj)
*/
DWORD
WINAPI
RegSetValueExW
(
HKEY
hkey
,
LPCWSTR
name
,
DWORD
reserved
,
DWORD
type
,
CONST
BYTE
*
data
,
DWORD
count
)
{
DWORD
ret
;
struct
set_key_value_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s,%ld,%ld,%p,%ld)
\n
"
,
hkey
,
debugstr_w
(
name
),
reserved
,
type
,
data
,
count
);
if
(
reserved
)
return
ERROR_INVALID_PARAMETER
;
if
(
count
&&
type
==
REG_SZ
)
{
LPCWSTR
str
=
(
LPCWSTR
)
data
;
/* if user forgot to count terminating null, add it (yes NT does this) */
if
(
str
[
count
/
sizeof
(
WCHAR
)
-
1
]
&&
!
str
[
count
/
sizeof
(
WCHAR
)])
count
+=
sizeof
(
WCHAR
);
}
if
(
count
>=
server_remaining
(
req
->
data
))
return
ERROR_OUTOFMEMORY
;
/* FIXME */
req
->
hkey
=
hkey
;
req
->
type
=
type
;
req
->
len
=
count
;
if
((
ret
=
copy_nameW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
memcpy
(
req
->
data
,
data
,
count
);
return
server_call_noerr
(
REQ_SET_KEY_VALUE
);
}
/******************************************************************************
* RegSetValueExA [ADVAPI32.169]
*/
DWORD
WINAPI
RegSetValueExA
(
HKEY
hkey
,
LPCSTR
name
,
DWORD
reserved
,
DWORD
type
,
CONST
BYTE
*
data
,
DWORD
count
)
{
DWORD
ret
;
struct
set_key_value_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s,%ld,%ld,%p,%ld)
\n
"
,
hkey
,
debugstr_a
(
name
),
reserved
,
type
,
data
,
count
);
if
(
reserved
)
return
ERROR_INVALID_PARAMETER
;
if
(
count
&&
type
==
REG_SZ
)
{
/* if user forgot to count terminating null, add it (yes NT does this) */
if
(
data
[
count
-
1
]
&&
!
data
[
count
])
count
++
;
}
if
(
is_string
(
type
))
{
/* need to convert to Unicode */
count
*=
sizeof
(
WCHAR
);
if
(
count
>=
server_remaining
(
req
->
data
))
return
ERROR_OUTOFMEMORY
;
/* FIXME */
memcpyAtoW
(
(
LPWSTR
)
req
->
data
,
data
,
count
/
sizeof
(
WCHAR
)
);
}
else
{
if
(
count
>=
server_remaining
(
req
->
data
))
return
ERROR_OUTOFMEMORY
;
/* FIXME */
memcpy
(
req
->
data
,
data
,
count
);
}
req
->
hkey
=
hkey
;
req
->
type
=
type
;
req
->
len
=
count
;
if
((
ret
=
copy_nameAtoW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
return
server_call_noerr
(
REQ_SET_KEY_VALUE
);
}
/******************************************************************************
* RegSetValueW [ADVAPI32.171]
*/
DWORD
WINAPI
RegSetValueW
(
HKEY
hkey
,
LPCWSTR
name
,
DWORD
type
,
LPCWSTR
data
,
DWORD
count
)
{
HKEY
subkey
=
hkey
;
DWORD
ret
;
TRACE
(
"(0x%x,%s,%ld,%s,%ld)
\n
"
,
hkey
,
debugstr_w
(
name
),
type
,
debugstr_w
(
data
),
count
);
if
(
type
!=
REG_SZ
)
return
ERROR_INVALID_PARAMETER
;
if
(
name
&&
name
[
0
])
/* need to create the subkey */
{
if
((
ret
=
RegCreateKeyW
(
hkey
,
name
,
&
subkey
))
!=
ERROR_SUCCESS
)
return
ret
;
}
ret
=
RegSetValueExW
(
subkey
,
NULL
,
0
,
REG_SZ
,
(
LPBYTE
)
data
,
(
lstrlenW
(
data
)
+
1
)
*
sizeof
(
WCHAR
)
);
if
(
subkey
!=
hkey
)
RegCloseKey
(
subkey
);
return
ret
;
}
/******************************************************************************
* RegSetValueA [ADVAPI32.168]
*/
DWORD
WINAPI
RegSetValueA
(
HKEY
hkey
,
LPCSTR
name
,
DWORD
type
,
LPCSTR
data
,
DWORD
count
)
{
HKEY
subkey
=
hkey
;
DWORD
ret
;
TRACE
(
"(0x%x,%s,%ld,%s,%ld)
\n
"
,
hkey
,
debugstr_a
(
name
),
type
,
debugstr_a
(
data
),
count
);
if
(
type
!=
REG_SZ
)
return
ERROR_INVALID_PARAMETER
;
if
(
name
&&
name
[
0
])
/* need to create the subkey */
{
if
((
ret
=
RegCreateKeyA
(
hkey
,
name
,
&
subkey
))
!=
ERROR_SUCCESS
)
return
ret
;
}
ret
=
RegSetValueExA
(
subkey
,
NULL
,
0
,
REG_SZ
,
(
LPBYTE
)
data
,
strlen
(
data
)
+
1
);
if
(
subkey
!=
hkey
)
RegCloseKey
(
subkey
);
return
ret
;
}
/******************************************************************************
* RegQueryValueExW [ADVAPI32.158]
*
* Retrieves type and data for a specified name associated with an open key
*
* PARAMS
* hkey [I] Handle of key to query
* name [I] Name of value to query
* reserved [I] Reserved - must be NULL
* type [O] Address of buffer for value type. If NULL, the type
* is not required.
* data [O] Address of data buffer. If NULL, the actual data is
* not required.
* count [I/O] Address of data buffer size
*
* RETURNS
* ERROR_SUCCESS: Success
* ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
* buffer is left untouched. The MS-documentation is wrong (js) !!!
*/
DWORD
WINAPI
RegQueryValueExW
(
HKEY
hkey
,
LPCWSTR
name
,
LPDWORD
reserved
,
LPDWORD
type
,
LPBYTE
data
,
LPDWORD
count
)
{
DWORD
ret
;
struct
get_key_value_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s,%p,%p,%p,%p=%ld)
\n
"
,
hkey
,
debugstr_w
(
name
),
reserved
,
type
,
data
,
count
,
count
?
*
count
:
0
);
if
(
!
count
||
reserved
)
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
if
((
ret
=
copy_nameW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
if
((
ret
=
server_call_noerr
(
REQ_GET_KEY_VALUE
))
==
ERROR_SUCCESS
)
{
if
(
type
)
*
type
=
req
->
type
;
ret
=
copy_data
(
data
,
req
->
data
,
req
->
len
,
count
);
}
return
ret
;
}
/******************************************************************************
* RegQueryValueExA [ADVAPI32.157]
*
* NOTES:
* the documentation is wrong: if the buffer is to small it remains untouched
*/
DWORD
WINAPI
RegQueryValueExA
(
HKEY
hkey
,
LPCSTR
name
,
LPDWORD
reserved
,
LPDWORD
type
,
LPBYTE
data
,
LPDWORD
count
)
{
DWORD
ret
;
struct
get_key_value_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s,%p,%p,%p,%p=%ld)
\n
"
,
hkey
,
debugstr_a
(
name
),
reserved
,
type
,
data
,
count
,
count
?
*
count
:
0
);
if
(
!
count
||
reserved
)
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
if
((
ret
=
copy_nameAtoW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
if
((
ret
=
server_call_noerr
(
REQ_GET_KEY_VALUE
))
==
ERROR_SUCCESS
)
{
if
(
type
)
*
type
=
req
->
type
;
ret
=
copy_data_WtoA
(
data
,
req
->
data
,
req
->
len
,
count
,
req
->
type
);
}
return
ret
;
}
/******************************************************************************
* RegQueryValueW [ADVAPI32.159]
*/
DWORD
WINAPI
RegQueryValueW
(
HKEY
hkey
,
LPCWSTR
name
,
LPWSTR
data
,
LPLONG
count
)
{
DWORD
ret
;
HKEY
subkey
=
hkey
;
TRACE
(
"(%x,%s,%p,%ld)
\n
"
,
hkey
,
debugstr_w
(
name
),
data
,
count
?
*
count
:
0
);
if
(
name
&&
name
[
0
])
{
if
((
ret
=
RegOpenKeyW
(
hkey
,
name
,
&
subkey
))
!=
ERROR_SUCCESS
)
return
ret
;
}
ret
=
RegQueryValueExW
(
subkey
,
NULL
,
NULL
,
NULL
,
(
LPBYTE
)
data
,
count
);
if
(
subkey
!=
hkey
)
RegCloseKey
(
subkey
);
if
(
ret
==
ERROR_FILE_NOT_FOUND
)
{
/* return empty string if default value not found */
if
(
data
)
*
data
=
0
;
if
(
count
)
*
count
=
1
;
ret
=
ERROR_SUCCESS
;
}
return
ret
;
}
/******************************************************************************
* RegQueryValueA [ADVAPI32.156]
*/
DWORD
WINAPI
RegQueryValueA
(
HKEY
hkey
,
LPCSTR
name
,
LPSTR
data
,
LPLONG
count
)
{
DWORD
ret
;
HKEY
subkey
=
hkey
;
TRACE
(
"(%x,%s,%p,%ld)
\n
"
,
hkey
,
debugstr_a
(
name
),
data
,
count
?
*
count
:
0
);
if
(
name
&&
name
[
0
])
{
if
((
ret
=
RegOpenKeyA
(
hkey
,
name
,
&
subkey
))
!=
ERROR_SUCCESS
)
return
ret
;
}
ret
=
RegQueryValueExA
(
subkey
,
NULL
,
NULL
,
NULL
,
(
LPBYTE
)
data
,
count
);
if
(
subkey
!=
hkey
)
RegCloseKey
(
subkey
);
if
(
ret
==
ERROR_FILE_NOT_FOUND
)
{
/* return empty string if default value not found */
if
(
data
)
*
data
=
0
;
if
(
count
)
*
count
=
1
;
ret
=
ERROR_SUCCESS
;
}
return
ret
;
}
/******************************************************************************
* RegEnumValueW [ADVAPI32.142]
*
* PARAMS
* hkey [I] Handle to key to query
* index [I] Index of value to query
* value [O] Value string
* val_count [I/O] Size of value buffer (in wchars)
* reserved [I] Reserved
* type [O] Type code
* data [O] Value data
* count [I/O] Size of data buffer (in bytes)
*/
DWORD
WINAPI
RegEnumValueW
(
HKEY
hkey
,
DWORD
index
,
LPWSTR
value
,
LPDWORD
val_count
,
LPDWORD
reserved
,
LPDWORD
type
,
LPBYTE
data
,
LPDWORD
count
)
{
DWORD
ret
,
len
;
struct
enum_key_value_request
*
req
=
get_req_buffer
();
TRACE
(
"(%x,%ld,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
index
,
value
,
val_count
,
reserved
,
type
,
data
,
count
);
/* NT only checks count, not val_count */
if
(
!
count
||
reserved
)
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
req
->
index
=
index
;
if
((
ret
=
server_call_noerr
(
REQ_ENUM_KEY_VALUE
))
!=
ERROR_SUCCESS
)
return
ret
;
len
=
lstrlenW
(
req
->
name
)
+
1
;
if
(
len
>
*
val_count
)
return
ERROR_MORE_DATA
;
memcpy
(
value
,
req
->
name
,
len
*
sizeof
(
WCHAR
)
);
*
val_count
=
len
-
1
;
if
(
type
)
*
type
=
req
->
type
;
return
copy_data
(
data
,
req
->
data
,
req
->
len
,
count
);
}
/******************************************************************************
* RegEnumValueA [ADVAPI32.141]
*/
DWORD
WINAPI
RegEnumValueA
(
HKEY
hkey
,
DWORD
index
,
LPSTR
value
,
LPDWORD
val_count
,
LPDWORD
reserved
,
LPDWORD
type
,
LPBYTE
data
,
LPDWORD
count
)
{
DWORD
ret
,
len
;
struct
enum_key_value_request
*
req
=
get_req_buffer
();
TRACE
(
"(%x,%ld,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
index
,
value
,
val_count
,
reserved
,
type
,
data
,
count
);
/* NT only checks count, not val_count */
if
(
!
count
||
reserved
)
return
ERROR_INVALID_PARAMETER
;
req
->
hkey
=
hkey
;
req
->
index
=
index
;
if
((
ret
=
server_call_noerr
(
REQ_ENUM_KEY_VALUE
))
!=
ERROR_SUCCESS
)
return
ret
;
len
=
lstrlenW
(
req
->
name
)
+
1
;
if
(
len
>
*
val_count
)
return
ERROR_MORE_DATA
;
memcpyWtoA
(
value
,
req
->
name
,
len
);
*
val_count
=
len
-
1
;
if
(
type
)
*
type
=
req
->
type
;
return
copy_data_WtoA
(
data
,
req
->
data
,
req
->
len
,
count
,
req
->
type
);
}
/******************************************************************************
* RegDeleteValueW [ADVAPI32.136]
*
* PARAMS
* hkey [I] handle to key
* name [I] name of value to delete
*
* RETURNS
* error status
*/
DWORD
WINAPI
RegDeleteValueW
(
HKEY
hkey
,
LPCWSTR
name
)
{
DWORD
ret
;
struct
delete_key_value_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s)
\n
"
,
hkey
,
debugstr_w
(
name
)
);
req
->
hkey
=
hkey
;
if
((
ret
=
copy_nameW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
return
server_call_noerr
(
REQ_DELETE_KEY_VALUE
);
}
/******************************************************************************
* RegDeleteValueA [ADVAPI32.135]
*/
DWORD
WINAPI
RegDeleteValueA
(
HKEY
hkey
,
LPCSTR
name
)
{
DWORD
ret
;
struct
delete_key_value_request
*
req
=
get_req_buffer
();
TRACE
(
"(0x%x,%s)
\n
"
,
hkey
,
debugstr_a
(
name
)
);
req
->
hkey
=
hkey
;
if
((
ret
=
copy_nameAtoW
(
req
->
name
,
name
))
!=
ERROR_SUCCESS
)
return
ret
;
return
server_call_noerr
(
REQ_DELETE_KEY_VALUE
);
}
/******************************************************************************
* RegLoadKeyW [ADVAPI32.185]
*
* PARAMS
* hkey [I] Handle of open key
* subkey [I] Address of name of subkey
* filename [I] Address of filename for registry information
*/
LONG
WINAPI
RegLoadKeyW
(
HKEY
hkey
,
LPCWSTR
subkey
,
LPCWSTR
filename
)
{
struct
load_registry_request
*
req
=
get_req_buffer
();
HANDLE
file
;
DWORD
ret
,
err
=
GetLastError
();
TRACE
(
"(%x,%s,%s)
\n
"
,
hkey
,
debugstr_w
(
subkey
),
debugstr_w
(
filename
)
);
if
(
!
filename
||
!*
filename
)
return
ERROR_INVALID_PARAMETER
;
if
(
!
subkey
||
!*
subkey
)
return
ERROR_INVALID_PARAMETER
;
if
((
file
=
CreateFileW
(
filename
,
GENERIC_READ
,
0
,
NULL
,
OPEN_EXISTING
,
FILE_ATTRIBUTE_NORMAL
,
-
1
))
==
INVALID_HANDLE_VALUE
)
{
ret
=
GetLastError
();
goto
done
;
}
req
->
hkey
=
hkey
;
req
->
file
=
file
;
if
((
ret
=
copy_nameW
(
req
->
name
,
subkey
))
!=
ERROR_SUCCESS
)
goto
done
;
ret
=
server_call_noerr
(
REQ_LOAD_REGISTRY
);
CloseHandle
(
file
);
done
:
SetLastError
(
err
);
/* restore the last error code */
return
ret
;
}
/******************************************************************************
* RegLoadKeyA [ADVAPI32.184]
*/
LONG
WINAPI
RegLoadKeyA
(
HKEY
hkey
,
LPCSTR
subkey
,
LPCSTR
filename
)
{
struct
load_registry_request
*
req
=
get_req_buffer
();
HANDLE
file
;
DWORD
ret
,
err
=
GetLastError
();
TRACE
(
"(%x,%s,%s)
\n
"
,
hkey
,
debugstr_a
(
subkey
),
debugstr_a
(
filename
)
);
if
(
!
filename
||
!*
filename
)
return
ERROR_INVALID_PARAMETER
;
if
(
!
subkey
||
!*
subkey
)
return
ERROR_INVALID_PARAMETER
;
if
((
file
=
CreateFileA
(
filename
,
GENERIC_READ
,
0
,
NULL
,
OPEN_EXISTING
,
FILE_ATTRIBUTE_NORMAL
,
-
1
))
==
INVALID_HANDLE_VALUE
)
{
ret
=
GetLastError
();
goto
done
;
}
req
->
hkey
=
hkey
;
req
->
file
=
file
;
if
((
ret
=
copy_nameAtoW
(
req
->
name
,
subkey
))
!=
ERROR_SUCCESS
)
goto
done
;
ret
=
server_call_noerr
(
REQ_LOAD_REGISTRY
);
CloseHandle
(
file
);
done
:
SetLastError
(
err
);
/* restore the last error code */
return
ret
;
}
/******************************************************************************
* RegSaveKeyA [ADVAPI32.165]
*
* PARAMS
* hkey [I] Handle of key where save begins
* lpFile [I] Address of filename to save to
* sa [I] Address of security structure
*/
LONG
WINAPI
RegSaveKeyA
(
HKEY
hkey
,
LPCSTR
file
,
LPSECURITY_ATTRIBUTES
sa
)
{
struct
save_registry_request
*
req
=
get_req_buffer
();
char
buffer
[
1024
];
int
count
=
0
;
LPSTR
name
;
DWORD
ret
,
err
;
HFILE
handle
;
TRACE
(
"(%x,%s,%p)
\n
"
,
hkey
,
debugstr_a
(
file
),
sa
);
if
(
!
file
||
!*
file
)
return
ERROR_INVALID_PARAMETER
;
err
=
GetLastError
();
GetFullPathNameA
(
file
,
sizeof
(
buffer
),
buffer
,
&
name
);
for
(;;)
{
sprintf
(
name
,
"reg%04x.tmp"
,
count
++
);
handle
=
CreateFileA
(
buffer
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_NEW
,
FILE_ATTRIBUTE_NORMAL
,
-
1
);
if
(
handle
!=
INVALID_HANDLE_VALUE
)
break
;
if
((
ret
=
GetLastError
())
!=
ERROR_FILE_EXISTS
)
goto
done
;
}
req
->
hkey
=
hkey
;
req
->
file
=
handle
;
ret
=
server_call_noerr
(
REQ_SAVE_REGISTRY
);
CloseHandle
(
handle
);
if
(
!
ret
)
{
if
(
!
MoveFileExA
(
buffer
,
file
,
MOVEFILE_REPLACE_EXISTING
))
{
ERR
(
"Failed to move %s to %s
\n
"
,
buffer
,
file
);
ret
=
GetLastError
();
}
}
if
(
ret
)
DeleteFileA
(
buffer
);
done
:
SetLastError
(
err
);
/* restore last error code */
return
ret
;
}
/******************************************************************************
* RegSaveKeyW [ADVAPI32.166]
*/
LONG
WINAPI
RegSaveKeyW
(
HKEY
hkey
,
LPCWSTR
file
,
LPSECURITY_ATTRIBUTES
sa
)
{
LPSTR
fileA
=
HEAP_strdupWtoA
(
GetProcessHeap
(),
0
,
file
);
DWORD
ret
=
RegSaveKeyA
(
hkey
,
fileA
,
sa
);
if
(
fileA
)
HeapFree
(
GetProcessHeap
(),
0
,
fileA
);
return
ret
;
}
dlls/shell32/shell.spec
View file @
2fab2ef1
...
...
@@ -3,7 +3,7 @@ type win16
1 pascal RegOpenKey(long str ptr) RegOpenKey16
2 pascal RegCreateKey(long str ptr) RegCreateKey16
3 pascal RegCloseKey(long) RegCloseKey
3 pascal RegCloseKey(long) RegCloseKey
16
4 pascal RegDeleteKey(long str) RegDeleteKey16
5 pascal RegSetValue(long str long str long) RegSetValue16
6 pascal RegQueryValue(long str ptr ptr) RegQueryValue16
...
...
if1632/kernel.spec
View file @
2fab2ef1
...
...
@@ -226,7 +226,7 @@ file krnl386.exe
217 pascal RegOpenKey(long str ptr) RegOpenKey16 # Both 95/NT
218 pascal RegCreateKey(long str ptr) RegCreateKey16
219 pascal RegDeleteKey(long str) RegDeleteKey16
220 pascal RegCloseKey(long) RegCloseKey
# Both 95/NT
220 pascal RegCloseKey(long) RegCloseKey
16
# Both 95/NT
221 pascal RegSetValue(long str long ptr long) RegSetValue16
222 pascal RegDeleteValue(long str) RegDeleteValue16
223 pascal RegEnumValue(long long ptr ptr ptr ptr ptr ptr) RegEnumValue16 # Both 95/NT
...
...
include/wine/winbase16.h
View file @
2fab2ef1
...
...
@@ -166,16 +166,17 @@ BOOL16 WINAPI LocalUnlock16(HLOCAL16);
HGLOBAL16
WINAPI
LockSegment16
(
HGLOBAL16
);
FARPROC16
WINAPI
MakeProcInstance16
(
FARPROC16
,
HANDLE16
);
VOID
WINAPI
OutputDebugString16
(
LPCSTR
);
DWORD
WINAPI
RegCloseKey16
(
HKEY
);
DWORD
WINAPI
RegCreateKey16
(
HKEY
,
LPCSTR
,
LPHKEY
);
DWORD
WINAPI
RegDeleteKey16
(
HKEY
,
LPCSTR
);
DWORD
WINAPI
RegDeleteValue16
(
HKEY
,
LPSTR
);
DWORD
WINAPI
RegEnumKey16
(
HKEY
,
DWORD
,
LPSTR
,
DWORD
);
DWORD
WINAPI
RegEnumValue16
(
HKEY
,
DWORD
,
LPSTR
,
LPDWORD
,
LPDWORD
,
LPDWORD
,
LPBYTE
,
LPDWORD
);
DWORD
WINAPI
RegOpenKey16
(
HKEY
,
LPCSTR
,
LPHKEY
);
DWORD
WINAPI
RegQueryValue16
(
HKEY
,
LPSTR
,
LPSTR
,
LPDWORD
);
DWORD
WINAPI
RegQueryValueEx16
(
HKEY
,
LPSTR
,
LPDWORD
,
LPDWORD
,
LPBYTE
,
LPDWORD
);
DWORD
WINAPI
RegQueryValue16
(
HKEY
,
LP
C
STR
,
LPSTR
,
LPDWORD
);
DWORD
WINAPI
RegQueryValueEx16
(
HKEY
,
LP
C
STR
,
LPDWORD
,
LPDWORD
,
LPBYTE
,
LPDWORD
);
DWORD
WINAPI
RegSetValue16
(
HKEY
,
LPCSTR
,
DWORD
,
LPCSTR
,
DWORD
);
DWORD
WINAPI
RegSetValueEx16
(
HKEY
,
LP
STR
,
DWORD
,
DWORD
,
LPBYTE
,
DWORD
);
DWORD
WINAPI
RegSetValueEx16
(
HKEY
,
LP
CSTR
,
DWORD
,
DWORD
,
CONST
BYTE
*
,
DWORD
);
BOOL16
WINAPI
RemoveDirectory16
(
LPCSTR
);
BOOL16
WINAPI
SetCurrentDirectory16
(
LPCSTR
);
UINT16
WINAPI
SetErrorMode16
(
UINT16
);
...
...
include/winnt.h
View file @
2fab2ef1
...
...
@@ -1282,6 +1282,9 @@ typedef enum tagSID_NAME_USE {
#define GENERIC_EXECUTE 0x20000000
#define GENERIC_ALL 0x10000000
#define MAXIMUM_ALLOWED 0x02000000
#define ACCESS_SYSTEM_SECURITY 0x01000000
#define EVENT_MODIFY_STATE 0x0002
#define EVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
...
...
include/winreg.h
View file @
2fab2ef1
...
...
@@ -50,7 +50,6 @@ extern "C" {
#define REG_OPTION_VOLATILE 0x00000001
#define REG_OPTION_CREATE_LINK 0x00000002
#define REG_OPTION_BACKUP_RESTORE 0x00000004
/* FIXME */
#define REG_OPTION_TAINTED 0x80000000
/* Internal? */
#define REG_CREATED_NEW_KEY 0x00000001
#define REG_OPENED_EXISTING_KEY 0x00000002
...
...
misc/registry.c
View file @
2fab2ef1
...
...
@@ -46,9 +46,9 @@
#include "options.h"
#include "winreg.h"
#include "winversion.h"
#include "server.h"
DECLARE_DEBUG_CHANNEL
(
reg
)
DECLARE_DEBUG_CHANNEL
(
string
)
DEFAULT_DEBUG_CHANNEL
(
reg
)
static
void
REGISTRY_Init
(
void
);
/* FIXME: following defines should be configured global ... */
...
...
@@ -66,56 +66,11 @@ static void REGISTRY_Init(void);
#define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
#define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
/* one value of a key */
typedef
struct
tagKEYVALUE
{
LPWSTR
name
;
/* name of value (UNICODE) or NULL for win31 */
DWORD
type
;
/* type of value */
DWORD
len
;
/* length of data in BYTEs */
DWORD
lastmodified
;
/* time of seconds since 1.1.1970 */
LPBYTE
data
;
/* content, may be strings, binaries, etc. */
}
KEYVALUE
,
*
LPKEYVALUE
;
/* a registry key */
typedef
struct
tagKEYSTRUCT
{
LPWSTR
keyname
;
/* name of THIS key (UNICODE) */
DWORD
flags
;
/* flags. */
LPWSTR
class
;
/* values */
DWORD
nrofvalues
;
/* nr of values in THIS key */
LPKEYVALUE
values
;
/* values in THIS key */
/* key management pointers */
struct
tagKEYSTRUCT
*
next
;
/* next key on same hierarchy */
struct
tagKEYSTRUCT
*
nextsub
;
/* keys that hang below THIS key */
}
KEYSTRUCT
,
*
LPKEYSTRUCT
;
static
KEYSTRUCT
*
key_classes_root
=
NULL
;
/* windows 3.1 global values */
static
KEYSTRUCT
*
key_current_user
=
NULL
;
/* user specific values */
static
KEYSTRUCT
*
key_local_machine
=
NULL
;
/* machine specific values */
static
KEYSTRUCT
*
key_users
=
NULL
;
/* all users? */
/* dynamic, not saved */
static
KEYSTRUCT
*
key_performance_data
=
NULL
;
static
KEYSTRUCT
*
key_current_config
=
NULL
;
static
KEYSTRUCT
*
key_dyn_data
=
NULL
;
/* what valuetypes do we need to convert? */
#define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
static
struct
openhandle
{
LPKEYSTRUCT
lpkey
;
HKEY
hkey
;
REGSAM
accessmask
;
}
*
openhandles
=
NULL
;
static
int
nrofopenhandles
=
0
;
/* Starts after 1 because 0,1 are reserved for Win16 */
/* Note: Should always be even, as Win95 ADVAPI32.DLL reserves odd
HKEYs for remote registry access */
static
int
currenthandle
=
2
;
/*
* QUESTION
...
...
@@ -136,19 +91,6 @@ static LPWSTR strdupA2W(LPCSTR src)
return
NULL
;
}
static
LPWSTR
strdupW
(
LPCWSTR
a
)
{
LPWSTR
b
;
int
len
;
if
(
a
)
{
len
=
sizeof
(
WCHAR
)
*
(
lstrlenW
(
a
)
+
1
);
b
=
(
LPWSTR
)
xmalloc
(
len
);
memcpy
(
b
,
a
,
len
);
return
b
;
}
return
NULL
;
}
LPWSTR
strcvtA2W
(
LPCSTR
src
,
int
nchars
)
{
...
...
@@ -158,388 +100,6 @@ LPWSTR strcvtA2W(LPCSTR src, int nchars)
dest
[
nchars
]
=
0
;
return
dest
;
}
/*
* we need to convert A to W with '\0' in strings (MULTI_SZ)
*/
static
LPWSTR
lmemcpynAtoW
(
LPWSTR
dst
,
LPCSTR
src
,
INT
n
)
{
LPWSTR
p
=
dst
;
TRACE_
(
reg
)(
"
\"
%s
\"
%i
\n
"
,
src
,
n
);
while
(
n
--
>
0
)
*
p
++
=
(
WCHAR
)(
unsigned
char
)
*
src
++
;
return
dst
;
}
static
LPSTR
lmemcpynWtoA
(
LPSTR
dst
,
LPCWSTR
src
,
INT
n
)
{
LPSTR
p
=
dst
;
TRACE_
(
string
)(
"L
\"
%s
\"
%i
\n
"
,
debugstr_w
(
src
),
n
);
while
(
n
--
>
0
)
*
p
++
=
(
CHAR
)
*
src
++
;
return
dst
;
}
static
void
debug_print_value
(
LPBYTE
lpbData
,
LPKEYVALUE
key
)
{
if
(
TRACE_ON
(
reg
)
&&
lpbData
)
{
switch
(
key
->
type
)
{
case
REG_EXPAND_SZ
:
case
REG_SZ
:
TRACE_
(
reg
)(
" Value %s, Data(sz)=%s
\n
"
,
debugstr_w
(
key
->
name
),
debugstr_w
((
LPCWSTR
)
lpbData
));
break
;
case
REG_DWORD
:
TRACE_
(
reg
)(
" Value %s, Data(dword)=0x%08lx
\n
"
,
debugstr_w
(
key
->
name
),
(
DWORD
)
*
lpbData
);
break
;
case
REG_MULTI_SZ
:
{
int
i
;
LPCWSTR
ptr
=
(
LPCWSTR
)
lpbData
;
for
(
i
=
0
;
ptr
[
0
];
i
++
)
{
TRACE_
(
reg
)(
" Value %s, MULTI_SZ(%i=%s)
\n
"
,
debugstr_w
(
key
->
name
),
i
,
debugstr_w
(
ptr
));
ptr
+=
lstrlenW
(
ptr
)
+
1
;
}
}
break
;
default:
{
char
szTemp
[
100
];
/* 3*32 + 3 + 1 */
int
i
;
for
(
i
=
0
;
i
<
key
->
len
;
i
++
)
{
sprintf
(
&
(
szTemp
[
i
*
3
]),
"%02x "
,
lpbData
[
i
]);
if
(
i
>=
31
)
{
sprintf
(
&
(
szTemp
[
i
*
3
+
3
]),
"..."
);
break
;
}
}
TRACE_
(
reg
)(
" Value %s, Data(raw)=(%s)
\n
"
,
debugstr_w
(
key
->
name
),
szTemp
);
}
}
/* switch */
}
/* if */
}
/******************************************************************************
* is_standard_hkey [Internal]
* Determines if a hkey is a standard key
*/
static
BOOL
is_standard_hkey
(
HKEY
hkey
)
{
switch
(
hkey
)
{
case
0x00000000
:
case
0x00000001
:
case
HKEY_CLASSES_ROOT
:
case
HKEY_CURRENT_CONFIG
:
case
HKEY_CURRENT_USER
:
case
HKEY_LOCAL_MACHINE
:
case
HKEY_USERS
:
case
HKEY_PERFORMANCE_DATA
:
case
HKEY_DYN_DATA
:
return
TRUE
;
default:
return
FALSE
;
}
}
/******************************************************************************
* add_handle [Internal]
*/
static
void
add_handle
(
HKEY
hkey
,
LPKEYSTRUCT
lpkey
,
REGSAM
accessmask
)
{
int
i
;
TRACE_
(
reg
)(
"(0x%x,%p,0x%lx)
\n
"
,
hkey
,
lpkey
,
accessmask
);
/* Check for duplicates */
for
(
i
=
0
;
i
<
nrofopenhandles
;
i
++
)
{
if
(
openhandles
[
i
].
lpkey
==
lpkey
)
{
/* This is not really an error - the user is allowed to create
two (or more) handles to the same key */
/*WARN(reg, "Adding key %p twice\n",lpkey);*/
}
if
(
openhandles
[
i
].
hkey
==
hkey
)
{
WARN_
(
reg
)(
"Adding handle %x twice
\n
"
,
hkey
);
}
}
openhandles
=
xrealloc
(
openhandles
,
sizeof
(
struct
openhandle
)
*
(
nrofopenhandles
+
1
));
openhandles
[
i
].
lpkey
=
lpkey
;
openhandles
[
i
].
hkey
=
hkey
;
openhandles
[
i
].
accessmask
=
accessmask
;
nrofopenhandles
++
;
}
/******************************************************************************
* get_handle [Internal]
*
* RETURNS
* Success: Pointer to key
* Failure: NULL
*/
static
LPKEYSTRUCT
get_handle
(
HKEY
hkey
)
{
int
i
;
for
(
i
=
0
;
i
<
nrofopenhandles
;
i
++
)
if
(
openhandles
[
i
].
hkey
==
hkey
)
return
openhandles
[
i
].
lpkey
;
WARN_
(
reg
)(
"Could not find handle 0x%x
\n
"
,
hkey
);
return
NULL
;
}
/******************************************************************************
* remove_handle [Internal]
*
* PARAMS
* hkey [I] Handle of key to remove
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: ERROR_INVALID_HANDLE
*/
static
DWORD
remove_handle
(
HKEY
hkey
)
{
int
i
;
for
(
i
=
0
;
i
<
nrofopenhandles
;
i
++
)
if
(
openhandles
[
i
].
hkey
==
hkey
)
break
;
if
(
i
==
nrofopenhandles
)
{
WARN_
(
reg
)(
"Could not find handle 0x%x
\n
"
,
hkey
);
return
ERROR_INVALID_HANDLE
;
}
memcpy
(
openhandles
+
i
,
openhandles
+
i
+
1
,
sizeof
(
struct
openhandle
)
*
(
nrofopenhandles
-
i
-
1
)
);
openhandles
=
xrealloc
(
openhandles
,
sizeof
(
struct
openhandle
)
*
(
nrofopenhandles
-
1
));
nrofopenhandles
--
;
return
ERROR_SUCCESS
;
}
/******************************************************************************
* lookup_hkey [Internal]
*
* Just as the name says. Creates the root keys on demand, so we can call the
* Reg* functions at any time.
*
* RETURNS
* Success: Pointer to key structure
* Failure: NULL
*/
#define ADD_ROOT_KEY(xx) \
xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
memset(xx,'\0',sizeof(KEYSTRUCT));\
xx->keyname= strdupA2W("<should_not_appear_anywhere>");
static
LPKEYSTRUCT
lookup_hkey
(
HKEY
hkey
)
{
switch
(
hkey
)
{
/* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
* some programs. Do not remove those cases. -MM
*/
case
0x00000000
:
case
0x00000001
:
case
HKEY_CLASSES_ROOT
:
{
if
(
!
key_classes_root
)
{
HKEY
cl_r_hkey
;
/* calls lookup_hkey recursively, TWICE */
if
(
RegCreateKey16
(
HKEY_LOCAL_MACHINE
,
"SOFTWARE
\\
Classes"
,
&
cl_r_hkey
)
!=
ERROR_SUCCESS
)
{
ERR_
(
reg
)(
"Could not create HKLM
\\
SOFTWARE
\\
Classes. This is impossible.
\n
"
);
exit
(
1
);
}
key_classes_root
=
lookup_hkey
(
cl_r_hkey
);
}
return
key_classes_root
;
}
case
HKEY_CURRENT_USER
:
if
(
!
key_current_user
)
{
ADD_ROOT_KEY
(
key_current_user
);
}
return
key_current_user
;
case
HKEY_LOCAL_MACHINE
:
if
(
!
key_local_machine
)
{
ADD_ROOT_KEY
(
key_local_machine
);
REGISTRY_Init
();
}
return
key_local_machine
;
case
HKEY_USERS
:
if
(
!
key_users
)
{
ADD_ROOT_KEY
(
key_users
);
}
return
key_users
;
case
HKEY_PERFORMANCE_DATA
:
if
(
!
key_performance_data
)
{
ADD_ROOT_KEY
(
key_performance_data
);
}
return
key_performance_data
;
case
HKEY_DYN_DATA
:
if
(
!
key_dyn_data
)
{
ADD_ROOT_KEY
(
key_dyn_data
);
}
return
key_dyn_data
;
case
HKEY_CURRENT_CONFIG
:
if
(
!
key_current_config
)
{
ADD_ROOT_KEY
(
key_current_config
);
}
return
key_current_config
;
default:
return
get_handle
(
hkey
);
}
/*NOTREACHED*/
}
/*
* recursively searches for lpkey_to_find in the root key branch
* given in lpcurrkey.
*/
static
int
subkey_found
(
LPKEYSTRUCT
lpcurrkey
,
LPKEYSTRUCT
lpkey_to_find
)
{
while
(
lpcurrkey
)
{
if
(
lpcurrkey
==
lpkey_to_find
)
return
1
;
if
(
subkey_found
(
lpcurrkey
->
nextsub
,
lpkey_to_find
))
return
1
;
lpcurrkey
=
lpcurrkey
->
next
;
}
TRACE_
(
reg
)(
"No key found in this root key branch
\n
"
);
return
0
;
}
/*
* finds the corresponding root key for a sub key, i.e. e.g. HKEY_CLASSES_ROOT.
*/
static
HKEY
find_root_key
(
LPKEYSTRUCT
lpkey
)
{
typedef
struct
tagROOT_KEYS
{
KEYSTRUCT
*
lpkey
;
HKEY
hkey
;
}
ROOT_KEYS
;
ROOT_KEYS
root_keys
[
4
];
int
i
;
root_keys
[
0
].
lpkey
=
key_classes_root
;
root_keys
[
0
].
hkey
=
HKEY_CLASSES_ROOT
;
root_keys
[
1
].
lpkey
=
key_current_user
;
root_keys
[
1
].
hkey
=
HKEY_CURRENT_USER
;
root_keys
[
2
].
lpkey
=
key_local_machine
;
root_keys
[
2
].
hkey
=
HKEY_LOCAL_MACHINE
;
root_keys
[
3
].
lpkey
=
key_users
;
root_keys
[
3
].
hkey
=
HKEY_USERS
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
if
(
subkey_found
(
root_keys
[
i
].
lpkey
,
lpkey
))
return
root_keys
[
i
].
hkey
;
}
ERR_
(
reg
)(
"Didn't find corresponding root key entry ! Search strategy broken ??
\n
"
);
return
0
;
#undef ROOT_KEYS
}
#undef ADD_ROOT_KEY
/* so we don't accidently access them ... */
#define key_current_config NULL NULL
#define key_current_user NULL NULL
#define key_users NULL NULL
#define key_local_machine NULL NULL
#define key_classes_root NULL NULL
#define key_dyn_data NULL NULL
#define key_performance_data NULL NULL
/******************************************************************************
* split_keypath [Internal]
* splits the unicode string 'wp' into an array of strings.
* the array is allocated by this function.
* Free the array using FREE_KEY_PATH
*
* PARAMS
* wp [I] String to split up
* wpv [O] Array of pointers to strings
* wpc [O] Number of components
*/
static
void
split_keypath
(
LPCWSTR
wp
,
LPWSTR
**
wpv
,
int
*
wpc
)
{
int
i
,
j
,
len
;
LPWSTR
ws
;
TRACE_
(
reg
)(
"(%s,%p,%p)
\n
"
,
debugstr_w
(
wp
),
wpv
,
wpc
);
ws
=
HEAP_strdupW
(
SystemHeap
,
0
,
wp
);
/* We know we have at least one substring */
*
wpc
=
1
;
/* Replace each backslash with NULL, and increment the count */
for
(
i
=
0
;
ws
[
i
];
i
++
)
{
if
(
ws
[
i
]
==
'\\'
)
{
ws
[
i
]
=
0
;
(
*
wpc
)
++
;
}
}
len
=
i
;
/* Allocate the space for the array of pointers, leaving room for the
NULL at the end */
*
wpv
=
(
LPWSTR
*
)
HeapAlloc
(
SystemHeap
,
0
,
sizeof
(
LPWSTR
)
*
(
*
wpc
+
2
));
(
*
wpv
)[
0
]
=
ws
;
/* Assign each pointer to the appropriate character in the string */
j
=
1
;
for
(
i
=
1
;
i
<
len
;
i
++
)
if
(
ws
[
i
-
1
]
==
0
)
{
(
*
wpv
)[
j
++
]
=
ws
+
i
;
/*TRACE_(reg) (" Subitem %d = %s\n",j-1,debugstr_w((*wpv)[j-1]));*/
}
(
*
wpv
)[
j
]
=
NULL
;
}
#define FREE_KEY_PATH HeapFree(SystemHeap,0,wps[0]);HeapFree(SystemHeap,0,wps);
...
...
@@ -553,12 +113,12 @@ static void REGISTRY_Init(void) {
TRACE_
(
reg
)(
"(void)
\n
"
);
RegCreateKey
16
(
HKEY_DYN_DATA
,
"PerfStats
\\
StatData"
,
&
hkey
);
RegCreateKey
A
(
HKEY_DYN_DATA
,
"PerfStats
\\
StatData"
,
&
hkey
);
RegCloseKey
(
hkey
);
/* This was an Open, but since it is called before the real registries
are loaded, it was changed to a Create - MTB 980507*/
RegCreateKey
16
(
HKEY_LOCAL_MACHINE
,
"HARDWARE
\\
DESCRIPTION
\\
System"
,
&
hkey
);
RegCreateKey
A
(
HKEY_LOCAL_MACHINE
,
"HARDWARE
\\
DESCRIPTION
\\
System"
,
&
hkey
);
RegSetValueExA
(
hkey
,
"Identifier"
,
0
,
REG_SZ
,
"SystemType WINE"
,
strlen
(
"SystemType WINE"
));
RegCloseKey
(
hkey
);
...
...
@@ -576,8 +136,8 @@ static void REGISTRY_Init(void) {
* SysServices
*/
if
(
-
1
!=
gethostname
(
buf
,
200
))
{
RegCreateKey
16
(
HKEY_LOCAL_MACHINE
,
"System
\\
CurrentControlSet
\\
Control
\\
ComputerName
\\
ComputerName"
,
&
hkey
);
RegSetValueEx
16
(
hkey
,
"ComputerName"
,
0
,
REG_SZ
,
buf
,
strlen
(
buf
)
+
1
);
RegCreateKey
A
(
HKEY_LOCAL_MACHINE
,
"System
\\
CurrentControlSet
\\
Control
\\
ComputerName
\\
ComputerName"
,
&
hkey
);
RegSetValueEx
A
(
hkey
,
"ComputerName"
,
0
,
REG_SZ
,
buf
,
strlen
(
buf
)
+
1
);
RegCloseKey
(
hkey
);
}
}
...
...
@@ -613,131 +173,6 @@ static void REGISTRY_Init(void) {
* SaveOnlyUpdatedKeys=yes
*/
/******************************************************************************
* _save_check_tainted [Internal]
*/
static
int
_save_check_tainted
(
LPKEYSTRUCT
lpkey
)
{
int
tainted
=
0
;
while
(
lpkey
)
{
if
(
_save_check_tainted
(
lpkey
->
nextsub
))
lpkey
->
flags
|=
REG_OPTION_TAINTED
;
if
(
lpkey
->
flags
&
REG_OPTION_TAINTED
)
tainted
=
1
;
lpkey
=
lpkey
->
next
;
}
return
tainted
;
}
/******************************************************************************
* _save_USTRING [Internal]
*/
static
void
_save_USTRING
(
FILE
*
F
,
LPWSTR
wstr
,
int
escapeeq
)
{
LPWSTR
s
;
int
doescape
;
if
(
wstr
==
NULL
)
return
;
s
=
wstr
;
while
(
*
s
)
{
doescape
=
0
;
if
(
*
s
>
0x7f
)
doescape
=
1
;
if
(
*
s
==
'\n'
)
doescape
=
1
;
if
(
escapeeq
&&
*
s
==
'='
)
doescape
=
1
;
if
(
*
s
==
'\\'
)
fputc
(
*
s
,
F
);
/* if \\ then put it twice. */
if
(
doescape
)
fprintf
(
F
,
"
\\
u%04x"
,
*
((
unsigned
short
*
)
s
));
else
fputc
(
*
s
,
F
);
s
++
;
}
}
/******************************************************************************
* _savesubkey [Internal]
*
* NOTES
* REG_MULTI_SZ is handled as binary (like in win95) (js)
*/
static
int
_savesubkey
(
FILE
*
F
,
LPKEYSTRUCT
lpkey
,
int
level
,
int
all
)
{
LPKEYSTRUCT
lpxkey
;
int
i
,
tabs
,
j
;
lpxkey
=
lpkey
;
while
(
lpxkey
)
{
if
(
!
(
lpxkey
->
flags
&
REG_OPTION_VOLATILE
)
&&
(
all
||
(
lpxkey
->
flags
&
REG_OPTION_TAINTED
))
)
{
for
(
tabs
=
level
;
tabs
--
;)
fputc
(
'\t'
,
F
);
_save_USTRING
(
F
,
lpxkey
->
keyname
,
1
);
fputs
(
"
\n
"
,
F
);
for
(
i
=
0
;
i
<
lpxkey
->
nrofvalues
;
i
++
)
{
LPKEYVALUE
val
=
lpxkey
->
values
+
i
;
for
(
tabs
=
level
+
1
;
tabs
--
;)
fputc
(
'\t'
,
F
);
_save_USTRING
(
F
,
val
->
name
,
0
);
fputc
(
'='
,
F
);
fprintf
(
F
,
"%ld,%ld,"
,
val
->
type
,
val
->
lastmodified
);
if
(
val
->
type
==
REG_SZ
||
val
->
type
==
REG_EXPAND_SZ
)
_save_USTRING
(
F
,(
LPWSTR
)
val
->
data
,
0
);
else
for
(
j
=
0
;
j
<
val
->
len
;
j
++
)
fprintf
(
F
,
"%02x"
,
*
((
unsigned
char
*
)
val
->
data
+
j
));
fputs
(
"
\n
"
,
F
);
}
/* descend recursively */
if
(
!
_savesubkey
(
F
,
lpxkey
->
nextsub
,
level
+
1
,
all
))
return
0
;
}
lpxkey
=
lpxkey
->
next
;
}
return
1
;
}
/******************************************************************************
* _savesubreg [Internal]
*/
static
int
_savesubreg
(
FILE
*
F
,
LPKEYSTRUCT
lpkey
,
int
all
)
{
fprintf
(
F
,
"WINE REGISTRY Version %d
\n
"
,
REGISTRY_SAVE_VERSION
);
_save_check_tainted
(
lpkey
->
nextsub
);
return
_savesubkey
(
F
,
lpkey
->
nextsub
,
0
,
all
);
}
/******************************************************************************
* _savereg [Internal]
*/
static
BOOL
_savereg
(
LPKEYSTRUCT
lpkey
,
char
*
fn
,
int
all
)
{
FILE
*
F
;
F
=
fopen
(
fn
,
"w"
);
if
(
F
==
NULL
)
{
WARN_
(
reg
)(
"Couldn't open %s for writing: %s
\n
"
,
fn
,
strerror
(
errno
)
);
return
FALSE
;
}
if
(
!
_savesubreg
(
F
,
lpkey
,
all
))
{
fclose
(
F
);
unlink
(
fn
);
WARN_
(
reg
)(
"Failed to save keys, perhaps no more diskspace for %s?
\n
"
,
fn
);
return
FALSE
;
}
fclose
(
F
);
return
TRUE
;
}
/******************************************************************************
...
...
@@ -745,9 +180,9 @@ static BOOL _savereg( LPKEYSTRUCT lpkey, char *fn, int all )
*
* Saves main registry branch specified by hkey.
*/
static
void
SHELL_SaveRegistryBranch
(
HKEY
hkey
,
int
all
)
static
void
SHELL_SaveRegistryBranch
(
HKEY
hkey
)
{
char
*
fn
,
*
home
,
*
tmp
;
char
*
fn
,
*
home
;
/* Find out what to save to, get from config file */
BOOL
writeToHome
=
PROFILE_GetWineIniBool
(
"registry"
,
"WritetoHomeRegistries"
,
1
);
...
...
@@ -766,7 +201,7 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all)
fn
=
xmalloc
(
MAX_PATHNAME_LEN
);
if
(
writeToAlt
&&
PROFILE_GetWineIniString
(
"registry"
,
"AltCurrentUserFile"
,
""
,
fn
,
MAX_PATHNAME_LEN
-
1
))
_savereg
(
lookup_hkey
(
HKEY_CURRENT_USER
),
fn
,
all
);
RegSaveKeyA
(
HKEY_CURRENT_USER
,
fn
,
NULL
);
free
(
fn
);
if
(
home
&&
writeToHome
)
...
...
@@ -779,18 +214,7 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all)
/* create the directory. don't care about errorcodes. */
mkdir
(
fn
,
0755
);
/* drwxr-xr-x */
strcat
(
fn
,
"/"
SAVE_CURRENT_USER
);
tmp
=
(
char
*
)
xmalloc
(
strlen
(
fn
)
+
strlen
(
".tmp"
)
+
1
);
strcpy
(
tmp
,
fn
);
strcat
(
tmp
,
".tmp"
);
if
(
_savereg
(
lookup_hkey
(
HKEY_CURRENT_USER
),
tmp
,
all
))
{
if
(
-
1
==
rename
(
tmp
,
fn
))
{
perror
(
"rename tmp registry"
);
unlink
(
tmp
);
}
}
free
(
tmp
);
RegSaveKeyA
(
HKEY_CURRENT_USER
,
fn
,
NULL
);
free
(
fn
);
}
break
;
...
...
@@ -799,7 +223,7 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all)
fn
=
xmalloc
(
MAX_PATHNAME_LEN
);
if
(
writeToAlt
&&
PROFILE_GetWineIniString
(
"Registry"
,
"AltLocalMachineFile"
,
""
,
fn
,
MAX_PATHNAME_LEN
-
1
))
_savereg
(
lookup_hkey
(
HKEY_LOCAL_MACHINE
),
fn
,
all
);
RegSaveKeyA
(
HKEY_LOCAL_MACHINE
,
fn
,
NULL
);
free
(
fn
);
if
(
home
&&
writeToHome
)
...
...
@@ -808,18 +232,7 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all)
strlen
(
SAVE_LOCAL_MACHINE
)
+
2
);
strcpy
(
fn
,
home
);
strcat
(
fn
,
WINE_PREFIX
"/"
SAVE_LOCAL_MACHINE
);
tmp
=
(
char
*
)
xmalloc
(
strlen
(
fn
)
+
strlen
(
".tmp"
)
+
1
);
strcpy
(
tmp
,
fn
);
strcat
(
tmp
,
".tmp"
);
if
(
_savereg
(
lookup_hkey
(
HKEY_LOCAL_MACHINE
),
tmp
,
all
))
{
if
(
-
1
==
rename
(
tmp
,
fn
))
{
perror
(
"rename tmp registry"
);
unlink
(
tmp
);
}
}
free
(
tmp
);
RegSaveKeyA
(
HKEY_LOCAL_MACHINE
,
fn
,
NULL
);
free
(
fn
);
}
break
;
...
...
@@ -827,7 +240,7 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all)
fn
=
xmalloc
(
MAX_PATHNAME_LEN
);
if
(
writeToAlt
&&
PROFILE_GetWineIniString
(
"Registry"
,
"AltUserFile"
,
""
,
fn
,
MAX_PATHNAME_LEN
-
1
))
_savereg
(
lookup_hkey
(
HKEY_LOCAL_MACHINE
),
fn
,
all
);
RegSaveKeyA
(
HKEY_USERS
,
fn
,
NULL
);
free
(
fn
);
if
(
home
&&
writeToHome
)
...
...
@@ -836,17 +249,7 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all)
strlen
(
SAVE_LOCAL_USERS_DEFAULT
)
+
2
);
strcpy
(
fn
,
home
);
strcat
(
fn
,
WINE_PREFIX
"/"
SAVE_LOCAL_USERS_DEFAULT
);
tmp
=
(
char
*
)
xmalloc
(
strlen
(
fn
)
+
strlen
(
".tmp"
)
+
1
);
strcpy
(
tmp
,
fn
);
strcat
(
tmp
,
".tmp"
);
if
(
_savereg
(
lookup_hkey
(
HKEY_USERS
),
tmp
,
FALSE
))
{
if
(
-
1
==
rename
(
tmp
,
fn
))
{
perror
(
"rename tmp registry"
);
unlink
(
tmp
);
}
}
free
(
tmp
);
RegSaveKeyA
(
HKEY_USERS
,
fn
,
NULL
);
free
(
fn
);
}
break
;
...
...
@@ -862,6 +265,7 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all)
*/
void
SHELL_SaveRegistry
(
void
)
{
struct
set_registry_levels_request
*
req
=
get_req_buffer
();
char
buf
[
4
];
HKEY
hkey
;
int
all
;
...
...
@@ -869,7 +273,7 @@ void SHELL_SaveRegistry( void )
TRACE_
(
reg
)(
"(void)
\n
"
);
all
=
0
;
if
(
RegOpenKey
16
(
HKEY_CURRENT_USER
,
KEY_REGISTRY
,
&
hkey
)
!=
ERROR_SUCCESS
)
if
(
RegOpenKey
A
(
HKEY_CURRENT_USER
,
KEY_REGISTRY
,
&
hkey
)
!=
ERROR_SUCCESS
)
{
strcpy
(
buf
,
"yes"
);
}
...
...
@@ -888,14 +292,18 @@ void SHELL_SaveRegistry( void )
strcpy
(
buf
,
"yes"
);
}
RegCloseKey
(
hkey
);
}
}
if
(
lstrcmpiA
(
buf
,
"yes"
))
all
=
1
;
if
(
lstrcmpiA
(
buf
,
"yes"
))
all
=
1
;
SHELL_SaveRegistryBranch
(
HKEY_CURRENT_USER
,
all
);
SHELL_SaveRegistryBranch
(
HKEY_LOCAL_MACHINE
,
all
);
SHELL_SaveRegistryBranch
(
HKEY_USERS
,
all
);
/* set saving level (0 for saving everything, 1 for saving only modified keys) */
req
->
current
=
1
;
req
->
saving
=
!
all
;
server_call
(
REQ_SET_REGISTRY_LEVELS
);
SHELL_SaveRegistryBranch
(
HKEY_CURRENT_USER
);
SHELL_SaveRegistryBranch
(
HKEY_LOCAL_MACHINE
);
SHELL_SaveRegistryBranch
(
HKEY_USERS
);
}
...
...
@@ -906,90 +314,22 @@ void SHELL_SaveRegistry( void )
/******************************************************************************
* _find_or_add_key [Internal]
*/
static
LPKEYSTRUCT
_find_or_add_key
(
LPKEYSTRUCT
lp
key
,
LPWSTR
keyname
)
static
inline
HKEY
_find_or_add_key
(
HKEY
h
key
,
LPWSTR
keyname
)
{
LPKEYSTRUCT
lpxkey
,
*
lplpkey
;
if
((
!
keyname
)
||
(
keyname
[
0
]
==
0
))
{
free
(
keyname
);
return
lpkey
;
}
lplpkey
=
&
(
lpkey
->
nextsub
);
lpxkey
=
*
lplpkey
;
while
(
lpxkey
)
{
if
(
tolower
(
lpxkey
->
keyname
[
0
])
==
tolower
(
keyname
[
0
])
&&
!
lstrcmpiW
(
lpxkey
->
keyname
,
keyname
)
)
break
;
lplpkey
=
&
(
lpxkey
->
next
);
lpxkey
=
*
lplpkey
;
}
if
(
lpxkey
==
NULL
)
{
*
lplpkey
=
(
LPKEYSTRUCT
)
xmalloc
(
sizeof
(
KEYSTRUCT
));
lpxkey
=
*
lplpkey
;
memset
(
lpxkey
,
'\0'
,
sizeof
(
KEYSTRUCT
));
lpxkey
->
keyname
=
keyname
;
}
else
free
(
keyname
);
return
lpxkey
;
HKEY
subkey
;
if
(
RegCreateKeyW
(
hkey
,
keyname
,
&
subkey
)
!=
ERROR_SUCCESS
)
subkey
=
0
;
if
(
keyname
)
free
(
keyname
);
return
subkey
;
}
/******************************************************************************
* _find_or_add_value [Internal]
*/
static
void
_find_or_add_value
(
LPKEYSTRUCT
lpkey
,
LPWSTR
name
,
DWORD
type
,
LPBYTE
data
,
DWORD
len
,
DWORD
lastmodified
)
static
void
_find_or_add_value
(
HKEY
hkey
,
LPWSTR
name
,
DWORD
type
,
LPBYTE
data
,
DWORD
len
)
{
LPKEYVALUE
val
=
NULL
;
int
i
;
if
(
name
&&
!*
name
)
{
/* empty string equals default (NULL) value */
free
(
name
);
name
=
NULL
;
}
for
(
i
=
0
;
i
<
lpkey
->
nrofvalues
;
i
++
)
{
val
=
lpkey
->
values
+
i
;
if
(
name
==
NULL
)
{
if
(
val
->
name
==
NULL
)
break
;
}
else
{
if
(
val
->
name
!=
NULL
&&
tolower
(
val
->
name
[
0
])
==
tolower
(
name
[
0
])
&&
!
lstrcmpiW
(
val
->
name
,
name
)
)
break
;
}
}
if
(
i
==
lpkey
->
nrofvalues
)
{
lpkey
->
values
=
xrealloc
(
lpkey
->
values
,
(
++
lpkey
->
nrofvalues
)
*
sizeof
(
KEYVALUE
)
);
val
=
lpkey
->
values
+
i
;
memset
(
val
,
'\0'
,
sizeof
(
KEYVALUE
));
val
->
name
=
name
;
}
else
{
if
(
name
)
free
(
name
);
}
if
(
val
->
lastmodified
<
lastmodified
)
{
val
->
lastmodified
=
lastmodified
;
val
->
type
=
type
;
if
((
type
==
REG_SZ
||
type
==
REG_EXPAND_SZ
)
&&
!
data
){
data
=
xmalloc
(
sizeof
(
WCHAR
));
memset
(
data
,
0
,
sizeof
(
WCHAR
));
len
=
sizeof
(
WCHAR
);
}
val
->
len
=
len
;
if
(
val
->
data
)
free
(
val
->
data
);
val
->
data
=
data
;
}
else
free
(
data
);
RegSetValueExW
(
hkey
,
name
,
0
,
type
,
data
,
len
);
if
(
name
)
free
(
name
);
if
(
data
)
free
(
data
);
}
...
...
@@ -1052,11 +392,6 @@ static char* _wine_read_USTRING( char *buf, LPWSTR *str )
/* read up to "=" or "\0" or "\n" */
s
=
buf
;
if
(
*
s
==
'='
)
{
/* empty string is the win3.1 default value(NULL)*/
*
str
=
NULL
;
return
s
;
}
*
str
=
(
LPWSTR
)
xmalloc
(
2
*
strlen
(
buf
)
+
2
);
ws
=
*
str
;
while
(
*
s
&&
(
*
s
!=
'\n'
)
&&
(
*
s
!=
'='
))
{
...
...
@@ -1093,12 +428,6 @@ static char* _wine_read_USTRING( char *buf, LPWSTR *str )
}
}
*
ws
=
0
;
ws
=
*
str
;
if
(
*
ws
)
*
str
=
strdupW
(
*
str
);
else
*
str
=
NULL
;
free
(
ws
);
return
s
;
}
...
...
@@ -1113,21 +442,17 @@ static char* _wine_read_USTRING( char *buf, LPWSTR *str )
* Success: 1
* Failure: 0
*/
static
int
_wine_loadsubkey
(
FILE
*
F
,
LPKEYSTRUCT
lpkey
,
int
level
,
char
**
buf
,
int
*
buflen
,
DWORD
optflag
)
static
int
_wine_loadsubkey
(
FILE
*
F
,
HKEY
hkey
,
int
level
,
char
**
buf
,
int
*
buflen
)
{
LPKEYSTRUCT
lpx
key
;
HKEY
sub
key
;
int
i
;
char
*
s
;
LPWSTR
name
;
TRACE_
(
reg
)(
"(%p,%p,%d,%s,%d,%lx)
\n
"
,
F
,
lpkey
,
level
,
debugstr_a
(
*
buf
),
*
buflen
,
optflag
);
lpkey
->
flags
|=
optflag
;
TRACE_
(
reg
)(
"(%p,%x,%d,%s,%d)
\n
"
,
F
,
hkey
,
level
,
debugstr_a
(
*
buf
),
*
buflen
);
/* Good. We already got a line here ... so parse it */
lpxkey
=
NULL
;
subkey
=
0
;
while
(
1
)
{
i
=
0
;
s
=*
buf
;
while
(
*
s
==
'\t'
)
{
...
...
@@ -1135,11 +460,11 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf,
i
++
;
}
if
(
i
>
level
)
{
if
(
lpxkey
==
NULL
)
{
if
(
!
subkey
)
{
WARN_
(
reg
)(
"Got a subhierarchy without resp. key?
\n
"
);
return
0
;
}
if
(
!
_wine_loadsubkey
(
F
,
lpxkey
,
level
+
1
,
buf
,
buflen
,
optflag
))
if
(
!
_wine_loadsubkey
(
F
,
subkey
,
level
+
1
,
buf
,
buflen
))
if
(
!
_wine_read_line
(
F
,
buf
,
buflen
))
return
1
;
continue
;
...
...
@@ -1156,7 +481,7 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf,
switch
(
0
)
{
default:
if
(
*
s
==
'\0'
)
{
lpxkey
=
_find_or_add_key
(
lp
key
,
name
);
subkey
=
_find_or_add_key
(
h
key
,
name
);
}
else
{
LPBYTE
data
;
int
len
,
lastmodified
,
type
;
...
...
@@ -1179,10 +504,7 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf,
}
if
(
type
==
REG_SZ
||
type
==
REG_EXPAND_SZ
)
{
s
=
_wine_read_USTRING
(
s
,(
LPWSTR
*
)
&
data
);
if
(
data
)
len
=
lstrlenW
((
LPWSTR
)
data
)
*
2
+
2
;
else
len
=
0
;
len
=
lstrlenW
((
LPWSTR
)
data
)
*
2
+
2
;
}
else
{
len
=
strlen
(
s
)
/
2
;
data
=
(
LPBYTE
)
xmalloc
(
len
+
1
);
...
...
@@ -1204,7 +526,7 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf,
s
++
;
}
}
_find_or_add_value
(
lpkey
,
name
,
type
,
data
,
len
,
lastmodified
);
_find_or_add_value
(
hkey
,
name
,
type
,
data
,
len
);
}
}
/* read the next line */
...
...
@@ -1218,7 +540,7 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf,
/******************************************************************************
* _wine_loadsubreg [Internal]
*/
static
int
_wine_loadsubreg
(
FILE
*
F
,
LPKEYSTRUCT
lpkey
,
DWORD
optflag
)
static
int
_wine_loadsubreg
(
FILE
*
F
,
HKEY
hkey
,
const
char
*
fn
)
{
int
ver
;
char
*
buf
;
...
...
@@ -1242,7 +564,7 @@ static int _wine_loadsubreg( FILE *F, LPKEYSTRUCT lpkey, DWORD optflag )
free
(
buf
);
return
0
;
}
if
(
!
_wine_loadsubkey
(
F
,
lpkey
,
0
,
&
buf
,
&
buflen
,
optflag
))
{
if
(
!
_wine_loadsubkey
(
F
,
hkey
,
0
,
&
buf
,
&
buflen
))
{
free
(
buf
);
return
0
;
}
...
...
@@ -1254,22 +576,18 @@ static int _wine_loadsubreg( FILE *F, LPKEYSTRUCT lpkey, DWORD optflag )
/******************************************************************************
* _wine_loadreg [Internal]
*/
static
void
_wine_loadreg
(
LPKEYSTRUCT
lpkey
,
char
*
fn
,
DWORD
optflag
)
static
void
_wine_loadreg
(
HKEY
hkey
,
char
*
fn
)
{
FILE
*
F
;
TRACE_
(
reg
)(
"(%
p,%s,%lx)
\n
"
,
lpkey
,
debugstr_a
(
fn
),
optflag
);
TRACE_
(
reg
)(
"(%
x,%s)
\n
"
,
hkey
,
debugstr_a
(
fn
)
);
F
=
fopen
(
fn
,
"rb"
);
if
(
F
==
NULL
)
{
WARN_
(
reg
)(
"Couldn't open %s for reading: %s
\n
"
,
fn
,
strerror
(
errno
)
);
return
;
}
if
(
!
_wine_loadsubreg
(
F
,
lpkey
,
optflag
))
{
fclose
(
F
);
unlink
(
fn
);
return
;
}
_wine_loadsubreg
(
F
,
hkey
,
fn
);
fclose
(
F
);
}
...
...
@@ -1284,95 +602,66 @@ static void _wine_loadreg( LPKEYSTRUCT lpkey, char *fn, DWORD optflag )
* which is bad...
*/
/* Forward declaration of recusive agent */
static
void
_flush_reg
(
LPKEYSTRUCT
from
);
static
void
_flush_registry
(
LPKEYSTRUCT
from
)
{
/* make sure we have something... */
if
(
from
==
NULL
)
return
;
/* Launch the recusive agent on sub branches */
_flush_reg
(
from
->
nextsub
);
_flush_reg
(
from
->
next
);
/* Initialize pointers */
from
->
nextsub
=
NULL
;
from
->
next
=
NULL
;
}
static
void
_flush_reg
(
LPKEYSTRUCT
from
)
static
void
_flush_registry
(
HKEY
hkey
)
{
int
j
;
/* make sure we have something... */
if
(
from
==
NULL
)
return
;
/*
* do the same for the child keys
*/
if
(
from
->
nextsub
!=
NULL
)
_flush_reg
(
from
->
nextsub
);
/*
* do the same for the sibling keys
*/
if
(
from
->
next
!=
NULL
)
_flush_reg
(
from
->
next
);
/*
* iterate through this key's values and delete them
*/
for
(
j
=
0
;
j
<
from
->
nrofvalues
;
j
++
)
{
free
(
(
from
->
values
+
j
)
->
name
);
free
(
(
from
->
values
+
j
)
->
data
);
}
WCHAR
name
[
MAX_PATH
];
/*
* free the structure
*/
if
(
from
!=
NULL
)
free
(
from
);
for
(;;)
{
HKEY
subkey
;
/* FIXME: we assume that deleting a key will move the other ones up, */
/* so that we can always use index 0 until there are no more keys */
if
(
RegEnumKeyW
(
hkey
,
0
,
name
,
sizeof
(
name
)
)
!=
ERROR_SUCCESS
)
break
;
if
(
RegOpenKeyW
(
hkey
,
name
,
&
subkey
)
!=
ERROR_SUCCESS
)
break
;
_flush_registry
(
subkey
);
if
(
RegDeleteKeyW
(
subkey
,
NULL
)
!=
ERROR_SUCCESS
)
break
;
RegCloseKey
(
subkey
);
}
}
/******************************************************************************
* _copy_registry [Internal]
*/
static
void
_copy_registry
(
LPKEYSTRUCT
from
,
LPKEYSTRUCT
to
)
static
void
_copy_registry
(
HKEY
from
,
HKEY
to
)
{
LPKEYSTRUCT
lpxkey
;
int
j
;
LPKEYVALUE
valfrom
;
from
=
from
->
nextsub
;
while
(
from
)
{
lpxkey
=
_find_or_add_key
(
to
,
strdupW
(
from
->
keyname
));
for
(
j
=
0
;
j
<
from
->
nrofvalues
;
j
++
)
{
LPWSTR
name
;
LPBYTE
data
;
valfrom
=
from
->
values
+
j
;
name
=
valfrom
->
name
;
if
(
name
)
name
=
strdupW
(
name
);
data
=
(
LPBYTE
)
xmalloc
(
valfrom
->
len
);
memcpy
(
data
,
valfrom
->
data
,
valfrom
->
len
);
_find_or_add_value
(
lpxkey
,
name
,
valfrom
->
type
,
data
,
valfrom
->
len
,
valfrom
->
lastmodified
);
}
_copy_registry
(
from
,
lpxkey
);
from
=
from
->
next
;
}
int
index
;
HKEY
subkey
;
FILETIME
ft
;
DWORD
type
,
name_len
,
len
;
static
WCHAR
name
[
MAX_PATH
];
static
BYTE
data
[
2048
];
/* copy values */
index
=
0
;
for
(;;)
{
len
=
sizeof
(
data
);
name_len
=
sizeof
(
name
);
if
(
RegEnumValueW
(
from
,
index
++
,
name
,
&
name_len
,
NULL
,
&
type
,
data
,
&
len
)
!=
ERROR_SUCCESS
)
break
;
RegSetValueW
(
to
,
name
,
type
,
(
LPCWSTR
)
data
,
len
);
}
/* copy subkeys */
index
=
0
;
for
(;;)
{
name_len
=
sizeof
(
name
);
if
(
RegEnumKeyExW
(
from
,
index
++
,
name
,
&
name_len
,
NULL
,
NULL
,
0
,
&
ft
)
!=
ERROR_SUCCESS
)
break
;
if
(
RegOpenKeyW
(
from
,
name
,
&
subkey
)
==
ERROR_SUCCESS
)
{
HKEY
newsub
;
if
(
RegCreateKeyW
(
to
,
name
,
&
newsub
)
==
ERROR_SUCCESS
)
{
_copy_registry
(
subkey
,
newsub
);
RegCloseKey
(
newsub
);
}
RegCloseKey
(
subkey
);
}
}
}
...
...
@@ -1496,8 +785,7 @@ struct _w95_info {
/******************************************************************************
* _w95_processKey [Internal]
*/
static
LPKEYSTRUCT
_w95_processKey
(
LPKEYSTRUCT
lpkey
,
int
nrLS
,
int
nrMS
,
struct
_w95_info
*
info
)
static
HKEY
_w95_processKey
(
HKEY
hkey
,
int
nrLS
,
int
nrMS
,
struct
_w95_info
*
info
)
{
/* Disk Key Header structure (RGDB part) */
...
...
@@ -1531,11 +819,11 @@ static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey,
int
off_next_rgdb
;
char
*
next
=
rgdbdata
;
int
nrgdb
,
i
;
LPKEYSTRUCT
lpx
key
;
HKEY
sub
key
;
do
{
curdata
=
next
;
if
(
strncmp
(
curdata
,
"RGDB"
,
4
))
return
(
NULL
)
;
if
(
strncmp
(
curdata
,
"RGDB"
,
4
))
return
0
;
memcpy
(
&
off_next_rgdb
,
curdata
+
4
,
4
);
next
=
curdata
+
off_next_rgdb
;
...
...
@@ -1565,13 +853,13 @@ static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey,
curdata
+=
xdkh
->
nextkeyoff
;
};
if
(
dkh
.
nrLS
!=
nrLS
)
return
(
NULL
)
;
if
(
dkh
.
nrLS
!=
nrLS
)
return
0
;
if
(
nrgdb
!=
dkh
.
nrMS
)
return
(
NULL
)
;
return
0
;
assert
((
dkh
.
keynamelen
<
2
)
||
curdata
[
0
]);
lpxkey
=
_find_or_add_key
(
lp
key
,
strcvtA2W
(
curdata
,
dkh
.
keynamelen
));
subkey
=
_find_or_add_key
(
h
key
,
strcvtA2W
(
curdata
,
dkh
.
keynamelen
));
curdata
+=
dkh
.
keynamelen
;
for
(
i
=
0
;
i
<
dkh
.
values
;
i
++
)
{
...
...
@@ -1597,22 +885,15 @@ static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey,
curdata
+=
dkv
.
valdatalen
;
_find_or_add_value
(
lpxkey
,
name
,
dkv
.
type
,
data
,
len
,
info
->
lastmodified
);
_find_or_add_value
(
subkey
,
name
,
dkv
.
type
,
data
,
len
);
}
return
(
lpxkey
)
;
return
subkey
;
}
/******************************************************************************
* _w95_walkrgkn [Internal]
*/
static
void
_w95_walkrgkn
(
LPKEYSTRUCT
prevkey
,
char
*
off
,
static
void
_w95_walkrgkn
(
HKEY
prevkey
,
char
*
off
,
struct
_w95_info
*
info
)
{
...
...
@@ -1627,23 +908,21 @@ static void _w95_walkrgkn( LPKEYSTRUCT prevkey, char *off,
unsigned
short
nrLS
;
unsigned
short
nrMS
;
}
*
dke
=
(
struct
dke
*
)
off
;
LPKEYSTRUCT
lpx
key
;
HKEY
sub
key
;
if
(
dke
==
NULL
)
{
dke
=
(
struct
dke
*
)
((
char
*
)
info
->
rgknbuffer
);
}
lpx
key
=
_w95_processKey
(
prevkey
,
dke
->
nrLS
,
dke
->
nrMS
,
info
);
sub
key
=
_w95_processKey
(
prevkey
,
dke
->
nrLS
,
dke
->
nrMS
,
info
);
/* XXX <-- This is a hack*/
if
(
!
lpxkey
)
{
lpxkey
=
prevkey
;
}
if
(
!
subkey
)
subkey
=
prevkey
;
if
(
dke
->
nextsub
!=
-
1
&&
((
dke
->
nextsub
-
0x20
)
<
info
->
rgknsize
)
&&
(
dke
->
nextsub
>
0x20
))
{
_w95_walkrgkn
(
lpx
key
,
_w95_walkrgkn
(
sub
key
,
info
->
rgknbuffer
+
dke
->
nextsub
-
0x20
,
info
);
}
...
...
@@ -1655,15 +934,13 @@ static void _w95_walkrgkn( LPKEYSTRUCT prevkey, char *off,
info
->
rgknbuffer
+
dke
->
next
-
0x20
,
info
);
}
return
;
}
/******************************************************************************
* _w95_loadreg [Internal]
*/
static
void
_w95_loadreg
(
char
*
fn
,
LPKEYSTRUCT
lp
key
)
static
void
_w95_loadreg
(
char
*
fn
,
HKEY
h
key
)
{
HFILE
hfd
;
char
magic
[
5
];
...
...
@@ -1723,7 +1000,7 @@ static void _w95_loadreg( char* fn, LPKEYSTRUCT lpkey )
return
;
_lclose
(
hfd
);
_w95_walkrgkn
(
lp
key
,
NULL
,
&
info
);
_w95_walkrgkn
(
h
key
,
NULL
,
&
info
);
free
(
info
.
rgdbbuffer
);
free
(
info
.
rgknbuffer
);
...
...
@@ -1816,15 +1093,14 @@ __w31_dumptree( unsigned short idx,
unsigned
char
*
txt
,
struct
_w31_tabent
*
tab
,
struct
_w31_header
*
head
,
LPKEYSTRUCT
lp
key
,
HKEY
h
key
,
time_t
lastmodified
,
int
level
)
{
struct
_w31_dirent
*
dir
;
struct
_w31_keyent
*
key
;
struct
_w31_valent
*
val
;
LPKEYSTRUCT
xlpkey
=
NULL
;
LPWSTR
name
,
value
;
HKEY
subkey
=
0
;
static
char
tail
[
400
];
while
(
idx
!=
0
)
{
...
...
@@ -1839,28 +1115,24 @@ __w31_dumptree( unsigned short idx,
* toplevel subdirectory belong to \SOFTWARE\Classes
*/
if
(
!
level
&&
!
lstrcmpA
(
tail
,
".classes"
))
{
__w31_dumptree
(
dir
->
child_idx
,
txt
,
tab
,
head
,
lp
key
,
lastmodified
,
level
+
1
);
__w31_dumptree
(
dir
->
child_idx
,
txt
,
tab
,
head
,
h
key
,
lastmodified
,
level
+
1
);
idx
=
dir
->
sibling_idx
;
continue
;
}
name
=
strdupA2W
(
tail
);
xlpkey
=
_find_or_add_key
(
lpkey
,
name
);
if
(
RegCreateKeyA
(
hkey
,
tail
,
&
subkey
)
!=
ERROR_SUCCESS
)
subkey
=
0
;
/* only add if leaf node or valued node */
if
(
dir
->
value_idx
!=
0
||
dir
->
child_idx
==
0
)
{
if
(
dir
->
value_idx
)
{
val
=
(
struct
_w31_valent
*
)
&
tab
[
dir
->
value_idx
];
memcpy
(
tail
,
&
txt
[
val
->
string_off
],
val
->
length
);
tail
[
val
->
length
]
=
'\0'
;
value
=
strdupA2W
(
tail
);
_find_or_add_value
(
xlpkey
,
NULL
,
REG_SZ
,(
LPBYTE
)
value
,
lstrlenW
(
value
)
*
2
+
2
,
lastmodified
);
RegSetValueA
(
hkey
,
NULL
,
REG_SZ
,
tail
,
0
);
}
}
}
else
{
TRACE_
(
reg
)(
"strange: no directory key name, idx=%04x
\n
"
,
idx
);
}
__w31_dumptree
(
dir
->
child_idx
,
txt
,
tab
,
head
,
xlp
key
,
lastmodified
,
level
+
1
);
__w31_dumptree
(
dir
->
child_idx
,
txt
,
tab
,
head
,
sub
key
,
lastmodified
,
level
+
1
);
idx
=
dir
->
sibling_idx
;
}
}
...
...
@@ -1878,7 +1150,6 @@ void _w31_loadreg(void) {
OFSTRUCT
ofs
;
BY_HANDLE_FILE_INFORMATION
hfinfo
;
time_t
lastmodified
;
LPKEYSTRUCT
lpkey
;
TRACE_
(
reg
)(
"(void)
\n
"
);
...
...
@@ -1933,8 +1204,7 @@ void _w31_loadreg(void) {
return
;
}
lastmodified
=
DOSFS_FileTimeToUnixTime
(
&
hfinfo
.
ftLastWriteTime
,
NULL
);
lpkey
=
lookup_hkey
(
HKEY_CLASSES_ROOT
);
__w31_dumptree
(
tab
[
0
].
w1
,
txt
,
tab
,
&
head
,
lpkey
,
lastmodified
,
0
);
__w31_dumptree
(
tab
[
0
].
w1
,
txt
,
tab
,
&
head
,
HKEY_CLASSES_ROOT
,
lastmodified
,
0
);
free
(
tab
);
free
(
txt
);
_lclose
(
hf
);
...
...
@@ -1947,24 +1217,27 @@ void _w31_loadreg(void) {
*/
void
SHELL_LoadRegistry
(
void
)
{
struct
set_registry_levels_request
*
req
=
get_req_buffer
();
char
*
fn
,
*
home
;
LPKEYSTRUCT
lpkey
,
HKCU
,
HKU
,
HKLM
;
HKEY
hkey
;
TRACE_
(
reg
)(
"(void)
\n
"
);
HKCU
=
lookup_hkey
(
HKEY_CURRENT_USER
);
HKU
=
lookup_hkey
(
HKEY_USERS
);
HKLM
=
lookup_hkey
(
HKEY_LOCAL_MACHINE
);
REGISTRY_Init
();
/* set level to 0 for loading system files */
req
->
current
=
0
;
req
->
saving
=
0
;
server_call
(
REQ_SET_REGISTRY_LEVELS
);
if
(
PROFILE_GetWineIniBool
(
"registry"
,
"LoadWindowsRegistryFiles"
,
1
))
{
/* Load windows 3.1 entries */
_w31_loadreg
();
/* Load windows 95 entries */
_w95_loadreg
(
"C:
\\
system.1st"
,
HKLM
);
_w95_loadreg
(
"system.dat"
,
HKLM
);
_w95_loadreg
(
"user.dat"
,
HKU
);
_w95_loadreg
(
"C:
\\
system.1st"
,
HKEY_LOCAL_MACHINE
);
_w95_loadreg
(
"system.dat"
,
HKEY_LOCAL_MACHINE
);
_w95_loadreg
(
"user.dat"
,
HKEY_USERS
);
}
if
(
PROFILE_GetWineIniBool
(
"registry"
,
"LoadGlobalRegistryFiles"
,
1
))
...
...
@@ -1972,14 +1245,19 @@ void SHELL_LoadRegistry( void )
/*
* Load the global HKU hive directly from sysconfdir
*/
_wine_loadreg
(
HK
U
,
SAVE_USERS_DEFAULT
,
0
);
_wine_loadreg
(
HK
EY_USERS
,
SAVE_USERS_DEFAULT
);
/*
* Load the global machine defaults directly form sysconfdir
*/
_wine_loadreg
(
HK
LM
,
SAVE_LOCAL_MACHINE_DEFAULT
,
0
);
_wine_loadreg
(
HK
EY_LOCAL_MACHINE
,
SAVE_LOCAL_MACHINE_DEFAULT
);
}
/* set level to 1 for loading user files */
req
->
current
=
1
;
req
->
saving
=
0
;
server_call
(
REQ_SET_REGISTRY_LEVELS
);
/*
* Load the user saved registries
*/
...
...
@@ -1994,13 +1272,13 @@ void SHELL_LoadRegistry( void )
strlen
(
SAVE_LOCAL_USERS_DEFAULT
)
+
2
);
strcpy
(
fn
,
home
);
strcat
(
fn
,
WINE_PREFIX
"/"
SAVE_LOCAL_USERS_DEFAULT
);
_wine_loadreg
(
HKU
,
fn
,
REG_OPTION_TAINTED
);
_wine_loadreg
(
HKEY_USERS
,
fn
);
free
(
fn
);
fn
=
(
char
*
)
xmalloc
(
strlen
(
home
)
+
strlen
(
WINE_PREFIX
)
+
strlen
(
SAVE_CURRENT_USER
)
+
2
);
strcpy
(
fn
,
home
);
strcat
(
fn
,
WINE_PREFIX
"/"
SAVE_CURRENT_USER
);
_wine_loadreg
(
HKCU
,
fn
,
REG_OPTION_TAINTED
);
_wine_loadreg
(
HKEY_CURRENT_USER
,
fn
);
free
(
fn
);
/*
...
...
@@ -2010,7 +1288,7 @@ void SHELL_LoadRegistry( void )
fn
=
(
char
*
)
xmalloc
(
strlen
(
home
)
+
strlen
(
WINE_PREFIX
)
+
strlen
(
SAVE_LOCAL_MACHINE
)
+
2
);
strcpy
(
fn
,
home
);
strcat
(
fn
,
WINE_PREFIX
"/"
SAVE_LOCAL_MACHINE
);
_wine_loadreg
(
HKLM
,
fn
,
REG_OPTION_TAINTED
);
_wine_loadreg
(
HKEY_LOCAL_MACHINE
,
fn
);
free
(
fn
);
}
...
...
@@ -2024,7 +1302,7 @@ void SHELL_LoadRegistry( void )
if
(
PROFILE_GetWineIniString
(
"registry"
,
"AltCurrentUserFile"
,
""
,
fn
,
MAX_PATHNAME_LEN
-
1
))
{
_wine_loadreg
(
HKCU
,
fn
,
REG_OPTION_TAINTED
);
_wine_loadreg
(
HKEY_CURRENT_USER
,
fn
);
}
free
(
fn
);
/*
...
...
@@ -2035,7 +1313,7 @@ void SHELL_LoadRegistry( void )
if
(
PROFILE_GetWineIniString
(
"registry"
,
"AltUserFile"
,
""
,
fn
,
MAX_PATHNAME_LEN
-
1
))
{
_wine_loadreg
(
HKU
,
fn
,
REG_OPTION_TAINTED
);
_wine_loadreg
(
HKEY_USERS
,
fn
);
}
free
(
fn
);
/*
...
...
@@ -2046,7 +1324,7 @@ void SHELL_LoadRegistry( void )
if
(
PROFILE_GetWineIniString
(
"registry"
,
"AltLocalMachineFile"
,
""
,
fn
,
MAX_PATHNAME_LEN
-
1
))
{
_wine_loadreg
(
HKLM
,
fn
,
REG_OPTION_TAINTED
);
_wine_loadreg
(
HKEY_LOCAL_MACHINE
,
fn
);
}
free
(
fn
);
}
...
...
@@ -2055,14 +1333,10 @@ void SHELL_LoadRegistry( void )
* Obtain the handle of the HKU\.Default key.
* in order to copy HKU\.Default\* onto HKEY_CURRENT_USER
*/
RegCreateKey16
(
HKEY_USERS
,
".Default"
,
&
hkey
);
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
){
WARN_
(
reg
)(
"Could not create global user default key
\n
"
);
}
else
{
_copy_registry
(
lpkey
,
HKCU
);
}
if
(
RegCreateKeyA
(
HKEY_USERS
,
".Default"
,
&
hkey
)
!=
ERROR_SUCCESS
)
WARN_
(
reg
)(
"Could not create global user default key
\n
"
);
else
_copy_registry
(
hkey
,
HKEY_CURRENT_USER
);
RegCloseKey
(
hkey
);
/*
...
...
@@ -2073,7 +1347,7 @@ void SHELL_LoadRegistry( void )
*/
/* Allways flush the HKU hive and reload it only with user's personal HKU */
_flush_registry
(
HKU
);
_flush_registry
(
HKEY_USERS
);
/* Reload user's local HKU hive */
if
(
home
&&
PROFILE_GetWineIniBool
(
"registry"
,
"LoadHomeRegistryFiles"
,
1
))
...
...
@@ -2084,7 +1358,7 @@ void SHELL_LoadRegistry( void )
strcpy
(
fn
,
home
);
strcat
(
fn
,
WINE_PREFIX
"/"
SAVE_LOCAL_USERS_DEFAULT
);
_wine_loadreg
(
HK
U
,
fn
,
REG_OPTION_TAINTED
);
_wine_loadreg
(
HK
EY_USERS
,
fn
);
free
(
fn
);
}
...
...
@@ -2115,1418 +1389,17 @@ void SHELL_LoadRegistry( void )
/********************* API FUNCTIONS ***************************************/
/*
* Open Keys.
*
* All functions are stubs to RegOpenKeyEx32W where all the
* magic happens.
*
* Callpath:
* RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
* RegOpenKey32W -> RegOpenKeyEx32W
*/
/******************************************************************************
* RegOpenKeyEx32W [ADVAPI32.150]
* Opens the specified key
*
* Unlike RegCreateKeyEx, this does not create the key if it does not exist.
*
* PARAMS
* hkey [I] Handle of open key
* lpszSubKey [I] Name of subkey to open
* dwReserved [I] Reserved - must be zero
* samDesired [I] Security access mask
* retkey [O] Address of handle of open key
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD
WINAPI
RegOpenKeyExW
(
HKEY
hkey
,
LPCWSTR
lpszSubKey
,
DWORD
dwReserved
,
REGSAM
samDesired
,
LPHKEY
retkey
)
{
LPKEYSTRUCT
lpNextKey
,
lpxkey
;
LPWSTR
*
wps
;
int
wpc
,
i
;
TRACE_
(
reg
)(
"(0x%x,%s,%ld,%lx,%p)
\n
"
,
hkey
,
debugstr_w
(
lpszSubKey
),
dwReserved
,
samDesired
,
retkey
);
lpNextKey
=
lookup_hkey
(
hkey
);
if
(
!
lpNextKey
)
return
ERROR_INVALID_HANDLE
;
if
(
!
lpszSubKey
||
!*
lpszSubKey
)
{
/* Either NULL or pointer to empty string, so return a new handle
to the original hkey */
currenthandle
+=
2
;
add_handle
(
currenthandle
,
lpNextKey
,
samDesired
);
*
retkey
=
currenthandle
;
return
ERROR_SUCCESS
;
}
if
(
lpszSubKey
[
0
]
==
'\\'
)
{
WARN_
(
reg
)(
"Subkey %s must not begin with backslash.
\n
"
,
debugstr_w
(
lpszSubKey
));
return
ERROR_BAD_PATHNAME
;
}
split_keypath
(
lpszSubKey
,
&
wps
,
&
wpc
);
i
=
0
;
while
((
i
<
wpc
)
&&
(
wps
[
i
][
0
]
==
'\0'
))
i
++
;
lpxkey
=
lpNextKey
;
while
(
wps
[
i
])
{
lpxkey
=
lpNextKey
->
nextsub
;
while
(
lpxkey
)
{
if
(
!
lstrcmpiW
(
wps
[
i
],
lpxkey
->
keyname
))
{
break
;
}
lpxkey
=
lpxkey
->
next
;
}
if
(
!
lpxkey
)
{
TRACE_
(
reg
)(
"Could not find subkey %s
\n
"
,
debugstr_w
(
wps
[
i
]));
FREE_KEY_PATH
;
return
ERROR_FILE_NOT_FOUND
;
}
i
++
;
lpNextKey
=
lpxkey
;
}
currenthandle
+=
2
;
add_handle
(
currenthandle
,
lpxkey
,
samDesired
);
*
retkey
=
currenthandle
;
TRACE_
(
reg
)(
" Returning %x
\n
"
,
currenthandle
);
FREE_KEY_PATH
;
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegOpenKeyEx32A [ADVAPI32.149]
*/
DWORD
WINAPI
RegOpenKeyExA
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
DWORD
dwReserved
,
REGSAM
samDesired
,
LPHKEY
retkey
)
{
LPWSTR
lpszSubKeyW
=
strdupA2W
(
lpszSubKey
);
DWORD
ret
;
TRACE_
(
reg
)(
"(%x,%s,%ld,%lx,%p)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
),
dwReserved
,
samDesired
,
retkey
);
ret
=
RegOpenKeyExW
(
hkey
,
lpszSubKeyW
,
dwReserved
,
samDesired
,
retkey
);
free
(
lpszSubKeyW
);
return
ret
;
}
/******************************************************************************
* RegOpenKey32W [ADVAPI32.151]
*
* PARAMS
* hkey [I] Handle of open key
* lpszSubKey [I] Address of name of subkey to open
* retkey [O] Address of handle of open key
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD
WINAPI
RegOpenKeyW
(
HKEY
hkey
,
LPCWSTR
lpszSubKey
,
LPHKEY
retkey
)
{
TRACE_
(
reg
)(
"(%x,%s,%p)
\n
"
,
hkey
,
debugstr_w
(
lpszSubKey
),
retkey
);
return
RegOpenKeyExW
(
hkey
,
lpszSubKey
,
0
,
KEY_ALL_ACCESS
,
retkey
);
}
/******************************************************************************
* RegOpenKey32A [ADVAPI32.148]
*/
DWORD
WINAPI
RegOpenKeyA
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
LPHKEY
retkey
)
{
DWORD
ret
;
LPWSTR
lpszSubKeyW
=
strdupA2W
(
lpszSubKey
);
TRACE_
(
reg
)(
"(%x,%s,%p)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
),
retkey
);
ret
=
RegOpenKeyW
(
hkey
,
lpszSubKeyW
,
retkey
);
free
(
lpszSubKeyW
);
return
ret
;
}
/******************************************************************************
* RegOpenKey16 [SHELL.1] [KERNEL.217]
*/
DWORD
WINAPI
RegOpenKey16
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
LPHKEY
retkey
)
{
TRACE_
(
reg
)(
"(%x,%s,%p)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
),
retkey
);
return
RegOpenKeyA
(
hkey
,
lpszSubKey
,
retkey
);
}
/*
* Create keys
*
* All those functions convert their respective
* arguments and call RegCreateKeyExW at the end.
*
* We stay away from the Ex functions as long as possible because there are
* differences in the return values
*
* Callpath:
* RegCreateKeyEx32A \
* RegCreateKey16 -> RegCreateKey32A -> RegCreateKey32W -> RegCreateKeyEx32W
*/
/******************************************************************************
* RegCreateKeyEx32W [ADVAPI32.131]
*
* PARAMS
* hkey [I] Handle of an open key
* lpszSubKey [I] Address of subkey name
* dwReserved [I] Reserved - must be 0
* lpszClass [I] Address of class string
* fdwOptions [I] Special options flag
* samDesired [I] Desired security access
* lpSecAttribs [I] Address of key security structure
* retkey [O] Address of buffer for opened handle
* lpDispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
*/
DWORD
WINAPI
RegCreateKeyExW
(
HKEY
hkey
,
LPCWSTR
lpszSubKey
,
DWORD
dwReserved
,
LPWSTR
lpszClass
,
DWORD
fdwOptions
,
REGSAM
samDesired
,
LPSECURITY_ATTRIBUTES
lpSecAttribs
,
LPHKEY
retkey
,
LPDWORD
lpDispos
)
{
LPKEYSTRUCT
*
lplpPrevKey
,
lpNextKey
,
lpxkey
;
LPWSTR
*
wps
;
int
wpc
,
i
;
TRACE_
(
reg
)(
"(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)
\n
"
,
hkey
,
debugstr_w
(
lpszSubKey
),
dwReserved
,
debugstr_w
(
lpszClass
),
fdwOptions
,
samDesired
,
lpSecAttribs
,
retkey
,
lpDispos
);
lpNextKey
=
lookup_hkey
(
hkey
);
if
(
!
lpNextKey
)
return
ERROR_INVALID_HANDLE
;
/* Check for valid options */
switch
(
fdwOptions
)
{
case
REG_OPTION_NON_VOLATILE
:
case
REG_OPTION_VOLATILE
:
case
REG_OPTION_BACKUP_RESTORE
:
break
;
default:
return
ERROR_INVALID_PARAMETER
;
}
/* Sam has to be a combination of the following */
if
(
!
(
samDesired
&
(
KEY_ALL_ACCESS
|
KEY_CREATE_LINK
|
KEY_CREATE_SUB_KEY
|
KEY_ENUMERATE_SUB_KEYS
|
KEY_EXECUTE
|
KEY_NOTIFY
|
KEY_QUERY_VALUE
|
KEY_READ
|
KEY_SET_VALUE
|
KEY_WRITE
)))
return
ERROR_INVALID_PARAMETER
;
if
(
!
lpszSubKey
||
!*
lpszSubKey
)
{
currenthandle
+=
2
;
add_handle
(
currenthandle
,
lpNextKey
,
samDesired
);
*
retkey
=
currenthandle
;
TRACE_
(
reg
)(
"Returning %x
\n
"
,
currenthandle
);
lpNextKey
->
flags
|=
REG_OPTION_TAINTED
;
return
ERROR_SUCCESS
;
}
if
(
lpszSubKey
[
0
]
==
'\\'
)
{
WARN_
(
reg
)(
"Subkey %s must not begin with backslash.
\n
"
,
debugstr_w
(
lpszSubKey
));
return
ERROR_BAD_PATHNAME
;
}
split_keypath
(
lpszSubKey
,
&
wps
,
&
wpc
);
i
=
0
;
while
((
i
<
wpc
)
&&
(
wps
[
i
][
0
]
==
'\0'
))
i
++
;
lpxkey
=
lpNextKey
;
while
(
wps
[
i
])
{
lpxkey
=
lpNextKey
->
nextsub
;
while
(
lpxkey
)
{
if
(
!
lstrcmpiW
(
wps
[
i
],
lpxkey
->
keyname
))
break
;
lpxkey
=
lpxkey
->
next
;
}
if
(
!
lpxkey
)
break
;
i
++
;
lpNextKey
=
lpxkey
;
}
if
(
lpxkey
)
{
currenthandle
+=
2
;
add_handle
(
currenthandle
,
lpxkey
,
samDesired
);
lpxkey
->
flags
|=
REG_OPTION_TAINTED
;
*
retkey
=
currenthandle
;
TRACE_
(
reg
)(
"Returning %x
\n
"
,
currenthandle
);
if
(
lpDispos
)
*
lpDispos
=
REG_OPENED_EXISTING_KEY
;
FREE_KEY_PATH
;
return
ERROR_SUCCESS
;
}
/* Good. Now the hard part */
while
(
wps
[
i
])
{
lplpPrevKey
=
&
(
lpNextKey
->
nextsub
);
lpxkey
=
*
lplpPrevKey
;
while
(
lpxkey
)
{
lplpPrevKey
=
&
(
lpxkey
->
next
);
lpxkey
=
*
lplpPrevKey
;
}
*
lplpPrevKey
=
malloc
(
sizeof
(
KEYSTRUCT
));
if
(
!*
lplpPrevKey
)
{
FREE_KEY_PATH
;
TRACE_
(
reg
)(
"Returning OUTOFMEMORY
\n
"
);
return
ERROR_OUTOFMEMORY
;
}
memset
(
*
lplpPrevKey
,
'\0'
,
sizeof
(
KEYSTRUCT
));
TRACE_
(
reg
)(
"Adding %s
\n
"
,
debugstr_w
(
wps
[
i
]));
(
*
lplpPrevKey
)
->
keyname
=
strdupW
(
wps
[
i
]);
(
*
lplpPrevKey
)
->
next
=
NULL
;
(
*
lplpPrevKey
)
->
nextsub
=
NULL
;
(
*
lplpPrevKey
)
->
values
=
NULL
;
(
*
lplpPrevKey
)
->
nrofvalues
=
0
;
(
*
lplpPrevKey
)
->
flags
=
REG_OPTION_TAINTED
;
if
(
lpszClass
)
(
*
lplpPrevKey
)
->
class
=
strdupW
(
lpszClass
);
else
(
*
lplpPrevKey
)
->
class
=
NULL
;
lpNextKey
=
*
lplpPrevKey
;
i
++
;
}
currenthandle
+=
2
;
add_handle
(
currenthandle
,
lpNextKey
,
samDesired
);
/*FIXME: flag handling correct? */
lpNextKey
->
flags
=
fdwOptions
|
REG_OPTION_TAINTED
;
if
(
lpszClass
)
lpNextKey
->
class
=
strdupW
(
lpszClass
);
else
lpNextKey
->
class
=
NULL
;
*
retkey
=
currenthandle
;
TRACE_
(
reg
)(
"Returning %x
\n
"
,
currenthandle
);
if
(
lpDispos
)
*
lpDispos
=
REG_CREATED_NEW_KEY
;
FREE_KEY_PATH
;
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegCreateKeyEx32A [ADVAPI32.130]
*/
DWORD
WINAPI
RegCreateKeyExA
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
DWORD
dwReserved
,
LPSTR
lpszClass
,
DWORD
fdwOptions
,
REGSAM
samDesired
,
LPSECURITY_ATTRIBUTES
lpSecAttribs
,
LPHKEY
retkey
,
LPDWORD
lpDispos
)
{
LPWSTR
lpszSubKeyW
,
lpszClassW
;
DWORD
ret
;
TRACE_
(
reg
)(
"(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
),
dwReserved
,
debugstr_a
(
lpszClass
),
fdwOptions
,
samDesired
,
lpSecAttribs
,
retkey
,
lpDispos
);
lpszSubKeyW
=
lpszSubKey
?
strdupA2W
(
lpszSubKey
)
:
NULL
;
lpszClassW
=
lpszClass
?
strdupA2W
(
lpszClass
)
:
NULL
;
ret
=
RegCreateKeyExW
(
hkey
,
lpszSubKeyW
,
dwReserved
,
lpszClassW
,
fdwOptions
,
samDesired
,
lpSecAttribs
,
retkey
,
lpDispos
);
if
(
lpszSubKeyW
)
free
(
lpszSubKeyW
);
if
(
lpszClassW
)
free
(
lpszClassW
);
return
ret
;
}
/******************************************************************************
* RegCreateKey32W [ADVAPI32.132]
*/
DWORD
WINAPI
RegCreateKeyW
(
HKEY
hkey
,
LPCWSTR
lpszSubKey
,
LPHKEY
retkey
)
{
DWORD
junk
;
LPKEYSTRUCT
lpNextKey
;
TRACE_
(
reg
)(
"(%x,%s,%p)
\n
"
,
hkey
,
debugstr_w
(
lpszSubKey
),
retkey
);
/* This check is here because the return value is different than the
one from the Ex functions */
lpNextKey
=
lookup_hkey
(
hkey
);
if
(
!
lpNextKey
)
return
ERROR_BADKEY
;
return
RegCreateKeyExW
(
hkey
,
lpszSubKey
,
0
,
NULL
,
REG_OPTION_NON_VOLATILE
,
KEY_ALL_ACCESS
,
NULL
,
retkey
,
&
junk
);
}
/******************************************************************************
* RegCreateKey32A [ADVAPI32.129]
*/
DWORD
WINAPI
RegCreateKeyA
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
LPHKEY
retkey
)
{
DWORD
ret
;
LPWSTR
lpszSubKeyW
;
TRACE_
(
reg
)(
"(%x,%s,%p)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
),
retkey
);
lpszSubKeyW
=
lpszSubKey
?
strdupA2W
(
lpszSubKey
)
:
NULL
;
ret
=
RegCreateKeyW
(
hkey
,
lpszSubKeyW
,
retkey
);
if
(
lpszSubKeyW
)
free
(
lpszSubKeyW
);
return
ret
;
}
/******************************************************************************
* RegCreateKey16 [SHELL.2] [KERNEL.218]
*/
DWORD
WINAPI
RegCreateKey16
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
LPHKEY
retkey
)
{
TRACE_
(
reg
)(
"(%x,%s,%p)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
),
retkey
);
return
RegCreateKeyA
(
hkey
,
lpszSubKey
,
retkey
);
}
/*
* Query Value Functions
* Win32 differs between keynames and valuenames.
* multiple values may belong to one key, the special value
* with name NULL is the default value used by the win31
* compat functions.
*
* Callpath:
* RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
* RegQueryValue32W -> RegQueryValueEx32W
*/
/******************************************************************************
* RegQueryValueEx32W [ADVAPI32.158]
* Retrieves type and data for a specified name associated with an open key
*
* PARAMS
* hkey [I] Handle of key to query
* lpValueName [I] Name of value to query
* lpdwReserved [I] Reserved - must be NULL
* lpdwType [O] Address of buffer for value type. If NULL, the type
* is not required.
* lpbData [O] Address of data buffer. If NULL, the actual data is
* not required.
* lpcbData [I/O] Address of data buffer size
*
* RETURNS
* ERROR_SUCCESS: Success
* ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
* buffer is left untouched. The MS-documentation is wrong (js) !!!
*/
DWORD
WINAPI
RegQueryValueExW
(
HKEY
hkey
,
LPCWSTR
lpValueName
,
LPDWORD
lpdwReserved
,
LPDWORD
lpdwType
,
LPBYTE
lpbData
,
LPDWORD
lpcbData
)
{
LPKEYSTRUCT
lpkey
;
int
i
;
DWORD
ret
;
TRACE_
(
reg
)(
"(0x%x,%s,%p,%p,%p,%p=%ld)
\n
"
,
hkey
,
debugstr_w
(
lpValueName
),
lpdwReserved
,
lpdwType
,
lpbData
,
lpcbData
,
lpcbData
?*
lpcbData
:
0
);
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
if
((
lpbData
&&
!
lpcbData
)
||
lpdwReserved
)
return
ERROR_INVALID_PARAMETER
;
/* An empty name string is equivalent to NULL */
if
(
lpValueName
&&
!*
lpValueName
)
lpValueName
=
NULL
;
if
(
lpValueName
==
NULL
)
{
/* Use key's unnamed or default value, if any */
for
(
i
=
0
;
i
<
lpkey
->
nrofvalues
;
i
++
)
if
(
lpkey
->
values
[
i
].
name
==
NULL
)
break
;
}
else
{
/* Search for the key name */
for
(
i
=
0
;
i
<
lpkey
->
nrofvalues
;
i
++
)
if
(
lpkey
->
values
[
i
].
name
&&
!
lstrcmpiW
(
lpValueName
,
lpkey
->
values
[
i
].
name
))
break
;
}
if
(
i
==
lpkey
->
nrofvalues
)
{
TRACE_
(
reg
)(
" Key not found
\n
"
);
if
(
lpValueName
==
NULL
)
{
/* Empty keyname not found */
if
(
lpbData
)
{
*
(
WCHAR
*
)
lpbData
=
0
;
*
lpcbData
=
2
;
}
if
(
lpdwType
)
*
lpdwType
=
REG_SZ
;
TRACE_
(
reg
)(
" Returning an empty string
\n
"
);
return
ERROR_SUCCESS
;
}
return
ERROR_FILE_NOT_FOUND
;
}
ret
=
ERROR_SUCCESS
;
if
(
lpdwType
)
/* type required ?*/
*
lpdwType
=
lpkey
->
values
[
i
].
type
;
if
(
lpbData
)
/* data required ?*/
{
if
(
*
lpcbData
>=
lpkey
->
values
[
i
].
len
)
/* buffer large enought ?*/
memcpy
(
lpbData
,
lpkey
->
values
[
i
].
data
,
lpkey
->
values
[
i
].
len
);
else
{
*
lpcbData
=
lpkey
->
values
[
i
].
len
;
ret
=
ERROR_MORE_DATA
;
}
}
if
(
lpcbData
)
/* size required ?*/
{
*
lpcbData
=
lpkey
->
values
[
i
].
len
;
}
debug_print_value
(
lpbData
,
&
lpkey
->
values
[
i
]);
TRACE_
(
reg
)(
" (ret=%lx, type=%lx, len=%ld)
\n
"
,
ret
,
lpdwType
?*
lpdwType
:
0
,
lpcbData
?*
lpcbData
:
0
);
return
ret
;
}
/******************************************************************************
* RegQueryValue32W [ADVAPI32.159]
*/
DWORD
WINAPI
RegQueryValueW
(
HKEY
hkey
,
LPCWSTR
lpszSubKey
,
LPWSTR
lpszData
,
LPLONG
lpcbData
)
{
HKEY
xhkey
;
DWORD
ret
,
lpdwType
;
TRACE_
(
reg
)(
"(%x,%s,%p,%ld)
\n
"
,
hkey
,
debugstr_w
(
lpszSubKey
),
lpszData
,
lpcbData
?*
lpcbData
:
0
);
/* Only open subkey, if we really do descend */
if
(
lpszSubKey
&&
*
lpszSubKey
)
{
ret
=
RegOpenKeyW
(
hkey
,
lpszSubKey
,
&
xhkey
);
if
(
ret
!=
ERROR_SUCCESS
)
{
WARN_
(
reg
)(
"Could not open %s
\n
"
,
debugstr_w
(
lpszSubKey
));
return
ret
;
}
}
else
xhkey
=
hkey
;
lpdwType
=
REG_SZ
;
ret
=
RegQueryValueExW
(
xhkey
,
NULL
,
NULL
,
&
lpdwType
,
(
LPBYTE
)
lpszData
,
lpcbData
);
if
(
xhkey
!=
hkey
)
RegCloseKey
(
xhkey
);
return
ret
;
}
/******************************************************************************
* RegQueryValueEx32A [ADVAPI32.157]
*
* NOTES:
* the documantation is wrong: if the buffer is to small it remains untouched
*
* FIXME: check returnvalue (len) for an empty key
*/
DWORD
WINAPI
RegQueryValueExA
(
HKEY
hkey
,
LPCSTR
lpszValueName
,
LPDWORD
lpdwReserved
,
LPDWORD
lpdwType
,
LPBYTE
lpbData
,
LPDWORD
lpcbData
)
{
LPWSTR
lpszValueNameW
;
LPBYTE
mybuf
=
NULL
;
DWORD
ret
,
mytype
,
mylen
=
0
;
TRACE_
(
reg
)(
"(%x,%s,%p,%p,%p,%p=%ld)
\n
"
,
hkey
,
debugstr_a
(
lpszValueName
),
lpdwReserved
,
lpdwType
,
lpbData
,
lpcbData
,
lpcbData
?*
lpcbData
:
0
);
if
(
!
lpcbData
&&
lpbData
)
/* buffer without size is illegal */
{
return
ERROR_INVALID_PARAMETER
;
}
lpszValueNameW
=
lpszValueName
?
strdupA2W
(
lpszValueName
)
:
NULL
;
/* get just the type first */
ret
=
RegQueryValueExW
(
hkey
,
lpszValueNameW
,
lpdwReserved
,
&
mytype
,
NULL
,
NULL
);
if
(
ret
!=
ERROR_SUCCESS
)
/* failed ?? */
{
if
(
lpszValueNameW
)
free
(
lpszValueNameW
);
return
ret
;
}
if
(
lpcbData
)
/* at least length requested? */
{
if
(
UNICONVMASK
&
(
1
<<
(
mytype
)))
/* string requested? */
{
if
(
lpbData
)
/* value requested? */
{
mylen
=
2
*
(
*
lpcbData
);
mybuf
=
(
LPBYTE
)
xmalloc
(
mylen
);
}
ret
=
RegQueryValueExW
(
hkey
,
lpszValueNameW
,
lpdwReserved
,
lpdwType
,
mybuf
,
&
mylen
);
if
(
ret
==
ERROR_SUCCESS
)
{
if
(
lpbData
)
{
lmemcpynWtoA
(
lpbData
,
(
LPWSTR
)
mybuf
,
mylen
/
2
);
}
}
*
lpcbData
=
mylen
/
2
;
/* size is in byte! */
}
else
/* no strings, call it straight */
{
ret
=
RegQueryValueExW
(
hkey
,
lpszValueNameW
,
lpdwReserved
,
lpdwType
,
lpbData
,
lpcbData
);
}
}
if
(
lpdwType
)
/* type when requested */
{
*
lpdwType
=
mytype
;
}
TRACE_
(
reg
)(
" (ret=%lx,type=%lx, len=%ld)
\n
"
,
ret
,
mytype
,
lpcbData
?*
lpcbData
:
0
);
if
(
mybuf
)
free
(
mybuf
);
if
(
lpszValueNameW
)
free
(
lpszValueNameW
);
return
ret
;
}
/******************************************************************************
* RegQueryValueEx16 [KERNEL.225]
*/
DWORD
WINAPI
RegQueryValueEx16
(
HKEY
hkey
,
LPSTR
lpszValueName
,
LPDWORD
lpdwReserved
,
LPDWORD
lpdwType
,
LPBYTE
lpbData
,
LPDWORD
lpcbData
)
{
TRACE_
(
reg
)(
"(%x,%s,%p,%p,%p,%ld)
\n
"
,
hkey
,
debugstr_a
(
lpszValueName
),
lpdwReserved
,
lpdwType
,
lpbData
,
lpcbData
?*
lpcbData
:
0
);
return
RegQueryValueExA
(
hkey
,
lpszValueName
,
lpdwReserved
,
lpdwType
,
lpbData
,
lpcbData
);
}
/******************************************************************************
* RegQueryValue32A [ADVAPI32.156]
*/
DWORD
WINAPI
RegQueryValueA
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
LPSTR
lpszData
,
LPLONG
lpcbData
)
{
HKEY
xhkey
;
DWORD
ret
,
dwType
;
TRACE_
(
reg
)(
"(%x,%s,%p,%ld)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
),
lpszData
,
lpcbData
?*
lpcbData
:
0
);
if
(
lpszSubKey
&&
*
lpszSubKey
)
{
ret
=
RegOpenKey16
(
hkey
,
lpszSubKey
,
&
xhkey
);
if
(
ret
!=
ERROR_SUCCESS
)
return
ret
;
}
else
xhkey
=
hkey
;
dwType
=
REG_SZ
;
ret
=
RegQueryValueExA
(
xhkey
,
NULL
,
NULL
,
&
dwType
,
(
LPBYTE
)
lpszData
,
lpcbData
);
if
(
xhkey
!=
hkey
)
RegCloseKey
(
xhkey
);
return
ret
;
}
/******************************************************************************
* RegQueryValue16 [SHELL.6] [KERNEL.224]
*
* NOTES
* Is this HACK still applicable?
*
* HACK
* The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
* mask out the high 16 bit. This (not so much incidently) hopefully fixes
* Aldus FH4)
*/
DWORD
WINAPI
RegQueryValue16
(
HKEY
hkey
,
LPSTR
lpszSubKey
,
LPSTR
lpszData
,
LPDWORD
lpcbData
)
{
TRACE_
(
reg
)(
"(%x,%s,%p,%ld)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
),
lpszData
,
lpcbData
?*
lpcbData
:
0
);
if
(
lpcbData
)
*
lpcbData
&=
0xFFFF
;
return
RegQueryValueA
(
hkey
,
lpszSubKey
,
lpszData
,
lpcbData
);
}
/*
* Setting values of Registry keys
*
* Callpath:
* RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
* RegSetValue32W -> RegSetValueEx32W
*/
/******************************************************************************
* RegSetValueEx32W [ADVAPI32.170]
* Sets the data and type of a value under a register key
*
* PARAMS
* hkey [I] Handle of key to set value for
* lpszValueName [I] Name of value to set
* dwReserved [I] Reserved - must be zero
* dwType [I] Flag for value type
* lpbData [I] Address of value data
* cbData [I] Size of value data
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*
* NOTES
* win95 does not care about cbData for REG_SZ and finds out the len by itself (js)
*/
DWORD
WINAPI
RegSetValueExW
(
HKEY
hkey
,
LPCWSTR
lpszValueName
,
DWORD
dwReserved
,
DWORD
dwType
,
CONST
BYTE
*
lpbData
,
DWORD
cbData
)
{
LPKEYSTRUCT
lpkey
;
int
i
;
TRACE_
(
reg
)(
"(%x,%s,%ld,%ld,%p,%ld)
\n
"
,
hkey
,
debugstr_w
(
lpszValueName
),
dwReserved
,
dwType
,
lpbData
,
cbData
);
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
lpkey
->
flags
|=
REG_OPTION_TAINTED
;
if
(
lpszValueName
==
NULL
)
{
/* Sets type and name for key's unnamed or default value */
for
(
i
=
0
;
i
<
lpkey
->
nrofvalues
;
i
++
)
if
(
lpkey
->
values
[
i
].
name
==
NULL
)
break
;
}
else
{
for
(
i
=
0
;
i
<
lpkey
->
nrofvalues
;
i
++
)
if
(
lpkey
->
values
[
i
].
name
&&
!
lstrcmpiW
(
lpszValueName
,
lpkey
->
values
[
i
].
name
)
)
break
;
}
if
(
i
==
lpkey
->
nrofvalues
)
{
lpkey
->
values
=
(
LPKEYVALUE
)
xrealloc
(
lpkey
->
values
,
(
lpkey
->
nrofvalues
+
1
)
*
sizeof
(
KEYVALUE
)
);
lpkey
->
nrofvalues
++
;
memset
(
lpkey
->
values
+
i
,
'\0'
,
sizeof
(
KEYVALUE
));
}
if
(
lpkey
->
values
[
i
].
name
==
NULL
)
{
if
(
lpszValueName
)
lpkey
->
values
[
i
].
name
=
strdupW
(
lpszValueName
);
else
lpkey
->
values
[
i
].
name
=
NULL
;
}
if
(
dwType
==
REG_SZ
)
cbData
=
2
*
(
lstrlenW
((
LPCWSTR
)
lpbData
)
+
1
);
lpkey
->
values
[
i
].
len
=
cbData
;
lpkey
->
values
[
i
].
type
=
dwType
;
if
(
lpkey
->
values
[
i
].
data
!=
NULL
)
free
(
lpkey
->
values
[
i
].
data
);
lpkey
->
values
[
i
].
data
=
(
LPBYTE
)
xmalloc
(
cbData
);
lpkey
->
values
[
i
].
lastmodified
=
time
(
NULL
);
memcpy
(
lpkey
->
values
[
i
].
data
,
lpbData
,
cbData
);
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegSetValueEx32A [ADVAPI32.169]
*
* NOTES
* win95 does not care about cbData for REG_SZ and finds out the len by itself (js)
*/
DWORD
WINAPI
RegSetValueExA
(
HKEY
hkey
,
LPCSTR
lpszValueName
,
DWORD
dwReserved
,
DWORD
dwType
,
CONST
BYTE
*
lpbData
,
DWORD
cbData
)
{
LPBYTE
buf
;
LPWSTR
lpszValueNameW
;
DWORD
ret
;
if
(
!
lpbData
)
return
(
ERROR_INVALID_PARAMETER
);
TRACE_
(
reg
)(
"(%x,%s,%ld,%ld,%p,%ld)
\n
"
,
hkey
,
debugstr_a
(
lpszValueName
),
dwReserved
,
dwType
,
lpbData
,
cbData
);
if
((
1
<<
dwType
)
&
UNICONVMASK
)
{
if
(
dwType
==
REG_SZ
)
cbData
=
strlen
((
LPCSTR
)
lpbData
)
+
1
;
buf
=
(
LPBYTE
)
xmalloc
(
cbData
*
2
);
lmemcpynAtoW
((
LPVOID
)
buf
,
lpbData
,
cbData
);
cbData
=
2
*
cbData
;
}
else
buf
=
(
LPBYTE
)
lpbData
;
if
(
lpszValueName
)
lpszValueNameW
=
strdupA2W
(
lpszValueName
);
else
lpszValueNameW
=
NULL
;
ret
=
RegSetValueExW
(
hkey
,
lpszValueNameW
,
dwReserved
,
dwType
,
buf
,
cbData
);
if
(
lpszValueNameW
)
free
(
lpszValueNameW
);
if
(
buf
!=
lpbData
)
free
(
buf
);
return
ret
;
}
/******************************************************************************
* RegSetValueEx16 [KERNEL.226]
*/
DWORD
WINAPI
RegSetValueEx16
(
HKEY
hkey
,
LPSTR
lpszValueName
,
DWORD
dwReserved
,
DWORD
dwType
,
LPBYTE
lpbData
,
DWORD
cbData
)
{
TRACE_
(
reg
)(
"(%x,%s,%ld,%ld,%p,%ld)
\n
"
,
hkey
,
debugstr_a
(
lpszValueName
),
dwReserved
,
dwType
,
lpbData
,
cbData
);
return
RegSetValueExA
(
hkey
,
lpszValueName
,
dwReserved
,
dwType
,
lpbData
,
cbData
);
}
/******************************************************************************
* RegSetValue32W [ADVAPI32.171]
*/
DWORD
WINAPI
RegSetValueW
(
HKEY
hkey
,
LPCWSTR
lpszSubKey
,
DWORD
dwType
,
LPCWSTR
lpszData
,
DWORD
cbData
)
{
HKEY
xhkey
;
DWORD
ret
;
TRACE_
(
reg
)(
"(%x,%s,%ld,%s,%ld)
\n
"
,
hkey
,
debugstr_w
(
lpszSubKey
),
dwType
,
debugstr_w
(
lpszData
),
cbData
);
if
(
lpszSubKey
&&
*
lpszSubKey
)
{
ret
=
RegCreateKeyW
(
hkey
,
lpszSubKey
,
&
xhkey
);
if
(
ret
!=
ERROR_SUCCESS
)
return
ret
;
}
else
xhkey
=
hkey
;
if
(
dwType
!=
REG_SZ
)
{
TRACE_
(
reg
)(
"dwType=%ld - Changing to REG_SZ
\n
"
,
dwType
);
dwType
=
REG_SZ
;
}
if
(
cbData
!=
2
*
lstrlenW
(
lpszData
)
+
2
)
{
TRACE_
(
reg
)(
"Len=%ld != strlen(%s)+1=%d!
\n
"
,
cbData
,
debugstr_w
(
lpszData
),
2
*
lstrlenW
(
lpszData
)
+
2
);
cbData
=
2
*
lstrlenW
(
lpszData
)
+
2
;
}
ret
=
RegSetValueExW
(
xhkey
,
NULL
,
0
,
dwType
,(
LPBYTE
)
lpszData
,
cbData
);
if
(
hkey
!=
xhkey
)
RegCloseKey
(
xhkey
);
return
ret
;
}
/******************************************************************************
* RegSetValue32A [ADVAPI32.168]
*
*/
DWORD
WINAPI
RegSetValueA
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
DWORD
dwType
,
LPCSTR
lpszData
,
DWORD
cbData
)
{
DWORD
ret
;
HKEY
xhkey
;
TRACE_
(
reg
)(
"(%x,%s,%ld,%s,%ld)
\n
"
,
hkey
,
lpszSubKey
,
dwType
,
lpszData
,
cbData
);
if
(
lpszSubKey
&&
*
lpszSubKey
)
{
ret
=
RegCreateKey16
(
hkey
,
lpszSubKey
,
&
xhkey
);
if
(
ret
!=
ERROR_SUCCESS
)
return
ret
;
}
else
xhkey
=
hkey
;
if
(
dwType
!=
REG_SZ
)
{
TRACE_
(
reg
)(
"dwType=%ld!
\n
"
,
dwType
);
dwType
=
REG_SZ
;
}
if
(
cbData
!=
strlen
(
lpszData
)
+
1
)
cbData
=
strlen
(
lpszData
)
+
1
;
ret
=
RegSetValueExA
(
xhkey
,
NULL
,
0
,
dwType
,(
LPBYTE
)
lpszData
,
cbData
);
if
(
xhkey
!=
hkey
)
RegCloseKey
(
xhkey
);
return
ret
;
}
/******************************************************************************
* RegSetValue16 [KERNEL.221] [SHELL.5]
*/
DWORD
WINAPI
RegSetValue16
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
DWORD
dwType
,
LPCSTR
lpszData
,
DWORD
cbData
)
{
TRACE_
(
reg
)(
"(%x,%s,%ld,%s,%ld)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
),
dwType
,
debugstr_a
(
lpszData
),
cbData
);
return
RegSetValueA
(
hkey
,
lpszSubKey
,
dwType
,
lpszData
,
cbData
);
}
/*
* Key Enumeration
*
* Callpath:
* RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
* RegEnumKey32W -> RegEnumKeyEx32W
*/
/******************************************************************************
* RegEnumKeyEx32W [ADVAPI32.139]
*
* PARAMS
* hkey [I] Handle to key to enumerate
* iSubKey [I] Index of subkey to enumerate
* lpszName [O] Buffer for subkey name
* lpcchName [O] Size of subkey buffer
* lpdwReserved [I] Reserved
* lpszClass [O] Buffer for class string
* lpcchClass [O] Size of class buffer
* ft [O] Time key last written to
*/
DWORD
WINAPI
RegEnumKeyExW
(
HKEY
hkey
,
DWORD
iSubkey
,
LPWSTR
lpszName
,
LPDWORD
lpcchName
,
LPDWORD
lpdwReserved
,
LPWSTR
lpszClass
,
LPDWORD
lpcchClass
,
FILETIME
*
ft
)
{
LPKEYSTRUCT
lpkey
,
lpxkey
;
TRACE_
(
reg
)(
"(%x,%ld,%p,%p(%ld),%p,%p,%p,%p)
\n
"
,
hkey
,
iSubkey
,
lpszName
,
lpcchName
,
lpcchName
?
*
lpcchName
:
-
1
,
lpdwReserved
,
lpszClass
,
lpcchClass
,
ft
);
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
if
(
!
lpcchName
)
return
ERROR_INVALID_PARAMETER
;
if
(
!
lpkey
->
nextsub
)
return
ERROR_NO_MORE_ITEMS
;
lpxkey
=
lpkey
->
nextsub
;
/* Traverse the subkeys */
while
(
iSubkey
&&
lpxkey
)
{
iSubkey
--
;
lpxkey
=
lpxkey
->
next
;
}
if
(
iSubkey
||
!
lpxkey
)
return
ERROR_NO_MORE_ITEMS
;
if
(
lstrlenW
(
lpxkey
->
keyname
)
+
1
>*
lpcchName
)
{
*
lpcchName
=
lstrlenW
(
lpxkey
->
keyname
);
return
ERROR_MORE_DATA
;
}
memcpy
(
lpszName
,
lpxkey
->
keyname
,
lstrlenW
(
lpxkey
->
keyname
)
*
2
+
2
);
*
lpcchName
=
lstrlenW
(
lpszName
);
if
(
lpszClass
)
{
/* FIXME: what should we write into it? */
*
lpszClass
=
0
;
*
lpcchClass
=
2
;
}
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegEnumKeyW [ADVAPI32.140]
*/
DWORD
WINAPI
RegEnumKeyW
(
HKEY
hkey
,
DWORD
iSubkey
,
LPWSTR
lpszName
,
DWORD
lpcchName
)
{
DWORD
ret
;
TRACE_
(
reg
)(
"(%x,%ld,%p,%ld)
\n
"
,
hkey
,
iSubkey
,
lpszName
,
lpcchName
);
ret
=
RegEnumKeyExW
(
hkey
,
iSubkey
,
lpszName
,
&
lpcchName
,
NULL
,
NULL
,
NULL
,
NULL
);
/* If lpszName is NULL then we have a slightly different behaviour than
RegEnumKeyExW */
if
(
lpszName
==
NULL
&&
ret
==
ERROR_MORE_DATA
)
ret
=
ERROR_SUCCESS
;
return
ret
;
}
/******************************************************************************
* RegEnumKeyEx32A [ADVAPI32.138]
*/
DWORD
WINAPI
RegEnumKeyExA
(
HKEY
hkey
,
DWORD
iSubkey
,
LPSTR
lpszName
,
LPDWORD
lpcchName
,
LPDWORD
lpdwReserved
,
LPSTR
lpszClass
,
LPDWORD
lpcchClass
,
FILETIME
*
ft
)
{
DWORD
ret
;
LPWSTR
lpszNameW
,
lpszClassW
;
TRACE_
(
reg
)(
"(%x,%ld,%p,%p(%ld),%p,%p,%p,%p)
\n
"
,
hkey
,
iSubkey
,
lpszName
,
lpcchName
,
lpcchName
?
*
lpcchName
:
-
1
,
lpdwReserved
,
lpszClass
,
lpcchClass
,
ft
);
lpszNameW
=
lpszName
?
(
LPWSTR
)
xmalloc
(
*
lpcchName
*
2
)
:
NULL
;
lpszClassW
=
lpszClass
?
(
LPWSTR
)
xmalloc
(
*
lpcchClass
*
2
)
:
NULL
;
ret
=
RegEnumKeyExW
(
hkey
,
iSubkey
,
lpszNameW
,
lpcchName
,
lpdwReserved
,
lpszClassW
,
lpcchClass
,
ft
);
if
(
ret
==
ERROR_SUCCESS
)
{
lstrcpyWtoA
(
lpszName
,
lpszNameW
);
if
(
lpszClassW
)
lstrcpyWtoA
(
lpszClass
,
lpszClassW
);
}
if
(
lpszNameW
)
free
(
lpszNameW
);
if
(
lpszClassW
)
free
(
lpszClassW
);
return
ret
;
}
/******************************************************************************
* RegEnumKeyA [ADVAPI32.137]
*/
DWORD
WINAPI
RegEnumKeyA
(
HKEY
hkey
,
DWORD
iSubkey
,
LPSTR
lpszName
,
DWORD
lpcchName
)
{
DWORD
ret
;
TRACE_
(
reg
)(
"(%x,%ld,%p,%ld)
\n
"
,
hkey
,
iSubkey
,
lpszName
,
lpcchName
);
ret
=
RegEnumKeyExA
(
hkey
,
iSubkey
,
lpszName
,
&
lpcchName
,
NULL
,
NULL
,
NULL
,
NULL
);
/* If lpszName is NULL then we have a slightly different behaviour than
RegEnumKeyExA */
if
(
lpszName
==
NULL
&&
ret
==
ERROR_MORE_DATA
)
ret
=
ERROR_SUCCESS
;
return
ret
;
}
/******************************************************************************
* RegEnumKey16 [SHELL.7] [KERNEL.216]
*/
DWORD
WINAPI
RegEnumKey16
(
HKEY
hkey
,
DWORD
iSubkey
,
LPSTR
lpszName
,
DWORD
lpcchName
)
{
TRACE_
(
reg
)(
"(%x,%ld,%p,%ld)
\n
"
,
hkey
,
iSubkey
,
lpszName
,
lpcchName
);
return
RegEnumKeyA
(
hkey
,
iSubkey
,
lpszName
,
lpcchName
);
}
/*
* Enumerate Registry Values
*
* Callpath:
* RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
*/
/******************************************************************************
* RegEnumValue32W [ADVAPI32.142]
*
* PARAMS
* hkey [I] Handle to key to query
* iValue [I] Index of value to query
* lpszValue [O] Value string
* lpcchValue [I/O] Size of value buffer (in wchars)
* lpdReserved [I] Reserved
* lpdwType [O] Type code
* lpbData [O] Value data
* lpcbData [I/O] Size of data buffer (in bytes)
*
* Note: wide character functions that take and/or return "character counts"
* use TCHAR (that is unsigned short or char) not byte counts.
*/
DWORD
WINAPI
RegEnumValueW
(
HKEY
hkey
,
DWORD
iValue
,
LPWSTR
lpszValue
,
LPDWORD
lpcchValue
,
LPDWORD
lpdReserved
,
LPDWORD
lpdwType
,
LPBYTE
lpbData
,
LPDWORD
lpcbData
)
{
LPKEYSTRUCT
lpkey
;
LPKEYVALUE
val
;
TRACE_
(
reg
)(
"(%x,%ld,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
iValue
,
debugstr_w
(
lpszValue
),
lpcchValue
,
lpdReserved
,
lpdwType
,
lpbData
,
lpcbData
);
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpcbData
&&
lpbData
)
return
ERROR_INVALID_PARAMETER
;
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
if
(
lpkey
->
nrofvalues
<=
iValue
)
return
ERROR_NO_MORE_ITEMS
;
val
=
&
(
lpkey
->
values
[
iValue
]);
if
(
val
->
name
)
{
if
(
lstrlenW
(
val
->
name
)
+
1
>*
lpcchValue
)
{
*
lpcchValue
=
lstrlenW
(
val
->
name
)
+
1
;
return
ERROR_MORE_DATA
;
}
memcpy
(
lpszValue
,
val
->
name
,
2
*
(
lstrlenW
(
val
->
name
)
+
1
)
);
*
lpcchValue
=
lstrlenW
(
val
->
name
);
}
else
{
*
lpszValue
=
0
;
*
lpcchValue
=
0
;
}
/* Can be NULL if the type code is not required */
if
(
lpdwType
)
*
lpdwType
=
val
->
type
;
if
(
lpbData
)
{
if
(
val
->
len
>*
lpcbData
)
{
*
lpcbData
=
val
->
len
;
return
ERROR_MORE_DATA
;
}
memcpy
(
lpbData
,
val
->
data
,
val
->
len
);
*
lpcbData
=
val
->
len
;
}
debug_print_value
(
val
->
data
,
val
);
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegEnumValue32A [ADVAPI32.141]
*/
DWORD
WINAPI
RegEnumValueA
(
HKEY
hkey
,
DWORD
iValue
,
LPSTR
lpszValue
,
LPDWORD
lpcchValue
,
LPDWORD
lpdReserved
,
LPDWORD
lpdwType
,
LPBYTE
lpbData
,
LPDWORD
lpcbData
)
{
LPWSTR
lpszValueW
;
LPBYTE
lpbDataW
;
DWORD
ret
,
lpcbDataW
;
DWORD
dwType
;
TRACE_
(
reg
)(
"(%x,%ld,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
iValue
,
lpszValue
,
lpcchValue
,
lpdReserved
,
lpdwType
,
lpbData
,
lpcbData
);
lpszValueW
=
(
LPWSTR
)
xmalloc
(
*
lpcchValue
*
2
);
if
(
lpbData
)
{
lpbDataW
=
(
LPBYTE
)
xmalloc
(
*
lpcbData
*
2
);
lpcbDataW
=
*
lpcbData
;
}
else
lpbDataW
=
NULL
;
ret
=
RegEnumValueW
(
hkey
,
iValue
,
lpszValueW
,
lpcchValue
,
lpdReserved
,
&
dwType
,
lpbDataW
,
&
lpcbDataW
);
if
(
lpdwType
)
*
lpdwType
=
dwType
;
if
(
ret
==
ERROR_SUCCESS
)
{
lstrcpyWtoA
(
lpszValue
,
lpszValueW
);
if
(
lpbData
)
{
if
((
1
<<
dwType
)
&
UNICONVMASK
)
{
lstrcpyWtoA
(
lpbData
,(
LPWSTR
)
lpbDataW
);
}
else
{
if
(
lpcbDataW
>
*
lpcbData
)
{
*
lpcbData
=
lpcbDataW
;
ret
=
ERROR_MORE_DATA
;
}
else
memcpy
(
lpbData
,
lpbDataW
,
lpcbDataW
);
}
*
lpcbData
=
lpcbDataW
;
}
}
if
(
lpbDataW
)
free
(
lpbDataW
);
if
(
lpszValueW
)
free
(
lpszValueW
);
return
ret
;
}
/******************************************************************************
* RegEnumValue16 [KERNEL.223]
*/
DWORD
WINAPI
RegEnumValue16
(
HKEY
hkey
,
DWORD
iValue
,
LPSTR
lpszValue
,
LPDWORD
lpcchValue
,
LPDWORD
lpdReserved
,
LPDWORD
lpdwType
,
LPBYTE
lpbData
,
LPDWORD
lpcbData
)
{
TRACE_
(
reg
)(
"(%x,%ld,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
iValue
,
lpszValue
,
lpcchValue
,
lpdReserved
,
lpdwType
,
lpbData
,
lpcbData
);
return
RegEnumValueA
(
hkey
,
iValue
,
lpszValue
,
lpcchValue
,
lpdReserved
,
lpdwType
,
lpbData
,
lpcbData
);
}
/******************************************************************************
* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126]
* Releases the handle of the specified key
*
* PARAMS
* hkey [I] Handle of key to close
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD
WINAPI
RegCloseKey
(
HKEY
hkey
)
{
TRACE_
(
reg
)(
"(%x)
\n
"
,
hkey
);
/* The standard handles are allowed to succeed, even though they are not
closed */
if
(
is_standard_hkey
(
hkey
))
return
ERROR_SUCCESS
;
return
remove_handle
(
hkey
);
}
/*
* Delete registry key
*
* Callpath:
* RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
*/
/******************************************************************************
* RegDeleteKey32W [ADVAPI32.134]
*
* PARAMS
* hkey [I] Handle to open key
* lpszSubKey [I] Name of subkey to delete
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD
WINAPI
RegDeleteKeyW
(
HKEY
hkey
,
LPCWSTR
lpszSubKey
)
{
LPKEYSTRUCT
*
lplpPrevKey
,
lpNextKey
,
lpxkey
;
LPWSTR
*
wps
;
int
wpc
,
i
;
TRACE_
(
reg
)(
"(%x,%s)
\n
"
,
hkey
,
debugstr_w
(
lpszSubKey
));
lpNextKey
=
lookup_hkey
(
hkey
);
if
(
!
lpNextKey
)
return
ERROR_INVALID_HANDLE
;
/* Subkey param cannot be NULL */
if
(
!
lpszSubKey
||
!*
lpszSubKey
)
return
ERROR_BADKEY
;
/* We need to know the previous key in the hier. */
split_keypath
(
lpszSubKey
,
&
wps
,
&
wpc
);
i
=
0
;
lpxkey
=
lpNextKey
;
while
(
i
<
wpc
-
1
)
{
lpxkey
=
lpNextKey
->
nextsub
;
while
(
lpxkey
)
{
TRACE_
(
reg
)(
" Scanning [%s]
\n
"
,
debugstr_w
(
lpxkey
->
keyname
));
if
(
!
lstrcmpiW
(
wps
[
i
],
lpxkey
->
keyname
))
break
;
lpxkey
=
lpxkey
->
next
;
}
if
(
!
lpxkey
)
{
FREE_KEY_PATH
;
TRACE_
(
reg
)(
" Not found.
\n
"
);
/* not found is success */
return
ERROR_SUCCESS
;
}
i
++
;
lpNextKey
=
lpxkey
;
}
lpxkey
=
lpNextKey
->
nextsub
;
lplpPrevKey
=
&
(
lpNextKey
->
nextsub
);
while
(
lpxkey
)
{
TRACE_
(
reg
)(
" Scanning [%s]
\n
"
,
debugstr_w
(
lpxkey
->
keyname
));
if
(
!
lstrcmpiW
(
wps
[
i
],
lpxkey
->
keyname
))
break
;
lplpPrevKey
=
&
(
lpxkey
->
next
);
lpxkey
=
lpxkey
->
next
;
}
if
(
!
lpxkey
)
{
FREE_KEY_PATH
;
WARN_
(
reg
)(
" Not found.
\n
"
);
return
ERROR_FILE_NOT_FOUND
;
}
if
(
lpxkey
->
nextsub
)
{
FREE_KEY_PATH
;
WARN_
(
reg
)(
" Not empty.
\n
"
);
return
ERROR_CANTWRITE
;
}
*
lplpPrevKey
=
lpxkey
->
next
;
free
(
lpxkey
->
keyname
);
if
(
lpxkey
->
class
)
free
(
lpxkey
->
class
);
if
(
lpxkey
->
values
)
free
(
lpxkey
->
values
);
free
(
lpxkey
);
FREE_KEY_PATH
;
TRACE_
(
reg
)(
" Done.
\n
"
);
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegDeleteKey32A [ADVAPI32.133]
*/
DWORD
WINAPI
RegDeleteKeyA
(
HKEY
hkey
,
LPCSTR
lpszSubKey
)
{
LPWSTR
lpszSubKeyW
;
DWORD
ret
;
TRACE_
(
reg
)(
"(%x,%s)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
));
lpszSubKeyW
=
lpszSubKey
?
strdupA2W
(
lpszSubKey
)
:
NULL
;
ret
=
RegDeleteKeyW
(
hkey
,
lpszSubKeyW
);
if
(
lpszSubKeyW
)
free
(
lpszSubKeyW
);
return
ret
;
}
/******************************************************************************
* RegDeleteKey16 [SHELL.4] [KERNEL.219]
*/
DWORD
WINAPI
RegDeleteKey16
(
HKEY
hkey
,
LPCSTR
lpszSubKey
)
{
TRACE_
(
reg
)(
"(%x,%s)
\n
"
,
hkey
,
debugstr_a
(
lpszSubKey
));
return
RegDeleteKeyA
(
hkey
,
lpszSubKey
);
}
/*
* Delete registry value
*
* Callpath:
* RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
*/
/******************************************************************************
* RegDeleteValue32W [ADVAPI32.136]
*
* PARAMS
* hkey [I]
* lpszValue [I]
*
* RETURNS
*/
DWORD
WINAPI
RegDeleteValueW
(
HKEY
hkey
,
LPCWSTR
lpszValue
)
{
DWORD
i
;
LPKEYSTRUCT
lpkey
;
LPKEYVALUE
val
;
TRACE_
(
reg
)(
"(%x,%s)
\n
"
,
hkey
,
debugstr_w
(
lpszValue
));
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
if
(
lpszValue
)
{
for
(
i
=
0
;
i
<
lpkey
->
nrofvalues
;
i
++
)
if
(
lpkey
->
values
[
i
].
name
&&
!
lstrcmpiW
(
lpkey
->
values
[
i
].
name
,
lpszValue
)
)
break
;
}
else
{
for
(
i
=
0
;
i
<
lpkey
->
nrofvalues
;
i
++
)
if
(
lpkey
->
values
[
i
].
name
==
NULL
)
break
;
}
if
(
i
==
lpkey
->
nrofvalues
)
return
ERROR_FILE_NOT_FOUND
;
val
=
lpkey
->
values
+
i
;
if
(
val
->
name
)
free
(
val
->
name
);
if
(
val
->
data
)
free
(
val
->
data
);
memcpy
(
lpkey
->
values
+
i
,
lpkey
->
values
+
i
+
1
,
sizeof
(
KEYVALUE
)
*
(
lpkey
->
nrofvalues
-
i
-
1
)
);
lpkey
->
values
=
(
LPKEYVALUE
)
xrealloc
(
lpkey
->
values
,
(
lpkey
->
nrofvalues
-
1
)
*
sizeof
(
KEYVALUE
)
);
lpkey
->
nrofvalues
--
;
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegDeleteValue32A [ADVAPI32.135]
*/
DWORD
WINAPI
RegDeleteValueA
(
HKEY
hkey
,
LPCSTR
lpszValue
)
{
LPWSTR
lpszValueW
;
DWORD
ret
;
TRACE_
(
reg
)(
"(%x,%s)
\n
"
,
hkey
,
debugstr_a
(
lpszValue
));
lpszValueW
=
lpszValue
?
strdupA2W
(
lpszValue
)
:
NULL
;
ret
=
RegDeleteValueW
(
hkey
,
lpszValueW
);
if
(
lpszValueW
)
free
(
lpszValueW
);
return
ret
;
}
/******************************************************************************
* RegDeleteValue16 [KERNEL.222]
*/
DWORD
WINAPI
RegDeleteValue16
(
HKEY
hkey
,
LPSTR
lpszValue
)
{
TRACE_
(
reg
)(
"(%x,%s)
\n
"
,
hkey
,
debugstr_a
(
lpszValue
));
return
RegDeleteValueA
(
hkey
,
lpszValue
);
}
/******************************************************************************
* RegFlushKey [KERNEL.227] [ADVAPI32.143]
* Immediately writes key to registry.
* Only returns after data has been written to disk.
* RegFlushKey [KERNEL.227] [ADVAPI32.143]
* Immediately writes key to registry.
* Only returns after data has been written to disk.
*
* FIXME: does it really wait until data is written ?
*
* I guess that we can remove the REG_OPTION_TAINTED flag from every key
* written if this function really works (and only if !).
*
* PARAMS
* hkey [I] Handle of key to write
*
...
...
@@ -3536,177 +1409,10 @@ DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR lpszValue )
*/
DWORD
WINAPI
RegFlushKey
(
HKEY
hkey
)
{
LPKEYSTRUCT
lpkey
;
TRACE_
(
reg
)(
"(%x)
\n
"
,
hkey
);
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_BADKEY
;
SHELL_SaveRegistryBranch
(
find_root_key
(
lpkey
),
TRUE
);
return
ERROR_SUCCESS
;
}
/* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
/******************************************************************************
* RegQueryInfoKey32W [ADVAPI32.153]
*
* PARAMS
* hkey [I] Handle to key to query
* lpszClass [O] Buffer for class string
* lpcchClass [O] Size of class string buffer
* lpdwReserved [I] Reserved
* lpcSubKeys [I] Buffer for number of subkeys
* lpcchMaxSubKey [O] Buffer for longest subkey name length
* lpcchMaxClass [O] Buffer for longest class string length
* lpcValues [O] Buffer for number of value entries
* lpcchMaxValueName [O] Buffer for longest value name length
* lpccbMaxValueData [O] Buffer for longest value data length
* lpcbSecurityDescriptor [O] Buffer for security descriptor length
* ft
* - win95 allows lpszClass to be valid and lpcchClass to be NULL
* - winnt returns ERROR_INVALID_PARAMETER if lpszClass is valid and
* lpcchClass is NULL
* - both allow lpszClass to be NULL and lpcchClass to be NULL
* (it's hard to test validity, so test !NULL instead)
*/
DWORD
WINAPI
RegQueryInfoKeyW
(
HKEY
hkey
,
LPWSTR
lpszClass
,
LPDWORD
lpcchClass
,
LPDWORD
lpdwReserved
,
LPDWORD
lpcSubKeys
,
LPDWORD
lpcchMaxSubkey
,
LPDWORD
lpcchMaxClass
,
LPDWORD
lpcValues
,
LPDWORD
lpcchMaxValueName
,
LPDWORD
lpccbMaxValueData
,
LPDWORD
lpcbSecurityDescriptor
,
FILETIME
*
ft
)
{
LPKEYSTRUCT
lpkey
,
lpxkey
;
int
nrofkeys
,
maxsubkey
,
maxclass
,
maxvname
,
maxvdata
;
int
i
;
TRACE_
(
reg
)(
"(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
lpszClass
,
lpcchClass
?*
lpcchClass
:
0
,
lpdwReserved
,
lpcSubKeys
,
lpcchMaxSubkey
,
lpcValues
,
lpcchMaxValueName
,
lpccbMaxValueData
,
lpcbSecurityDescriptor
,
ft
);
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
if
(
lpszClass
)
{
if
(
VERSION_GetVersion
()
==
NT40
&&
lpcchClass
==
NULL
)
{
return
ERROR_INVALID_PARAMETER
;
}
/* either lpcchClass is valid or this is win95 and lpcchClass
could be invalid */
if
(
lpkey
->
class
)
{
DWORD
classLen
=
lstrlenW
(
lpkey
->
class
);
if
(
lpcchClass
&&
classLen
+
1
>*
lpcchClass
)
{
*
lpcchClass
=
classLen
+
1
;
return
ERROR_MORE_DATA
;
}
if
(
lpcchClass
)
*
lpcchClass
=
classLen
;
memcpy
(
lpszClass
,
lpkey
->
class
,
classLen
*
2
+
2
);
}
else
{
*
lpszClass
=
0
;
if
(
lpcchClass
)
*
lpcchClass
=
0
;
}
}
else
{
if
(
lpcchClass
)
*
lpcchClass
=
lstrlenW
(
lpkey
->
class
);
}
lpxkey
=
lpkey
->
nextsub
;
nrofkeys
=
maxsubkey
=
maxclass
=
maxvname
=
maxvdata
=
0
;
while
(
lpxkey
)
{
nrofkeys
++
;
if
(
lstrlenW
(
lpxkey
->
keyname
)
>
maxsubkey
)
maxsubkey
=
lstrlenW
(
lpxkey
->
keyname
);
if
(
lpxkey
->
class
&&
lstrlenW
(
lpxkey
->
class
)
>
maxclass
)
maxclass
=
lstrlenW
(
lpxkey
->
class
);
lpxkey
=
lpxkey
->
next
;
}
for
(
i
=
0
;
i
<
lpkey
->
nrofvalues
;
i
++
)
{
LPKEYVALUE
val
=
lpkey
->
values
+
i
;
if
(
val
->
name
&&
lstrlenW
(
val
->
name
)
>
maxvname
)
maxvname
=
lstrlenW
(
val
->
name
);
if
(
val
->
len
>
maxvdata
)
maxvdata
=
val
->
len
;
}
if
(
!
maxclass
)
maxclass
=
1
;
if
(
!
maxvname
)
maxvname
=
1
;
if
(
lpcValues
)
*
lpcValues
=
lpkey
->
nrofvalues
;
if
(
lpcSubKeys
)
*
lpcSubKeys
=
nrofkeys
;
if
(
lpcchMaxSubkey
)
*
lpcchMaxSubkey
=
maxsubkey
;
if
(
lpcchMaxClass
)
*
lpcchMaxClass
=
maxclass
;
if
(
lpcchMaxValueName
)
*
lpcchMaxValueName
=
maxvname
;
if
(
lpccbMaxValueData
)
*
lpccbMaxValueData
=
maxvdata
;
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegQueryInfoKey32A [ADVAPI32.152]
*/
DWORD
WINAPI
RegQueryInfoKeyA
(
HKEY
hkey
,
LPSTR
lpszClass
,
LPDWORD
lpcchClass
,
LPDWORD
lpdwReserved
,
LPDWORD
lpcSubKeys
,
LPDWORD
lpcchMaxSubkey
,
LPDWORD
lpcchMaxClass
,
LPDWORD
lpcValues
,
LPDWORD
lpcchMaxValueName
,
LPDWORD
lpccbMaxValueData
,
LPDWORD
lpcbSecurityDescriptor
,
FILETIME
*
ft
)
{
LPWSTR
lpszClassW
=
NULL
;
DWORD
ret
;
TRACE_
(
reg
)(
"(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)
\n
"
,
hkey
,
lpszClass
,
lpcchClass
?*
lpcchClass
:
0
,
lpdwReserved
,
lpcSubKeys
,
lpcchMaxSubkey
,
lpcValues
,
lpcchMaxValueName
,
lpccbMaxValueData
,
lpcbSecurityDescriptor
,
ft
);
if
(
lpszClass
)
{
if
(
lpcchClass
)
{
lpszClassW
=
(
LPWSTR
)
xmalloc
((
*
lpcchClass
)
*
2
);
}
else
if
(
VERSION_GetVersion
()
==
WIN95
)
{
/* win95 allows lpcchClass to be null */
/* we don't know how big lpszClass is, would
MAX_PATHNAME_LEN be the correct default? */
lpszClassW
=
(
LPWSTR
)
xmalloc
(
MAX_PATHNAME_LEN
*
2
);
}
}
else
lpszClassW
=
NULL
;
ret
=
RegQueryInfoKeyW
(
hkey
,
lpszClassW
,
lpcchClass
,
lpdwReserved
,
lpcSubKeys
,
lpcchMaxSubkey
,
lpcchMaxClass
,
lpcValues
,
lpcchMaxValueName
,
lpccbMaxValueData
,
lpcbSecurityDescriptor
,
ft
);
if
(
ret
==
ERROR_SUCCESS
&&
lpszClass
)
lstrcpyWtoA
(
lpszClass
,
lpszClassW
);
if
(
lpszClassW
)
free
(
lpszClassW
);
return
ret
;
FIXME
(
"(%x): stub
\n
"
,
hkey
);
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegConnectRegistry32W [ADVAPI32.128]
*
...
...
@@ -3762,15 +1468,9 @@ LONG WINAPI RegGetKeySecurity( HKEY hkey,
PSECURITY_DESCRIPTOR
pSecurityDescriptor
,
LPDWORD
lpcbSecurityDescriptor
)
{
LPKEYSTRUCT
lpkey
;
TRACE_
(
reg
)(
"(%x,%ld,%p,%ld)
\n
"
,
hkey
,
SecurityInformation
,
pSecurityDescriptor
,
lpcbSecurityDescriptor
?*
lpcbSecurityDescriptor
:
0
);
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
/* FIXME: Check for valid SecurityInformation values */
if
(
*
lpcbSecurityDescriptor
<
sizeof
(
SECURITY_DESCRIPTOR
))
...
...
@@ -3784,49 +1484,6 @@ LONG WINAPI RegGetKeySecurity( HKEY hkey,
/******************************************************************************
* RegLoadKey32W [ADVAPI32.???]
*
* PARAMS
* hkey [I] Handle of open key
* lpszSubKey [I] Address of name of subkey
* lpszFile [I] Address of filename for registry information
*/
LONG
WINAPI
RegLoadKeyW
(
HKEY
hkey
,
LPCWSTR
lpszSubKey
,
LPCWSTR
lpszFile
)
{
LPKEYSTRUCT
lpkey
;
TRACE_
(
reg
)(
"(%x,%s,%s)
\n
"
,
hkey
,
debugstr_w
(
lpszSubKey
),
debugstr_w
(
lpszFile
));
/* Do this check before the hkey check */
if
(
!
lpszSubKey
||
!*
lpszSubKey
||
!
lpszFile
||
!*
lpszFile
)
return
ERROR_INVALID_PARAMETER
;
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
FIXME_
(
reg
)(
"(%x,%s,%s): stub
\n
"
,
hkey
,
debugstr_w
(
lpszSubKey
),
debugstr_w
(
lpszFile
));
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegLoadKey32A [ADVAPI32.???]
*/
LONG
WINAPI
RegLoadKeyA
(
HKEY
hkey
,
LPCSTR
lpszSubKey
,
LPCSTR
lpszFile
)
{
LONG
ret
;
LPWSTR
lpszSubKeyW
=
strdupA2W
(
lpszSubKey
);
LPWSTR
lpszFileW
=
strdupA2W
(
lpszFile
);
ret
=
RegLoadKeyW
(
hkey
,
lpszSubKeyW
,
lpszFileW
);
if
(
lpszFileW
)
free
(
lpszFileW
);
if
(
lpszSubKeyW
)
free
(
lpszSubKeyW
);
return
ret
;
}
/******************************************************************************
* RegNotifyChangeKeyValue [ADVAPI32.???]
*
* PARAMS
...
...
@@ -3840,17 +1497,8 @@ LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree,
DWORD
fdwNotifyFilter
,
HANDLE
hEvent
,
BOOL
fAsync
)
{
LPKEYSTRUCT
lpkey
;
TRACE_
(
reg
)(
"(%x,%i,%ld,%x,%i)
\n
"
,
hkey
,
fWatchSubTree
,
fdwNotifyFilter
,
hEvent
,
fAsync
);
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
FIXME_
(
reg
)(
"(%x,%i,%ld,%x,%i): stub
\n
"
,
hkey
,
fWatchSubTree
,
fdwNotifyFilter
,
hEvent
,
fAsync
);
return
ERROR_SUCCESS
;
}
...
...
@@ -3893,8 +1541,6 @@ LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
LONG
WINAPI
RegSetKeySecurity
(
HKEY
hkey
,
SECURITY_INFORMATION
SecurityInfo
,
PSECURITY_DESCRIPTOR
pSecurityDesc
)
{
LPKEYSTRUCT
lpkey
;
TRACE_
(
reg
)(
"(%x,%ld,%p)
\n
"
,
hkey
,
SecurityInfo
,
pSecurityDesc
);
/* It seems to perform this check before the hkey check */
...
...
@@ -3909,10 +1555,6 @@ LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
if
(
!
pSecurityDesc
)
return
ERROR_INVALID_PARAMETER
;
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
FIXME_
(
reg
)(
":(%x,%ld,%p): stub
\n
"
,
hkey
,
SecurityInfo
,
pSecurityDesc
);
return
ERROR_SUCCESS
;
...
...
@@ -3920,49 +1562,6 @@ LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
/******************************************************************************
* RegSaveKey32W [ADVAPI32.166]
*
* PARAMS
* hkey [I] Handle of key where save begins
* lpFile [I] Address of filename to save to
* sa [I] Address of security structure
*/
LONG
WINAPI
RegSaveKeyW
(
HKEY
hkey
,
LPCWSTR
lpFile
,
LPSECURITY_ATTRIBUTES
sa
)
{
LPKEYSTRUCT
lpkey
;
TRACE_
(
reg
)(
"(%x,%s,%p)
\n
"
,
hkey
,
debugstr_w
(
lpFile
),
sa
);
/* It appears to do this check before the hkey check */
if
(
!
lpFile
||
!*
lpFile
)
return
ERROR_INVALID_PARAMETER
;
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
FIXME_
(
reg
)(
"(%x,%s,%p): stub
\n
"
,
hkey
,
debugstr_w
(
lpFile
),
sa
);
return
ERROR_SUCCESS
;
}
/******************************************************************************
* RegSaveKey32A [ADVAPI32.165]
*/
LONG
WINAPI
RegSaveKeyA
(
HKEY
hkey
,
LPCSTR
lpFile
,
LPSECURITY_ATTRIBUTES
sa
)
{
LONG
ret
;
LPWSTR
lpFileW
=
strdupA2W
(
lpFile
);
ret
=
RegSaveKeyW
(
hkey
,
lpFileW
,
sa
);
free
(
lpFileW
);
return
ret
;
}
/******************************************************************************
* RegRestoreKey32W [ADVAPI32.164]
*
* PARAMS
...
...
@@ -3972,18 +1571,12 @@ LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR lpFile,
*/
LONG
WINAPI
RegRestoreKeyW
(
HKEY
hkey
,
LPCWSTR
lpFile
,
DWORD
dwFlags
)
{
LPKEYSTRUCT
lpkey
;
TRACE_
(
reg
)(
"(%x,%s,%ld)
\n
"
,
hkey
,
debugstr_w
(
lpFile
),
dwFlags
);
/* It seems to do this check before the hkey check */
if
(
!
lpFile
||
!*
lpFile
)
return
ERROR_INVALID_PARAMETER
;
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
FIXME_
(
reg
)(
"(%x,%s,%ld): stub
\n
"
,
hkey
,
debugstr_w
(
lpFile
),
dwFlags
);
/* Check for file existence */
...
...
@@ -4017,18 +1610,8 @@ LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
LONG
WINAPI
RegReplaceKeyW
(
HKEY
hkey
,
LPCWSTR
lpSubKey
,
LPCWSTR
lpNewFile
,
LPCWSTR
lpOldFile
)
{
LPKEYSTRUCT
lpkey
;
TRACE_
(
reg
)(
"(%x,%s,%s,%s)
\n
"
,
hkey
,
debugstr_w
(
lpSubKey
),
debugstr_w
(
lpNewFile
),
debugstr_w
(
lpOldFile
));
lpkey
=
lookup_hkey
(
hkey
);
if
(
!
lpkey
)
return
ERROR_INVALID_HANDLE
;
FIXME_
(
reg
)(
"(%x,%s,%s,%s): stub
\n
"
,
hkey
,
debugstr_w
(
lpSubKey
),
debugstr_w
(
lpNewFile
),
debugstr_w
(
lpOldFile
));
return
ERROR_SUCCESS
;
}
...
...
@@ -4050,3 +1633,128 @@ LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
return
ret
;
}
/* 16-bit functions */
/* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
* some programs. Do not remove those cases. -MM
*/
static
inline
void
fix_win16_hkey
(
HKEY
*
hkey
)
{
if
(
*
hkey
==
0
||
*
hkey
==
1
)
*
hkey
=
HKEY_CLASSES_ROOT
;
}
/******************************************************************************
* RegEnumKey16 [KERNEL.216] [SHELL.7]
*/
DWORD
WINAPI
RegEnumKey16
(
HKEY
hkey
,
DWORD
index
,
LPSTR
name
,
DWORD
name_len
)
{
fix_win16_hkey
(
&
hkey
);
return
RegEnumKeyA
(
hkey
,
index
,
name
,
name_len
);
}
/******************************************************************************
* RegOpenKey16 [KERNEL.217] [SHELL.1]
*/
DWORD
WINAPI
RegOpenKey16
(
HKEY
hkey
,
LPCSTR
name
,
LPHKEY
retkey
)
{
fix_win16_hkey
(
&
hkey
);
return
RegOpenKeyA
(
hkey
,
name
,
retkey
);
}
/******************************************************************************
* RegCreateKey16 [KERNEL.218] [SHELL.2]
*/
DWORD
WINAPI
RegCreateKey16
(
HKEY
hkey
,
LPCSTR
name
,
LPHKEY
retkey
)
{
fix_win16_hkey
(
&
hkey
);
return
RegCreateKeyA
(
hkey
,
name
,
retkey
);
}
/******************************************************************************
* RegDeleteKey16 [KERNEL.219] [SHELL.4]
*/
DWORD
WINAPI
RegDeleteKey16
(
HKEY
hkey
,
LPCSTR
name
)
{
fix_win16_hkey
(
&
hkey
);
return
RegDeleteKeyA
(
hkey
,
name
);
}
/******************************************************************************
* RegCloseKey16 [KERNEL.220] [SHELL.3]
*/
DWORD
WINAPI
RegCloseKey16
(
HKEY
hkey
)
{
fix_win16_hkey
(
&
hkey
);
return
RegCloseKey
(
hkey
);
}
/******************************************************************************
* RegSetValue16 [KERNEL.221] [SHELL.5]
*/
DWORD
WINAPI
RegSetValue16
(
HKEY
hkey
,
LPCSTR
name
,
DWORD
type
,
LPCSTR
data
,
DWORD
count
)
{
fix_win16_hkey
(
&
hkey
);
return
RegSetValueA
(
hkey
,
name
,
type
,
data
,
count
);
}
/******************************************************************************
* RegDeleteValue16 [KERNEL.222]
*/
DWORD
WINAPI
RegDeleteValue16
(
HKEY
hkey
,
LPSTR
name
)
{
fix_win16_hkey
(
&
hkey
);
return
RegDeleteValueA
(
hkey
,
name
);
}
/******************************************************************************
* RegEnumValue16 [KERNEL.223]
*/
DWORD
WINAPI
RegEnumValue16
(
HKEY
hkey
,
DWORD
index
,
LPSTR
value
,
LPDWORD
val_count
,
LPDWORD
reserved
,
LPDWORD
type
,
LPBYTE
data
,
LPDWORD
count
)
{
fix_win16_hkey
(
&
hkey
);
return
RegEnumValueA
(
hkey
,
index
,
value
,
val_count
,
reserved
,
type
,
data
,
count
);
}
/******************************************************************************
* RegQueryValue16 [KERNEL.224] [SHELL.6]
*
* NOTES
* Is this HACK still applicable?
*
* HACK
* The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
* mask out the high 16 bit. This (not so much incidently) hopefully fixes
* Aldus FH4)
*/
DWORD
WINAPI
RegQueryValue16
(
HKEY
hkey
,
LPCSTR
name
,
LPSTR
data
,
LPDWORD
count
)
{
fix_win16_hkey
(
&
hkey
);
if
(
count
)
*
count
&=
0xffff
;
return
RegQueryValueA
(
hkey
,
name
,
data
,
count
);
}
/******************************************************************************
* RegQueryValueEx16 [KERNEL.225]
*/
DWORD
WINAPI
RegQueryValueEx16
(
HKEY
hkey
,
LPCSTR
name
,
LPDWORD
reserved
,
LPDWORD
type
,
LPBYTE
data
,
LPDWORD
count
)
{
fix_win16_hkey
(
&
hkey
);
return
RegQueryValueExA
(
hkey
,
name
,
reserved
,
type
,
data
,
count
);
}
/******************************************************************************
* RegSetValueEx16 [KERNEL.226]
*/
DWORD
WINAPI
RegSetValueEx16
(
HKEY
hkey
,
LPCSTR
name
,
DWORD
reserved
,
DWORD
type
,
CONST
BYTE
*
data
,
DWORD
count
)
{
fix_win16_hkey
(
&
hkey
);
return
RegSetValueExA
(
hkey
,
name
,
reserved
,
type
,
data
,
count
);
}
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