365 lines
7.6 KiB
C++
365 lines
7.6 KiB
C++
|
|
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1995.
|
|
|
|
// File: enum.cxx
|
|
|
|
// Contents: Implementation of IEnumIDList
|
|
|
|
// History: 13-Dec-95 BruceFo Created
|
|
|
|
|
|
|
|
#include "headers.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "resource.h"
|
|
#include "enum.hxx"
|
|
#include "util.hxx"
|
|
#include "shri.hxx"
|
|
|
|
|
|
CSharesEnum::CSharesEnum(
|
|
IN PWSTR pszMachine,
|
|
IN DWORD level
|
|
)
|
|
:
|
|
m_pszMachine(pszMachine),
|
|
m_level(level),
|
|
m_uFlags(0),
|
|
m_bDoSmb(TRUE),
|
|
m_bDoFpnw(FALSE),
|
|
m_bDoSfm(FALSE),
|
|
m_pShares(NULL),
|
|
m_cShares(0),
|
|
m_pSfmShares(NULL),
|
|
m_cSfmShares(0),
|
|
m_pFpnwShares(NULL),
|
|
m_cFpnwShares(0),
|
|
m_ulRefs(0),
|
|
m_pShareList(NULL),
|
|
m_pShareCurrent(NULL)
|
|
{
|
|
AddRef();
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSharesEnum::Init(
|
|
ULONG uFlags
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPBYTE pBuf = NULL;
|
|
DWORD entriesread, totalentries;
|
|
NET_API_STATUS ret = NERR_Success;
|
|
DWORD svtype = 0;
|
|
DWORD err;
|
|
|
|
m_uFlags = uFlags;
|
|
|
|
// See what servers are running: SMB, FPNW, and/or SFM
|
|
|
|
PSERVER_INFO_101 pServerInfo;
|
|
ret = NetServerGetInfo(m_pszMachine, 101, (LPBYTE*)&pServerInfo);
|
|
if (NERR_Success != ret)
|
|
{
|
|
return HRESULT_FROM_WIN32(ret);
|
|
}
|
|
else
|
|
{
|
|
svtype = pServerInfo->sv101_type;
|
|
NetApiBufferFree(pServerInfo);
|
|
|
|
if (svtype & SV_TYPE_AFP && LoadSFMSupportLibrary())
|
|
{
|
|
m_bDoSfm = TRUE;
|
|
}
|
|
if (svtype & SV_TYPE_SERVER_MFPN && LoadFPNWSupportLibrary())
|
|
{
|
|
m_bDoFpnw = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
// Enumerate shares from all file servers. Do SMB first.
|
|
|
|
|
|
appAssert(m_level == 1 || m_level == 2);
|
|
|
|
ret = NetShareEnum(
|
|
m_pszMachine,
|
|
m_level,
|
|
&pBuf,
|
|
0xffffffff, // get them all!
|
|
&entriesread,
|
|
&totalentries,
|
|
NULL);
|
|
if (NERR_Success != ret)
|
|
{
|
|
appDebugOut((DEB_ERROR, "NetShareEnum(%ws...) failed! Error = 0x%08lx\n", m_pszMachine, ret));
|
|
hr = HRESULT_FROM_WIN32(ret);
|
|
}
|
|
else
|
|
{
|
|
appAssert(entriesread == totalentries);
|
|
appAssert(0 == entriesread || NULL != pBuf);
|
|
m_pShares = (SHARE_INFO_2*)pBuf; // possibly level one info
|
|
m_cShares = entriesread;
|
|
}
|
|
|
|
|
|
// Do SFM shares
|
|
|
|
|
|
if (m_bDoSfm)
|
|
{
|
|
AFP_SERVER_HANDLE hServer;
|
|
err = (*g_pfnAfpAdminConnect)(m_pszMachine, &hServer);
|
|
if (NO_ERROR == err)
|
|
{
|
|
err = (*g_pfnAfpAdminVolumeEnum)(
|
|
hServer,
|
|
&pBuf,
|
|
MAX_PREFERRED_LENGTH,
|
|
&entriesread,
|
|
&totalentries,
|
|
NULL);
|
|
if (NO_ERROR == err)
|
|
{
|
|
appAssert(entriesread == totalentries);
|
|
appAssert(0 == entriesread || NULL != pBuf);
|
|
m_pSfmShares = (AFP_VOLUME_INFO*)pBuf;
|
|
m_cSfmShares = entriesread;
|
|
|
|
(*g_pfnAfpAdminDisconnect)(hServer);
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(err);
|
|
appDebugOut((DEB_ERROR, "AfpAdminVolumeEnum(%ws...) failed! Error = 0x%08lx\n", m_pszMachine, err));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
appDebugOut((DEB_ERROR, "AfpAdminConnect(%ws...) failed! Error = 0x%08lx\n", m_pszMachine, err));
|
|
hr = HRESULT_FROM_WIN32(err);
|
|
}
|
|
}
|
|
|
|
|
|
// Do FPNW shares
|
|
|
|
|
|
if (m_bDoFpnw)
|
|
{
|
|
// BUGBUG: do level 1 or level 2 based on security?
|
|
|
|
err = (*g_pfnFpnwVolumeEnum)(
|
|
m_pszMachine,
|
|
1, // level
|
|
&pBuf,
|
|
&entriesread,
|
|
NULL);
|
|
if (NO_ERROR == err)
|
|
{
|
|
appAssert(0 == entriesread || NULL != pBuf);
|
|
m_pFpnwShares = (FPNWVOLUMEINFO*)pBuf;
|
|
m_cFpnwShares = entriesread;
|
|
}
|
|
else
|
|
{
|
|
appDebugOut((DEB_ERROR, "FpnwVolumeEnum(%ws...) failed! Error = 0x%08lx\n", m_pszMachine, err));
|
|
hr = HRESULT_FROM_WIN32(err);
|
|
}
|
|
}
|
|
|
|
// Now create a linked list of shares. This just makes them easier to
|
|
// handle, though is arguably a waste of memory.
|
|
|
|
m_pShareList = new CShare(); // dummy head node
|
|
if (NULL == m_pShareList)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
DWORD i;
|
|
for (i = 0; i < m_cShares; i++)
|
|
{
|
|
CShare* ptmp = new CShare();
|
|
if (NULL == ptmp)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
ptmp->AddSmb(&m_pShares[i]);
|
|
ptmp->InsertBefore(m_pShareList);
|
|
}
|
|
|
|
for (i = 0; i < m_cSfmShares; i++)
|
|
{
|
|
CShare* ptmp = new CShare();
|
|
if (NULL == ptmp)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
ptmp->AddSfm(&m_pSfmShares[i]);
|
|
ptmp->InsertBefore(m_pShareList);
|
|
}
|
|
|
|
for (i = 0; i < m_cFpnwShares; i++)
|
|
{
|
|
CShare* ptmp = new CShare();
|
|
if (NULL == ptmp)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
ptmp->AddFpnw(&m_pFpnwShares[i]);
|
|
ptmp->InsertBefore(m_pShareList);
|
|
}
|
|
|
|
m_pShareCurrent = (CShare*)m_pShareList->Next();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
CSharesEnum::~CSharesEnum()
|
|
{
|
|
if (NULL != m_pShares)
|
|
{
|
|
NetApiBufferFree(m_pShares);
|
|
}
|
|
if (NULL != m_pSfmShares)
|
|
{
|
|
(*g_pfnAfpAdminBufferFree)(m_pSfmShares);
|
|
}
|
|
if (NULL != m_pFpnwShares)
|
|
{
|
|
DWORD err = (*g_pfnFpnwApiBufferFree)(m_pFpnwShares);
|
|
if (NO_ERROR != err)
|
|
{
|
|
appDebugOut((DEB_ERROR, "FpnwApiBufferFree() failed! Error = 0x%08lx\n", err));
|
|
}
|
|
}
|
|
|
|
CShare* pCurrent = (CShare*) m_pShareList->Next();
|
|
while (pCurrent != m_pShareList)
|
|
{
|
|
CShare* pTmp = pCurrent;
|
|
pCurrent = (CShare*) pCurrent->Next();
|
|
pTmp->Unlink();
|
|
delete pTmp;
|
|
}
|
|
delete m_pShareList;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CSharesEnum::Next(
|
|
ULONG celt,
|
|
LPITEMIDLIST* ppidlOut,
|
|
ULONG* pceltFetched
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IDSHARE ids;
|
|
ULONG celtFetched = 0;
|
|
CShare* pShare;
|
|
|
|
if (NULL == pceltFetched)
|
|
{
|
|
if (celt != 1)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pceltFetched = 0;
|
|
}
|
|
|
|
if (celt == 0)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
if (!(m_uFlags & SHCONTF_NONFOLDERS))
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
CopyAnother:
|
|
|
|
if (celtFetched == celt)
|
|
{
|
|
if (NULL != pceltFetched)
|
|
{
|
|
*pceltFetched = celtFetched;
|
|
}
|
|
return S_OK; // got celt elements
|
|
}
|
|
|
|
// Do we have anything else left?
|
|
|
|
if (m_pShareCurrent == m_pShareList) // we're done iterating
|
|
{
|
|
if (NULL != pceltFetched)
|
|
{
|
|
*pceltFetched = celtFetched;
|
|
}
|
|
return S_FALSE; // didn't copy celt
|
|
}
|
|
|
|
// Get the next share
|
|
pShare = m_pShareCurrent;
|
|
appAssert(NULL != pShare);
|
|
pShare->FillID(&ids);
|
|
m_pShareCurrent = (CShare*) m_pShareCurrent->Next();
|
|
|
|
// CopyOne:
|
|
|
|
ppidlOut[celtFetched] = ILClone((LPCITEMIDLIST)(&ids));
|
|
if (NULL == ppidlOut[celtFetched])
|
|
{
|
|
// free up everything so far
|
|
for (ULONG i = 0; i < celtFetched; i++)
|
|
{
|
|
ILFree(ppidlOut[i]);
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
++celtFetched;
|
|
goto CopyAnother;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CSharesEnum::Skip(
|
|
ULONG celt
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CSharesEnum::Reset(
|
|
VOID
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CSharesEnum::Clone(
|
|
IEnumIDList** ppenum
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|