From 378b26ce2714c8039e23932e0fa4e365c149c106 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Thu, 17 Sep 2020 23:51:47 +0900 Subject: [PATCH] [KERNEL32] Improve SetComputerNameExW (#3171) Reduce failures of kernel32_apitest SetComputerNameExW testcase and improve SetComputerNameExW. --- dll/win32/kernel32/client/compname.c | 96 ++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 25 deletions(-) diff --git a/dll/win32/kernel32/client/compname.c b/dll/win32/kernel32/client/compname.c index 46d05e78d32..2b4b335d4f7 100644 --- a/dll/win32/kernel32/client/compname.c +++ b/dll/win32/kernel32/client/compname.c @@ -21,16 +21,19 @@ * PROJECT: ReactOS system libraries * PURPOSE: Computer name functions * FILE: dll/win32/kernel32/client/compname.c - * PROGRAMER: Eric Kohl + * PROGRAMERS: Eric Kohl + * Katayama Hirofumi MZ */ /* INCLUDES ******************************************************************/ #include +#include #define NDEBUG #include +typedef NTSTATUS (WINAPI *FN_DnsValidateName_W)(LPCWSTR, DNS_NAME_FORMAT); /* FUNCTIONS *****************************************************************/ @@ -451,6 +454,31 @@ GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize) return ret; } +static +BOOL +BaseVerifyDnsName(LPCWSTR lpDnsName) +{ + HINSTANCE hDNSAPI; + FN_DnsValidateName_W fnValidate; + NTSTATUS Status; + BOOL ret = FALSE; + + hDNSAPI = LoadLibraryW(L"dnsapi.dll"); + if (hDNSAPI == NULL) + return FALSE; + + fnValidate = (FN_DnsValidateName_W)GetProcAddress(hDNSAPI, "DnsValidateName_W"); + if (fnValidate) + { + Status = (*fnValidate)(lpDnsName, DnsNameHostnameLabel); + if (Status == STATUS_SUCCESS || Status == DNS_ERROR_NON_RFC_NAME) + ret = TRUE; + } + + FreeLibrary(hDNSAPI); + + return ret; +} /* * @implemented @@ -460,40 +488,57 @@ BOOL IsValidComputerName(COMPUTER_NAME_FORMAT NameType, LPCWSTR lpComputerName) { - PWCHAR p; - ULONG Length; + size_t Length; + static const WCHAR s_szInvalidChars[] = + L"\"/\\[]:|<>+=;,?" + L"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; - /* FIXME: do verification according to NameType */ + if (lpComputerName == NULL) + return FALSE; - Length = 0; - p = (PWCHAR)lpComputerName; +#define MAX_COMPUTER_NAME_EX 64 + /* Get string length */ + if (!NT_SUCCESS(RtlStringCchLengthW(lpComputerName, MAX_COMPUTER_NAME_EX + 1, &Length))) + return FALSE; +#undef MAX_COMPUTER_NAME_EX - while (*p != 0) + /* An empty name is invalid, except a DNS name */ + if (Length == 0 && NameType != ComputerNamePhysicalDnsDomain) + return FALSE; + + /* Leading or trailing spaces are invalid */ + if (Length > 0 && + (lpComputerName[0] == L' ' || lpComputerName[Length - 1] == L' ')) { - if (!(iswctype(*p, _ALPHA | _DIGIT) || *p == L'!' || *p == L'@' || *p == L'#' || - *p == L'$' || *p == L'%' || *p == L'^' || *p == L'&' || *p == L'\'' || - *p == L')' || *p == L'(' || *p == L'.' || *p == L'-' || *p == L'_' || - *p == L'{' || *p == L'}' || *p == L'~')) - return FALSE; - - Length++; - p++; + return FALSE; } - if (NameType == ComputerNamePhysicalDnsDomain) - return TRUE; - - if (Length == 0) + /* Check whether the name contains any invalid character */ + if (wcscspn(lpComputerName, s_szInvalidChars) < Length) return FALSE; - if (NameType == ComputerNamePhysicalNetBIOS && - Length > MAX_COMPUTERNAME_LENGTH) - return FALSE; + switch (NameType) + { + case ComputerNamePhysicalNetBIOS: + if (Length > MAX_COMPUTERNAME_LENGTH) + return FALSE; + return TRUE; - return TRUE; + case ComputerNamePhysicalDnsDomain: + /* An empty DNS name is valid */ + if (Length != 0) + return BaseVerifyDnsName(lpComputerName); + return TRUE; + + case ComputerNamePhysicalDnsHostname: + return BaseVerifyDnsName(lpComputerName); + + default: + return FALSE; + } } - static BOOL SetComputerNameToRegistry(LPCWSTR RegistryKey, @@ -547,6 +592,7 @@ SetComputerNameToRegistry(LPCWSTR RegistryKey, NtFlushKey(KeyHandle); NtClose(KeyHandle); + SetLastError(ERROR_SUCCESS); return TRUE; } @@ -637,7 +683,7 @@ SetComputerNameExW(COMPUTER_NAME_FORMAT NameType, lpBuffer); default: - SetLastError (ERROR_INVALID_PARAMETER); + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } }