From 199b0bf84eb8f4cc8ab2bc44f8e40f0b42d48575 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 24 Oct 2016 10:04:19 +0200 Subject: [PATCH] netapi32: Implement DavGetUNCFromHTTPPath. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/netapi32/netapi32.c | 85 +++++++++++++++++++ dlls/netapi32/netapi32.spec | 1 + dlls/netapi32/tests/access.c | 153 +++++++++++++++++++++++++++++++++++ include/davclnt.h | 1 + 4 files changed, 240 insertions(+) diff --git a/dlls/netapi32/netapi32.c b/dlls/netapi32/netapi32.c index bb61e7fff98..278d4528b01 100644 --- a/dlls/netapi32/netapi32.c +++ b/dlls/netapi32/netapi32.c @@ -3442,3 +3442,88 @@ DWORD WINAPI DavGetHTTPFromUNCPath(const WCHAR *unc_path, WCHAR *buf, DWORD *buf return ERROR_SUCCESS; } + +/************************************************************ + * DavGetUNCFromHTTPPath (NETAPI32.@) + */ +DWORD WINAPI DavGetUNCFromHTTPPath(const WCHAR *http_path, WCHAR *buf, DWORD *buflen) +{ + static const WCHAR httpW[] = {'h','t','t','p'}; + static const WCHAR httpsW[] = {'h','t','t','p','s'}; + static const WCHAR davrootW[] = {'\\','D','a','v','W','W','W','R','o','o','t'}; + static const WCHAR sslW[] = {'@','S','S','L'}; + static const WCHAR port80W[] = {'8','0'}; + static const WCHAR port443W[] = {'4','4','3'}; + const WCHAR *p = http_path, *server, *port = NULL, *path = NULL; + DWORD i, len = 0, len_server = 0, len_port = 0, len_path = 0; + BOOL ssl; + + TRACE("(%s %p %p)\n", debugstr_w(http_path), buf, buflen); + + while (*p && *p != ':') { p++; len++; }; + if (len == sizeof(httpW)/sizeof(httpW[0]) && !memicmpW( http_path, httpW, len )) ssl = FALSE; + else if (len == sizeof(httpsW)/sizeof(httpsW[0]) && !memicmpW( http_path, httpsW, len )) ssl = TRUE; + else return ERROR_INVALID_PARAMETER; + + if (p[0] != ':' || p[1] != '/' || p[2] != '/') return ERROR_INVALID_PARAMETER; + server = p += 3; + + while (*p && *p != ':' && *p != '/') { p++; len_server++; }; + if (!len_server) return ERROR_BAD_NET_NAME; + if (*p == ':') + { + port = ++p; + while (*p && isdigitW(*p)) { p++; len_port++; }; + if (len_port == 2 && !ssl && !memcmp( port, port80W, sizeof(port80W) )) port = NULL; + else if (len_port == 3 && ssl && !memcmp( port, port443W, sizeof(port443W) )) port = NULL; + path = p; + } + else if (*p == '/') path = p; + + while (*p) + { + if (p[0] == '/' && p[1] == '/') return ERROR_BAD_NET_NAME; + p++; len_path++; + } + if (len_path && path[len_path - 1] == '/') len_path--; + + len = len_server + 2; /* \\ */ + if (ssl) len += 4; /* @SSL */ + if (port) len += len_port + 1 /* @ */; + len += sizeof(davrootW)/sizeof(davrootW[0]); + len += len_path + 1; /* nul */ + + if (*buflen < len) + { + *buflen = len; + return ERROR_INSUFFICIENT_BUFFER; + } + + buf[0] = buf[1] = '\\'; + buf += 2; + memcpy( buf, server, len_server * sizeof(WCHAR) ); + buf += len_server; + if (ssl) + { + memcpy( buf, sslW, sizeof(sslW) ); + buf += 4; + } + if (port) + { + *buf++ = '@'; + memcpy( buf, port, len_port * sizeof(WCHAR) ); + buf += len_port; + } + memcpy( buf, davrootW, sizeof(davrootW) ); + buf += sizeof(davrootW)/sizeof(davrootW[0]); + for (i = 0; i < len_path; i++) + { + if (path[i] == '/') *buf++ = '\\'; + else *buf++ = path[i]; + } + + *buf = 0; + *buflen = len; + + return ERROR_SUCCESS; +} diff --git a/dlls/netapi32/netapi32.spec b/dlls/netapi32/netapi32.spec index 64314af8bac..8dbd3785217 100644 --- a/dlls/netapi32/netapi32.spec +++ b/dlls/netapi32/netapi32.spec @@ -1,4 +1,5 @@ @ stdcall DavGetHTTPFromUNCPath(wstr ptr ptr) +@ stdcall DavGetUNCFromHTTPPath(wstr ptr ptr) @ stub DsAddressToSiteNames @ stub DsAddressToSiteNamesEx @ stub DsDeregisterDnsHostRecords diff --git a/dlls/netapi32/tests/access.c b/dlls/netapi32/tests/access.c index a57c5643e37..f44a6d3d439 100644 --- a/dlls/netapi32/tests/access.c +++ b/dlls/netapi32/tests/access.c @@ -66,6 +66,7 @@ static NET_API_STATUS (WINAPI *pNetUserDel)(LPCWSTR,LPCWSTR); static NET_API_STATUS (WINAPI *pNetLocalGroupGetInfo)(LPCWSTR,LPCWSTR,DWORD,LPBYTE*); static NET_API_STATUS (WINAPI *pNetLocalGroupGetMembers)(LPCWSTR,LPCWSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,PDWORD_PTR); static DWORD (WINAPI *pDavGetHTTPFromUNCPath)(LPCWSTR,LPWSTR,LPDWORD); +static DWORD (WINAPI *pDavGetUNCFromHTTPPath)(LPCWSTR,LPWSTR,LPDWORD); static BOOL init_access_tests(void) { @@ -550,6 +551,156 @@ static void test_DavGetHTTPFromUNCPath(void) } } +static void test_DavGetUNCFromHTTPPath(void) +{ + static const WCHAR path[] = + {0}; + static const WCHAR path2[] = + {'h','t','t','p',':','/','/','s','e','r','v','e','r','/','p','a','t','h',0}; + static const WCHAR path3[] = + {'h','t','t','p','s',':','/','/','s','e','r','v','e','r','/','p','a','t','h',0}; + static const WCHAR path4[] = + {'\\','\\','s','e','r','v','e','r',0}; + static const WCHAR path5[] = + {'\\','\\','s','e','r','v','e','r','\\','p','a','t','h',0}; + static const WCHAR path6[] = + {'\\','\\','h','t','t','p',':','/','/','s','e','r','v','e','r','/','p','a','t','h',0}; + static const WCHAR path7[] = + {'h','t','t','p',':','/','/',0}; + static const WCHAR path8[] = + {'h','t','t','p',':',0}; + static const WCHAR path9[] = + {'h','t','t','p',0}; + static const WCHAR path10[] = + {'h','t','t','p',':','s','e','r','v','e','r',0}; + static const WCHAR path11[] = + {'h','t','t','p',':','/','/','s','e','r','v','e','r',':','8','0',0}; + static const WCHAR path12[] = + {'h','t','t','p',':','/','/','s','e','r','v','e','r',':','8','1',0}; + static const WCHAR path13[] = + {'h','t','t','p','s',':','/','/','s','e','r','v','e','r',':','8','0',0}; + static const WCHAR path14[] = + {'H','T','T','P',':','/','/','s','e','r','v','e','r','/','p','a','t','h',0}; + static const WCHAR path15[] = + {'h','t','t','p',':','/','/','s','e','r','v','e','r',':','6','5','5','3','7',0}; + static const WCHAR path16[] = + {'h','t','t','p',':','/','/','s','e','r','v','e','r','/','p','a','t','h','/',0}; + static const WCHAR path17[] = + {'h','t','t','p',':','/','/','s','e','r','v','e','r','/','p','a','t','h','/','/',0}; + static const WCHAR path18[] = + {'h','t','t','p',':','/','/','s','e','r','v','e','r',':','/','p','a','t','h',0}; + static const WCHAR path19[] = + {'h','t','t','p',':','/','/','s','e','r','v','e','r',0}; + static const WCHAR path20[] = + {'h','t','t','p','s',':','/','/','s','e','r','v','e','r',':','4','4','3',0}; + static const WCHAR path21[] = + {'h','t','t','p','s',':','/','/','s','e','r','v','e','r',':','8','0',0}; + static const WCHAR result[] = + {'\\','\\','s','e','r','v','e','r','\\','D','a','v','W','W','W','R','o','o','t','\\','p','a','t','h',0}; + static const WCHAR result2[] = + {'\\','\\','s','e','r','v','e','r','@','S','S','L','\\','D','a','v','W','W','W','R','o','o','t','\\', + 'p','a','t','h',0}; + static const WCHAR result3[] = + {'\\','\\','s','e','r','v','e','r','\\','D','a','v','W','W','W','R','o','o','t',0}; + static const WCHAR result4[] = + {'\\','\\','s','e','r','v','e','r','@','8','1','\\','D','a','v','W','W','W','R','o','o','t',0}; + static const WCHAR result5[] = + {'\\','\\','s','e','r','v','e','r','@','S','S','L','@','8','0','\\','D','a','v','W','W','W','R','o','o','t',0}; + static const WCHAR result6[] = + {'\\','\\','s','e','r','v','e','r','@','6','5','5','3','7','\\','D','a','v','W','W','W','R','o','o','t',0}; + static const WCHAR result7[] = + {'\\','\\','s','e','r','v','e','r','@','\\','D','a','v','W','W','W','R','o','o','t','\\','p','a','t','h',0}; + static const WCHAR result8[] = + {'\\','\\','s','e','r','v','e','r','@','S','S','L','\\','D','a','v','W','W','W','R','o','o','t',0}; + static const WCHAR result9[] = + {'\\','\\','s','e','r','v','e','r','@','S','S','L','@','8','0','\\','D','a','v','W','W','W','R','o','o','t',0}; + static const struct + { + const WCHAR *path; + DWORD size; + DWORD ret; + const WCHAR *ret_path; + DWORD ret_size; + } + tests[] = + { + { path, MAX_PATH, ERROR_INVALID_PARAMETER, NULL, MAX_PATH }, + { path2, MAX_PATH, ERROR_SUCCESS, result, 25 }, + { path3, MAX_PATH, ERROR_SUCCESS, result2, 29 }, + { path4, MAX_PATH, ERROR_INVALID_PARAMETER, NULL, MAX_PATH }, + { path5, MAX_PATH, ERROR_INVALID_PARAMETER, NULL, MAX_PATH }, + { path6, MAX_PATH, ERROR_INVALID_PARAMETER, NULL, MAX_PATH }, + { path7, MAX_PATH, ERROR_BAD_NET_NAME, NULL, MAX_PATH }, + { path8, MAX_PATH, ERROR_INVALID_PARAMETER, NULL, MAX_PATH }, + { path9, MAX_PATH, ERROR_INVALID_PARAMETER, NULL, MAX_PATH }, + { path10, MAX_PATH, ERROR_INVALID_PARAMETER, NULL, MAX_PATH }, + { path11, MAX_PATH, ERROR_SUCCESS, result3, 20 }, + { path12, MAX_PATH, ERROR_SUCCESS, result4, 23 }, + { path13, MAX_PATH, ERROR_SUCCESS, result5, 27 }, + { path14, MAX_PATH, ERROR_SUCCESS, result, 25 }, + { path15, MAX_PATH, ERROR_SUCCESS, result6, 26 }, + { path16, MAX_PATH, ERROR_SUCCESS, result, 25 }, + { path17, MAX_PATH, ERROR_BAD_NET_NAME, NULL, MAX_PATH }, + { path18, MAX_PATH, ERROR_SUCCESS, result7, 26 }, + { path19, MAX_PATH, ERROR_SUCCESS, result3, 20 }, + { path20, MAX_PATH, ERROR_SUCCESS, result8, 24 }, + { path21, MAX_PATH, ERROR_SUCCESS, result9, 27 }, + }; + WCHAR buf[MAX_PATH]; + DWORD i, ret, size; + + if (!pDavGetUNCFromHTTPPath) + { + win_skip( "DavGetUNCFromHTTPPath is missing\n" ); + return; + } + + if (0) { /* crash */ + ret = pDavGetUNCFromHTTPPath( NULL, NULL, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + } + ret = pDavGetUNCFromHTTPPath( path, buf, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + size = 0; + ret = pDavGetUNCFromHTTPPath( path, NULL, &size ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + buf[0] = 0; + size = 0; + ret = pDavGetUNCFromHTTPPath( path, buf, &size ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + if (0) { /* crash */ + ret = pDavGetUNCFromHTTPPath( path2, buf, NULL ); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + } + size = 0; + ret = pDavGetUNCFromHTTPPath( path2, NULL, &size ); + ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret ); + + buf[0] = 0; + size = 0; + ret = pDavGetUNCFromHTTPPath( path2, buf, &size ); + ok( ret == ERROR_INSUFFICIENT_BUFFER, "got %u\n", ret ); + ok( size == 25, "got %u\n", size ); + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) + { + buf[0] = 0; + size = tests[i].size; + ret = pDavGetUNCFromHTTPPath( tests[i].path, buf, &size ); + ok( ret == tests[i].ret, "%u: expected %u got %u\n", i, tests[i].ret, ret ); + if (tests[i].ret_path) + { + ok( !lstrcmpW( buf, tests[i].ret_path ), "%u: expected %s got %s\n", + i, wine_dbgstr_w(tests[i].ret_path), wine_dbgstr_w(buf) ); + } + ok( size == tests[i].ret_size, "%u: expected %u got %u\n", i, tests[i].ret_size, size ); + } +} + + START_TEST(access) { HMODULE hnetapi32=LoadLibraryA("netapi32.dll"); @@ -564,6 +715,7 @@ START_TEST(access) pNetLocalGroupGetInfo=(void*)GetProcAddress(hnetapi32, "NetLocalGroupGetInfo"); pNetLocalGroupGetMembers=(void*)GetProcAddress(hnetapi32, "NetLocalGroupGetMembers"); pDavGetHTTPFromUNCPath = (void*)GetProcAddress(hnetapi32, "DavGetHTTPFromUNCPath"); + pDavGetUNCFromHTTPPath = (void*)GetProcAddress(hnetapi32, "DavGetUNCFromHTTPPath"); /* These functions were introduced with NT. It's safe to assume that * if one is not available, none are. @@ -583,5 +735,6 @@ START_TEST(access) } test_DavGetHTTPFromUNCPath(); + test_DavGetUNCFromHTTPPath(); FreeLibrary(hnetapi32); } diff --git a/include/davclnt.h b/include/davclnt.h index dbb25ee9c42..77c22e0762e 100644 --- a/include/davclnt.h +++ b/include/davclnt.h @@ -66,6 +66,7 @@ typedef DWORD (*PFNDAVAUTHCALLBACK) (LPWSTR,LPWSTR,DWORD,DWORD,PDAV_CALLBACK_CRED,AUTHNEXTSTEP*,PFNDAVAUTHCALLBACK_FREECRED*); DWORD WINAPI DavGetHTTPFromUNCPath(LPCWSTR,LPWSTR,LPDWORD); +DWORD WINAPI DavGetUNCFromHTTPPath(LPCWSTR,LPWSTR,LPDWORD); OPAQUE_HANDLE WINAPI DavRegisterAuthCallback(PFNDAVAUTHCALLBACK,ULONG); VOID WINAPI DavUnregisterAuthCallback(OPAQUE_HANDLE);