From 0cb2f117e7348f3dfc02c6de0712e5f9b40e68f5 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Fri, 20 Jul 2012 15:39:19 +0200 Subject: ntdll: Implement RtlIpv4StringToAddressW. --- dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/rtl.c | 202 +++++++++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- 3 files changed, 204 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 8de353f..7454414 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -699,7 +699,7 @@ # @ stub RtlIpv4StringToAddressA # @ stub RtlIpv4StringToAddressExA @ stdcall RtlIpv4StringToAddressExW(ptr ptr wstr ptr) -# @ stub RtlIpv4StringToAddressW +@ stdcall RtlIpv4StringToAddressW(wstr long ptr ptr) # @ stub RtlIpv6AddressToStringA # @ stub RtlIpv6AddressToStringExA # @ stub RtlIpv6AddressToStringExW diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c index 34869e7..4b00778 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef HAVE_NETINET_IN_H #include #endif @@ -47,6 +48,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll); +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) + static RTL_CRITICAL_SECTION peb_lock; static RTL_CRITICAL_SECTION_DEBUG critsect_debug = { @@ -871,6 +874,205 @@ void WINAPI RtlCopyLuidAndAttributesArray( for (i = 0; i < Count; i++) Dest[i] = Src[i]; } +static NTSTATUS RtlpStringToUlong(PCWSTR String, BOOLEAN Strict, + PCWSTR *Terminator, PULONG Out) +{ + NTSTATUS Status = STATUS_INVALID_PARAMETER; + ULONG Result = 0; + INT Digit; + INT Base = 10; + BOOLEAN GotFirstDigit = FALSE; + + if (*String == L'0') + { + String++; + + /* Simply zero */ + if ((*String < L'0' || *String > L'9') && + (*String != L'x' && *String != L'X')) + { + Status = STATUS_SUCCESS; + goto Done; + } + + if (*String == L'x' || *String == L'X') + { + String++; + Base = 16; + } + else + Base = 8; + + /* Strict forbids anything but decimal */ + if (Strict) + { + Status = STATUS_INVALID_PARAMETER; + goto Done; + } + } + + while (1) + { + if (*String >= L'0' && *String <= L'7') + { + /* Octal digit */ + Digit = *String - L'0'; + } + else if (*String >= L'0' && *String <= L'9' && Base >= 10) + { + /* Decimal digit */ + Digit = *String - L'0'; + } + else if (*String >= L'A' && *String <= L'F' && Base >= 16) + { + /* Capital hex digit */ + Digit = 10 + (*String - L'A'); + } + else if (*String >= L'a' && *String <= L'f' && Base >= 16) + { + /* Lowercase hex digit */ + Digit = 10 + (*String - L'a'); + } + else + { + /* We're done. Fail if we haven't read at least one digit */ + Status = GotFirstDigit ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER; + break; + } + + GotFirstDigit = TRUE; + + if (Result > ULONG_MAX / Base) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + Result *= Base; + + if (Result > ULONG_MAX - Digit) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + Result += Digit; + + String++; + } + +Done: + *Terminator = String; + *Out = Result; + return Status; +} + +/*********************************************************************** + * RtlIpv4StringToAddressW [NTDLL.@] + * + * Parse the given string into an ipv4 address + * + * PARAMS + * String [I] PTR to the string to convert + * Strict [I] If TRUE, forbid hex/oct or short-hand notation + * Terminator [O] PTR to receive the address of the character within String + * that terminated the conversion + * Addr [O] PTR to receive the ip address (network byte order) + * + * RETURNS + * Success: STATUS_SUCCESS + * Failure: STATUS_INVALID_PARAMETER + * + */ +NTSTATUS WINAPI RtlIpv4StringToAddressW(PCWSTR String, BOOLEAN Strict, + PCWSTR *Terminator, IN_ADDR *Addr) +{ + NTSTATUS Status; + ULONG Result[4]; + INT Parts = 0; + INT i; + + do + { + Status = RtlpStringToUlong(String, Strict, &String, &Result[Parts]); + Parts++; + + if (*String != L'.') break; + + /* Already four parts, but a dot follows? */ + if (Parts == 4) + { + Status = STATUS_INVALID_PARAMETER; + goto Done; + } + + /* Skip the dot */ + String++; + } while (NT_SUCCESS(Status)); + + if (Strict && Parts < 4) Status = STATUS_INVALID_PARAMETER; + + if (!NT_SUCCESS(Status)) goto Done; + + /* Verify all but the last part */ + for (i = 0; i < Parts - 1; i++) + if (Result[i] > 0xFF) + { + Status = STATUS_INVALID_PARAMETER; + goto Done; + } + + /* Now handle the last part, depending on how many there are */ + switch (Parts) + { + case 1: + Result[3] = Result[0] >> 0 & 0xFF; + Result[2] = Result[0] >> 8 & 0xFF; + Result[1] = Result[0] >> 16 & 0xFF; + Result[0] = Result[0] >> 24 & 0xFF; + break; + case 2: + if (Result[1] > 0xFFFFFF) + { + Status = STATUS_INVALID_PARAMETER; + goto Done; + } + + Result[3] = Result[1] >> 0 & 0xFF; + Result[2] = Result[1] >> 8 & 0xFF; + Result[1] = Result[1] >> 16 & 0xFF; + break; + case 3: + if (Result[2] > 0xFFFF) + { + Status = STATUS_INVALID_PARAMETER; + goto Done; + } + + Result[3] = Result[2] >> 0 & 0xFF; + Result[2] = Result[2] >> 8 & 0xFF; + break; + case 4: + if (Result[3] > 0xFF) + { + Status = STATUS_INVALID_PARAMETER; + goto Done; + } + break; + } + + /* Finally, assign the result */ + if (NT_SUCCESS(Status)) + { + Addr->S_un.S_un_b.s_b1 = (UCHAR)Result[0]; + Addr->S_un.S_un_b.s_b2 = (UCHAR)Result[1]; + Addr->S_un.S_un_b.s_b3 = (UCHAR)Result[2]; + Addr->S_un.S_un_b.s_b4 = (UCHAR)Result[3]; + } + +Done: + *Terminator = String; + return Status; +} + NTSTATUS WINAPI RtlIpv4StringToAddressExW(PULONG IP, PULONG Port, LPCWSTR Buffer, PULONG MaxSize) { diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 97a71fc..be7c6e3 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1076,7 +1076,7 @@ @ stub RtlIpv4StringToAddressA @ stub RtlIpv4StringToAddressExA @ stdcall RtlIpv4StringToAddressExW(ptr ptr wstr ptr) ntdll.RtlIpv4StringToAddressExW -@ stub RtlIpv4StringToAddressW +@ stdcall RtlIpv4StringToAddressW(wstr long ptr ptr) ntdll.RtlIpv4StringToAddressW @ stub RtlIpv6AddressToStringA @ stub RtlIpv6AddressToStringExA @ stub RtlIpv6AddressToStringExW -- 1.7.10.msysgit.1