diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index 8a83feb15ac..50597148e34 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -24,6 +24,7 @@ #include #include "ntdll_test.h" +#include "inaddr.h" #ifndef __WINE_WINTERNL_H @@ -45,6 +46,20 @@ typedef struct _RTL_HANDLE_TABLE #endif +/* avoid #include */ +#undef htons +#ifdef WORDS_BIGENDIAN +#define htons(s) ((USHORT)(s)) +#else /* WORDS_BIGENDIAN */ +static inline USHORT __my_ushort_swap(USHORT s) +{ + return (s >> 8) | (s << 8); +} +#define htons(s) __my_ushort_swap(s) +#endif /* WORDS_BIGENDIAN */ + + + /* Function ptrs for ntdll calls */ static HMODULE hntdll = 0; static SIZE_T (WINAPI *pRtlCompareMemory)(LPCVOID,LPCVOID,SIZE_T); @@ -70,9 +85,12 @@ static NTSTATUS (WINAPI *pRtlFreeSid)(PSID); static struct _TEB * (WINAPI *pNtCurrentTeb)(void); static DWORD (WINAPI *pRtlGetThreadErrorMode)(void); static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD); +static IMAGE_BASE_RELOCATION *(WINAPI *pLdrProcessRelocationBlock)(void*,UINT,USHORT*,INT_PTR); +static CHAR * (WINAPI *pRtlIpv4AddressToStringA)(const IN_ADDR *, LPSTR); +static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG); + static HMODULE hkernel32 = 0; static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); -static IMAGE_BASE_RELOCATION *(WINAPI *pLdrProcessRelocationBlock)(void*,UINT,USHORT*,INT_PTR); #define LEN 16 @@ -111,6 +129,8 @@ static void InitFunctionPtrs(void) pRtlGetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlGetThreadErrorMode"); pRtlSetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlSetThreadErrorMode"); pLdrProcessRelocationBlock = (void *)GetProcAddress(hntdll, "LdrProcessRelocationBlock"); + pRtlIpv4AddressToStringA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringA"); + pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringExA"); } hkernel32 = LoadLibraryA("kernel32.dll"); ok(hkernel32 != 0, "LoadLibrary failed\n"); @@ -1129,6 +1149,170 @@ static void test_LdrProcessRelocationBlock(void) ok(addr16 == 0x565, "addr16 = %x, expected 0x565\n", addr16); } +static void test_RtlIpv4AddressToString(void) +{ + CHAR buffer[20]; + CHAR *res; + IN_ADDR ip; + DWORD len; + + if (!pRtlIpv4AddressToStringA) + { + win_skip("RtlIpv4AddressToStringA not available\n"); + return; + } + + ip.S_un.S_un_b.s_b1 = 1; + ip.S_un.S_un_b.s_b2 = 2; + ip.S_un.S_un_b.s_b3 = 3; + ip.S_un.S_un_b.s_b4 = 4; + + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringA(&ip, buffer); + len = strlen(buffer); + ok(res == (buffer + len), "got %p with '%s' (expected %p)\n", res, buffer, buffer + len); + + res = pRtlIpv4AddressToStringA(&ip, NULL); + ok( (res == (char *)~0) || + broken(res == (char *)0 + len), /* XP and w2003 */ + "got %p (expected ~0)\n", res); + + if (0) { + /* this crashes in windows */ + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringA(NULL, buffer); + trace("got %p with '%s'\n", res, buffer); + } + + if (0) { + /* this crashes in windows */ + res = pRtlIpv4AddressToStringA(NULL, NULL); + trace("got %p\n", res); + } +} + +static void test_RtlIpv4AddressToStringEx(void) +{ + CHAR ip_1234[] = "1.2.3.4"; + CHAR ip_1234_80[] = "1.2.3.4:80"; + LPSTR expect; + CHAR buffer[30]; + NTSTATUS res; + IN_ADDR ip; + ULONG size; + DWORD used; + USHORT port; + + if (!pRtlIpv4AddressToStringExA) + { + win_skip("RtlIpv4AddressToStringExA not available\n"); + return; + } + + ip.S_un.S_un_b.s_b1 = 1; + ip.S_un.S_un_b.s_b2 = 2; + ip.S_un.S_un_b.s_b3 = 3; + ip.S_un.S_un_b.s_b4 = 4; + + port = htons(80); + expect = ip_1234_80; + + size = sizeof(buffer); + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size); + used = strlen(buffer); + ok( (res == STATUS_SUCCESS) && + (size == strlen(expect) + 1) && !strcmp(buffer, expect), + "got 0x%x and size %d with '%s'\n", res, size, buffer); + + size = used + 1; + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size); + ok( (res == STATUS_SUCCESS) && + (size == strlen(expect) + 1) && !strcmp(buffer, expect), + "got 0x%x and size %d with '%s'\n", res, size, buffer); + + size = used; + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size); + ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1), + "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n", + res, size, buffer, used + 1); + + size = used - 1; + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size); + ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1), + "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n", + res, size, buffer, used + 1); + + + /* to get only the ip, use 0 as port */ + port = 0; + expect = ip_1234; + + size = sizeof(buffer); + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size); + used = strlen(buffer); + ok( (res == STATUS_SUCCESS) && + (size == strlen(expect) + 1) && !strcmp(buffer, expect), + "got 0x%x and size %d with '%s'\n", res, size, buffer); + + size = used + 1; + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size); + ok( (res == STATUS_SUCCESS) && + (size == strlen(expect) + 1) && !strcmp(buffer, expect), + "got 0x%x and size %d with '%s'\n", res, size, buffer); + + size = used; + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size); + ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1), + "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n", + res, size, buffer, used + 1); + + size = used - 1; + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size); + ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1), + "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n", + res, size, buffer, used + 1); + + + /* parameters are checked */ + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(&ip, 0, buffer, NULL); + ok(res == STATUS_INVALID_PARAMETER, + "got 0x%x with '%s' (expected STATUS_INVALID_PARAMETER)\n", res, buffer); + + size = sizeof(buffer); + res = pRtlIpv4AddressToStringExA(&ip, 0, NULL, &size); + ok( res == STATUS_INVALID_PARAMETER, + "got 0x%x and size %d (expected STATUS_INVALID_PARAMETER)\n", res, size); + + size = sizeof(buffer); + memset(buffer, '#', sizeof(buffer) - 1); + buffer[sizeof(buffer) -1] = 0; + res = pRtlIpv4AddressToStringExA(NULL, 0, buffer, &size); + ok( res == STATUS_INVALID_PARAMETER, + "got 0x%x and size %d with '%s' (expected STATUS_INVALID_PARAMETER)\n", + res, size, buffer); +} + + START_TEST(rtl) { InitFunctionPtrs(); @@ -1150,4 +1334,6 @@ START_TEST(rtl) test_RtlDeleteTimer(); test_RtlThreadErrorMode(); test_LdrProcessRelocationBlock(); + test_RtlIpv4AddressToString(); + test_RtlIpv4AddressToStringEx(); }