[MPR]
[reactos.git] / reactos / dll / win32 / mpr / wnet.c
index 4c6f929..6446862 100644 (file)
@@ -46,6 +46,11 @@ typedef struct _WNetProvider
     PF_NPEnumResource enumResource;
     PF_NPCloseEnum    closeEnum;
     PF_NPGetResourceInformation getResourceInformation;
+    PF_NPAddConnection addConnection;
+    PF_NPAddConnection3 addConnection3;
+#ifdef __REACTOS__
+    PF_NPGetConnection getConnection;
+#endif
 } WNetProvider, *PWNetProvider;
 
 typedef struct _WNetProviderTable
@@ -152,8 +157,9 @@ static void _tryLoadProvider(PCWSTR provider)
 
                 if (hLib)
                 {
-                    PF_NPGetCaps getCaps = (PF_NPGetCaps)GetProcAddress(hLib,
-                     "NPGetCaps");
+#define MPR_GETPROC(proc) ((PF_##proc)GetProcAddress(hLib, #proc))
+
+                    PF_NPGetCaps getCaps = MPR_GETPROC(NPGetCaps);
 
                     TRACE("loaded lib %p\n", hLib);
                     if (getCaps)
@@ -172,22 +178,17 @@ static void _tryLoadProvider(PCWSTR provider)
                         if (provider->dwEnumScopes)
                         {
                             TRACE("supports enumeration\n");
-                            provider->openEnum = (PF_NPOpenEnum)
-                             GetProcAddress(hLib, "NPOpenEnum");
-                            TRACE("openEnum is %p\n", provider->openEnum);
-                            provider->enumResource = (PF_NPEnumResource)
-                             GetProcAddress(hLib, "NPEnumResource");
-                            TRACE("enumResource is %p\n",
-                             provider->enumResource);
-                            provider->closeEnum = (PF_NPCloseEnum)
-                             GetProcAddress(hLib, "NPCloseEnum");
-                            TRACE("closeEnum is %p\n", provider->closeEnum);
-                            provider->getResourceInformation = (PF_NPGetResourceInformation)
-                                    GetProcAddress(hLib, "NPGetResourceInformation");
-                            TRACE("getResourceInformation is %p\n",
-                                  provider->getResourceInformation);
-                            if (!provider->openEnum || !provider->enumResource
-                             || !provider->closeEnum)
+                            provider->openEnum = MPR_GETPROC(NPOpenEnum);
+                            TRACE("NPOpenEnum %p\n", provider->openEnum);
+                            provider->enumResource = MPR_GETPROC(NPEnumResource);
+                            TRACE("NPEnumResource %p\n", provider->enumResource);
+                            provider->closeEnum = MPR_GETPROC(NPCloseEnum);
+                            TRACE("NPCloseEnum %p\n", provider->closeEnum);
+                            provider->getResourceInformation = MPR_GETPROC(NPGetResourceInformation);
+                            TRACE("NPGetResourceInformation %p\n", provider->getResourceInformation);
+                            if (!provider->openEnum ||
+                                !provider->enumResource ||
+                                !provider->closeEnum)
                             {
                                 provider->openEnum = NULL;
                                 provider->enumResource = NULL;
@@ -196,6 +197,13 @@ static void _tryLoadProvider(PCWSTR provider)
                                 WARN("Couldn't load enumeration functions\n");
                             }
                         }
+                        provider->addConnection = MPR_GETPROC(NPAddConnection);
+                        provider->addConnection3 = MPR_GETPROC(NPAddConnection3);
+#ifdef __REACTOS__
+                        provider->getConnection = MPR_GETPROC(NPGetConnection);
+#endif
+                        TRACE("NPAddConnection %p\n", provider->addConnection);
+                        TRACE("NPAddConnection3 %p\n", provider->addConnection3);
                         providerTable->numProviders++;
                     }
                     else
@@ -205,6 +213,8 @@ static void _tryLoadProvider(PCWSTR provider)
                         HeapFree(GetProcessHeap(), 0, name);
                         FreeLibrary(hLib);
                     }
+
+#undef MPR_GETPROC
                 }
                 else
                 {
@@ -746,6 +756,11 @@ DWORD WINAPI WNetOpenEnumW( DWORD dwScope, DWORD dwType, DWORD dwUsage,
                              providerTable->table[index].dwEnumScopes & WNNC_ENUM_GLOBAL)
                             {
                                 HANDLE handle;
+                                PWSTR RemoteName = lpNet->lpRemoteName;
+
+                                if ((lpNet->dwUsage & RESOURCEUSAGE_CONTAINER) &&
+                                    RemoteName && !strcmpW(RemoteName, lpNet->lpProvider))
+                                    lpNet->lpRemoteName = NULL;
 
                                 ret = providerTable->table[index].openEnum(
                                  dwScope, dwType, dwUsage, lpNet, &handle);
@@ -756,6 +771,8 @@ DWORD WINAPI WNetOpenEnumW( DWORD dwScope, DWORD dwType, DWORD dwUsage,
                                     ret = *lphEnum ? WN_SUCCESS :
                                      WN_OUT_OF_MEMORY;
                                 }
+
+                                lpNet->lpRemoteName = RemoteName;
                             }
                             else
                                 ret = WN_NOT_SUPPORTED;
@@ -1549,179 +1566,314 @@ DWORD WINAPI WNetAddConnection3W( HWND hwndOwner, LPNETRESOURCEW lpNetResource,
                               dwFlags, NULL, 0, NULL);
 }
 
-/* Convert an ANSI string to wide */
-static LPWSTR strdupAtoW( LPCSTR str )
+struct use_connection_context
 {
-    LPWSTR ret;
-    INT len;
+    HWND hwndOwner;
+    NETRESOURCEW *resource;
+    NETRESOURCEA *resourceA; /* only set for WNetUseConnectionA */
+    WCHAR *password;
+    WCHAR *userid;
+    DWORD flags;
+    void *accessname;
+    DWORD *buffer_size;
+    DWORD *result;
+    DWORD (*pre_set_accessname)(struct use_connection_context*);
+    void  (*set_accessname)(struct use_connection_context*);
+};
 
-    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;
+static DWORD use_connection_pre_set_accessnameW(struct use_connection_context *ctxt)
+{
+    if (ctxt->accessname && ctxt->buffer_size && *ctxt->buffer_size)
+    {
+        DWORD len;
+
+        if (ctxt->resource->lpLocalName)
+            len = strlenW(ctxt->resource->lpLocalName);
+        else
+            len = strlenW(ctxt->resource->lpRemoteName);
+
+        if (++len > *ctxt->buffer_size)
+        {
+            *ctxt->buffer_size = len;
+            return ERROR_MORE_DATA;
+        }
+    }
+    else
+        ctxt->accessname = NULL;
+
+    return ERROR_SUCCESS;
 }
 
-/* Convert ANSI NETRESOURCE struct to wide structure */
-static VOID convert_netresourcea_to_w( LPNETRESOURCEA lpNetResourceA,
-                                       LPNETRESOURCEW lpNetResourceW )
+static void use_connection_set_accessnameW(struct use_connection_context *ctxt)
 {
-    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);
+    WCHAR *accessname = ctxt->accessname;
+    if (ctxt->resource->lpLocalName)
+        strcpyW(accessname, ctxt->resource->lpLocalName);
+    else
+        strcpyW(accessname, ctxt->resource->lpRemoteName);
 }
 
-/*****************************************************************
- *  WNetUseConnectionA [MPR.@]
- */
-DWORD WINAPI WNetUseConnectionA( HWND hwndOwner, LPNETRESOURCEA lpNetResource,
-                                 LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags,
-                                 LPSTR lpAccessName, LPDWORD lpBufferSize,
-                                 LPDWORD lpResult )
-{
-    NETRESOURCEW resourcesW, *pRes = NULL;
-    PWSTR passW, userIDW, accessNameW = NULL;
-    DWORD ret = WN_MORE_DATA;
-    DWORD bufferSize = 1;
-    int len;
-
-    if (lpNetResource)
-    {
-        convert_netresourcea_to_w(lpNetResource, &resourcesW);
-        pRes = &resourcesW;
-    }
-
-    passW = strdupAtoW(lpPassword);
-    userIDW = strdupAtoW(lpUserID);
+static WCHAR * select_provider(struct use_connection_context *ctxt)
+{
+    DWORD ret, prov_size = 0x1000, len;
+    LPNETRESOURCEW provider;
+    WCHAR * system;
 
-    if (lpAccessName && lpBufferSize && *lpBufferSize)
+    provider = HeapAlloc(GetProcessHeap(), 0, prov_size);
+    if (!provider)
     {
-        WCHAR probe;
-
-        ret = WNetUseConnectionW(hwndOwner, pRes, passW, userIDW, dwFlags,
-                                 &probe, &bufferSize, lpResult);
-        if (ret == WN_MORE_DATA)
-            accessNameW = HeapAlloc(GetProcessHeap(), 0, bufferSize * sizeof(WCHAR));
+        return NULL;
     }
 
-    if (ret == WN_MORE_DATA)
+    ret = WNetGetResourceInformationW(ctxt->resource, provider, &prov_size, &system);
+    if (ret == ERROR_MORE_DATA)
     {
-        ret = WNetUseConnectionW(hwndOwner, pRes, passW, userIDW, dwFlags,
-                                 accessNameW, &bufferSize, lpResult);
-        if (ret == WN_SUCCESS)
+        HeapFree(GetProcessHeap(), 0, provider);
+        provider = HeapAlloc(GetProcessHeap(), 0, prov_size);
+        if (!provider)
         {
-            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;
-                    }
-                }
-            }
+            return NULL;
         }
+
+        ret = WNetGetResourceInformationW(ctxt->resource, provider, &prov_size, &system);
     }
 
-    if (lpNetResource)
+    if (ret != NO_ERROR)
     {
-        HeapFree(GetProcessHeap(), 0, resourcesW.lpLocalName);
-        HeapFree(GetProcessHeap(), 0, resourcesW.lpRemoteName);
-        HeapFree(GetProcessHeap(), 0, resourcesW.lpComment);
-        HeapFree(GetProcessHeap(), 0, resourcesW.lpProvider);
+        HeapFree(GetProcessHeap(), 0, provider);
+        return NULL;
     }
-    HeapFree(GetProcessHeap(), 0, passW);
-    HeapFree(GetProcessHeap(), 0, userIDW);
-    HeapFree(GetProcessHeap(), 0, accessNameW);
 
-    return ret;
+    len = WideCharToMultiByte(CP_ACP, 0, provider->lpProvider, -1, NULL, 0, NULL, NULL);
+    ctxt->resource->lpProvider = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+    if (ctxt->resource->lpProvider)
+        memcpy(ctxt->resource->lpProvider, provider->lpProvider, len * sizeof(WCHAR));
+
+    HeapFree(GetProcessHeap(), 0, provider);
+
+    return ctxt->resource->lpProvider;
 }
 
-/*****************************************************************
- *  WNetUseConnectionW [MPR.@]
- */
-DWORD WINAPI WNetUseConnectionW( HWND hwndOwner, LPNETRESOURCEW lpNetResource,
-                                 LPCWSTR lpPassword, LPCWSTR lpUserID, DWORD dwFlags,
-                                 LPWSTR lpAccessName, LPDWORD lpBufferSize,
-                                 LPDWORD lpResult )
-{
-    DWORD provider;
-    DWORD cap;
-    char id;
-    DWORD drives;
-    DWORD ret;
-    PF_NPAddConnection3 addConn3;
-    PF_NPAddConnection addConn;
+static DWORD wnet_use_connection( struct use_connection_context *ctxt )
+{
+    WNetProvider *provider;
+    DWORD index, ret, caps;
+    BOOLEAN redirect = FALSE, prov = FALSE;
+    WCHAR letter[3] = {'z', ':', 0};
 
-    if (!providerTable || providerTable->numProviders == 0) {
-        SetLastError(WN_NO_NETWORK);
+    if (!providerTable || providerTable->numProviders == 0)
         return WN_NO_NETWORK;
-    }
 
-    if (!lpNetResource) {
-        SetLastError(ERROR_INVALID_PARAMETER);
+    if (!ctxt->resource)
         return ERROR_INVALID_PARAMETER;
-    }
 
-    if (!lpNetResource->lpProvider || !*lpNetResource->lpProvider) {
-        SetLastError(ERROR_BAD_PROVIDER);
-        return ERROR_BAD_PROVIDER;
+    if (!ctxt->resource->lpLocalName && (ctxt->flags & CONNECT_REDIRECT))
+    {
+        if (ctxt->resource->dwType != RESOURCETYPE_DISK && ctxt->resource->dwType != RESOURCETYPE_PRINT)
+        {
+            return ERROR_BAD_DEV_TYPE;
+        }
+
+        if (ctxt->resource->dwType == RESOURCETYPE_PRINT)
+        {
+            FIXME("Locale device selection is not implemented for printers.\n");
+            return WN_NO_NETWORK;
+        }
+
+        redirect = TRUE;
+        ctxt->resource->lpLocalName = letter;
     }
 
-    if (!lpNetResource->lpLocalName || !*lpNetResource->lpLocalName) {
-        SetLastError(ERROR_BAD_DEVICE);
-        return ERROR_BAD_DEVICE;
+    if (ctxt->flags & CONNECT_INTERACTIVE)
+    {
+        ret = ERROR_BAD_NET_NAME;
+        goto done;
     }
 
-    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;
+    if (!ctxt->resource->lpProvider)
+    {
+        ctxt->resource->lpProvider = select_provider(ctxt);
+        if (!ctxt->resource->lpProvider)
+        {
+            ret = ERROR_NO_NET_OR_BAD_PATH;
+            goto done;
+        }
+
+        prov = TRUE;
     }
 
-    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;
+    index = _findProviderIndexW(ctxt->resource->lpProvider);
+    if (index == BAD_PROVIDER_INDEX)
+    {
+        ret = ERROR_BAD_PROVIDER;
+        goto done;
     }
 
-    provider = _findProviderIndexW(lpNetResource->lpProvider);
-    if (provider == BAD_PROVIDER_INDEX) {
-        SetLastError(ERROR_BAD_PROVIDER);
-        return ERROR_BAD_PROVIDER;
+    provider = &providerTable->table[index];
+    caps = provider->getCaps(WNNC_CONNECTION);
+    if (!(caps & (WNNC_CON_ADDCONNECTION | WNNC_CON_ADDCONNECTION3)))
+    {
+        ret = ERROR_BAD_PROVIDER;
+        goto done;
     }
 
-    cap = providerTable->table[provider].getCaps(WNNC_CONNECTION);
-    if (!(cap & WNNC_CON_ADDCONNECTION) && !(cap & WNNC_CON_ADDCONNECTION3)) {
-        SetLastError(ERROR_BAD_PROVIDER);
-        return ERROR_BAD_PROVIDER;
+    if ((ret = ctxt->pre_set_accessname(ctxt)))
+    {
+        goto done;
     }
 
     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);
-        }
+    do
+    {
+        if ((caps & WNNC_CON_ADDCONNECTION3) && provider->addConnection3)
+            ret = provider->addConnection3(ctxt->hwndOwner, ctxt->resource, ctxt->password, ctxt->userid, ctxt->flags);
+        else if ((caps & WNNC_CON_ADDCONNECTION) && provider->addConnection)
+            ret = provider->addConnection(ctxt->resource, ctxt->password, ctxt->userid);
+
+        if (redirect)
+            letter[0] -= 1;
+    } while (redirect && ret == WN_ALREADY_CONNECTED && letter[0] >= 'c');
+
+    if (ret == WN_SUCCESS && ctxt->accessname)
+        ctxt->set_accessname(ctxt);
+
+done:
+    if (prov)
+    {
+        HeapFree(GetProcessHeap(), 0, ctxt->resource->lpProvider);
+        ctxt->resource->lpProvider = NULL;
     }
-    else if (cap & WNNC_CON_ADDCONNECTION) {
-        addConn = (PF_NPAddConnection)GetProcAddress(providerTable->table[provider].hLib, "NPAddConnection");
-        if (addConn) {
-            ret = addConn(lpNetResource, (LPWSTR)lpPassword, (LPWSTR)lpUserID);
+
+    if (redirect)
+        ctxt->resource->lpLocalName = NULL;
+
+    return ret;
+}
+
+/*****************************************************************
+ *  WNetUseConnectionW [MPR.@]
+ */
+DWORD WINAPI WNetUseConnectionW( HWND hwndOwner, NETRESOURCEW *resource, LPCWSTR password,
+    LPCWSTR userid, DWORD flags, LPWSTR accessname, DWORD *buffer_size, DWORD *result )
+{
+    struct use_connection_context ctxt;
+
+    TRACE( "(%p, %p, %p, %s, 0x%08X, %p, %p, %p)\n",
+           hwndOwner, resource, password, debugstr_w(userid), flags,
+           accessname, buffer_size, result );
+
+    ctxt.hwndOwner = hwndOwner;
+    ctxt.resource = resource;
+    ctxt.resourceA = NULL;
+    ctxt.password = (WCHAR*)password;
+    ctxt.userid = (WCHAR*)userid;
+    ctxt.flags = flags;
+    ctxt.accessname = accessname;
+    ctxt.buffer_size = buffer_size;
+    ctxt.result = result;
+    ctxt.pre_set_accessname = use_connection_pre_set_accessnameW;
+    ctxt.set_accessname = use_connection_set_accessnameW;
+
+    return wnet_use_connection(&ctxt);
+}
+
+static DWORD use_connection_pre_set_accessnameA(struct use_connection_context *ctxt)
+{
+    if (ctxt->accessname && ctxt->buffer_size && *ctxt->buffer_size)
+    {
+        DWORD len;
+
+        if (ctxt->resourceA->lpLocalName)
+            len = strlen(ctxt->resourceA->lpLocalName);
+        else
+            len = strlen(ctxt->resourceA->lpRemoteName);
+
+        if (++len > *ctxt->buffer_size)
+        {
+            *ctxt->buffer_size = len;
+            return ERROR_MORE_DATA;
         }
     }
+    else
+        ctxt->accessname = NULL;
+
+    return ERROR_SUCCESS;
+}
+
+static void use_connection_set_accessnameA(struct use_connection_context *ctxt)
+{
+    char *accessname = ctxt->accessname;
+    if (ctxt->resourceA->lpLocalName)
+        strcpy(accessname, ctxt->resourceA->lpLocalName);
+    else
+        strcpy(accessname, ctxt->resourceA->lpRemoteName);
+}
+
+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;
+}
+
+static void netresource_a_to_w( NETRESOURCEA *resourceA, NETRESOURCEW *resourceW )
+{
+    resourceW->dwScope = resourceA->dwScope;
+    resourceW->dwType = resourceA->dwType;
+    resourceW->dwDisplayType = resourceA->dwDisplayType;
+    resourceW->dwUsage = resourceA->dwUsage;
+    resourceW->lpLocalName = strdupAtoW(resourceA->lpLocalName);
+    resourceW->lpRemoteName = strdupAtoW(resourceA->lpRemoteName);
+    resourceW->lpComment = strdupAtoW(resourceA->lpComment);
+    resourceW->lpProvider = strdupAtoW(resourceA->lpProvider);
+}
+
+static void free_netresourceW( NETRESOURCEW *resource )
+{
+    HeapFree(GetProcessHeap(), 0, resource->lpLocalName);
+    HeapFree(GetProcessHeap(), 0, resource->lpRemoteName);
+    HeapFree(GetProcessHeap(), 0, resource->lpComment);
+    HeapFree(GetProcessHeap(), 0, resource->lpProvider);
+}
+
+/*****************************************************************
+ *  WNetUseConnectionA [MPR.@]
+ */
+DWORD WINAPI WNetUseConnectionA( HWND hwndOwner, NETRESOURCEA *resource,
+    LPCSTR password, LPCSTR userid, DWORD flags, LPSTR accessname,
+    DWORD *buffer_size, DWORD *result )
+{
+    struct use_connection_context ctxt;
+    NETRESOURCEW resourceW;
+    DWORD ret;
+
+    TRACE( "(%p, %p, %p, %s, 0x%08X, %p, %p, %p)\n", hwndOwner, resource, password, debugstr_a(userid), flags,
+        accessname, buffer_size, result );
+
+    netresource_a_to_w(resource, &resourceW);
+
+    ctxt.hwndOwner = hwndOwner;
+    ctxt.resource = &resourceW;
+    ctxt.resourceA = resource;
+    ctxt.password = strdupAtoW(password);
+    ctxt.userid = strdupAtoW(userid);
+    ctxt.flags = flags;
+    ctxt.accessname = accessname;
+    ctxt.buffer_size = buffer_size;
+    ctxt.result = result;
+    ctxt.pre_set_accessname = use_connection_pre_set_accessnameA;
+    ctxt.set_accessname = use_connection_set_accessnameA;
+
+    ret = wnet_use_connection(&ctxt);
+
+    free_netresourceW(&resourceW);
+    HeapFree(GetProcessHeap(), 0, ctxt.password);
+    HeapFree(GetProcessHeap(), 0, ctxt.userid);
 
     return ret;
 }
@@ -1890,6 +2042,7 @@ DWORD WINAPI WNetGetConnectionA( LPCSTR lpLocalName,
 /* find the network connection for a given drive; helper for WNetGetConnection */
 static DWORD get_drive_connection( WCHAR letter, LPWSTR remote, LPDWORD size )
 {
+#ifndef __REACTOS__
     char buffer[1024];
     struct mountmgr_unix_drive *data = (struct mountmgr_unix_drive *)buffer;
     HANDLE mgr;
@@ -1932,6 +2085,32 @@ static DWORD get_drive_connection( WCHAR letter, LPWSTR remote, LPDWORD size )
     }
     CloseHandle( mgr );
     return ret;
+#else
+    DWORD ret = WN_NO_NETWORK;
+    DWORD index;
+    WCHAR local[3] = {letter, ':', 0};
+
+    if (providerTable != NULL)
+    {
+        for (index = 0; index < providerTable->numProviders; index++)
+        {
+            if(providerTable->table[index].getCaps(WNNC_CONNECTION) &
+                WNNC_CON_GETCONNECTIONS)
+            {
+                if (providerTable->table[index].getConnection)
+                    ret = providerTable->table[index].getConnection(
+                        local, remote, size);
+                else
+                    ret = WN_NO_NETWORK;
+                if (ret == WN_SUCCESS || ret == WN_MORE_DATA)
+                    break;
+            }
+        }
+    }
+    if (ret)
+        SetLastError(ret);
+    return ret;
+#endif
 }
 
 /**************************************************************************
@@ -2042,7 +2221,7 @@ DWORD WINAPI WNetGetUniversalNameA ( LPCSTR lpLocalPath, DWORD dwInfoLevel,
         break;
     }
     case REMOTE_NAME_INFO_LEVEL:
-        err = WN_NO_NETWORK;
+        err = WN_NOT_CONNECTED;
         break;
 
     default:
@@ -2089,7 +2268,7 @@ DWORD WINAPI WNetGetUniversalNameW ( LPCWSTR lpLocalPath, DWORD dwInfoLevel,
         break;
     }
     case REMOTE_NAME_INFO_LEVEL:
-        err = WN_NOT_CONNECTED;
+        err = WN_NO_NETWORK;
         break;
 
     default: