FYI, Local* or Base functions are typically always W.
Best regards,
Alex Ionescu
On Sun, May 24, 2009 at 6:13 PM, Ged <gedmurphy(a)gmail.com> wrote:
And somewhere in the middle of that there's an RPC
call picked up by the
linux host which calls a bash script to do the work.
I was initially worried about scenarios which may brake apps, for example an
app hooks RegQueryValueEx and expects to pick up all calls to
RegQueryValue(Ex|A|W) (stupid, but possible). I think it's important to keep
the call chains as close to Windows as possible.
Anyway, I've just checked the call chain and it seems both ansi and Unicode
functions call a LocalBase* function to do the work, so this isn't so much
of an issue.
I still disagree with this change though as we're doubling up on the code to
do the same operation, meaning we now have 2 failure points instead of 1.
This is one of the main reasons for getting A functions to call their W
counterpart. If it's broken, you only have 1 code path to fix.
Ged.
-----Original Message-----
From: ros-dev-bounces(a)reactos.org [mailto:ros-dev-bounces@reactos.org] On
Behalf Of Alex Ionescu
Sent: 24 May 2009 15:19
To: ReactOS Development List
Subject: Re: [ros-dev] [ros-diffs] [cwittich] 41093: sync RegQueryValueExA,
RegQueryValueA, RegQueryValueW and RegSetValueExA to wine patch by Giannis
Adamopoulos <johnyadams at hotmail dot com> See issue #4528 for more
details.
Lol, Ged...this is Wine, remember?
It works like this:
Ntoskrnl calls user32, which calls kernel32, which calls ntdll, which
then calls msi.
Msi's A function then calls ntoskrnl's W function, which calls back
into gdi32's A function (after converting all the parameters).
Best regards,
Alex Ionescu
On Sun, May 24, 2009 at 3:35 PM, Ged <gedmurphy(a)gmail.com> wrote:
Is this really right?
I haven't checked the call chain in Windows, but 'A' functions generally
call their 'W' counterpart to do the work.
Ged.
-----Original Message-----
From: ros-diffs-bounces(a)reactos.org [mailto:ros-diffs-bounces@reactos.org]
On
Behalf Of cwittich(a)svn.reactos.org
Sent: 24 May 2009 09:45
To: ros-diffs(a)reactos.org
Subject: [ros-diffs] [cwittich] 41093: sync RegQueryValueExA,
RegQueryValueA,
RegQueryValueW and RegSetValueExA to wine patch by Giannis
Adamopoulos <johnyadams at hotmail dot com> See issue #4528 for more
details.
Author: cwittich
Date: Sun May 24 12:45:05 2009
New Revision: 41093
URL:
http://svn.reactos.org/svn/reactos?rev=41093&view=rev
Log:
sync RegQueryValueExA, RegQueryValueA, RegQueryValueW and RegSetValueExA
to wine
patch by Giannis Adamopoulos <johnyadams at
hotmail dot com
See issue #4528 for more
details.
Modified:
trunk/reactos/dll/win32/advapi32/reg/reg.c
Modified: trunk/reactos/dll/win32/advapi32/reg/reg.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/reg/reg.
c?rev=41093&r1=41092&r2=41093&view=diff
============================================================================
==
--- trunk/reactos/dll/win32/advapi32/reg/reg.c
[iso-8859-1] (original)
+++ trunk/reactos/dll/win32/advapi32/reg/reg.c [iso-8859-1] Sun May 24
12:45:05
2009
@@ -3964,110 +3964,96 @@
*
* @implemented
*/
-LONG WINAPI
-RegQueryValueExA(HKEY hKey,
- LPCSTR lpValueName,
- LPDWORD lpReserved,
- LPDWORD lpType,
- LPBYTE lpData,
- LPDWORD lpcbData)
-{
- UNICODE_STRING ValueName;
- UNICODE_STRING ValueData;
- ANSI_STRING AnsiString;
- LONG ErrorCode;
- DWORD Length;
- DWORD Type;
-
- TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
- hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
-
- if (lpData != NULL && lpcbData == NULL)
- {
- return ERROR_INVALID_PARAMETER;
- }
-
- if (lpData)
- {
- ValueData.Length = 0;
- ValueData.MaximumLength = (*lpcbData + 1) * sizeof(WCHAR);
- ValueData.Buffer = RtlAllocateHeap(ProcessHeap,
- 0,
- ValueData.MaximumLength);
- if (!ValueData.Buffer)
- {
- return ERROR_OUTOFMEMORY;
- }
- }
- else
- {
- ValueData.Buffer = NULL;
- ValueData.Length = 0;
- ValueData.MaximumLength = 0;
-
- if (lpcbData)
- *lpcbData = 0;
- }
-
- RtlCreateUnicodeStringFromAsciiz(&ValueName,
- (LPSTR)lpValueName);
-
- Length = (lpcbData == NULL) ? 0 : *lpcbData * sizeof(WCHAR);
- ErrorCode = RegQueryValueExW(hKey,
- ValueName.Buffer,
- lpReserved,
- &Type,
- (lpData == NULL) ? NULL :
(LPBYTE)ValueData.Buffer,
- &Length);
- TRACE("ErrorCode %lu\n", ErrorCode);
- RtlFreeUnicodeString(&ValueName);
-
- if (ErrorCode == ERROR_SUCCESS ||
- ErrorCode == ERROR_MORE_DATA)
- {
- if (lpType != NULL)
- {
- *lpType = Type;
- }
-
- if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type ==
REG_EXPAND_SZ))
- {
- if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
+LSTATUS WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD
reserved,
LPDWORD type,
+ LPBYTE data,
LPDWORD count )
+{
+ NTSTATUS status;
+ ANSI_STRING nameA;
+ DWORD total_size, datalen = 0;
+ char buffer[256], *buf_ptr = buffer;
+ KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION
*)buffer;
+ static const int info_size = offsetof(
KEY_VALUE_PARTIAL_INFORMATION,
Data );
+
+ TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
+ hkey, debugstr_a(name), reserved, type, data, count, count ?
*count : 0
);
+
+ if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
+
+ status = MapDefaultKey( (PHANDLE)&hkey, hkey);
+ if (!NT_SUCCESS(status))
+ {
+ return RtlNtStatusToDosError(status);
+ }
+
+ if (count) datalen = *count;
+ if (!data && count) *count = 0;
+
+ /* this matches Win9x behaviour - NT sets *type to a random value */
+ if (type) *type = REG_NONE;
+
+ RtlInitAnsiString( &nameA, name );
+ if ((status = RtlAnsiStringToUnicodeString(
&NtCurrentTeb()->StaticUnicodeString,
+
&nameA, FALSE )))
+ return RtlNtStatusToDosError(status);
+
+ status = NtQueryValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString,
+ KeyValuePartialInformation, buffer,
sizeof(buffer),
&total_size );
+ if (status && status !=
STATUS_BUFFER_OVERFLOW) goto done;
+
+ /* we need to fetch the contents for a string type even if not
requested,
+ * because we need to compute the length of
the ASCII string. */
+ if (data || is_string(info->Type))
+ {
+ /* retry with a dynamically allocated buffer */
+ while (status == STATUS_BUFFER_OVERFLOW)
+ {
+ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr
);
+ if (!(buf_ptr = HeapAlloc(
GetProcessHeap(), 0, total_size
)))
{
- RtlInitAnsiString(&AnsiString, NULL);
- AnsiString.Buffer = (LPSTR)lpData;
- AnsiString.MaximumLength = *lpcbData;
- ValueData.Length = Length;
- ValueData.MaximumLength = ValueData.Length +
sizeof(WCHAR);
-
RtlUnicodeStringToAnsiString(&AnsiString, &ValueData,
FALSE);
+ status = STATUS_NO_MEMORY;
+ goto done;
}
-
- Length = Length / sizeof(WCHAR);
- }
- else if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL)
- {
- if (*lpcbData < Length)
+ info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
+ status = NtQueryValueKey( hkey,
&NtCurrentTeb()->StaticUnicodeString,
+
KeyValuePartialInformation, buf_ptr,
total_size, &total_size );
+ }
+
+ if (status) goto done;
+
+ if (is_string(info->Type))
+ {
+ DWORD len;
+
+ RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr +
info_size),
+
total_size - info_size );
+ if (data && len)
{
- ErrorCode = ERROR_MORE_DATA;
+ if (len > datalen) status = STATUS_BUFFER_OVERFLOW;
+ else
+ {
+ RtlUnicodeToMultiByteN( (char*)data, len, NULL,
(WCHAR
*)(buf_ptr + info_size),
+
total_size - info_size );
+ /* if the type is REG_SZ and data is not 0-terminated
+ * and there is enough space in the buffer NT appends
a \0
*/
+ if (len < datalen
&& data[len-1]) data[len] = 0;
+ }
}
- else
- {
- RtlMoveMemory(lpData, ValueData.Buffer, Length);
- }
- }
-
- if (lpcbData != NULL)
- {
- *lpcbData = Length;
- }
- }
-
- if (ValueData.Buffer != NULL)
- {
- RtlFreeHeap(ProcessHeap, 0, ValueData.Buffer);
- }
-
- return ErrorCode;
+ total_size = len + info_size;
+ }
+ else if (data)
+ {
+ if (total_size - info_size > datalen) status =
STATUS_BUFFER_OVERFLOW;
+ else memcpy( data, buf_ptr +
info_size, total_size -
info_size );
> + }
> + }
> + else status = STATUS_SUCCESS;
> +
> + if (type) *type = info->Type;
> + if (count) *count = total_size - info_size;
> +
> + done:
> + if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
> + return RtlNtStatusToDosError(status);
> }
> @@ -4098,7 +4084,6 @@
> (count && data) ? *count : 0 );
> if ((data && !count) ||
reserved) return ERROR_INVALID_PARAMETER;
> - //if (!(hkey = get_special_root_hkey( hkey ))) return
ERROR_INVALID_HANDLE;
> status = MapDefaultKey(&hkey,
hkeyorg);
> if (!NT_SUCCESS(status))
> @@ -4162,93 +4147,27 @@
> *
> * @implemented
> */
> -LONG WINAPI
> -RegQueryValueA(HKEY hKey,
> - LPCSTR lpSubKey,
> - LPSTR lpValue,
> - PLONG lpcbValue)
> -{
> - WCHAR SubKeyNameBuffer[MAX_PATH+1];
> - UNICODE_STRING SubKeyName;
> - UNICODE_STRING Value;
> - ANSI_STRING AnsiString;
> - LONG ValueSize;
> - LONG ErrorCode;
> -
> - TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
> - hKey, lpSubKey, lpValue, lpcbValue ? *lpcbValue : 0);
> -
> - if (lpValue != NULL &&
> - lpcbValue == NULL)
> - {
> - return ERROR_INVALID_PARAMETER;
> - }
> -
> - RtlInitUnicodeString(&SubKeyName,
> - NULL);
> - RtlInitUnicodeString(&Value,
> - NULL);
> - if (lpSubKey != NULL &&
> - strlen(lpSubKey) != 0)
> - {
> - RtlInitAnsiString(&AnsiString,
> - (LPSTR)lpSubKey);
> - SubKeyName.Buffer = &SubKeyNameBuffer[0];
> - SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
> - RtlAnsiStringToUnicodeString(&SubKeyName,
> - &AnsiString,
> - FALSE);
> - }
> -
> - if (lpValue != NULL)
> - {
> - ValueSize = *lpcbValue * sizeof(WCHAR);
> - Value.MaximumLength = ValueSize;
> - Value.Buffer = RtlAllocateHeap(ProcessHeap,
> - 0,
> - ValueSize);
> - if (Value.Buffer == NULL)
> - {
> - return ERROR_OUTOFMEMORY;
> - }
> - }
> - else
> - {
> - ValueSize = 0;
> - }
> -
> - ErrorCode = RegQueryValueW(hKey,
> - (LPCWSTR)SubKeyName.Buffer,
> - Value.Buffer,
> - &ValueSize);
> - if (ErrorCode == ERROR_SUCCESS)
> - {
> - if (lpValue != NULL)
> - {
> - Value.Length = ValueSize;
> - RtlInitAnsiString(&AnsiString,
> - NULL);
> - AnsiString.Buffer = lpValue;
> - AnsiString.MaximumLength = *lpcbValue;
> - RtlUnicodeStringToAnsiString(&AnsiString,
> - &Value,
> - FALSE);
> - *lpcbValue = ValueSize;
> - }
> - else if (lpcbValue != NULL)
> - {
> - *lpcbValue = ValueSize;
> - }
> - }
> -
> - if (Value.Buffer != NULL)
> - {
> - RtlFreeHeap(ProcessHeap,
> - 0,
> - Value.Buffer);
> - }
> -
> - return ErrorCode;
> +LSTATUS WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG
count )
+{
+ DWORD ret;
+ HKEY subkey = hkey;
+
+ TRACE("(%p,%s,%p,%d)\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,
(LPDWORD)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;
> }
> @@ -4257,75 +4176,42 @@
> *
> * @implemented
> */
> -LONG WINAPI
> -RegQueryValueW(HKEY hKey,
> - LPCWSTR lpSubKey,
> - LPWSTR lpValue,
> - PLONG lpcbValue)
> -{
> - OBJECT_ATTRIBUTES ObjectAttributes;
> - UNICODE_STRING SubKeyString;
> - HANDLE KeyHandle;
> - HANDLE RealKey;
> - LONG ErrorCode;
> - BOOL CloseRealKey;
> - NTSTATUS Status;
> -
> - TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
> - hKey, lpSubKey, lpValue, lpcbValue ? *lpcbValue : 0);
> - if (hKey == NULL)
> +LSTATUS WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data,
LPLONG count )
+{
+ DWORD ret;
+ HKEY subkey = hkey;
+
+ TRACE("(%p,%s,%p,%d)\n", hkey, debugstr_w(name), data, count ? *count
: 0 );
+ if (hkey == NULL)
{
return ERROR_INVALID_HANDLE;
}
- Status = MapDefaultKey(&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- return RtlNtStatusToDosError(Status);
- }
-
- if (lpSubKey != NULL &&
- wcslen(lpSubKey) != 0)
- {
- RtlInitUnicodeString(&SubKeyString,
- (LPWSTR)lpSubKey);
- InitializeObjectAttributes(&ObjectAttributes,
- &SubKeyString,
- OBJ_CASE_INSENSITIVE,
- KeyHandle,
- NULL);
- Status = NtOpenKey(&RealKey,
- KEY_QUERY_VALUE,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError(Status);
- goto Cleanup;
- }
-
- CloseRealKey = TRUE;
- }
- else
- {
- RealKey = hKey;
- CloseRealKey = FALSE;
- }
-
- ErrorCode = RegQueryValueExW(RealKey,
- NULL,
- NULL,
- NULL,
- (LPBYTE)lpValue,
- (LPDWORD)lpcbValue);
- if (CloseRealKey)
- {
- NtClose(RealKey);
- }
-
-Cleanup:
- ClosePredefKey(KeyHandle);
-
- return ErrorCode;
+ if (name && name[0])
+ {
+ ret = RegOpenKeyW( hkey, name, &subkey);
+ if (ret != ERROR_SUCCESS)
+ {
+ return ret;
+ }
+ }
+
+ ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data,
(LPDWORD)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 = sizeof(WCHAR);
> + ret = ERROR_SUCCESS;
> + }
> + return ret;
> }
> @@ -4806,86 +4692,43 @@
> *
> * @implemented
> */
> -LONG WINAPI
> -RegSetValueExA(HKEY hKey,
> - LPCSTR lpValueName,
> - DWORD Reserved,
> - DWORD dwType,
> - CONST BYTE* lpData,
> - DWORD cbData)
> -{
> - UNICODE_STRING ValueName;
> - LPWSTR pValueName;
> - ANSI_STRING AnsiString;
> - UNICODE_STRING Data;
> - LONG ErrorCode;
> - LPBYTE pData;
> - DWORD DataSize;
> -
> - if (lpValueName != NULL &&
> - strlen(lpValueName) != 0)
> - {
> - RtlCreateUnicodeStringFromAsciiz(&ValueName,
> - (PSTR)lpValueName);
> - }
> - else
> - {
> - ValueName.Buffer = NULL;
> - }
> -
> - pValueName = (LPWSTR)ValueName.Buffer;
> -
> - if (((dwType == REG_SZ) ||
> - (dwType == REG_MULTI_SZ) ||
> - (dwType == REG_EXPAND_SZ)) &&
> - (cbData != 0))
> - {
> - /* NT adds one if the caller forgot the NULL-termination
character */
- if (lpData[cbData - 1] != '\0')
- {
- cbData++;
- }
-
- RtlInitAnsiString(&AnsiString,
- NULL);
- AnsiString.Buffer = (PSTR)lpData;
- AnsiString.Length = cbData - 1;
- AnsiString.MaximumLength = cbData;
- RtlAnsiStringToUnicodeString(&Data,
- &AnsiString,
- TRUE);
- pData = (LPBYTE)Data.Buffer;
- DataSize = cbData * sizeof(WCHAR);
- }
- else
- {
- RtlInitUnicodeString(&Data,
- NULL);
- pData = (LPBYTE)lpData;
- DataSize = cbData;
- }
-
- ErrorCode = RegSetValueExW(hKey,
- pValueName,
- Reserved,
- dwType,
- pData,
- DataSize);
- if (pValueName != NULL)
- {
- RtlFreeHeap(ProcessHeap,
- 0,
- ValueName.Buffer);
- }
-
- if (Data.Buffer != NULL)
- {
- RtlFreeHeap(ProcessHeap,
- 0,
- Data.Buffer);
- }
-
- return ErrorCode;
+LSTATUS WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved,
DWORD
type,
+ CONST BYTE *data,
DWORD count )
+{
+ ANSI_STRING nameA;
+ WCHAR *dataW = NULL;
+ NTSTATUS status;
+
+ if (count && is_string(type))
+ {
+ /* if user forgot to count terminating null, add it (yes NT does
this)
*/
+ if (data[count-1] &&
!data[count]) count++;
+ }
+
+ status = MapDefaultKey( (PHANDLE)&hkey, hkey);
+ if (!NT_SUCCESS(status))
+ {
+ return RtlNtStatusToDosError(status);
+ }
+
+ if (is_string( type )) /* need to convert to Unicode */
+ {
+ DWORD lenW;
+ RtlMultiByteToUnicodeSize( &lenW, (const char *)data, count );
+ if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW ))) return
ERROR_OUTOFMEMORY;
+ RtlMultiByteToUnicodeN( dataW, lenW,
NULL, (const char *)data,
count );
+ count = lenW;
+ data = (BYTE *)dataW;
+ }
+
+ RtlInitAnsiString( &nameA, name );
+ if (!(status = RtlAnsiStringToUnicodeString(
&NtCurrentTeb()->StaticUnicodeString,
+
&nameA, FALSE )))
+ {
+ status = NtSetValueKey( hkey,
&NtCurrentTeb()->StaticUnicodeString, 0, type, (PVOID)data, count );
> + }
> + HeapFree( GetProcessHeap(), 0, dataW );
> + return RtlNtStatusToDosError( status );
> }
> _______________________________________________
> Ros-dev mailing list
> Ros-dev(a)reactos.org
>
http://www.reactos.org/mailman/listinfo/ros-dev
_______________________________________________
Ros-dev mailing list
Ros-dev(a)reactos.org
http://www.reactos.org/mailman/listinfo/ros-dev
_______________________________________________
Ros-dev mailing list
Ros-dev(a)reactos.org
http://www.reactos.org/mailman/listinfo/ros-dev