From ef3e0ddadc2ece549e7e286301f9310b875a3fd4 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Mon, 1 Feb 2016 21:59:47 +0000 Subject: [PATCH] [MPR] Time to (re)act! Step 1/2: - Implement WNetUseConnectionA() as a simple forwarder to WNetUseConnectionW(). This function should make it somehow, somewhen to Wine. Feel free to help the process by lighting cierges. - Halplement WNetUseConnectionW() to match a really specific case: it can handle requests from VBoxTray and pass them properly to VBox NP. In its current state, this function isn't to be shared with Wine. Other calls (specifically without local path, nor network provider) aren't handled and will lead to an error. But, in itself, this commit obsoletes rosvboxmgmt by making ReactOS able to autostart (on VBoxTray demand :-)) the VBox shared folders. Furthermore, if you ask for a drive letter to be assigned to your shared folder, it will happen! Now, in order to use VBox shared folders, just configure VBox to assign them a drive letter, install ReactOS, install VBox Guest Additions... Profit! CORE-10032 ROSAPPS-303 svn path=/trunk/; revision=70670 --- reactos/dll/win32/mpr/mpr_ros.diff | 192 +++++++++++++++++++++++++++++ reactos/dll/win32/mpr/wnet.c | 165 +++++++++++++++++++++++-- 2 files changed, 347 insertions(+), 10 deletions(-) diff --git a/reactos/dll/win32/mpr/mpr_ros.diff b/reactos/dll/win32/mpr/mpr_ros.diff index 82eb990fbca..95b5ca4c7f9 100644 --- a/reactos/dll/win32/mpr/mpr_ros.diff +++ b/reactos/dll/win32/mpr/mpr_ros.diff @@ -45,3 +45,195 @@ Index: mpr.spec 22 stdcall @(long) MPR_Alloc 23 stdcall @(ptr long) MPR_ReAlloc 24 stdcall @(ptr) MPR_Free +Index: wnet.c +=================================================================== +--- wnet.c (révision 70645) ++++ wnet.c (copie de travail) +@@ -1549,6 +1549,33 @@ + dwFlags, NULL, 0, NULL); + } + ++/* Convert an ANSI string to wide */ ++static LPWSTR strdupAtoW( LPCSTR str ) ++{ ++ LPWSTR ret; ++ INT len; ++ ++ if (!str) return NULL; ++ len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); ++ ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); ++ if (ret) MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); ++ return ret; ++} ++ ++/* Convert ANSI NETRESOURCE struct to wide structure */ ++static VOID convert_netresourcea_to_w( LPNETRESOURCEA lpNetResourceA, ++ LPNETRESOURCEW lpNetResourceW ) ++{ ++ lpNetResourceW->dwScope = lpNetResourceA->dwScope; ++ lpNetResourceW->dwType = lpNetResourceA->dwType; ++ lpNetResourceW->dwDisplayType = lpNetResourceA->dwDisplayType; ++ lpNetResourceW->dwUsage = lpNetResourceA->dwUsage; ++ lpNetResourceW->lpLocalName = strdupAtoW(lpNetResourceA->lpLocalName); ++ lpNetResourceW->lpRemoteName = strdupAtoW(lpNetResourceA->lpRemoteName); ++ lpNetResourceW->lpComment = strdupAtoW(lpNetResourceA->lpComment); ++ lpNetResourceW->lpProvider = strdupAtoW(lpNetResourceA->lpProvider); ++} ++ + /***************************************************************** + * WNetUseConnectionA [MPR.@] + */ +@@ -1557,12 +1584,67 @@ + LPSTR lpAccessName, LPDWORD lpBufferSize, + LPDWORD lpResult ) + { +- FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n", +- hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags, +- debugstr_a(lpAccessName), lpBufferSize, lpResult ); ++ NETRESOURCEW resourcesW, *pRes = NULL; ++ PWSTR passW, userIDW, accessNameW = NULL; ++ DWORD ret = WN_MORE_DATA; ++ DWORD bufferSize = 1; ++ int len; + +- SetLastError(WN_NO_NETWORK); +- return WN_NO_NETWORK; ++ if (lpNetResource) ++ { ++ convert_netresourcea_to_w(lpNetResource, &resourcesW); ++ pRes = &resourcesW; ++ } ++ ++ passW = strdupAtoW(lpPassword); ++ userIDW = strdupAtoW(lpUserID); ++ ++ if (lpAccessName && lpBufferSize && *lpBufferSize) ++ { ++ WCHAR probe; ++ ++ ret = WNetUseConnectionW(hwndOwner, pRes, passW, userIDW, dwFlags, ++ &probe, &bufferSize, lpResult); ++ if (ret == WN_MORE_DATA) ++ accessNameW = HeapAlloc(GetProcessHeap(), 0, bufferSize * sizeof(WCHAR)); ++ } ++ ++ if (ret == WN_MORE_DATA) ++ { ++ ret = WNetUseConnectionW(hwndOwner, pRes, passW, userIDW, dwFlags, ++ accessNameW, &bufferSize, lpResult); ++ if (ret == WN_SUCCESS) ++ { ++ if (lpAccessName && lpBufferSize && *lpBufferSize && accessNameW) ++ { ++ len = WideCharToMultiByte(CP_ACP, 0, accessNameW, -1, NULL, 0, NULL, NULL); ++ if (len) ++ { ++ if (len <= *lpBufferSize) ++ WideCharToMultiByte(CP_ACP, 0, accessNameW, -1, lpAccessName, len, NULL, NULL); ++ else ++ { ++ WNetCancelConnectionW(accessNameW, TRUE); ++ *lpBufferSize = len; ++ ret = WN_MORE_DATA; ++ } ++ } ++ } ++ } ++ } ++ ++ if (lpNetResource) ++ { ++ HeapFree(GetProcessHeap(), 0, resourcesW.lpLocalName); ++ HeapFree(GetProcessHeap(), 0, resourcesW.lpRemoteName); ++ HeapFree(GetProcessHeap(), 0, resourcesW.lpComment); ++ HeapFree(GetProcessHeap(), 0, resourcesW.lpProvider); ++ } ++ HeapFree(GetProcessHeap(), 0, passW); ++ HeapFree(GetProcessHeap(), 0, userIDW); ++ HeapFree(GetProcessHeap(), 0, accessNameW); ++ ++ return ret; + } + + /***************************************************************** +@@ -1573,12 +1655,75 @@ + LPWSTR lpAccessName, LPDWORD lpBufferSize, + LPDWORD lpResult ) + { +- FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n", +- hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags, +- debugstr_w(lpAccessName), lpBufferSize, lpResult ); ++ DWORD provider; ++ DWORD cap; ++ char id; ++ DWORD drives; ++ DWORD ret; ++ PF_NPAddConnection3 addConn3; ++ PF_NPAddConnection addConn; + +- SetLastError(WN_NO_NETWORK); +- return WN_NO_NETWORK; ++ if (!providerTable || providerTable->numProviders == 0) { ++ SetLastError(WN_NO_NETWORK); ++ return WN_NO_NETWORK; ++ } ++ ++ if (!lpNetResource) { ++ SetLastError(ERROR_INVALID_PARAMETER); ++ return ERROR_INVALID_PARAMETER; ++ } ++ ++ if (!lpNetResource->lpProvider || !*lpNetResource->lpProvider) { ++ SetLastError(ERROR_BAD_PROVIDER); ++ return ERROR_BAD_PROVIDER; ++ } ++ ++ if (!lpNetResource->lpLocalName || !*lpNetResource->lpLocalName) { ++ SetLastError(ERROR_BAD_DEVICE); ++ return ERROR_BAD_DEVICE; ++ } ++ ++ if ((!(lpNetResource->lpLocalName[0] >= 'a' && lpNetResource->lpLocalName[0] <= 'z') && ++ !(lpNetResource->lpLocalName[0] >= 'A' && lpNetResource->lpLocalName[0] <= 'Z')) || ++ lpNetResource->lpLocalName[1] != ':' || lpNetResource->lpLocalName[2]) { ++ SetLastError(ERROR_BAD_DEVICE); ++ return ERROR_BAD_DEVICE; ++ } ++ ++ id = (lpNetResource->lpLocalName[0] >= 'a') ? lpNetResource->lpLocalName[0] - 'a' : lpNetResource->lpLocalName[0] - 'A'; ++ drives = GetLogicalDrives(); ++ if (drives & (1 << id)) { ++ SetLastError(ERROR_ALREADY_ASSIGNED); ++ return ERROR_ALREADY_ASSIGNED; ++ } ++ ++ provider = _findProviderIndexW(lpNetResource->lpProvider); ++ if (provider == BAD_PROVIDER_INDEX) { ++ SetLastError(ERROR_BAD_PROVIDER); ++ return ERROR_BAD_PROVIDER; ++ } ++ ++ cap = providerTable->table[provider].getCaps(WNNC_CONNECTION); ++ if (!(cap & WNNC_CON_ADDCONNECTION) && !(cap & WNNC_CON_ADDCONNECTION3)) { ++ SetLastError(ERROR_BAD_PROVIDER); ++ return ERROR_BAD_PROVIDER; ++ } ++ ++ ret = WN_ACCESS_DENIED; ++ if (cap & WNNC_CON_ADDCONNECTION3) { ++ addConn3 = (PF_NPAddConnection3)GetProcAddress(providerTable->table[provider].hLib, "NPAddConnection3"); ++ if (addConn3) { ++ ret = addConn3(hwndOwner, lpNetResource, (LPWSTR)lpPassword, (LPWSTR)lpUserID, dwFlags); ++ } ++ } ++ else if (cap & WNNC_CON_ADDCONNECTION) { ++ addConn = (PF_NPAddConnection)GetProcAddress(providerTable->table[provider].hLib, "NPAddConnection"); ++ if (addConn) { ++ ret = addConn(lpNetResource, (LPWSTR)lpPassword, (LPWSTR)lpUserID); ++ } ++ } ++ ++ return ret; + } + + /********************************************************************* diff --git a/reactos/dll/win32/mpr/wnet.c b/reactos/dll/win32/mpr/wnet.c index 5e140236a08..4c6f9299f59 100644 --- a/reactos/dll/win32/mpr/wnet.c +++ b/reactos/dll/win32/mpr/wnet.c @@ -1549,6 +1549,33 @@ DWORD WINAPI WNetAddConnection3W( HWND hwndOwner, LPNETRESOURCEW lpNetResource, dwFlags, NULL, 0, NULL); } +/* Convert an ANSI string to wide */ +static LPWSTR strdupAtoW( LPCSTR str ) +{ + LPWSTR ret; + INT len; + + if (!str) return NULL; + len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + if (ret) MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); + return ret; +} + +/* Convert ANSI NETRESOURCE struct to wide structure */ +static VOID convert_netresourcea_to_w( LPNETRESOURCEA lpNetResourceA, + LPNETRESOURCEW lpNetResourceW ) +{ + lpNetResourceW->dwScope = lpNetResourceA->dwScope; + lpNetResourceW->dwType = lpNetResourceA->dwType; + lpNetResourceW->dwDisplayType = lpNetResourceA->dwDisplayType; + lpNetResourceW->dwUsage = lpNetResourceA->dwUsage; + lpNetResourceW->lpLocalName = strdupAtoW(lpNetResourceA->lpLocalName); + lpNetResourceW->lpRemoteName = strdupAtoW(lpNetResourceA->lpRemoteName); + lpNetResourceW->lpComment = strdupAtoW(lpNetResourceA->lpComment); + lpNetResourceW->lpProvider = strdupAtoW(lpNetResourceA->lpProvider); +} + /***************************************************************** * WNetUseConnectionA [MPR.@] */ @@ -1557,12 +1584,67 @@ DWORD WINAPI WNetUseConnectionA( HWND hwndOwner, LPNETRESOURCEA lpNetResource, LPSTR lpAccessName, LPDWORD lpBufferSize, LPDWORD lpResult ) { - FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n", - hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags, - debugstr_a(lpAccessName), lpBufferSize, lpResult ); + NETRESOURCEW resourcesW, *pRes = NULL; + PWSTR passW, userIDW, accessNameW = NULL; + DWORD ret = WN_MORE_DATA; + DWORD bufferSize = 1; + int len; - SetLastError(WN_NO_NETWORK); - return WN_NO_NETWORK; + if (lpNetResource) + { + convert_netresourcea_to_w(lpNetResource, &resourcesW); + pRes = &resourcesW; + } + + passW = strdupAtoW(lpPassword); + userIDW = strdupAtoW(lpUserID); + + if (lpAccessName && lpBufferSize && *lpBufferSize) + { + WCHAR probe; + + ret = WNetUseConnectionW(hwndOwner, pRes, passW, userIDW, dwFlags, + &probe, &bufferSize, lpResult); + if (ret == WN_MORE_DATA) + accessNameW = HeapAlloc(GetProcessHeap(), 0, bufferSize * sizeof(WCHAR)); + } + + if (ret == WN_MORE_DATA) + { + ret = WNetUseConnectionW(hwndOwner, pRes, passW, userIDW, dwFlags, + accessNameW, &bufferSize, lpResult); + if (ret == WN_SUCCESS) + { + if (lpAccessName && lpBufferSize && *lpBufferSize && accessNameW) + { + len = WideCharToMultiByte(CP_ACP, 0, accessNameW, -1, NULL, 0, NULL, NULL); + if (len) + { + if (len <= *lpBufferSize) + WideCharToMultiByte(CP_ACP, 0, accessNameW, -1, lpAccessName, len, NULL, NULL); + else + { + WNetCancelConnectionW(accessNameW, TRUE); + *lpBufferSize = len; + ret = WN_MORE_DATA; + } + } + } + } + } + + if (lpNetResource) + { + HeapFree(GetProcessHeap(), 0, resourcesW.lpLocalName); + HeapFree(GetProcessHeap(), 0, resourcesW.lpRemoteName); + HeapFree(GetProcessHeap(), 0, resourcesW.lpComment); + HeapFree(GetProcessHeap(), 0, resourcesW.lpProvider); + } + HeapFree(GetProcessHeap(), 0, passW); + HeapFree(GetProcessHeap(), 0, userIDW); + HeapFree(GetProcessHeap(), 0, accessNameW); + + return ret; } /***************************************************************** @@ -1573,12 +1655,75 @@ DWORD WINAPI WNetUseConnectionW( HWND hwndOwner, LPNETRESOURCEW lpNetResource, LPWSTR lpAccessName, LPDWORD lpBufferSize, LPDWORD lpResult ) { - FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n", - hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags, - debugstr_w(lpAccessName), lpBufferSize, lpResult ); + DWORD provider; + DWORD cap; + char id; + DWORD drives; + DWORD ret; + PF_NPAddConnection3 addConn3; + PF_NPAddConnection addConn; - SetLastError(WN_NO_NETWORK); - return WN_NO_NETWORK; + if (!providerTable || providerTable->numProviders == 0) { + SetLastError(WN_NO_NETWORK); + return WN_NO_NETWORK; + } + + if (!lpNetResource) { + SetLastError(ERROR_INVALID_PARAMETER); + return ERROR_INVALID_PARAMETER; + } + + if (!lpNetResource->lpProvider || !*lpNetResource->lpProvider) { + SetLastError(ERROR_BAD_PROVIDER); + return ERROR_BAD_PROVIDER; + } + + if (!lpNetResource->lpLocalName || !*lpNetResource->lpLocalName) { + SetLastError(ERROR_BAD_DEVICE); + return ERROR_BAD_DEVICE; + } + + if ((!(lpNetResource->lpLocalName[0] >= 'a' && lpNetResource->lpLocalName[0] <= 'z') && + !(lpNetResource->lpLocalName[0] >= 'A' && lpNetResource->lpLocalName[0] <= 'Z')) || + lpNetResource->lpLocalName[1] != ':' || lpNetResource->lpLocalName[2]) { + SetLastError(ERROR_BAD_DEVICE); + return ERROR_BAD_DEVICE; + } + + id = (lpNetResource->lpLocalName[0] >= 'a') ? lpNetResource->lpLocalName[0] - 'a' : lpNetResource->lpLocalName[0] - 'A'; + drives = GetLogicalDrives(); + if (drives & (1 << id)) { + SetLastError(ERROR_ALREADY_ASSIGNED); + return ERROR_ALREADY_ASSIGNED; + } + + provider = _findProviderIndexW(lpNetResource->lpProvider); + if (provider == BAD_PROVIDER_INDEX) { + SetLastError(ERROR_BAD_PROVIDER); + return ERROR_BAD_PROVIDER; + } + + cap = providerTable->table[provider].getCaps(WNNC_CONNECTION); + if (!(cap & WNNC_CON_ADDCONNECTION) && !(cap & WNNC_CON_ADDCONNECTION3)) { + SetLastError(ERROR_BAD_PROVIDER); + return ERROR_BAD_PROVIDER; + } + + ret = WN_ACCESS_DENIED; + if (cap & WNNC_CON_ADDCONNECTION3) { + addConn3 = (PF_NPAddConnection3)GetProcAddress(providerTable->table[provider].hLib, "NPAddConnection3"); + if (addConn3) { + ret = addConn3(hwndOwner, lpNetResource, (LPWSTR)lpPassword, (LPWSTR)lpUserID, dwFlags); + } + } + else if (cap & WNNC_CON_ADDCONNECTION) { + addConn = (PF_NPAddConnection)GetProcAddress(providerTable->table[provider].hLib, "NPAddConnection"); + if (addConn) { + ret = addConn(lpNetResource, (LPWSTR)lpPassword, (LPWSTR)lpUserID); + } + } + + return ret; } /*********************************************************************