/*++ Copyright (c) 1996 Microsoft Corporation Module Name: cenumfsh.cxx Abstract: Contains methods for implementing the Enumeration of session on a server. Has methods for the CWinNTFileSharesEnumVar object. Author: Ram Viswanathan (ramv) 11-28-95 Revision History: --*/ #include "winnt.hxx" #pragma hdrstop #if DBG DECLARE_INFOLEVEL(EnumFileShare); DECLARE_DEBUG(EnumFileShare); #define EnumFileShareDebugOut(x) EnumFileShareInlineDebugOut x #endif //+--------------------------------------------------------------------------- // // Function: CWinNTFileSharesEnumVar::CWinNTFileSharesEnumVar // // Synopsis: // // // Arguments: // // // Returns: // // Modifies: // // History: 11-22-95 RamV Created. // //---------------------------------------------------------------------------- CWinNTFileSharesEnumVar::CWinNTFileSharesEnumVar() { _pszADsPath = NULL; _pszServerName = NULL; _pbFileShares = NULL; _cElements = 0; _lLBound = 0; _lCurrentPosition = _lLBound; _dwTotalEntries = 0; _dwResumeHandle = 0; VariantInit(&_vFilter); } //+--------------------------------------------------------------------------- // // Function: CWinNTFileSharesEnumVar::~CWinNTFileSharesEnumVar // // Synopsis: // // // Arguments: // // Returns: // // Modifies: // // History: 11-22-95 RamV Created. // //---------------------------------------------------------------------------- CWinNTFileSharesEnumVar::~CWinNTFileSharesEnumVar() { if(_pszADsPath){ FreeADsStr(_pszADsPath); } if(_pszServerName){ FreeADsStr(_pszServerName); } if(_pbFileShares){ NetApiBufferFree(_pbFileShares); } VariantClear(&_vFilter); } HRESULT CWinNTFileSharesEnumVar::Create(LPTSTR pszServerName, LPTSTR pszADsPath, CWinNTFileSharesEnumVar **ppCFileSharesEnumVar, VARIANT vFilter, CWinNTCredentials& Credentials ) { HRESULT hr = S_OK; BOOL fStatus = FALSE; CWinNTFileSharesEnumVar FAR* pCFileSharesEnumVar = NULL; *ppCFileSharesEnumVar = NULL; pCFileSharesEnumVar = new CWinNTFileSharesEnumVar(); if (pCFileSharesEnumVar == NULL){ hr = E_OUTOFMEMORY; goto error; } pCFileSharesEnumVar->_pszServerName = AllocADsStr(pszServerName); if(!(pCFileSharesEnumVar->_pszServerName)){ hr = E_OUTOFMEMORY; goto error; } pCFileSharesEnumVar->_pszADsPath = AllocADsStr(pszADsPath); if(!(pCFileSharesEnumVar->_pszADsPath)){ hr = E_OUTOFMEMORY; goto error; } hr = VariantCopy(&(pCFileSharesEnumVar->_vFilter), &vFilter); BAIL_ON_FAILURE(hr); pCFileSharesEnumVar->_Credentials = Credentials; hr = pCFileSharesEnumVar->_Credentials.RefServer(pszServerName); BAIL_ON_FAILURE(hr); *ppCFileSharesEnumVar = pCFileSharesEnumVar; RRETURN(hr); error: delete pCFileSharesEnumVar; RRETURN_EXP_IF_ERR(hr); } //+--------------------------------------------------------------------------- // // Function: CWinNTFileSharesEnumVar::Next // // Synopsis: Returns cElements number of requested Share objects in the // array supplied in pvar. // // Arguments: [cElements] -- The number of elements requested by client // [pvar] -- ptr to array of VARIANTs to for return objects // [ulNumFetched] -- if non-NULL, then number of elements // -- actually returned is placed here // // Returns: HRESULT -- S_OK if number of elements requested are returned // -- S_FALSE if number of elements is < requested // // Modifies: // // History: 11-27-95 RamV Created. // //---------------------------------------------------------------------------- STDMETHODIMP CWinNTFileSharesEnumVar::Next(ULONG ulNumElementsRequested, VARIANT FAR* pvar, ULONG FAR* pulNumFetched) { HRESULT hresult = S_OK; ULONG l; ULONG lNewCurrent; ULONG lNumFetched; LPSHARE_INFO_1 lpShareInfo = NULL; VARIANT v; IDispatch * pDispatch = NULL; if (pulNumFetched != NULL){ *pulNumFetched = 0; } // // Check the out parameter to ensure it is valid // if (!pvar) return S_FALSE; // // Initialize the elements to be returned // for (l=0; lshi1_type == STYPE_DISKTREE){ // // file share object // hresult = CWinNTFileShare::Create(_pszADsPath, _pszServerName, FILESHARE_CLASS_NAME, lpShareInfo->shi1_netname, ADS_OBJECT_BOUND, IID_IDispatch, _Credentials, (void **)&pDispatch); BAIL_IF_ERROR(hresult); VariantInit(&v); V_VT(&v) = VT_DISPATCH; V_DISPATCH(&v) = pDispatch; pvar[lNumFetched] = v; lNumFetched++; } lNewCurrent++; if(lNumFetched == ulNumElementsRequested){ // // we got all elements // break; } if(lNewCurrent==(_lLBound+_cElements)){ // // first free our current buffer // if(_pbFileShares){ NetApiBufferFree(_pbFileShares); _pbFileShares = NULL; } if(_cElements < _dwTotalEntries){ hresult = WinNTEnumFileShares(_pszServerName, &_cElements, &_dwTotalEntries, &_dwResumeHandle, &_pbFileShares); if(hresult == S_FALSE){ if (pulNumFetched != NULL){ *pulNumFetched = lNumFetched; } goto cleanup; } _lLBound = 0; _lCurrentPosition = _lLBound; lNewCurrent = _lCurrentPosition; } else{ // // you have gone through every share object // return S_FALSE // hresult = S_FALSE; if (pulNumFetched != NULL){ *pulNumFetched = lNumFetched; } goto cleanup; } lNewCurrent = _lCurrentPosition; } } // // Tell the caller how many we got (which may be less than the number // requested), and save the current position // if (pulNumFetched != NULL) *pulNumFetched = lNumFetched; _lCurrentPosition = lNewCurrent; // // If we're returning less than they asked for return S_FALSE, but // they still have the data (S_FALSE is a success code) // return (lNumFetched < ulNumElementsRequested) ? S_FALSE : S_OK; cleanup: if(_pbFileShares){ NetApiBufferFree(_pbFileShares); } if(FAILED(hresult)){ #if DBG EnumFileShareDebugOut((DEB_TRACE, "hresult Failed with value: %ld \n", hresult )); #endif RRETURN(S_FALSE); } else { if(hresult == S_FALSE) RRETURN(S_FALSE); RRETURN(S_OK); } } HRESULT WinNTEnumFileShares(LPTSTR pszServerName, PDWORD pdwElements, PDWORD pdwTotalEntries, PDWORD pdwResumeHandle, LPBYTE * ppMem ) { NET_API_STATUS nasStatus; nasStatus = NetShareEnum(pszServerName, 1, ppMem, MAX_PREFERRED_LENGTH, pdwElements, pdwTotalEntries, pdwResumeHandle ); if(*ppMem == NULL || (nasStatus!= NERR_Success)){ // //no more entries returned by FileShares // RRETURN(S_FALSE); } RRETURN(S_OK); } BOOL ValidateFilterValue(VARIANT vFilter) { // this function unpacks vFilter and scans the safearray to investigate // whether or not it contains the string "fileshare". If it does, // we return true so that enumeration can proceed. BOOL fRetval = FALSE; HRESULT hr = S_OK; LONG lIndices; ULONG cElements; SAFEARRAY *psa = NULL; VARIANT vElement; ULONG i; VariantInit(&vElement); if(V_VT(&vFilter) == VT_EMPTY){ // // if no filter is set, you can still enumerate // fRetval = TRUE; goto cleanup; }else if (!(V_VT(&vFilter) == (VT_VARIANT|VT_ARRAY))) { fRetval = FALSE; goto cleanup; } psa = V_ARRAY(&vFilter); // // Check that there is only one dimension in this array // if (psa->cDims != 1) { fRetval = FALSE; goto cleanup; } // // Check that there is atleast one element in this array // cElements = psa->rgsabound[0].cElements; if (cElements == 0){ fRetval = TRUE; // // If filter is set and is empty, then // we return all objects. // goto cleanup; } // // We know that this is a valid single dimension array // for(lIndices=0; lIndices< (LONG)cElements; lIndices++){ VariantInit(&vElement); hr = SafeArrayGetElement(psa, &lIndices, &vElement); BAIL_IF_ERROR(hr); if(!(V_VT(&vElement) == VT_BSTR)){ hr = E_FAIL; goto cleanup; } if ( _tcsicmp(vElement.bstrVal, TEXT("fileshare")) == 0){ // // found it, you can return TRUE now // fRetval = TRUE; goto cleanup; } VariantClear(&vElement); } cleanup: // // In success case as well as error if we tripped after // getting the value but not clearing it in the for loop. // VariantClear(&vElement); if(FAILED(hr)){ return FALSE; } return fRetval; }