[PATCH] mpr: Implement WNetUseConnectionA()

Nikolay Sivov nsivov at codeweavers.com
Mon Mar 7 08:08:55 CST 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

A->W conversion is taken from original patch by Pierre Schweitzer; the rest comes
from the idea of sharing common WNetUseConnection logic for A and W variants, while
keeping important error handling order.

 dlls/mpr/wnet.c | 223 ++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 177 insertions(+), 46 deletions(-)

diff --git a/dlls/mpr/wnet.c b/dlls/mpr/wnet.c
index 62e1479..fab91c7 100644
--- a/dlls/mpr/wnet.c
+++ b/dlls/mpr/wnet.c
@@ -1563,57 +1563,80 @@ DWORD WINAPI WNetAddConnection3W( HWND hwndOwner, LPNETRESOURCEW lpNetResource,
                               dwFlags, NULL, 0, NULL);
 }
 
-/*****************************************************************
- *  WNetUseConnectionA [MPR.@]
- */
-DWORD WINAPI WNetUseConnectionA( HWND hwndOwner, LPNETRESOURCEA lpNetResource,
-                                 LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags,
-                                 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 );
+struct use_connection_context
+{
+    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*);
+};
+
+static DWORD use_connection_pre_set_accessnameW(struct use_connection_context *ctxt)
+{
+    if (ctxt->accessname && ctxt->buffer_size && *ctxt->buffer_size)
+    {
+        DWORD len;
 
-    SetLastError(WN_NO_NETWORK);
-    return WN_NO_NETWORK;
+        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;
 }
 
-/*****************************************************************
- *  WNetUseConnectionW [MPR.@]
- */
-DWORD WINAPI WNetUseConnectionW( HWND hwndOwner, NETRESOURCEW *resource, LPCWSTR password,
-    LPCWSTR userid, DWORD flags, LPWSTR accessname, DWORD *buffer_size, DWORD *result )
+static void use_connection_set_accessnameW(struct use_connection_context *ctxt)
+{
+    WCHAR *accessname = ctxt->accessname;
+    if (ctxt->resource->lpLocalName)
+        strcpyW(accessname, ctxt->resource->lpLocalName);
+    else
+        strcpyW(accessname, ctxt->resource->lpRemoteName);
+}
+
+static DWORD wnet_use_connection( struct use_connection_context *ctxt )
 {
     WNetProvider *provider;
     DWORD index, ret, caps;
 
-    TRACE( "(%p, %p, %p, %s, 0x%08X, %p, %p, %p)\n",
-           hwndOwner, resource, password, debugstr_w(userid), flags,
-           accessname, buffer_size, result );
-
     if (!providerTable || providerTable->numProviders == 0)
         return WN_NO_NETWORK;
 
-    if (!resource)
+    if (!ctxt->resource)
         return ERROR_INVALID_PARAMETER;
 
-    if (!resource->lpProvider)
+    if (!ctxt->resource->lpProvider)
     {
         FIXME("Networking provider selection is not implemented.\n");
         return WN_NO_NETWORK;
     }
 
-    if (!resource->lpLocalName && (flags & CONNECT_REDIRECT))
+    if (!ctxt->resource->lpLocalName && (ctxt->flags & CONNECT_REDIRECT))
     {
         FIXME("Locale device selection is not implemented.\n");
         return WN_NO_NETWORK;
     }
 
-    if (flags & CONNECT_INTERACTIVE)
+    if (ctxt->flags & CONNECT_INTERACTIVE)
         return ERROR_BAD_NET_NAME;
 
-    index = _findProviderIndexW(resource->lpProvider);
+    index = _findProviderIndexW(ctxt->resource->lpProvider);
     if (index == BAD_PROVIDER_INDEX)
         return ERROR_BAD_PROVIDER;
 
@@ -1622,37 +1645,145 @@ DWORD WINAPI WNetUseConnectionW( HWND hwndOwner, NETRESOURCEW *resource, LPCWSTR
     if (!(caps & (WNNC_CON_ADDCONNECTION | WNNC_CON_ADDCONNECTION3)))
         return ERROR_BAD_PROVIDER;
 
-    if (accessname && buffer_size && *buffer_size)
+    if ((ret = ctxt->pre_set_accessname(ctxt)))
+        return ret;
+
+    ret = WN_ACCESS_DENIED;
+    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 (ret == WN_SUCCESS && ctxt->accessname)
+        ctxt->set_accessname(ctxt);
+
+    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 (resource->lpLocalName)
-            len = strlenW(resource->lpLocalName);
+        if (ctxt->resourceA->lpLocalName)
+            len = strlen(ctxt->resourceA->lpLocalName);
         else
-            len = strlenW(resource->lpRemoteName);
+            len = strlen(ctxt->resourceA->lpRemoteName);
 
-        if (++len > *buffer_size)
+        if (++len > *ctxt->buffer_size)
         {
-            *buffer_size = len;
+            *ctxt->buffer_size = len;
             return ERROR_MORE_DATA;
         }
     }
     else
-        accessname = NULL;
+        ctxt->accessname = NULL;
 
-    ret = WN_ACCESS_DENIED;
-    if ((caps & WNNC_CON_ADDCONNECTION3) && provider->addConnection3)
-        ret = provider->addConnection3(hwndOwner, resource, (LPWSTR)password, (LPWSTR)userid, flags);
-    else if ((caps & WNNC_CON_ADDCONNECTION) && provider->addConnection)
-        ret = provider->addConnection(resource, (LPWSTR)password, (LPWSTR)userid);
+    return ERROR_SUCCESS;
+}
 
-    if (ret == WN_SUCCESS && accessname)
-    {
-        if (resource->lpLocalName)
-            strcpyW(accessname, resource->lpLocalName);
-        else
-            strcpyW(accessname, resource->lpRemoteName);
-    }
+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;
 }
-- 
2.7.0




More information about the wine-patches mailing list