386 lines
9.2 KiB
C++
386 lines
9.2 KiB
C++
//+----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1992, Microsoft Corporation.
|
|
//
|
|
// File: enumnode.cxx
|
|
//
|
|
// Contents: This has the implementation for enumeration helper classes
|
|
// CDfsEnumNode, CDfsEnumHandleTable.
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 21-June-1994 SudK Created.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
extern "C"
|
|
{
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntlsa.h>
|
|
}
|
|
|
|
#include <dfsfsctl.h>
|
|
#include <windows.h>
|
|
#include <string.h>
|
|
#include <wchar.h>
|
|
#include <npapi.h>
|
|
#include <lm.h>
|
|
|
|
#define appDebugOut(x)
|
|
|
|
#define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
#define INCL_NETLIB
|
|
#include <lmui.hxx>
|
|
|
|
#include <dfsutil.hxx>
|
|
#include "dfsenum.hxx"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CDfsEnumNode::CDfsEnumNode
|
|
//
|
|
// Synopsis: Constructor for this enumeration node.
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
CDfsEnumNode::CDfsEnumNode(
|
|
DWORD dwScope,
|
|
DWORD dwType,
|
|
DWORD dwUsage
|
|
)
|
|
:
|
|
_dwScope(dwScope),
|
|
_dwType(dwType),
|
|
_dwUsage(dwUsage)
|
|
{
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CDfsEnumNode::~CDfsEnumNode
|
|
//
|
|
// Synopsis: Destructor.
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
CDfsEnumNode::~CDfsEnumNode()
|
|
{
|
|
//
|
|
// Nothing to do
|
|
//
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CDfsEnumConnectedNode::CDfsEnumConnectedNode
|
|
//
|
|
// Synopsis: Constructor for this enumeration node.
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#define OFFSET_TO_POINTER(p, o) \
|
|
if ((o)) *((LPBYTE *) &(o)) = (((LPBYTE) (o)) + ((DWORD_PTR) (p)))
|
|
|
|
CDfsEnumConnectedNode::CDfsEnumConnectedNode(
|
|
DWORD dwScope,
|
|
DWORD dwType,
|
|
DWORD dwUsage,
|
|
LPCTSTR pszProviderName,
|
|
const LPNETRESOURCE lpNetResource
|
|
)
|
|
:
|
|
CDfsEnumNode(dwScope, dwType, dwUsage),
|
|
_iNext(0),
|
|
_cTotal(0),
|
|
_lpNetResource(NULL)
|
|
{
|
|
NTSTATUS Status;
|
|
DWORD cbSize;
|
|
|
|
//
|
|
// We are only going to enumerate disk resources.
|
|
//
|
|
|
|
if ((dwType != RESOURCETYPE_ANY) &&
|
|
((dwType & RESOURCETYPE_DISK) == 0))
|
|
return;
|
|
|
|
_lpNetResource = (LPNETRESOURCE) _buffer;
|
|
cbSize = sizeof(_buffer);
|
|
|
|
do {
|
|
|
|
Status = DfsFsctl(
|
|
FSCTL_DFS_GET_CONNECTED_RESOURCES,
|
|
(PVOID) pszProviderName,
|
|
(strlenf( pszProviderName ) + 1) * sizeof(TCHAR),
|
|
(PVOID) _lpNetResource,
|
|
cbSize,
|
|
NULL);
|
|
|
|
if (Status == STATUS_BUFFER_OVERFLOW) {
|
|
|
|
if (_lpNetResource != (LPNETRESOURCE) _buffer) {
|
|
|
|
delete _lpNetResource;
|
|
}
|
|
|
|
cbSize *= 2;
|
|
|
|
_lpNetResource = (LPNETRESOURCE) new BYTE[ cbSize ];
|
|
|
|
}
|
|
|
|
} while ( Status == STATUS_BUFFER_OVERFLOW && _lpNetResource != NULL );
|
|
|
|
if ( Status == STATUS_SUCCESS && _lpNetResource != NULL ) {
|
|
|
|
_cTotal = *((LPDWORD)
|
|
( ((PUCHAR) _lpNetResource) + cbSize - sizeof(DWORD) ));
|
|
|
|
for(DWORD i = 0; i < _cTotal; i++) {
|
|
|
|
LPNETRESOURCE res;
|
|
|
|
res = &_lpNetResource[i];
|
|
|
|
OFFSET_TO_POINTER(_lpNetResource, res->lpProvider);
|
|
OFFSET_TO_POINTER(_lpNetResource, res->lpComment);
|
|
OFFSET_TO_POINTER(_lpNetResource, res->lpLocalName);
|
|
OFFSET_TO_POINTER(_lpNetResource, res->lpRemoteName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CDfsEnumConnectedNode::~CDfsEnumConnectedNode
|
|
//
|
|
// Synopsis: Destructor.
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
CDfsEnumConnectedNode::~CDfsEnumConnectedNode()
|
|
{
|
|
|
|
if (_lpNetResource != (LPNETRESOURCE) _buffer && _lpNetResource != NULL) {
|
|
|
|
delete _lpNetResource;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CDfsEnumConnectedNode::Init
|
|
//
|
|
// Synopsis: Do the actual enumeration here
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
DWORD
|
|
CDfsEnumConnectedNode::Init(
|
|
VOID
|
|
)
|
|
{
|
|
return WN_SUCCESS;
|
|
}
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Method: CDfsEnumConnectedNode::PackString
|
|
//
|
|
// Synopsis: Packs a string into the end of a buffer, returning a pointer
|
|
// to where the string was put.
|
|
//
|
|
// Arguments: [pBuffer] -- The Buffer to stuff into.
|
|
//
|
|
// [wszString] -- The string to stuff.
|
|
//
|
|
// [cbString] -- Size, in bytes of wszString, including
|
|
// terminating NULL, if any.
|
|
//
|
|
// [lpcbBuf] -- On entry, contains size in bytes of pBuffer. On
|
|
// return, this size is decremented by cbString.
|
|
//
|
|
// Returns: Pointer (into pBuffer) where wszString was stuffed.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline LPWSTR
|
|
CDfsEnumConnectedNode::PackString(
|
|
IN LPVOID pBuffer,
|
|
IN LPCWSTR wszString,
|
|
IN DWORD cbString,
|
|
IN OUT LPDWORD lpcbBuf)
|
|
{
|
|
LPWSTR wszDest;
|
|
|
|
ASSERT( cbString <= *lpcbBuf );
|
|
ASSERT( cbString != 0 );
|
|
|
|
wszDest = (LPWSTR) ( ((LPBYTE)pBuffer) + *lpcbBuf - cbString);
|
|
|
|
MoveMemory( (PVOID) wszDest, wszString, cbString );
|
|
|
|
(*lpcbBuf) -= cbString;
|
|
|
|
return( wszDest );
|
|
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CDfsEnumConnectedNode::GetNetResource
|
|
//
|
|
// Synopsis: Returns a single NETRESOURCE for a CONNECTED resource.
|
|
//
|
|
// Returns: Same error codes as WNetEnumResources.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
CDfsEnumConnectedNode::GetNetResource(
|
|
LPVOID lpBuffer,
|
|
LPDWORD lpBufferSize
|
|
)
|
|
{
|
|
DWORD cbRes, cbLocal, cbRemote, cbComment, cbProvider;
|
|
LPNETRESOURCE res, dest;
|
|
|
|
//
|
|
// This call retrieves the next CONNECTED Resource from the list retrieved
|
|
// in the constructor.
|
|
//
|
|
|
|
//
|
|
// See if we are done
|
|
//
|
|
|
|
if (_iNext == _cTotal) {
|
|
return( WN_NO_MORE_ENTRIES );
|
|
}
|
|
|
|
if (_lpNetResource == NULL) {
|
|
return( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
|
|
//
|
|
// We have entries to return, so lets try to.
|
|
//
|
|
|
|
ASSERT(_iNext < _cTotal);
|
|
|
|
res = &_lpNetResource[_iNext];
|
|
|
|
//
|
|
// First, determine the size of the strings and the total NETRESOURCE
|
|
// to see if it will fit in the provided buffer.
|
|
//
|
|
|
|
cbLocal = cbRemote = cbComment = cbProvider = 0;
|
|
|
|
if (res->lpLocalName) {
|
|
cbLocal = (wcslen(res->lpLocalName) + 1) * sizeof(WCHAR);
|
|
}
|
|
|
|
if (res->lpRemoteName) {
|
|
cbRemote = (wcslen(res->lpRemoteName) + 1) * sizeof(WCHAR);
|
|
}
|
|
|
|
if (res->lpComment) {
|
|
cbComment = (wcslen(res->lpComment) + 1) * sizeof(WCHAR);
|
|
}
|
|
|
|
if (res->lpProvider) {
|
|
cbProvider = (wcslen(res->lpProvider) + 1) * sizeof(WCHAR);
|
|
}
|
|
|
|
cbRes = sizeof(NETRESOURCE) + cbLocal + cbRemote + cbComment + cbProvider;
|
|
|
|
if (cbRes > *lpBufferSize) {
|
|
|
|
*lpBufferSize = cbRes;
|
|
|
|
return( WN_MORE_DATA );
|
|
}
|
|
|
|
//
|
|
// Ok, looks like this NETRESOURCE will fit. Stuff it into the user
|
|
// buffer, packing strings at the end of the buffer
|
|
//
|
|
|
|
dest = (LPNETRESOURCE) lpBuffer;
|
|
|
|
*dest = *res;
|
|
|
|
if (res->lpProvider) {
|
|
dest->lpProvider = PackString(
|
|
lpBuffer,
|
|
res->lpProvider,
|
|
cbProvider,
|
|
lpBufferSize);
|
|
}
|
|
|
|
if (res->lpComment) {
|
|
dest->lpComment = PackString(
|
|
lpBuffer,
|
|
res->lpComment,
|
|
cbComment,
|
|
lpBufferSize);
|
|
}
|
|
|
|
if (res->lpRemoteName) {
|
|
dest->lpRemoteName = PackString(
|
|
lpBuffer,
|
|
res->lpRemoteName,
|
|
cbRemote,
|
|
lpBufferSize);
|
|
}
|
|
|
|
if (res->lpLocalName) {
|
|
res->lpLocalName = PackString(
|
|
lpBuffer,
|
|
res->lpLocalName,
|
|
cbLocal,
|
|
lpBufferSize);
|
|
}
|
|
|
|
//
|
|
// Update our own records to indicate that we successfully returned one
|
|
// more NETRESOURCE ...
|
|
//
|
|
|
|
_iNext++;
|
|
|
|
//
|
|
// And return.
|
|
//
|
|
|
|
return( WN_SUCCESS );
|
|
|
|
}
|