📄 wnet.c
字号:
else if (lpNet->lpRemoteName)
{
*lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope,
dwType, dwUsage, lpNet);
ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
}
else
{
if (lpNet->lpComment && !strcmpW(lpNet->lpComment,
providerTable->entireNetwork))
{
/* comment matches the "Entire Network", enumerate
* global scope of every provider
*/
*lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope,
dwType, dwUsage, lpNet);
}
else
{
/* this is the same as not having passed lpNet */
*lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope,
dwType, dwUsage, NULL);
}
ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
}
}
else
{
*lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope, dwType,
dwUsage, lpNet);
ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
}
break;
case RESOURCE_CONTEXT:
*lphEnum = (HANDLE)_createContextEnumerator(dwScope, dwType,
dwUsage);
ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
break;
case RESOURCE_REMEMBERED:
case RESOURCE_CONNECTED:
*lphEnum = (HANDLE)_createNullEnumerator();
ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
break;
default:
WARN("unknown scope 0x%08x\n", dwScope);
ret = WN_BAD_VALUE;
}
}
if (ret)
SetLastError(ret);
TRACE("Returning %d\n", ret);
return ret;
}
/*********************************************************************
* WNetEnumResourceA [MPR.@]
*/
DWORD WINAPI WNetEnumResourceA( HANDLE hEnum, LPDWORD lpcCount,
LPVOID lpBuffer, LPDWORD lpBufferSize )
{
DWORD ret;
TRACE( "(%p, %p, %p, %p)\n", hEnum, lpcCount, lpBuffer, lpBufferSize );
if (!hEnum)
ret = WN_BAD_POINTER;
else if (!lpcCount)
ret = WN_BAD_POINTER;
else if (!lpBuffer)
ret = WN_BAD_POINTER;
else if (!lpBufferSize)
ret = WN_BAD_POINTER;
else if (*lpBufferSize < sizeof(NETRESOURCEA))
{
*lpBufferSize = sizeof(NETRESOURCEA);
ret = WN_MORE_DATA;
}
else
{
DWORD localCount = *lpcCount, localSize = *lpBufferSize;
LPVOID localBuffer = HeapAlloc(GetProcessHeap(), 0, localSize);
if (localBuffer)
{
ret = WNetEnumResourceW(hEnum, &localCount, localBuffer,
&localSize);
if (ret == WN_SUCCESS || (ret == WN_MORE_DATA && localCount != -1))
{
/* FIXME: this isn't necessarily going to work in the case of
* WN_MORE_DATA, because our enumerator may have moved on to
* the next provider. MSDN states that a large (16KB) buffer
* size is the appropriate usage of this function, so
* hopefully it won't be an issue.
*/
ret = _thunkNetResourceArrayWToA((LPNETRESOURCEW)localBuffer,
&localCount, lpBuffer, lpBufferSize);
*lpcCount = localCount;
}
HeapFree(GetProcessHeap(), 0, localBuffer);
}
else
ret = WN_OUT_OF_MEMORY;
}
if (ret)
SetLastError(ret);
TRACE("Returning %d\n", ret);
return ret;
}
static DWORD _countProviderBytesW(PWNetProvider provider)
{
DWORD ret;
if (provider)
{
ret = sizeof(NETRESOURCEW);
ret += 2 * (strlenW(provider->name) + 1) * sizeof(WCHAR);
}
else
ret = 0;
return ret;
}
static DWORD _enumerateProvidersW(PWNetEnumerator enumerator, LPDWORD lpcCount,
LPVOID lpBuffer, const DWORD *lpBufferSize)
{
DWORD ret;
if (!enumerator)
return WN_BAD_POINTER;
if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
return WN_BAD_VALUE;
if (!lpcCount)
return WN_BAD_POINTER;
if (!lpBuffer)
return WN_BAD_POINTER;
if (!lpBufferSize)
return WN_BAD_POINTER;
if (*lpBufferSize < sizeof(NETRESOURCEA))
return WN_MORE_DATA;
if (!providerTable || enumerator->providerIndex >=
providerTable->numProviders)
ret = WN_NO_MORE_ENTRIES;
else
{
DWORD bytes = 0, count = 0, countLimit, i;
LPNETRESOURCEW resource;
LPWSTR strNext;
countLimit = *lpcCount == -1 ?
providerTable->numProviders - enumerator->providerIndex : *lpcCount;
while (count < countLimit && bytes < *lpBufferSize)
{
DWORD bytesNext = _countProviderBytesW(
&providerTable->table[count + enumerator->providerIndex]);
if (bytes + bytesNext < *lpBufferSize)
{
bytes += bytesNext;
count++;
}
}
strNext = (LPWSTR)((LPBYTE)lpBuffer + count * sizeof(NETRESOURCEW));
for (i = 0, resource = (LPNETRESOURCEW)lpBuffer; i < count;
i++, resource++)
{
resource->dwScope = RESOURCE_GLOBALNET;
resource->dwType = RESOURCETYPE_ANY;
resource->dwDisplayType = RESOURCEDISPLAYTYPE_NETWORK;
resource->dwUsage = RESOURCEUSAGE_CONTAINER |
RESOURCEUSAGE_RESERVED;
resource->lpLocalName = NULL;
resource->lpRemoteName = strNext;
strcpyW(resource->lpRemoteName,
providerTable->table[i + enumerator->providerIndex].name);
strNext += strlenW(resource->lpRemoteName) + 1;
resource->lpComment = NULL;
resource->lpProvider = strNext;
strcpyW(resource->lpProvider,
providerTable->table[i + enumerator->providerIndex].name);
strNext += strlenW(resource->lpProvider) + 1;
}
enumerator->providerIndex += count;
*lpcCount = count;
ret = count > 0 ? WN_SUCCESS : WN_MORE_DATA;
}
TRACE("Returning %d\n", ret);
return ret;
}
/* Advances the enumerator (assumed to be a global enumerator) to the next
* provider that supports the enumeration scope passed to WNetOpenEnum. Does
* not open a handle with the next provider.
* If the existing handle is NULL, may leave the enumerator unchanged, since
* the current provider may support the desired scope.
* If the existing handle is not NULL, closes it before moving on.
* Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available
* provider, and another error on failure.
*/
static DWORD _globalEnumeratorAdvance(PWNetEnumerator enumerator)
{
if (!enumerator)
return WN_BAD_POINTER;
if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
return WN_BAD_VALUE;
if (!providerTable || enumerator->providerIndex >=
providerTable->numProviders)
return WN_NO_MORE_ENTRIES;
if (enumerator->providerDone)
{
enumerator->providerDone = FALSE;
if (enumerator->handle)
{
providerTable->table[enumerator->providerIndex].closeEnum(
enumerator->handle);
enumerator->handle = NULL;
enumerator->providerIndex++;
}
for (; enumerator->providerIndex < providerTable->numProviders &&
!(enumerator->dwScope & providerTable->table
[enumerator->providerIndex].dwEnumScopes);
enumerator->providerIndex++)
;
}
return enumerator->providerIndex < providerTable->numProviders ?
WN_SUCCESS : WN_NO_MORE_ENTRIES;
}
/* "Passes through" call to the next provider that supports the enumeration
* type.
* FIXME: if one call to a provider's enumerator succeeds while there's still
* space in lpBuffer, I don't call to the next provider. The caller may not
* expect that it should call EnumResourceW again with a return value of
* WN_SUCCESS (depending what *lpcCount was to begin with). That means strings
* may have to be moved around a bit, ick.
*/
static DWORD _enumerateGlobalPassthroughW(PWNetEnumerator enumerator,
LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
{
DWORD ret;
if (!enumerator)
return WN_BAD_POINTER;
if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
return WN_BAD_VALUE;
if (!lpcCount)
return WN_BAD_POINTER;
if (!lpBuffer)
return WN_BAD_POINTER;
if (!lpBufferSize)
return WN_BAD_POINTER;
if (*lpBufferSize < sizeof(NETRESOURCEW))
return WN_MORE_DATA;
ret = _globalEnumeratorAdvance(enumerator);
if (ret == WN_SUCCESS)
{
ret = providerTable->table[enumerator->providerIndex].
openEnum(enumerator->dwScope, enumerator->dwType,
enumerator->dwUsage, enumerator->lpNet,
&enumerator->handle);
if (ret == WN_SUCCESS)
{
ret = providerTable->table[enumerator->providerIndex].
enumResource(enumerator->handle, lpcCount, lpBuffer,
lpBufferSize);
if (ret != WN_MORE_DATA)
enumerator->providerDone = TRUE;
}
}
TRACE("Returning %d\n", ret);
return ret;
}
static DWORD _enumerateGlobalW(PWNetEnumerator enumerator, LPDWORD lpcCount,
LPVOID lpBuffer, LPDWORD lpBufferSize)
{
DWORD ret;
if (!enumerator)
return WN_BAD_POINTER;
if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
return WN_BAD_VALUE;
if (!lpcCount)
return WN_BAD_POINTER;
if (!lpBuffer)
return WN_BAD_POINTER;
if (!lpBufferSize)
return WN_BAD_POINTER;
if (*lpBufferSize < sizeof(NETRESOURCEW))
return WN_MORE_DATA;
if (!providerTable)
return WN_NO_NETWORK;
switch (enumerator->dwScope)
{
case RESOURCE_GLOBALNET:
if (enumerator->lpNet)
ret = _enumerateGlobalPassthroughW(enumerator, lpcCount,
lpBuffer, lpBufferSize);
else
ret = _enumerateProvidersW(enumerator, lpcCount, lpBuffer,
lpBufferSize);
break;
case RESOURCE_CONTEXT:
ret = _enumerateGlobalPassthroughW(enumerator, lpcCount, lpBuffer,
lpBufferSize);
break;
default:
WARN("unexpected scope 0x%08x\n", enumerator->dwScope);
ret = WN_NO_MORE_ENTRIES;
}
TRACE("Returning %d\n", ret);
return ret;
}
static DWORD _enumerateProviderW(PWNetEnumerator enumerator, LPDWORD lpcCount,
LPVOID lpBuffer, LPDWORD lpBufferSize)
{
if (!enumerator)
return WN_BAD_POINTER;
if (enumerator->enumType != WNET_ENUMERATOR_TYPE_PROVIDER)
return WN_BAD_VALUE;
if (!enumerator->handle)
return WN_BAD_VALUE;
if (!lpcCount)
return WN_BAD_POINTER;
if (!lpBuffer)
return WN_BAD_POINTER;
if (!lpBufferSize)
return WN_BAD_POINTER;
if (!providerTable)
return WN_NO_NETWORK;
if (enumerator->providerIndex >= providerTable->numProviders)
return WN_NO_MORE_ENTRIES;
if (!providerTable->table[enumerator->providerIndex].enumResource)
return WN_BAD_VALUE;
return providerTable->table[enumerator->providerIndex].enumResource(
enumerator->handle, lpcCount, lpBuffer, lpBufferSize);
}
static DWORD _enumerateContextW(PWNetEnumerator enumerator, LPDWORD lpcCount,
LPVOID lpBuffer, LPDWORD lpBufferSize)
{
DWORD ret;
size_t cchEntireNetworkLen, bytesNeeded;
if (!enumerator)
return WN_BAD_POINTER;
if (enumerator->enumType != WNET_ENUMERATOR_TYPE_CONTEXT)
return WN_BAD_VALUE;
if (!lpcCount)
return WN_BAD_POINTER;
if (!lpBuffer)
return WN_BAD_POINTER;
if (!lpBufferSize)
return WN_BAD_POINTER;
if (!providerTable)
return WN_NO_NETWORK;
cchEntireNetworkLen = strlenW(providerTable->entireNetwork) + 1;
bytesNeeded = sizeof(NETRESOURCEW) + cchEntireNetworkLen * sizeof(WCHAR);
if (*lpBufferSize < bytesNeeded)
{
*lpBufferSize = bytesNeeded;
ret = WN_MORE_DATA;
}
else
{
LPNETRESOURCEW lpNet = (LPNETRESOURCEW)lpBuffer;
lpNet->dwScope = RESOURCE_GLOBALNET;
lpNet->dwType = enumerator->dwType;
lpNet->dwDisplayType = RESOURCEDISPLAYTYPE_ROOT;
lpNet->dwUsage = RESOURCEUSAGE_CONTAINER;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -