Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
6ae247bb
Commit
6ae247bb
authored
Nov 30, 2018
by
Nikolay Sivov
Committed by
Alexandre Julliard
Nov 30, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
shcore: Add registry access helpers.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
1fd60d56
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
796 additions
and
21 deletions
+796
-21
main.c
dlls/shcore/main.c
+442
-0
shcore.spec
dlls/shcore/shcore.spec
+21
-21
shcore.c
dlls/shcore/tests/shcore.c
+333
-0
No files found.
dlls/shcore/main.c
View file @
6ae247bb
...
...
@@ -1873,3 +1873,445 @@ DWORD WINAPI SHDeleteValueA(HKEY hkey, const char *subkey, const char *value)
CoTaskMemFree
(
valueW
);
return
ret
;
}
/*************************************************************************
* SHCopyKeyA [SHCORE.@]
*/
DWORD
WINAPI
SHCopyKeyA
(
HKEY
hkey_src
,
const
char
*
subkey
,
HKEY
hkey_dst
,
DWORD
reserved
)
{
WCHAR
*
subkeyW
=
NULL
;
DWORD
ret
;
TRACE
(
"(%p, %s, %p, %d)
\n
"
,
hkey_src
,
debugstr_a
(
subkey
),
hkey_dst
,
reserved
);
if
(
subkey
&&
FAILED
(
SHStrDupA
(
subkey
,
&
subkeyW
)))
return
0
;
ret
=
SHCopyKeyW
(
hkey_src
,
subkeyW
,
hkey_dst
,
reserved
);
CoTaskMemFree
(
subkeyW
);
return
ret
;
}
/*************************************************************************
* SHCopyKeyW [SHCORE.@]
*/
DWORD
WINAPI
SHCopyKeyW
(
HKEY
hkey_src
,
const
WCHAR
*
subkey
,
HKEY
hkey_dst
,
DWORD
reserved
)
{
DWORD
key_count
=
0
,
value_count
=
0
,
max_key_len
=
0
;
WCHAR
name
[
MAX_PATH
],
*
ptr_name
=
name
;
BYTE
buff
[
1024
],
*
ptr
=
buff
;
DWORD
max_data_len
=
0
,
i
;
DWORD
ret
=
0
;
TRACE
(
"(%p, %s, %p, %d)
\n
"
,
hkey_src
,
debugstr_w
(
subkey
),
hkey_dst
,
reserved
);
if
(
!
hkey_dst
||
!
hkey_src
)
return
ERROR_INVALID_PARAMETER
;
if
(
subkey
)
ret
=
RegOpenKeyExW
(
hkey_src
,
subkey
,
0
,
KEY_ALL_ACCESS
,
&
hkey_src
);
if
(
ret
)
hkey_src
=
NULL
;
/* Don't close this key since we didn't open it */
else
{
DWORD
max_value_len
;
ret
=
RegQueryInfoKeyW
(
hkey_src
,
NULL
,
NULL
,
NULL
,
&
key_count
,
&
max_key_len
,
NULL
,
&
value_count
,
&
max_value_len
,
&
max_data_len
,
NULL
,
NULL
);
if
(
!
ret
)
{
/* Get max size for key/value names */
max_key_len
=
max
(
max_key_len
,
max_value_len
);
if
(
max_key_len
++
>
MAX_PATH
-
1
)
ptr_name
=
heap_alloc
(
max_key_len
*
sizeof
(
WCHAR
));
if
(
max_data_len
>
sizeof
(
buff
))
ptr
=
heap_alloc
(
max_data_len
);
if
(
!
ptr_name
||
!
ptr
)
ret
=
ERROR_NOT_ENOUGH_MEMORY
;
}
}
for
(
i
=
0
;
i
<
key_count
&&
!
ret
;
i
++
)
{
HKEY
hsubkey_src
,
hsubkey_dst
;
DWORD
length
=
max_key_len
;
ret
=
RegEnumKeyExW
(
hkey_src
,
i
,
ptr_name
,
&
length
,
NULL
,
NULL
,
NULL
,
NULL
);
if
(
!
ret
)
{
ret
=
RegOpenKeyExW
(
hkey_src
,
ptr_name
,
0
,
KEY_READ
,
&
hsubkey_src
);
if
(
!
ret
)
{
/* Create destination sub key */
ret
=
RegCreateKeyW
(
hkey_dst
,
ptr_name
,
&
hsubkey_dst
);
if
(
!
ret
)
{
/* Recursively copy keys and values from the sub key */
ret
=
SHCopyKeyW
(
hsubkey_src
,
NULL
,
hsubkey_dst
,
0
);
RegCloseKey
(
hsubkey_dst
);
}
}
RegCloseKey
(
hsubkey_src
);
}
}
/* Copy all the values in this key */
for
(
i
=
0
;
i
<
value_count
&&
!
ret
;
i
++
)
{
DWORD
length
=
max_key_len
,
type
,
data_len
=
max_data_len
;
ret
=
RegEnumValueW
(
hkey_src
,
i
,
ptr_name
,
&
length
,
NULL
,
&
type
,
ptr
,
&
data_len
);
if
(
!
ret
)
{
ret
=
SHSetValueW
(
hkey_dst
,
NULL
,
ptr_name
,
type
,
ptr
,
data_len
);
}
}
/* Free buffers if allocated */
if
(
ptr_name
!=
name
)
heap_free
(
ptr_name
);
if
(
ptr
!=
buff
)
heap_free
(
ptr
);
if
(
subkey
&&
hkey_src
)
RegCloseKey
(
hkey_src
);
return
ret
;
}
/*************************************************************************
* SHEnumKeyExA [SHCORE.@]
*/
LONG
WINAPI
SHEnumKeyExA
(
HKEY
hkey
,
DWORD
index
,
char
*
subkey
,
DWORD
*
length
)
{
TRACE
(
"(%p, %d, %s, %p)
\n
"
,
hkey
,
index
,
debugstr_a
(
subkey
),
length
);
return
RegEnumKeyExA
(
hkey
,
index
,
subkey
,
length
,
NULL
,
NULL
,
NULL
,
NULL
);
}
/*************************************************************************
* SHEnumKeyExW [SHCORE.@]
*/
LONG
WINAPI
SHEnumKeyExW
(
HKEY
hkey
,
DWORD
index
,
WCHAR
*
subkey
,
DWORD
*
length
)
{
TRACE
(
"(%p, %d, %s, %p)
\n
"
,
hkey
,
index
,
debugstr_w
(
subkey
),
length
);
return
RegEnumKeyExW
(
hkey
,
index
,
subkey
,
length
,
NULL
,
NULL
,
NULL
,
NULL
);
}
/*************************************************************************
* SHEnumValueA [SHCORE.@]
*/
LONG
WINAPI
SHEnumValueA
(
HKEY
hkey
,
DWORD
index
,
char
*
value
,
DWORD
*
length
,
DWORD
*
type
,
void
*
data
,
DWORD
*
data_len
)
{
TRACE
(
"(%p, %d, %s, %p, %p, %p, %p)
\n
"
,
hkey
,
index
,
debugstr_a
(
value
),
length
,
type
,
data
,
data_len
);
return
RegEnumValueA
(
hkey
,
index
,
value
,
length
,
NULL
,
type
,
data
,
data_len
);
}
/*************************************************************************
* SHEnumValueW [SHCORE.@]
*/
LONG
WINAPI
SHEnumValueW
(
HKEY
hkey
,
DWORD
index
,
WCHAR
*
value
,
DWORD
*
length
,
DWORD
*
type
,
void
*
data
,
DWORD
*
data_len
)
{
TRACE
(
"(%p, %d, %s, %p, %p, %p, %p)
\n
"
,
hkey
,
index
,
debugstr_w
(
value
),
length
,
type
,
data
,
data_len
);
return
RegEnumValueW
(
hkey
,
index
,
value
,
length
,
NULL
,
type
,
data
,
data_len
);
}
/*************************************************************************
* SHQueryValueExW [SHCORE.@]
*/
DWORD
WINAPI
SHQueryValueExW
(
HKEY
hkey
,
const
WCHAR
*
name
,
DWORD
*
reserved
,
DWORD
*
type
,
void
*
buff
,
DWORD
*
buff_len
)
{
DWORD
ret
,
value_type
,
data_len
=
0
;
TRACE
(
"(%p, %s, %p, %p, %p, %p)
\n
"
,
hkey
,
debugstr_w
(
name
),
reserved
,
type
,
buff
,
buff_len
);
if
(
buff_len
)
data_len
=
*
buff_len
;
ret
=
RegQueryValueExW
(
hkey
,
name
,
reserved
,
&
value_type
,
buff
,
&
data_len
);
if
(
ret
!=
ERROR_SUCCESS
&&
ret
!=
ERROR_MORE_DATA
)
return
ret
;
if
(
buff_len
&&
value_type
==
REG_EXPAND_SZ
)
{
DWORD
length
;
WCHAR
*
value
;
if
(
!
buff
||
ret
==
ERROR_MORE_DATA
)
{
length
=
data_len
;
value
=
heap_alloc
(
length
);
RegQueryValueExW
(
hkey
,
name
,
reserved
,
NULL
,
(
BYTE
*
)
value
,
&
length
);
length
=
ExpandEnvironmentStringsW
(
value
,
NULL
,
0
);
}
else
{
length
=
(
strlenW
(
buff
)
+
1
)
*
sizeof
(
WCHAR
);
value
=
heap_alloc
(
length
);
memcpy
(
value
,
buff
,
length
);
length
=
ExpandEnvironmentStringsW
(
value
,
buff
,
*
buff_len
/
sizeof
(
WCHAR
));
if
(
length
>
*
buff_len
)
ret
=
ERROR_MORE_DATA
;
}
data_len
=
max
(
data_len
,
length
);
heap_free
(
value
);
}
if
(
type
)
*
type
=
value_type
==
REG_EXPAND_SZ
?
REG_SZ
:
value_type
;
if
(
buff_len
)
*
buff_len
=
data_len
;
return
ret
;
}
/*************************************************************************
* SHQueryValueExA [SHCORE.@]
*/
DWORD
WINAPI
SHQueryValueExA
(
HKEY
hkey
,
const
char
*
name
,
DWORD
*
reserved
,
DWORD
*
type
,
void
*
buff
,
DWORD
*
buff_len
)
{
DWORD
ret
,
value_type
,
data_len
=
0
;
TRACE
(
"(%p, %s, %p, %p, %p, %p)
\n
"
,
hkey
,
debugstr_a
(
name
),
reserved
,
type
,
buff
,
buff_len
);
if
(
buff_len
)
data_len
=
*
buff_len
;
ret
=
RegQueryValueExA
(
hkey
,
name
,
reserved
,
&
value_type
,
buff
,
&
data_len
);
if
(
ret
!=
ERROR_SUCCESS
&&
ret
!=
ERROR_MORE_DATA
)
return
ret
;
if
(
buff_len
&&
value_type
==
REG_EXPAND_SZ
)
{
DWORD
length
;
char
*
value
;
if
(
!
buff
||
ret
==
ERROR_MORE_DATA
)
{
length
=
data_len
;
value
=
heap_alloc
(
length
);
RegQueryValueExA
(
hkey
,
name
,
reserved
,
NULL
,
(
BYTE
*
)
value
,
&
length
);
length
=
ExpandEnvironmentStringsA
(
value
,
NULL
,
0
);
}
else
{
length
=
strlen
(
buff
)
+
1
;
value
=
heap_alloc
(
length
);
memcpy
(
value
,
buff
,
length
);
length
=
ExpandEnvironmentStringsA
(
value
,
buff
,
*
buff_len
);
if
(
length
>
*
buff_len
)
ret
=
ERROR_MORE_DATA
;
}
data_len
=
max
(
data_len
,
length
);
heap_free
(
value
);
}
if
(
type
)
*
type
=
value_type
==
REG_EXPAND_SZ
?
REG_SZ
:
value_type
;
if
(
buff_len
)
*
buff_len
=
data_len
;
return
ret
;
}
/*************************************************************************
* SHGetValueA [SHCORE.@]
*/
DWORD
WINAPI
SHGetValueA
(
HKEY
hkey
,
const
char
*
subkey
,
const
char
*
value
,
DWORD
*
type
,
void
*
data
,
DWORD
*
data_len
)
{
HKEY
hsubkey
=
0
;
DWORD
ret
=
0
;
TRACE
(
"(%p, %s, %s, %p, %p, %p)
\n
"
,
hkey
,
debugstr_a
(
subkey
),
debugstr_a
(
value
),
type
,
data
,
data_len
);
if
(
subkey
)
ret
=
RegOpenKeyExA
(
hkey
,
subkey
,
0
,
KEY_QUERY_VALUE
,
&
hsubkey
);
if
(
!
ret
)
{
ret
=
SHQueryValueExA
(
hsubkey
?
hsubkey
:
hkey
,
value
,
0
,
type
,
data
,
data_len
);
if
(
subkey
)
RegCloseKey
(
hsubkey
);
}
return
ret
;
}
/*************************************************************************
* SHGetValueW [SHCORE.@]
*/
DWORD
WINAPI
SHGetValueW
(
HKEY
hkey
,
const
WCHAR
*
subkey
,
const
WCHAR
*
value
,
DWORD
*
type
,
void
*
data
,
DWORD
*
data_len
)
{
HKEY
hsubkey
=
0
;
DWORD
ret
=
0
;
TRACE
(
"(%p, %s, %s, %p, %p, %p)
\n
"
,
hkey
,
debugstr_w
(
subkey
),
debugstr_w
(
value
),
type
,
data
,
data_len
);
if
(
subkey
)
ret
=
RegOpenKeyExW
(
hkey
,
subkey
,
0
,
KEY_QUERY_VALUE
,
&
hsubkey
);
if
(
!
ret
)
{
ret
=
SHQueryValueExW
(
hsubkey
?
hsubkey
:
hkey
,
value
,
0
,
type
,
data
,
data_len
);
if
(
subkey
)
RegCloseKey
(
hsubkey
);
}
return
ret
;
}
/*************************************************************************
* SHRegGetIntW [SHCORE.280]
*/
int
WINAPI
SHRegGetIntW
(
HKEY
hkey
,
const
WCHAR
*
value
,
int
default_value
)
{
WCHAR
buff
[
32
];
DWORD
buff_len
;
TRACE
(
"(%p, %s, %d)
\n
"
,
hkey
,
debugstr_w
(
value
),
default_value
);
buff
[
0
]
=
0
;
buff_len
=
sizeof
(
buff
);
if
(
SHQueryValueExW
(
hkey
,
value
,
0
,
0
,
buff
,
&
buff_len
))
return
default_value
;
if
(
*
buff
>=
'0'
&&
*
buff
<=
'9'
)
return
atoiW
(
buff
);
return
default_value
;
}
/*************************************************************************
* SHRegGetPathA [SHCORE.@]
*/
DWORD
WINAPI
SHRegGetPathA
(
HKEY
hkey
,
const
char
*
subkey
,
const
char
*
value
,
char
*
path
,
DWORD
flags
)
{
DWORD
length
=
MAX_PATH
;
TRACE
(
"(%p, %s, %s, %p, %#x)
\n
"
,
hkey
,
debugstr_a
(
subkey
),
debugstr_a
(
value
),
path
,
flags
);
return
SHGetValueA
(
hkey
,
subkey
,
value
,
0
,
path
,
&
length
);
}
/*************************************************************************
* SHRegGetPathW [SHCORE.@]
*/
DWORD
WINAPI
SHRegGetPathW
(
HKEY
hkey
,
const
WCHAR
*
subkey
,
const
WCHAR
*
value
,
WCHAR
*
path
,
DWORD
flags
)
{
DWORD
length
=
MAX_PATH
;
TRACE
(
"(%p, %s, %s, %p, %d)
\n
"
,
hkey
,
debugstr_w
(
subkey
),
debugstr_w
(
value
),
path
,
flags
);
return
SHGetValueW
(
hkey
,
subkey
,
value
,
0
,
path
,
&
length
);
}
/*************************************************************************
* SHSetValueW [SHCORE.@]
*/
DWORD
WINAPI
SHSetValueW
(
HKEY
hkey
,
const
WCHAR
*
subkey
,
const
WCHAR
*
value
,
DWORD
type
,
const
void
*
data
,
DWORD
data_len
)
{
DWORD
ret
=
ERROR_SUCCESS
,
dummy
;
HKEY
hsubkey
;
TRACE
(
"(%p, %s, %s, %d, %p, %d)
\n
"
,
hkey
,
debugstr_w
(
subkey
),
debugstr_w
(
value
),
type
,
data
,
data_len
);
if
(
subkey
&&
*
subkey
)
ret
=
RegCreateKeyExW
(
hkey
,
subkey
,
0
,
NULL
,
0
,
KEY_SET_VALUE
,
NULL
,
&
hsubkey
,
&
dummy
);
else
hsubkey
=
hkey
;
if
(
!
ret
)
{
ret
=
RegSetValueExW
(
hsubkey
,
value
,
0
,
type
,
data
,
data_len
);
if
(
hsubkey
!=
hkey
)
RegCloseKey
(
hsubkey
);
}
return
ret
;
}
/*************************************************************************
* SHSetValueA [SHCORE.@]
*/
DWORD
WINAPI
SHSetValueA
(
HKEY
hkey
,
const
char
*
subkey
,
const
char
*
value
,
DWORD
type
,
const
void
*
data
,
DWORD
data_len
)
{
DWORD
ret
=
ERROR_SUCCESS
,
dummy
;
HKEY
hsubkey
;
TRACE
(
"(%p, %s, %s, %d, %p, %d)
\n
"
,
hkey
,
debugstr_a
(
subkey
),
debugstr_a
(
value
),
type
,
data
,
data_len
);
if
(
subkey
&&
*
subkey
)
ret
=
RegCreateKeyExA
(
hkey
,
subkey
,
0
,
NULL
,
0
,
KEY_SET_VALUE
,
NULL
,
&
hsubkey
,
&
dummy
);
else
hsubkey
=
hkey
;
if
(
!
ret
)
{
ret
=
RegSetValueExA
(
hsubkey
,
value
,
0
,
type
,
data
,
data_len
);
if
(
hsubkey
!=
hkey
)
RegCloseKey
(
hsubkey
);
}
return
ret
;
}
/*************************************************************************
* SHRegSetPathA [SHCORE.@]
*/
DWORD
WINAPI
SHRegSetPathA
(
HKEY
hkey
,
const
char
*
subkey
,
const
char
*
value
,
const
char
*
path
,
DWORD
flags
)
{
FIXME
(
"(%p, %s, %s, %p, %#x) - semi-stub
\n
"
,
hkey
,
debugstr_a
(
subkey
),
debugstr_a
(
value
),
debugstr_a
(
path
),
flags
);
/* FIXME: PathUnExpandEnvStringsA() */
return
SHSetValueA
(
hkey
,
subkey
,
value
,
REG_SZ
,
path
,
lstrlenA
(
path
));
}
/*************************************************************************
* SHRegSetPathW [SHCORE.@]
*/
DWORD
WINAPI
SHRegSetPathW
(
HKEY
hkey
,
const
WCHAR
*
subkey
,
const
WCHAR
*
value
,
const
WCHAR
*
path
,
DWORD
flags
)
{
FIXME
(
"(%p, %s, %s, %s, %#x) - semi-stub
\n
"
,
hkey
,
debugstr_w
(
subkey
),
debugstr_w
(
value
),
debugstr_w
(
path
),
flags
);
/* FIXME: PathUnExpandEnvStringsW(); */
return
SHSetValueW
(
hkey
,
subkey
,
value
,
REG_SZ
,
path
,
lstrlenW
(
path
));
}
/*************************************************************************
* SHQueryInfoKeyA [SHCORE.@]
*/
LONG
WINAPI
SHQueryInfoKeyA
(
HKEY
hkey
,
DWORD
*
subkeys
,
DWORD
*
subkey_max
,
DWORD
*
values
,
DWORD
*
value_max
)
{
TRACE
(
"(%p, %p, %p, %p, %p)
\n
"
,
hkey
,
subkeys
,
subkey_max
,
values
,
value_max
);
return
RegQueryInfoKeyA
(
hkey
,
NULL
,
NULL
,
NULL
,
subkeys
,
subkey_max
,
NULL
,
values
,
value_max
,
NULL
,
NULL
,
NULL
);
}
/*************************************************************************
* SHQueryInfoKeyW [SHCORE.@]
*/
LONG
WINAPI
SHQueryInfoKeyW
(
HKEY
hkey
,
DWORD
*
subkeys
,
DWORD
*
subkey_max
,
DWORD
*
values
,
DWORD
*
value_max
)
{
TRACE
(
"(%p, %p, %p, %p, %p)
\n
"
,
hkey
,
subkeys
,
subkey_max
,
values
,
value_max
);
return
RegQueryInfoKeyW
(
hkey
,
NULL
,
NULL
,
NULL
,
subkeys
,
subkey_max
,
NULL
,
values
,
value_max
,
NULL
,
NULL
,
NULL
);
}
dlls/shcore/shcore.spec
View file @
6ae247bb
...
...
@@ -31,8 +31,8 @@
@ stub RevokeScaleChangeNotifications
@ stdcall SHAnsiToAnsi(str ptr long)
@ stdcall SHAnsiToUnicode(str ptr long)
@ stdcall SHCopyKeyA(long str long long)
shlwapi.SHCopyKeyA
@ stdcall SHCopyKeyW(long wstr long long)
shlwapi.SHCopyKeyW
@ stdcall SHCopyKeyA(long str long long)
@ stdcall SHCopyKeyW(long wstr long long)
@ stdcall SHCreateMemStream(ptr long)
@ stdcall SHCreateStreamOnFileA(str long ptr)
@ stdcall SHCreateStreamOnFileEx(wstr long long long ptr ptr)
...
...
@@ -46,33 +46,33 @@
@ stdcall SHDeleteKeyW(long wstr)
@ stdcall SHDeleteValueA(long str str)
@ stdcall SHDeleteValueW(long wstr wstr)
@ stdcall SHEnumKeyExA(long long str ptr)
shlwapi.SHEnumKeyExA
@ stdcall SHEnumKeyExW(long long wstr ptr)
shlwapi.SHEnumKeyExW
@ stdcall SHEnumValueA(long long str ptr ptr ptr ptr)
shlwapi.SHEnumValueA
@ stdcall SHEnumValueW(long long wstr ptr ptr ptr ptr)
shlwapi.SHEnumValueW
@ stdcall SHEnumKeyExA(long long str ptr)
@ stdcall SHEnumKeyExW(long long wstr ptr)
@ stdcall SHEnumValueA(long long str ptr ptr ptr ptr)
@ stdcall SHEnumValueW(long long wstr ptr ptr ptr ptr)
@ stdcall SHGetThreadRef(ptr)
@ stdcall SHGetValueA(
long str str ptr ptr ptr ) shlwapi.SHGetValueA
@ stdcall SHGetValueW(
long wstr wstr ptr ptr ptr ) shlwapi.SHGetValueW
@ stdcall SHGetValueA(
long str str ptr ptr ptr)
@ stdcall SHGetValueW(
long wstr wstr ptr ptr ptr)
@ stdcall SHOpenRegStream2A(long str str long)
@ stdcall SHOpenRegStream2W(long wstr wstr long)
@ stdcall SHOpenRegStreamA(long str str long)
@ stdcall SHOpenRegStreamW(long wstr wstr long)
@ stdcall SHQueryInfoKeyA(long ptr ptr ptr ptr)
shlwapi.SHQueryInfoKeyA
@ stdcall SHQueryInfoKeyW(long ptr ptr ptr ptr)
shlwapi.SHQueryInfoKeyW
@ stdcall SHQueryValueExA(long str ptr ptr ptr ptr)
shlwapi.SHQueryValueExA
@ stdcall SHQueryValueExW(long wstr ptr ptr ptr ptr)
shlwapi.SHQueryValueExW
@ stdcall SHQueryInfoKeyA(long ptr ptr ptr ptr)
@ stdcall SHQueryInfoKeyW(long ptr ptr ptr ptr)
@ stdcall SHQueryValueExA(long str ptr ptr ptr ptr)
@ stdcall SHQueryValueExW(long wstr ptr ptr ptr ptr)
@ stdcall SHRegDuplicateHKey(long)
@ stdcall SHRegGetIntW(ptr wstr long)
shlwapi.SHRegGetIntW
@ stdcall SHRegGetPathA(long str str ptr long)
shlwapi.SHRegGetPathA
@ stdcall SHRegGetPathW(long wstr wstr ptr long)
shlwapi.SHRegGetPathW
@ stdcall SHRegGetValueA(
long str str long ptr ptr ptr ) shlwapi.SH
RegGetValueA
@ stdcall SHRegGetValueW(
long wstr wstr long ptr ptr ptr ) shlwapi.SH
RegGetValueW
@ stdcall SHRegSetPathA(long str str str long)
shlwapi.SHRegSetPathA
@ stdcall SHRegSetPathW(long wstr wstr wstr long)
shlwapi.SHRegSetPathW
@ stdcall SHRegGetIntW(ptr wstr long)
@ stdcall SHRegGetPathA(long str str ptr long)
@ stdcall SHRegGetPathW(long wstr wstr ptr long)
@ stdcall SHRegGetValueA(
long str str long ptr ptr ptr) advapi32.
RegGetValueA
@ stdcall SHRegGetValueW(
long wstr wstr long ptr ptr ptr) advapi32.
RegGetValueW
@ stdcall SHRegSetPathA(long str str str long)
@ stdcall SHRegSetPathW(long wstr wstr wstr long)
@ stdcall SHReleaseThreadRef()
@ stdcall SHSetThreadRef(ptr)
@ stdcall SHSetValueA(long
str str long ptr long) shlwapi.SHSetValueA
@ stdcall SHSetValueW(long wstr wstr long ptr long)
shlwapi.SHSetValueW
@ stdcall SHSetValueA(long
str str long ptr long)
@ stdcall SHSetValueW(long wstr wstr long ptr long)
@ stdcall SHStrDupA(str ptr)
@ stdcall SHStrDupW(wstr ptr)
@ stdcall SHUnicodeToAnsi(wstr ptr ptr)
...
...
dlls/shcore/tests/shcore.c
View file @
6ae247bb
...
...
@@ -23,6 +23,7 @@
#include <windows.h>
#include "initguid.h"
#include "objidl.h"
#include "shlwapi.h"
#include "wine/test.h"
...
...
@@ -35,6 +36,26 @@ static int (WINAPI *pSHAnsiToAnsi)(const char *, char *, int);
static
int
(
WINAPI
*
pSHUnicodeToUnicode
)(
const
WCHAR
*
,
WCHAR
*
,
int
);
static
HKEY
(
WINAPI
*
pSHRegDuplicateHKey
)(
HKEY
);
static
DWORD
(
WINAPI
*
pSHDeleteKeyA
)(
HKEY
,
const
char
*
);
static
DWORD
(
WINAPI
*
pSHGetValueA
)(
HKEY
,
const
char
*
,
const
char
*
,
DWORD
*
,
void
*
,
DWORD
*
);
static
LSTATUS
(
WINAPI
*
pSHRegGetValueA
)(
HKEY
,
const
char
*
,
const
char
*
,
SRRF
,
DWORD
*
,
void
*
,
DWORD
*
);
static
DWORD
(
WINAPI
*
pSHQueryValueExA
)(
HKEY
,
const
char
*
,
DWORD
*
,
DWORD
*
,
void
*
buff
,
DWORD
*
buff_len
);
static
DWORD
(
WINAPI
*
pSHRegGetPathA
)(
HKEY
,
const
char
*
,
const
char
*
,
char
*
,
DWORD
);
static
DWORD
(
WINAPI
*
pSHCopyKeyA
)(
HKEY
,
const
char
*
,
HKEY
,
DWORD
);
/* Keys used for testing */
#define REG_TEST_KEY "Software\\Wine\\Test"
#define REG_CURRENT_VERSION "Software\\Microsoft\\Windows\\CurrentVersion\\explorer"
static
const
char
test_path1
[]
=
"%LONGSYSTEMVAR%
\\
subdir1"
;
static
const
char
test_path2
[]
=
"%FOO%
\\
subdir1"
;
static
const
char
*
test_envvar1
=
"bar"
;
static
const
char
*
test_envvar2
=
"ImARatherLongButIndeedNeededString"
;
static
char
test_exp_path1
[
MAX_PATH
];
static
char
test_exp_path2
[
MAX_PATH
];
static
DWORD
exp_len1
;
static
DWORD
exp_len2
;
static
const
char
*
initial_buffer
=
"0123456789"
;
static
void
init
(
HMODULE
hshcore
)
{
...
...
@@ -47,6 +68,11 @@ static void init(HMODULE hshcore)
X
(
SHUnicodeToUnicode
);
X
(
SHRegDuplicateHKey
);
X
(
SHDeleteKeyA
);
X
(
SHGetValueA
);
X
(
SHRegGetValueA
);
X
(
SHQueryValueExA
);
X
(
SHRegGetPathA
);
X
(
SHCopyKeyA
);
#undef X
}
...
...
@@ -343,6 +369,308 @@ static void test_SHDeleteKey(void)
ok
(
!
ret
,
"Failed to delete a key, %d.
\n
"
,
ret
);
}
static
HKEY
create_test_entries
(
void
)
{
HKEY
hKey
;
DWORD
ret
;
DWORD
nExpectedLen1
,
nExpectedLen2
;
SetEnvironmentVariableA
(
"LONGSYSTEMVAR"
,
test_envvar1
);
SetEnvironmentVariableA
(
"FOO"
,
test_envvar2
);
ret
=
RegCreateKeyA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
&
hKey
);
ok
(
!
ret
,
"RegCreateKeyA failed, ret=%u
\n
"
,
ret
);
if
(
hKey
)
{
ok
(
!
RegSetValueExA
(
hKey
,
"Test1"
,
0
,
REG_EXPAND_SZ
,
(
BYTE
*
)
test_path1
,
strlen
(
test_path1
)
+
1
),
"RegSetValueExA failed
\n
"
);
ok
(
!
RegSetValueExA
(
hKey
,
"Test2"
,
0
,
REG_SZ
,
(
BYTE
*
)
test_path1
,
strlen
(
test_path1
)
+
1
),
"RegSetValueExA failed
\n
"
);
ok
(
!
RegSetValueExA
(
hKey
,
"Test3"
,
0
,
REG_EXPAND_SZ
,
(
BYTE
*
)
test_path2
,
strlen
(
test_path2
)
+
1
),
"RegSetValueExA failed
\n
"
);
}
exp_len1
=
ExpandEnvironmentStringsA
(
test_path1
,
test_exp_path1
,
sizeof
(
test_exp_path1
));
exp_len2
=
ExpandEnvironmentStringsA
(
test_path2
,
test_exp_path2
,
sizeof
(
test_exp_path2
));
nExpectedLen1
=
strlen
(
test_path1
)
-
strlen
(
"%LONGSYSTEMVAR%"
)
+
strlen
(
test_envvar1
)
+
1
;
nExpectedLen2
=
strlen
(
test_path2
)
-
strlen
(
"%FOO%"
)
+
strlen
(
test_envvar2
)
+
1
;
/* Make sure we carry on with correct values */
exp_len1
=
nExpectedLen1
;
exp_len2
=
nExpectedLen2
;
return
hKey
;
}
/* delete key and all its subkeys */
static
DWORD
delete_key
(
HKEY
hkey
,
LPCSTR
parent
,
LPCSTR
keyname
)
{
HKEY
parentKey
;
DWORD
ret
;
RegCloseKey
(
hkey
);
/* open the parent of the key to close */
ret
=
RegOpenKeyExA
(
HKEY_CURRENT_USER
,
parent
,
0
,
KEY_ALL_ACCESS
,
&
parentKey
);
if
(
ret
!=
ERROR_SUCCESS
)
return
ret
;
ret
=
pSHDeleteKeyA
(
parentKey
,
keyname
);
RegCloseKey
(
parentKey
);
return
ret
;
}
static
void
test_SHGetValue
(
void
)
{
DWORD
size
;
DWORD
type
;
DWORD
ret
;
char
buf
[
MAX_PATH
];
HKEY
hkey
=
create_test_entries
();
strcpy
(
buf
,
initial_buffer
);
size
=
MAX_PATH
;
type
=
-
1
;
ret
=
pSHGetValueA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
"Test1"
,
&
type
,
buf
,
&
size
);
ok
(
!
ret
,
"Failed to get value, ret %u.
\n
"
,
ret
);
ok
(
!
strcmp
(
test_exp_path1
,
buf
),
"Unexpected value %s.
\n
"
,
buf
);
ok
(
type
==
REG_SZ
,
"Unexpected value type %d.
\n
"
,
type
);
strcpy
(
buf
,
initial_buffer
);
size
=
MAX_PATH
;
type
=
-
1
;
ret
=
pSHGetValueA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
"Test2"
,
&
type
,
buf
,
&
size
);
ok
(
!
ret
,
"Failed to get value, ret %u.
\n
"
,
ret
);
ok
(
!
strcmp
(
test_path1
,
buf
),
"Unexpected value %s.
\n
"
,
buf
);
ok
(
type
==
REG_SZ
,
"Unexpected value type %d.
\n
"
,
type
);
delete_key
(
hkey
,
"Software
\\
Wine"
,
"Test"
);
}
static
void
test_SHRegGetValue
(
void
)
{
LSTATUS
ret
;
DWORD
size
,
type
;
char
data
[
MAX_PATH
];
HKEY
hkey
=
create_test_entries
();
size
=
MAX_PATH
;
ret
=
pSHRegGetValueA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
"Test1"
,
SRRF_RT_REG_EXPAND_SZ
,
&
type
,
data
,
&
size
);
ok
(
ret
==
ERROR_INVALID_PARAMETER
,
"SHRegGetValue failed, ret=%u
\n
"
,
ret
);
size
=
MAX_PATH
;
ret
=
pSHRegGetValueA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
"Test1"
,
SRRF_RT_REG_SZ
,
&
type
,
data
,
&
size
);
ok
(
ret
==
ERROR_SUCCESS
,
"SHRegGetValue failed, ret=%u
\n
"
,
ret
);
ok
(
!
strcmp
(
data
,
test_exp_path1
),
"data = %s, expected %s
\n
"
,
data
,
test_exp_path1
);
ok
(
type
==
REG_SZ
,
"type = %d, expected REG_SZ
\n
"
,
type
);
size
=
MAX_PATH
;
ret
=
pSHRegGetValueA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
"Test1"
,
SRRF_RT_REG_DWORD
,
&
type
,
data
,
&
size
);
ok
(
ret
==
ERROR_UNSUPPORTED_TYPE
,
"SHRegGetValue failed, ret=%u
\n
"
,
ret
);
size
=
MAX_PATH
;
ret
=
pSHRegGetValueA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
"Test2"
,
SRRF_RT_REG_EXPAND_SZ
,
&
type
,
data
,
&
size
);
ok
(
ret
==
ERROR_INVALID_PARAMETER
,
"SHRegGetValue failed, ret=%u
\n
"
,
ret
);
size
=
MAX_PATH
;
ret
=
pSHRegGetValueA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
"Test2"
,
SRRF_RT_REG_SZ
,
&
type
,
data
,
&
size
);
ok
(
ret
==
ERROR_SUCCESS
,
"SHRegGetValue failed, ret=%u
\n
"
,
ret
);
ok
(
!
strcmp
(
data
,
test_path1
),
"data = %s, expected %s
\n
"
,
data
,
test_path1
);
ok
(
type
==
REG_SZ
,
"type = %d, expected REG_SZ
\n
"
,
type
);
size
=
MAX_PATH
;
ret
=
pSHRegGetValueA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
"Test2"
,
SRRF_RT_REG_QWORD
,
&
type
,
data
,
&
size
);
ok
(
ret
==
ERROR_UNSUPPORTED_TYPE
,
"SHRegGetValue failed, ret=%u
\n
"
,
ret
);
delete_key
(
hkey
,
"Software
\\
Wine"
,
"Test"
);
}
static
void
test_SHQueryValueEx
(
void
)
{
DWORD
buffer_len1
,
buffer_len2
;
DWORD
ret
,
type
,
size
;
char
buf
[
MAX_PATH
];
HKEY
hKey
,
testkey
;
testkey
=
create_test_entries
();
ret
=
RegOpenKeyExA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
0
,
KEY_QUERY_VALUE
,
&
hKey
);
ok
(
!
ret
,
"Failed to open a key, ret %u.
\n
"
,
ret
);
/****** SHQueryValueExA ******/
buffer_len1
=
max
(
strlen
(
test_exp_path1
)
+
1
,
strlen
(
test_path1
)
+
1
);
buffer_len2
=
max
(
strlen
(
test_exp_path2
)
+
1
,
strlen
(
test_path2
)
+
1
);
/*
* Case 1.1 All arguments are NULL
*/
ret
=
pSHQueryValueExA
(
hKey
,
"Test1"
,
NULL
,
NULL
,
NULL
,
NULL
);
ok
(
!
ret
,
"Failed to query value, ret %u.
\n
"
,
ret
);
/*
* Case 1.2 dwType is set
*/
type
=
-
1
;
ret
=
pSHQueryValueExA
(
hKey
,
"Test1"
,
NULL
,
&
type
,
NULL
,
NULL
);
ok
(
!
ret
,
"Failed to query value, ret %u.
\n
"
,
ret
);
ok
(
type
==
REG_SZ
,
"Expected REG_SZ, got (%u)
\n
"
,
type
);
size
=
6
;
ret
=
pSHQueryValueExA
(
hKey
,
"Test1"
,
NULL
,
NULL
,
NULL
,
&
size
);
ok
(
!
ret
,
"Failed to query value, ret %u.
\n
"
,
ret
);
ok
(
size
==
buffer_len1
,
"Buffer sizes (%u) and (%u) are not equal
\n
"
,
size
,
buffer_len1
);
/*
* Expanded > unexpanded
*/
size
=
6
;
ret
=
pSHQueryValueExA
(
hKey
,
"Test3"
,
NULL
,
NULL
,
NULL
,
&
size
);
ok
(
!
ret
,
"Failed to query value, ret %u.
\n
"
,
ret
);
ok
(
size
>=
buffer_len2
,
"Buffer size (%u) should be >= (%u)
\n
"
,
size
,
buffer_len2
);
/*
* Case 1 string shrinks during expanding
*/
strcpy
(
buf
,
initial_buffer
);
size
=
6
;
type
=
-
1
;
ret
=
pSHQueryValueExA
(
hKey
,
"Test1"
,
NULL
,
&
type
,
buf
,
&
size
);
ok
(
ret
==
ERROR_MORE_DATA
,
"Expected ERROR_MORE_DATA, got (%u)
\n
"
,
ret
);
ok
(
!
strcmp
(
initial_buffer
,
buf
),
"Comparing (%s) with (%s) failed
\n
"
,
buf
,
initial_buffer
);
ok
(
size
==
buffer_len1
,
"Buffer sizes (%u) and (%u) are not equal
\n
"
,
size
,
buffer_len1
);
ok
(
type
==
REG_SZ
,
"Expected REG_SZ, got (%u)
\n
"
,
type
);
/*
* string grows during expanding
* dwSize is smaller than the size of the unexpanded string
*/
strcpy
(
buf
,
initial_buffer
);
size
=
6
;
type
=
-
1
;
ret
=
pSHQueryValueExA
(
hKey
,
"Test3"
,
NULL
,
&
type
,
buf
,
&
size
);
ok
(
ret
==
ERROR_MORE_DATA
,
"Expected ERROR_MORE_DATA, got (%u)
\n
"
,
ret
);
ok
(
!
strcmp
(
initial_buffer
,
buf
),
"Comparing (%s) with (%s) failed
\n
"
,
buf
,
initial_buffer
);
ok
(
size
>=
buffer_len2
,
"Buffer size (%u) should be >= (%u)
\n
"
,
size
,
buffer_len2
);
ok
(
type
==
REG_SZ
,
"Expected REG_SZ, got (%u)
\n
"
,
type
);
/*
* string grows during expanding
* dwSize is larger than the size of the unexpanded string, but
* smaller than the part before the backslash. If the unexpanded
* string fits into the buffer, it can get cut when expanded.
*/
strcpy
(
buf
,
initial_buffer
);
size
=
strlen
(
test_envvar2
)
-
2
;
type
=
-
1
;
ret
=
pSHQueryValueExA
(
hKey
,
"Test3"
,
NULL
,
&
type
,
buf
,
&
size
);
ok
(
ret
==
ERROR_MORE_DATA
,
"Expected ERROR_MORE_DATA, got (%u)
\n
"
,
ret
);
todo_wine
{
ok
(
!
strcmp
(
""
,
buf
),
"Unexpanded string %s.
\n
"
,
buf
);
}
ok
(
size
>=
buffer_len2
,
"Buffer size (%u) should be >= (%u)
\n
"
,
size
,
buffer_len2
);
ok
(
type
==
REG_SZ
,
"Expected REG_SZ, got (%u)
\n
"
,
type
);
/*
* string grows during expanding
* dwSize is larger than the size of the part before the backslash,
* but smaller than the expanded string. If the unexpanded string fits
* into the buffer, it can get cut when expanded.
*/
strcpy
(
buf
,
initial_buffer
);
size
=
exp_len2
-
4
;
type
=
-
1
;
ret
=
pSHQueryValueExA
(
hKey
,
"Test3"
,
NULL
,
&
type
,
buf
,
&
size
);
ok
(
ret
==
ERROR_MORE_DATA
,
"Expected ERROR_MORE_DATA, got (%u)
\n
"
,
ret
);
todo_wine
{
ok
(
(
0
==
strcmp
(
""
,
buf
))
||
(
0
==
strcmp
(
test_envvar2
,
buf
)),
"Expected empty or first part of the string
\"
%s
\"
, got
\"
%s
\"\n
"
,
test_envvar2
,
buf
);
}
ok
(
size
>=
buffer_len2
,
"Buffer size (%u) should be >= (%u)
\n
"
,
size
,
buffer_len2
);
ok
(
type
==
REG_SZ
,
"Expected REG_SZ, got (%u)
\n
"
,
type
);
/*
* The buffer is NULL but the size is set
*/
strcpy
(
buf
,
initial_buffer
);
size
=
6
;
type
=
-
1
;
ret
=
pSHQueryValueExA
(
hKey
,
"Test3"
,
NULL
,
&
type
,
NULL
,
&
size
);
ok
(
!
ret
,
"Failed to query value, ret %u.
\n
"
,
ret
);
ok
(
size
>=
buffer_len2
,
"Buffer size (%u) should be >= (%u)
\n
"
,
size
,
buffer_len2
);
ok
(
type
==
REG_SZ
,
"Expected REG_SZ, got (%u)
\n
"
,
type
);
RegCloseKey
(
hKey
);
delete_key
(
testkey
,
"Software
\\
Wine"
,
"Test"
);
}
static
void
test_SHRegGetPath
(
void
)
{
char
buf
[
MAX_PATH
];
DWORD
ret
;
HKEY
hkey
;
hkey
=
create_test_entries
();
strcpy
(
buf
,
initial_buffer
);
ret
=
pSHRegGetPathA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
,
"Test1"
,
buf
,
0
);
ok
(
!
ret
,
"Failed to get path, ret %u.
\n
"
,
ret
);
ok
(
!
strcmp
(
test_exp_path1
,
buf
),
"Unexpected path %s.
\n
"
,
buf
);
delete_key
(
hkey
,
"Software
\\
Wine"
,
"Test"
);
}
static
void
test_SHCopyKey
(
void
)
{
HKEY
hKeySrc
,
hKeyDst
;
DWORD
ret
;
HKEY
hkey
=
create_test_entries
();
/* Delete existing destination sub keys */
hKeyDst
=
NULL
;
if
(
!
RegOpenKeyA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
"
\\
CopyDestination"
,
&
hKeyDst
)
&&
hKeyDst
)
{
pSHDeleteKeyA
(
hKeyDst
,
NULL
);
RegCloseKey
(
hKeyDst
);
}
hKeyDst
=
NULL
;
ret
=
RegCreateKeyA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
"
\\
CopyDestination"
,
&
hKeyDst
);
ok
(
!
ret
,
"Failed to create a test key, ret %d.
\n
"
,
ret
);
hKeySrc
=
NULL
;
ret
=
RegOpenKeyA
(
HKEY_LOCAL_MACHINE
,
REG_CURRENT_VERSION
,
&
hKeySrc
);
ok
(
!
ret
,
"Failed to open a test key, ret %d.
\n
"
,
ret
);
ret
=
pSHCopyKeyA
(
hKeySrc
,
NULL
,
hKeyDst
,
0
);
ok
(
!
ret
,
"Copy failed, ret=(%u)
\n
"
,
ret
);
RegCloseKey
(
hKeySrc
);
RegCloseKey
(
hKeyDst
);
/* Check we copied the sub keys, i.e. something that's on every windows system (including Wine) */
hKeyDst
=
NULL
;
ret
=
RegOpenKeyA
(
HKEY_CURRENT_USER
,
REG_TEST_KEY
"
\\
CopyDestination
\\
Shell Folders"
,
&
hKeyDst
);
ok
(
!
ret
,
"Failed to open a test key, ret %d.
\n
"
,
ret
);
/* And the we copied the values too */
ok
(
!
pSHQueryValueExA
(
hKeyDst
,
"Common AppData"
,
NULL
,
NULL
,
NULL
,
NULL
),
"SHQueryValueExA failed
\n
"
);
RegCloseKey
(
hKeyDst
);
delete_key
(
hkey
,
"Software
\\
Wine"
,
"Test"
);
}
START_TEST
(
shcore
)
{
HMODULE
hshcore
=
LoadLibraryA
(
"shcore.dll"
);
...
...
@@ -362,4 +690,9 @@ START_TEST(shcore)
test_SHUnicodeToUnicode
();
test_SHRegDuplicateHKey
();
test_SHDeleteKey
();
test_SHGetValue
();
test_SHRegGetValue
();
test_SHQueryValueEx
();
test_SHRegGetPath
();
test_SHCopyKey
();
}
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