Index: mpr.spec =================================================================== --- mpr.spec (revision 49877) +++ mpr.spec (working copy) @@ -1,23 +1,23 @@ # ordinal exports - 1 stub @ - 2 stub @ - 3 stub @ - 4 stub @ - 5 stub @ - 6 stub @ - 7 stub @ - 8 stub @ - 9 stub @ -12 stub @ -13 stub @ -14 stub @ -15 stub @ -16 stub @ -17 stub @ -18 stub @ -19 stub @ -20 stub @ -21 stub @ + 1 stub MPR_1 + 2 stub MPR_2 + 3 stub MPR_3 + 4 stub MPR_4 + 5 stub MPR_5 + 6 stub MPR_6 + 7 stub MPR_7 + 8 stub MPR_8 + 9 stub MPR_9 +12 stub MPR_12 +13 stub MPR_13 +14 stub MPR_14 +15 stub MPR_15 +16 stub MPR_16 +17 stub MPR_17 +18 stub MPR_18 +19 stub MPR_19 +20 stub MPR_20 +21 stub MPR_21 22 stdcall @(long) MPR_Alloc 23 stdcall @(ptr long) MPR_ReAlloc 24 stdcall @(ptr) MPR_Free Index: wnet.c =================================================================== --- wnet.c (revision 71983) +++ wnet.c (working copy) @@ -60,6 +50,9 @@ PF_NPAddConnection addConnection; PF_NPAddConnection3 addConnection3; PF_NPCancelConnection cancelConnection; +#ifdef __REACTOS__ + PF_NPGetConnection getConnection; +#endif } WNetProvider, *PWNetProvider; typedef struct _WNetProviderTable @@ -219,6 +212,10 @@ provider->addConnection3 = MPR_GETPROC(NPAddConnection3); if (connectCap & WNNC_CON_CANCELCONNECTION) provider->cancelConnection = MPR_GETPROC(NPCancelConnection); +#ifdef __REACTOS__ + if (connectCap & WNNC_CON_GETCONNECTIONS) + provider->getConnection = MPR_GETPROC(NPGetConnection); +#endif TRACE("NPAddConnection %p\n", provider->addConnection); TRACE("NPAddConnection3 %p\n", provider->addConnection3); TRACE("NPCancelConnection %p\n", provider->cancelConnection); @@ -256,6 +253,85 @@ debugstr_w(provider)); } +#ifdef __REACTOS__ +static void _restoreSavedConnection(HKEY connection, WCHAR * local) +{ + NETRESOURCEW net; + DWORD type, prov, index, size; + + net.lpProvider = NULL; + net.lpRemoteName = NULL; + net.lpLocalName = NULL; + + TRACE("Restoring: %S\n", local); + + size = sizeof(DWORD); + if (RegQueryValueExW(connection, L"ConnectionType", NULL, &type, (BYTE *)&net.dwType, &size) != ERROR_SUCCESS) + return; + + if (type != REG_DWORD || size != sizeof(DWORD)) + return; + + if (RegQueryValueExW(connection, L"ProviderName", NULL, &type, NULL, &size) != ERROR_SUCCESS) + return; + + if (type != REG_SZ) + return; + + net.lpProvider = HeapAlloc(GetProcessHeap(), 0, size); + if (!net.lpProvider) + return; + + if (RegQueryValueExW(connection, L"ProviderName", NULL, NULL, (BYTE *)net.lpProvider, &size) != ERROR_SUCCESS) + goto cleanup; + + size = sizeof(DWORD); + if (RegQueryValueExW(connection, L"ProviderType", NULL, &type, (BYTE *)&prov, &size) != ERROR_SUCCESS) + goto cleanup; + + if (type != REG_DWORD || size != sizeof(DWORD)) + goto cleanup; + + index = _findProviderIndexW(net.lpProvider); + if (index == BAD_PROVIDER_INDEX) + goto cleanup; + + if (providerTable->table[index].dwNetType != prov) + goto cleanup; + + if (RegQueryValueExW(connection, L"RemotePath", NULL, &type, NULL, &size) != ERROR_SUCCESS) + goto cleanup; + + if (type != REG_SZ) + goto cleanup; + + net.lpRemoteName = HeapAlloc(GetProcessHeap(), 0, size); + if (!net.lpRemoteName) + goto cleanup; + + if (RegQueryValueExW(connection, L"RemotePath", NULL, NULL, (BYTE *)net.lpRemoteName, &size) != ERROR_SUCCESS) + goto cleanup; + + size = strlenW(local); + net.lpLocalName = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR) + 2 * sizeof(WCHAR)); + if (!net.lpLocalName) + goto cleanup; + + strcpyW(net.lpLocalName, local); + net.lpLocalName[size] = ':'; + net.lpLocalName[size + 1] = 0; + + TRACE("Attempting connection\n"); + + WNetAddConnection2W(&net, NULL, NULL, 0); + +cleanup: + HeapFree(GetProcessHeap(), 0, net.lpProvider); + HeapFree(GetProcessHeap(), 0, net.lpRemoteName); + HeapFree(GetProcessHeap(), 0, net.lpLocalName); +} +#endif + void wnetInit(HINSTANCE hInstDll) { static const WCHAR providerOrderKey[] = { 'S','y','s','t','e','m','\\', @@ -334,6 +410,64 @@ } RegCloseKey(hKey); } + +#ifdef __REACTOS__ + if (providerTable) + { + HKEY user_profile; + + if (RegOpenCurrentUser(KEY_ALL_ACCESS, &user_profile) == ERROR_SUCCESS) + { + HKEY network; + WCHAR subkey[8] = {'N', 'e', 't', 'w', 'o', 'r', 'k', 0}; + + if (RegOpenKeyExW(user_profile, subkey, 0, KEY_READ, &network) == ERROR_SUCCESS) + { + DWORD size, max; + + TRACE("Enumerating remembered connections\n"); + + if (RegQueryInfoKey(network, NULL, NULL, NULL, &max, &size, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) + { + WCHAR *local; + + TRACE("There are %lu connections\n", max); + + local = HeapAlloc(GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR)); + if (local) + { + DWORD index; + + for (index = 0; index < max; ++index) + { + DWORD len = size + 1; + HKEY connection; + + TRACE("Trying connection %lu\n", index); + + if (RegEnumKeyExW(network, index, local, &len, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) + continue; + + TRACE("It is %S\n", local); + + if (RegOpenKeyExW(network, local, 0, KEY_READ, &connection) != ERROR_SUCCESS) + continue; + + _restoreSavedConnection(connection, local); + RegCloseKey(connection); + } + + HeapFree(GetProcessHeap(), 0, local); + } + } + + RegCloseKey(network); + } + + RegCloseKey(user_profile); + } + } +#endif } void wnetFree(void) @@ -1875,6 +2009,43 @@ } } +#ifdef __REACTOS__ + if (ret == WN_SUCCESS && ctxt->flags & CONNECT_UPDATE_PROFILE) + { + HKEY user_profile; + + if (netres.dwType == RESOURCETYPE_PRINT) + { + FIXME("Persistent connection are not supported for printers\n"); + return ret; + } + + if (RegOpenCurrentUser(KEY_ALL_ACCESS, &user_profile) == ERROR_SUCCESS) + { + HKEY network; + WCHAR subkey[10] = {'N', 'e', 't', 'w', 'o', 'r', 'k', '\\', netres.lpLocalName[0], 0}; + + if (RegCreateKeyExW(user_profile, subkey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &network, NULL) == ERROR_SUCCESS) + { + DWORD dword_arg = RESOURCETYPE_DISK; + DWORD len = (strlenW(provider->name) + 1) * sizeof(WCHAR); + + RegSetValueExW(network, L"ConnectionType", 0, REG_DWORD, (const BYTE *)&dword_arg, sizeof(DWORD)); + RegSetValueExW(network, L"ProviderName", 0, REG_SZ, (const BYTE *)provider->name, len); + dword_arg = provider->dwNetType; + RegSetValueExW(network, L"ProviderType", 0, REG_DWORD, (const BYTE *)&dword_arg, sizeof(DWORD)); + len = (strlenW(netres.lpRemoteName) + 1) * sizeof(WCHAR); + RegSetValueExW(network, L"RemotePath", 0, REG_SZ, (const BYTE *)netres.lpRemoteName, len); + len = 0; + RegSetValueExW(network, L"UserName", 0, REG_SZ, (const BYTE *)netres.lpRemoteName, len); + RegCloseKey(network); + } + + RegCloseKey(user_profile); + } + } +#endif + return ret; } @@ -2066,6 +2237,37 @@ } } } +#ifdef __REACTOS__ + + if (dwFlags & CONNECT_UPDATE_PROFILE) + { + HKEY user_profile; + WCHAR *coma = strchrW(lpName, ':'); + + if (coma && RegOpenCurrentUser(KEY_ALL_ACCESS, &user_profile) == ERROR_SUCCESS) + { + WCHAR *subkey; + DWORD len; + + len = (ULONG_PTR)coma - (ULONG_PTR)lpName + sizeof(L"Network\\"); + subkey = HeapAlloc(GetProcessHeap(), 0, len); + if (subkey) + { + strcpyW(subkey, L"Network\\"); + memcpy(subkey + (sizeof(L"Network\\") / sizeof(WCHAR)) - 1, lpName, (ULONG_PTR)coma - (ULONG_PTR)lpName); + subkey[len / sizeof(WCHAR) - 1] = 0; + + TRACE("Removing: %S\n", subkey); + + RegDeleteKeyW(user_profile, subkey); + HeapFree(GetProcessHeap(), 0, subkey); + } + + RegCloseKey(user_profile); + } + } + +#endif return ret; } @@ -2193,6 +2395,7 @@ /* 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; @@ -2235,6 +2438,32 @@ } 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 } /**************************************************************************