//+---------------------------------------------------------------------------- // // 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 #include #include #include } #include #include #include #include #include #include #define appDebugOut(x) #define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0])) #define INCL_NETLIB #include #include #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 ); }