PF_NPEnumResource enumResource;
PF_NPCloseEnum closeEnum;
PF_NPGetResourceInformation getResourceInformation;
+ PF_NPAddConnection addConnection;
+ PF_NPAddConnection3 addConnection3;
+ PF_NPCancelConnection cancelConnection;
+#ifdef __REACTOS__
+ PF_NPGetConnection getConnection;
+#endif
} WNetProvider, *PWNetProvider;
typedef struct _WNetProviderTable
DWORD type, size = sizeof(providerPath);
if (RegQueryValueExW(hKey, szProviderPath, NULL, &type,
- (LPBYTE)providerPath, &size) == ERROR_SUCCESS && type == REG_SZ)
+ (LPBYTE)providerPath, &size) == ERROR_SUCCESS && (type == REG_SZ || type == REG_EXPAND_SZ))
{
static const WCHAR szProviderName[] = { 'N','a','m','e',0 };
PWSTR name = NULL;
-
+
+ if (type == REG_EXPAND_SZ)
+ {
+ WCHAR path[MAX_PATH];
+ if (ExpandEnvironmentStringsW(providerPath, path, MAX_PATH)) lstrcpyW( providerPath, path );
+ }
+
size = 0;
RegQueryValueExW(hKey, szProviderName, NULL, NULL, NULL, &size);
if (size)
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)
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;
WARN("Couldn't load enumeration functions\n");
}
}
+ provider->addConnection = MPR_GETPROC(NPAddConnection);
+ provider->addConnection3 = MPR_GETPROC(NPAddConnection3);
+ provider->cancelConnection = MPR_GETPROC(NPCancelConnection);
+#ifdef __REACTOS__
+ provider->getConnection = MPR_GETPROC(NPGetConnection);
+#endif
+ TRACE("NPAddConnection %p\n", provider->addConnection);
+ TRACE("NPAddConnection3 %p\n", provider->addConnection3);
+ TRACE("NPCancelConnection %p\n", provider->cancelConnection);
providerTable->numProviders++;
}
else
HeapFree(GetProcessHeap(), 0, name);
FreeLibrary(hLib);
}
+
+#undef MPR_GETPROC
}
else
{
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);
ret = *lphEnum ? WN_SUCCESS :
WN_OUT_OF_MEMORY;
}
+
+ lpNet->lpRemoteName = RemoteName;
}
else
ret = WN_NOT_SUPPORTED;
DWORD WINAPI WNetAddConnectionA( LPCSTR lpRemoteName, LPCSTR lpPassword,
LPCSTR lpLocalName )
{
- FIXME( "(%s, %p, %s): stub\n",
- debugstr_a(lpRemoteName), lpPassword, debugstr_a(lpLocalName) );
+ NETRESOURCEA resourcesA;
- SetLastError(WN_NO_NETWORK);
- return WN_NO_NETWORK;
+ memset(&resourcesA, 0, sizeof(resourcesA));
+ resourcesA.lpRemoteName = (LPSTR)lpRemoteName;
+ resourcesA.lpLocalName = (LPSTR)lpLocalName;
+ return WNetUseConnectionA(NULL, &resourcesA, lpPassword, NULL, 0, NULL, 0, NULL);
}
/*********************************************************************
DWORD WINAPI WNetAddConnectionW( LPCWSTR lpRemoteName, LPCWSTR lpPassword,
LPCWSTR lpLocalName )
{
- FIXME( "(%s, %p, %s): stub\n",
- debugstr_w(lpRemoteName), lpPassword, debugstr_w(lpLocalName) );
+ NETRESOURCEW resourcesW;
- SetLastError(WN_NO_NETWORK);
- return WN_NO_NETWORK;
+ memset(&resourcesW, 0, sizeof(resourcesW));
+ resourcesW.lpRemoteName = (LPWSTR)lpRemoteName;
+ resourcesW.lpLocalName = (LPWSTR)lpLocalName;
+ return WNetUseConnectionW(NULL, &resourcesW, lpPassword, NULL, 0, NULL, 0, NULL);
}
/*********************************************************************
LPCSTR lpPassword, LPCSTR lpUserID,
DWORD dwFlags )
{
- FIXME( "(%p, %p, %s, 0x%08X): stub\n",
- lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags );
-
- SetLastError(WN_NO_NETWORK);
- return WN_NO_NETWORK;
+ return WNetUseConnectionA(NULL, lpNetResource, lpPassword, lpUserID, dwFlags,
+ NULL, 0, NULL);
}
/*********************************************************************
LPCWSTR lpPassword, LPCWSTR lpUserID,
DWORD dwFlags )
{
- FIXME( "(%p, %p, %s, 0x%08X): stub\n",
- lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags );
-
- SetLastError(WN_NO_NETWORK);
- return WN_NO_NETWORK;
+ return WNetUseConnectionW(NULL, lpNetResource, lpPassword, lpUserID, dwFlags,
+ NULL, 0, NULL);
}
/*********************************************************************
LPCSTR lpPassword, LPCSTR lpUserID,
DWORD dwFlags )
{
- FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
- hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags );
-
- SetLastError(WN_NO_NETWORK);
- return WN_NO_NETWORK;
+ return WNetUseConnectionA(hwndOwner, lpNetResource, lpPassword, lpUserID,
+ dwFlags, NULL, 0, NULL);
}
/*********************************************************************
LPCWSTR lpPassword, LPCWSTR lpUserID,
DWORD dwFlags )
{
- FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
- hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags );
+ return WNetUseConnectionW(hwndOwner, lpNetResource, lpPassword, lpUserID,
+ dwFlags, NULL, 0, NULL);
+}
- SetLastError(WN_NO_NETWORK);
- return WN_NO_NETWORK;
+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;
+
+ 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;
+}
+
+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 WCHAR * select_provider(struct use_connection_context *ctxt)
+{
+ DWORD ret, prov_size = 0x1000, len;
+ LPNETRESOURCEW provider;
+ WCHAR * system;
+
+ provider = HeapAlloc(GetProcessHeap(), 0, prov_size);
+ if (!provider)
+ {
+ return NULL;
+ }
+
+ ret = WNetGetResourceInformationW(ctxt->resource, provider, &prov_size, &system);
+ if (ret == ERROR_MORE_DATA)
+ {
+ HeapFree(GetProcessHeap(), 0, provider);
+ provider = HeapAlloc(GetProcessHeap(), 0, prov_size);
+ if (!provider)
+ {
+ return NULL;
+ }
+
+ ret = WNetGetResourceInformationW(ctxt->resource, provider, &prov_size, &system);
+ }
+
+ if (ret != NO_ERROR)
+ {
+ HeapFree(GetProcessHeap(), 0, provider);
+ return NULL;
+ }
+
+ 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;
+}
+
+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)
+ return WN_NO_NETWORK;
+
+ if (!ctxt->resource)
+ return ERROR_INVALID_PARAMETER;
+
+ 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 (ctxt->flags & CONNECT_INTERACTIVE)
+ {
+ ret = ERROR_BAD_NET_NAME;
+ goto done;
+ }
+
+ 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;
+ }
+
+ index = _findProviderIndexW(ctxt->resource->lpProvider);
+ if (index == BAD_PROVIDER_INDEX)
+ {
+ ret = ERROR_BAD_PROVIDER;
+ goto done;
+ }
+
+ provider = &providerTable->table[index];
+ caps = provider->getCaps(WNNC_CONNECTION);
+ if (!(caps & (WNNC_CON_ADDCONNECTION | WNNC_CON_ADDCONNECTION3)))
+ {
+ ret = ERROR_BAD_PROVIDER;
+ goto done;
+ }
+
+ if ((ret = ctxt->pre_set_accessname(ctxt)))
+ {
+ goto done;
+ }
+
+ ret = WN_ACCESS_DENIED;
+ 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;
+ }
+
+ if (redirect)
+ ctxt->resource->lpLocalName = NULL;
+
+ return ret;
}
/*****************************************************************
- * WNetUseConnectionA [MPR.@]
+ * WNetUseConnectionW [MPR.@]
*/
-DWORD WINAPI WNetUseConnectionA( HWND hwndOwner, LPNETRESOURCEA lpNetResource,
- LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags,
- LPSTR lpAccessName, LPDWORD lpBufferSize,
- LPDWORD lpResult )
+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)
{
- FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
- hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags,
- debugstr_a(lpAccessName), lpBufferSize, lpResult );
+ if (ctxt->accessname && ctxt->buffer_size && *ctxt->buffer_size)
+ {
+ DWORD len;
- SetLastError(WN_NO_NETWORK);
- return WN_NO_NETWORK;
+ 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);
}
/*****************************************************************
- * WNetUseConnectionW [MPR.@]
+ * WNetUseConnectionA [MPR.@]
*/
-DWORD WINAPI WNetUseConnectionW( HWND hwndOwner, LPNETRESOURCEW lpNetResource,
- LPCWSTR lpPassword, LPCWSTR lpUserID, DWORD dwFlags,
- LPWSTR lpAccessName, LPDWORD lpBufferSize,
- LPDWORD lpResult )
+DWORD WINAPI WNetUseConnectionA( HWND hwndOwner, NETRESOURCEA *resource,
+ LPCSTR password, LPCSTR userid, DWORD flags, LPSTR accessname,
+ DWORD *buffer_size, DWORD *result )
{
- FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
- hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags,
- debugstr_w(lpAccessName), lpBufferSize, lpResult );
+ struct use_connection_context ctxt;
+ NETRESOURCEW resourceW;
+ DWORD ret;
- SetLastError(WN_NO_NETWORK);
- return WN_NO_NETWORK;
+ 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;
}
/*********************************************************************
*/
DWORD WINAPI WNetCancelConnection2W( LPCWSTR lpName, DWORD dwFlags, BOOL fForce )
{
- FIXME( "(%s, %08X, %d), stub\n", debugstr_w(lpName), dwFlags, fForce );
+ DWORD ret = WN_NO_NETWORK;
+ DWORD index;
- return WN_SUCCESS;
+ if (providerTable != NULL)
+ {
+ for (index = 0; index < providerTable->numProviders; index++)
+ {
+ if(providerTable->table[index].getCaps(WNNC_CONNECTION) &
+ WNNC_CON_GETCONNECTIONS)
+ {
+ if (providerTable->table[index].cancelConnection)
+ ret = providerTable->table[index].cancelConnection((LPWSTR)lpName, fForce);
+ else
+ ret = WN_NO_NETWORK;
+ if (ret == WN_SUCCESS || ret == WN_OPEN_FILES)
+ break;
+ }
+ }
+ }
+ return ret;
}
/*****************************************************************
/* 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;
}
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
}
/**************************************************************************
break;
}
case REMOTE_NAME_INFO_LEVEL:
- err = WN_NO_NETWORK;
+ err = WN_NOT_CONNECTED;
break;
default:
break;
}
case REMOTE_NAME_INFO_LEVEL:
- err = WN_NOT_CONNECTED;
+ err = WN_NO_NETWORK;
break;
default: