From 190d075d2119f4d200f43de85a9c0f1bbd217339 Mon Sep 17 00:00:00 2001 From: Gregor Schneider Date: Sun, 13 Dec 2009 16:25:50 +0000 Subject: [PATCH] Alexander Yastrebov : - Simplify and fix error checking in RegQuery/SetEx functions - Add handling for missing termination characters - Fixes one advapi32 winetest See issue #4993 for more details. svn path=/trunk/; revision=44566 --- reactos/dll/win32/advapi32/reg/reg.c | 104 ++++++++++++++------------- 1 file changed, 56 insertions(+), 48 deletions(-) diff --git a/reactos/dll/win32/advapi32/reg/reg.c b/reactos/dll/win32/advapi32/reg/reg.c index 49230b9cd1a..4a2ce7e96d6 100644 --- a/reactos/dll/win32/advapi32/reg/reg.c +++ b/reactos/dll/win32/advapi32/reg/reg.c @@ -3989,10 +3989,11 @@ RegQueryValueExA(HKEY hKey, { UNICODE_STRING ValueName; UNICODE_STRING ValueData; - ANSI_STRING AnsiString; LONG ErrorCode; DWORD Length; DWORD Type; + NTSTATUS Status; + ULONG Index; TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n", hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0); @@ -4041,16 +4042,23 @@ RegQueryValueExA(HKEY hKey, ErrorCode == ERROR_MORE_DATA) { - if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ)) + if (is_string(Type)) { if (ErrorCode == ERROR_SUCCESS && ValueData.Buffer != NULL) { - RtlInitAnsiString(&AnsiString, NULL); - AnsiString.Buffer = (LPSTR)lpData; - AnsiString.MaximumLength = *lpcbData; - ValueData.Length = Length; - ValueData.MaximumLength = ValueData.Length + sizeof(WCHAR); - RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE); + Status = RtlUnicodeToMultiByteN((PCHAR)lpData, *lpcbData, &Index, (PWCHAR)ValueData.Buffer, Length); + if (NT_SUCCESS(Status)) + { + PCHAR szData = (PCHAR)lpData; + if(&szData[Index] < (PCHAR)(lpData + *lpcbData)) + { + szData[Index] = '\0'; + } + } + else + { + ErrorCode = RtlNtStatusToDosError(Status); + } } Length = Length / sizeof(WCHAR); @@ -4135,7 +4143,7 @@ RegQueryValueExW(HKEY hkeyorg, status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation, buffer, total_size, &total_size ); - if (status && status != STATUS_BUFFER_OVERFLOW) goto done; + if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) goto done; if (data) { @@ -4153,12 +4161,12 @@ RegQueryValueExW(HKEY hkeyorg, buf_ptr, total_size, &total_size ); } - if (!status) + if (NT_SUCCESS(status)) { memcpy( data, buf_ptr + info_size, total_size - info_size ); /* if the type is REG_SZ and data is not 0-terminated * and there is enough space in the buffer NT appends a \0 */ - if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type)) + if (is_string(info->Type) && total_size - info_size <= *count-sizeof(WCHAR)) { WCHAR *ptr = (WCHAR *)(data + total_size - info_size); if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0; @@ -4743,12 +4751,16 @@ RegSetValueExA(HKEY hKey, LONG ErrorCode; LPBYTE pData; DWORD DataSize; + NTSTATUS Status; - if (lpValueName != NULL && - strlen(lpValueName) != 0) + /* Convert SubKey name to Unicode */ + if (lpValueName != NULL && lpValueName[0] != '\0') { - RtlCreateUnicodeStringFromAsciiz(&ValueName, - (PSTR)lpValueName); + BOOL bConverted; + bConverted = RtlCreateUnicodeStringFromAsciiz(&ValueName, + (PSTR)lpValueName); + if(!bConverted) + return ERROR_NOT_ENOUGH_MEMORY; } else { @@ -4757,32 +4769,32 @@ RegSetValueExA(HKEY hKey, 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); + if (is_string(dwType) && (cbData != 0)) + { + /* Convert ANSI string Data to Unicode */ + /* If last character NOT zero then increment length */ + LONG bNoNulledStr = ((lpData[cbData-1] != '\0') ? 1 : 0); AnsiString.Buffer = (PSTR)lpData; - AnsiString.Length = cbData - 1; - AnsiString.MaximumLength = cbData; - RtlAnsiStringToUnicodeString(&Data, + AnsiString.Length = cbData + bNoNulledStr; + AnsiString.MaximumLength = cbData + bNoNulledStr; + Status = RtlAnsiStringToUnicodeString(&Data, &AnsiString, TRUE); + + if (!NT_SUCCESS(Status)) + { + if (pValueName != NULL) + RtlFreeUnicodeString(&ValueName); + + return RtlNtStatusToDosError(Status); + } pData = (LPBYTE)Data.Buffer; DataSize = cbData * sizeof(WCHAR); } else { - RtlInitUnicodeString(&Data, - NULL); + Data.Buffer = NULL; pData = (LPBYTE)lpData; DataSize = cbData; } @@ -4793,19 +4805,12 @@ RegSetValueExA(HKEY hKey, dwType, pData, DataSize); + if (pValueName != NULL) - { - RtlFreeHeap(ProcessHeap, - 0, - ValueName.Buffer); - } + RtlFreeUnicodeString(&ValueName); if (Data.Buffer != NULL) - { - RtlFreeHeap(ProcessHeap, - 0, - Data.Buffer); - } + RtlFreeUnicodeString(&Data); return ErrorCode; } @@ -4847,13 +4852,16 @@ RegSetValueExW(HKEY hKey, } pValueName = &ValueName; - if (((dwType == REG_SZ) || - (dwType == REG_MULTI_SZ) || - (dwType == REG_EXPAND_SZ)) && - (cbData != 0) && (*(((PWCHAR)lpData) + (cbData / sizeof(WCHAR)) - 1) != L'\0')) + if (is_string(dwType) && (cbData != 0)) { - /* NT adds one if the caller forgot the NULL-termination character */ - cbData += sizeof(WCHAR); + PWSTR pwsData = (PWSTR)lpData; + + if((pwsData[cbData / sizeof(WCHAR) - 1] != L'\0') && + (pwsData[cbData / sizeof(WCHAR)] == L'\0')) + { + /* Increment length if last character is not zero and next is zero */ + cbData += sizeof(WCHAR); + } } Status = NtSetValueKey(KeyHandle,