windows-nt/Source/XPSP1/NT/admin/netui/shell/enum/dfsenum.cxx
2020-09-26 16:20:57 +08:00

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 );
}