FYI, Local* or Base functions are typically always W. Best regards, Alex Ionescu
On Sun, May 24, 2009 at 6:13 PM, Ged <[email protected]> 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: [email protected] [mailto:[email protected]] 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 <[email protected]> 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: [email protected] [mailto:[email protected]] > On Behalf Of [email protected] >> Sent: 24 May 2009 09:45 >> To: [email protected] >> 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 >> [email protected] >> http://www.reactos.org/mailman/listinfo/ros-dev >> > > _______________________________________________ > Ros-dev mailing list > [email protected] > http://www.reactos.org/mailman/listinfo/ros-dev > > > _______________________________________________ > Ros-dev mailing list > [email protected] > http://www.reactos.org/mailman/listinfo/ros-dev > _______________________________________________ Ros-dev mailing list [email protected] http://www.reactos.org/mailman/listinfo/ros-dev
