📄 wnet.c
字号:
/*
* MPR WNet functions
*
* Copyright 1999 Ulrich Weigand
* Copyright 2004 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winnetwk.h"
#include "npapi.h"
#include "winreg.h"
#include "winuser.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "mprres.h"
#include "wnetpriv.h"
WINE_DEFAULT_DEBUG_CHANNEL(mpr);
/* Data structures representing network service providers. Assumes only one
* thread creates them, and that they are constant for the life of the process
* (and therefore doesn't synchronize access).
* FIXME: only basic provider data and enumeration-related data are implemented
* so far, need to implement the rest too.
*/
typedef struct _WNetProvider
{
HMODULE hLib;
PWSTR name;
PF_NPGetCaps getCaps;
DWORD dwSpecVersion;
DWORD dwNetType;
DWORD dwEnumScopes;
PF_NPOpenEnum openEnum;
PF_NPEnumResource enumResource;
PF_NPCloseEnum closeEnum;
} WNetProvider, *PWNetProvider;
typedef struct _WNetProviderTable
{
LPWSTR entireNetwork;
DWORD numAllocated;
DWORD numProviders;
WNetProvider table[1];
} WNetProviderTable, *PWNetProviderTable;
#define WNET_ENUMERATOR_TYPE_NULL 0
#define WNET_ENUMERATOR_TYPE_GLOBAL 1
#define WNET_ENUMERATOR_TYPE_PROVIDER 2
#define WNET_ENUMERATOR_TYPE_CONTEXT 3
/* An WNet enumerator. Note that the type doesn't correspond to the scope of
* the enumeration; it represents one of the following types:
* - a 'null' enumeration, one that contains no members
* - a global enumeration, one that's executed across all providers
* - a provider-specific enumeration, one that's only executed by a single
* provider
* - a context enumeration. I know this contradicts what I just said about
* there being no correspondence between the scope and the type, but it's
* necessary for the special case that a "Entire Network" entry needs to
* be enumerated in an enumeration of the context scope. Thus an enumeration
* of the context scope results in a context type enumerator, which morphs
* into a global enumeration (so the enumeration continues across all
* providers).
*/
typedef struct _WNetEnumerator
{
DWORD enumType;
DWORD providerIndex;
HANDLE handle;
BOOL providerDone;
DWORD dwScope;
DWORD dwType;
DWORD dwUsage;
LPNETRESOURCEW lpNet;
} WNetEnumerator, *PWNetEnumerator;
#define BAD_PROVIDER_INDEX (DWORD)0xffffffff
/* Returns an index (into the global WNetProviderTable) of the provider with
* the given name, or BAD_PROVIDER_INDEX if not found.
*/
static DWORD _findProviderIndexW(LPCWSTR lpProvider);
PWNetProviderTable providerTable;
/*
* Global provider table functions
*/
static void _tryLoadProvider(PCWSTR provider)
{
static const WCHAR servicePrefix[] = { 'S','y','s','t','e','m','\\',
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
'S','e','r','v','i','c','e','s','\\',0 };
static const WCHAR serviceFmt[] = { '%','s','%','s','\\',
'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 };
WCHAR serviceName[MAX_PATH];
HKEY hKey;
TRACE("%s\n", debugstr_w(provider));
snprintfW(serviceName, sizeof(serviceName) / sizeof(WCHAR), serviceFmt,
servicePrefix, provider);
serviceName[sizeof(serviceName) / sizeof(WCHAR) - 1] = '\0';
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, serviceName, 0, KEY_READ, &hKey) ==
ERROR_SUCCESS)
{
static const WCHAR szProviderPath[] = { 'P','r','o','v','i','d','e','r',
'P','a','t','h',0 };
WCHAR providerPath[MAX_PATH];
DWORD type, size = sizeof(providerPath);
if (RegQueryValueExW(hKey, szProviderPath, NULL, &type,
(LPBYTE)providerPath, &size) == ERROR_SUCCESS && type == REG_SZ)
{
static const WCHAR szProviderName[] = { 'N','a','m','e',0 };
PWSTR name = NULL;
size = 0;
RegQueryValueExW(hKey, szProviderName, NULL, NULL, NULL, &size);
if (size)
{
name = HeapAlloc(GetProcessHeap(), 0, size);
if (RegQueryValueExW(hKey, szProviderName, NULL, &type,
(LPBYTE)name, &size) != ERROR_SUCCESS || type != REG_SZ)
{
HeapFree(GetProcessHeap(), 0, name);
name = NULL;
}
}
if (name)
{
HMODULE hLib = LoadLibraryW(providerPath);
if (hLib)
{
PF_NPGetCaps getCaps = (PF_NPGetCaps)GetProcAddress(hLib,
"NPGetCaps");
TRACE("loaded lib %p\n", hLib);
if (getCaps)
{
PWNetProvider provider =
&providerTable->table[providerTable->numProviders];
provider->hLib = hLib;
provider->name = name;
TRACE("name is %s\n", debugstr_w(name));
provider->getCaps = getCaps;
provider->dwSpecVersion = getCaps(WNNC_SPEC_VERSION);
provider->dwNetType = getCaps(WNNC_NET_TYPE);
TRACE("net type is 0x%08x\n", provider->dwNetType);
provider->dwEnumScopes = getCaps(WNNC_ENUMERATION);
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);
if (!provider->openEnum || !provider->enumResource
|| !provider->closeEnum)
{
provider->openEnum = NULL;
provider->enumResource = NULL;
provider->closeEnum = NULL;
provider->dwEnumScopes = 0;
WARN("Couldn't load enumeration functions\n");
}
}
providerTable->numProviders++;
}
else
{
WARN("Provider %s didn't export NPGetCaps\n",
debugstr_w(provider));
HeapFree(GetProcessHeap(), 0, name);
FreeLibrary(hLib);
}
}
else
{
WARN("Couldn't load library %s for provider %s\n",
debugstr_w(providerPath), debugstr_w(provider));
HeapFree(GetProcessHeap(), 0, name);
}
}
else
{
WARN("Couldn't get provider name for provider %s\n",
debugstr_w(provider));
}
}
else
WARN("Couldn't open value %s\n", debugstr_w(szProviderPath));
RegCloseKey(hKey);
}
else
WARN("Couldn't open service key for provider %s\n",
debugstr_w(provider));
}
void wnetInit(HINSTANCE hInstDll)
{
static const WCHAR providerOrderKey[] = { 'S','y','s','t','e','m','\\',
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
'C','o','n','t','r','o','l','\\',
'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\',
'O','r','d','e','r',0 };
static const WCHAR providerOrder[] = { 'P','r','o','v','i','d','e','r',
'O','r','d','e','r',0 };
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, providerOrderKey, 0, KEY_READ, &hKey)
== ERROR_SUCCESS)
{
DWORD size = 0;
RegQueryValueExW(hKey, providerOrder, NULL, NULL, NULL, &size);
if (size)
{
PWSTR providers = HeapAlloc(GetProcessHeap(), 0, size);
if (providers)
{
DWORD type;
if (RegQueryValueExW(hKey, providerOrder, NULL, &type,
(LPBYTE)providers, &size) == ERROR_SUCCESS && type == REG_SZ)
{
PWSTR ptr;
DWORD numToAllocate;
TRACE("provider order is %s\n", debugstr_w(providers));
/* first count commas as a heuristic for how many to
* allocate space for */
for (ptr = providers, numToAllocate = 1; ptr; )
{
ptr = strchrW(ptr, ',');
if (ptr) {
numToAllocate++;
ptr++;
}
}
providerTable =
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(WNetProviderTable)
+ (numToAllocate - 1) * sizeof(WNetProvider));
if (providerTable)
{
PWSTR ptrPrev;
int entireNetworkLen;
entireNetworkLen = LoadStringW(hInstDll,
IDS_ENTIRENETWORK, NULL, 0);
providerTable->entireNetwork = HeapAlloc(
GetProcessHeap(), 0, (entireNetworkLen + 1) *
sizeof(WCHAR));
if (providerTable->entireNetwork)
LoadStringW(hInstDll, IDS_ENTIRENETWORK,
providerTable->entireNetwork,
entireNetworkLen + 1);
providerTable->numAllocated = numToAllocate;
for (ptr = providers; ptr; )
{
ptrPrev = ptr;
ptr = strchrW(ptr, ',');
if (ptr)
*ptr++ = '\0';
_tryLoadProvider(ptrPrev);
}
}
}
HeapFree(GetProcessHeap(), 0, providers);
}
}
RegCloseKey(hKey);
}
}
void wnetFree(void)
{
if (providerTable)
{
DWORD i;
for (i = 0; i < providerTable->numProviders; i++)
{
HeapFree(GetProcessHeap(), 0, providerTable->table[i].name);
FreeModule(providerTable->table[i].hLib);
}
HeapFree(GetProcessHeap(), 0, providerTable->entireNetwork);
HeapFree(GetProcessHeap(), 0, providerTable);
providerTable = NULL;
}
}
static DWORD _findProviderIndexW(LPCWSTR lpProvider)
{
DWORD ret = BAD_PROVIDER_INDEX;
if (providerTable && providerTable->numProviders)
{
DWORD i;
for (i = 0; i < providerTable->numProviders &&
ret == BAD_PROVIDER_INDEX; i++)
if (!strcmpW(lpProvider, providerTable->table[i].name))
ret = i;
}
return ret;
}
/*
* Browsing Functions
*/
static LPNETRESOURCEW _copyNetResourceForEnumW(LPNETRESOURCEW lpNet)
{
LPNETRESOURCEW ret;
if (lpNet)
{
ret = HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW));
if (ret)
{
size_t len;
memcpy(ret, lpNet, sizeof(ret));
ret->lpLocalName = ret->lpComment = ret->lpProvider = NULL;
if (lpNet->lpRemoteName)
{
len = strlenW(lpNet->lpRemoteName) + 1;
ret->lpRemoteName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (ret->lpRemoteName)
strcpyW(ret->lpRemoteName, lpNet->lpRemoteName);
}
}
}
else
ret = NULL;
return ret;
}
static void _freeEnumNetResource(LPNETRESOURCEW lpNet)
{
if (lpNet)
{
HeapFree(GetProcessHeap(), 0, lpNet->lpRemoteName);
HeapFree(GetProcessHeap(), 0, lpNet);
}
}
static PWNetEnumerator _createNullEnumerator(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -