windows-nt/Source/XPSP1/NT/shell/ext/cscui/filelist.cpp

1189 lines
25 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: filelist.cpp
//
//--------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////
/* File: filelist.cpp
Description: Simplifies the transmission of a list of share and
associated file names between components of the CSC UI. See
description in filelist.h for details.
Classes:
CscFilenameList
CscFilenameList::HSHARE
CscFilenameList::ShareIter
CscFilenameList::FileIter
Note: This module was written to be used by any part of the CSCUI,
not just the viewer. Therefore, I don't assume that the
new operator will throw an exception on allocation failures.
I don't like all the added code to detect allocation failures
but it's not reasonable to expect code in the other components
to become exception-aware with respect to "new" failures.
Revision History:
Date Description Programmer
-------- --------------------------------------------------- ----------
11/28/97 Initial creation. BrianAu
*/
///////////////////////////////////////////////////////////////////////////////
#include "pch.h"
#pragma hdrstop
#include "filelist.h"
#ifdef FILELIST_TEST
#include <stdio.h>
#include <tchar.h>
#endif
static LPTSTR DupStr(LPCTSTR psz)
{
LPTSTR pszNew = new TCHAR[lstrlen(psz) + 1];
if (NULL != pszNew)
{
lstrcpy(pszNew, psz);
}
return pszNew;
}
int CscFilenameList::m_cGrow = 4;
int CscFilenameList::Share::m_cGrow = 10;
CscFilenameList::CscFilenameList(
void
) : m_cShares(0),
m_cAllocated(0),
m_rgpShares(NULL),
m_bValid(true)
{
}
CscFilenameList::CscFilenameList(
PCSC_NAMELIST_HDR pbNames,
bool bCopy
) : m_cShares(0),
m_cAllocated(0),
m_rgpShares(NULL),
m_bValid(true)
{
m_bValid = LoadFromBuffer(pbNames, bCopy);
}
CscFilenameList::~CscFilenameList(
void
)
{
for (int i = 0; i < m_cShares; i++)
{
delete m_rgpShares[i];
}
delete[] m_rgpShares;
}
bool
CscFilenameList::LoadFromBuffer(
PCSC_NAMELIST_HDR pHdr,
bool bCopy
)
{
LPBYTE pbBuffer = reinterpret_cast<LPBYTE>(pHdr);
CSC_NAMELIST_SHARE_DESC *pShareDesc = (CSC_NAMELIST_SHARE_DESC *)(pbBuffer + sizeof(CSC_NAMELIST_HDR));
for (UINT i = 0; i < pHdr->cShares; i++)
{
LPCTSTR pszShareName = (LPCTSTR)(pbBuffer + pShareDesc->cbOfsShareName);
LPCTSTR pszFileName = (LPCTSTR)(pbBuffer + pShareDesc->cbOfsFileNames);
HSHARE hShare;
if (!AddShare(pszShareName, &hShare, bCopy))
{
return false; // memory allocation failure.
}
else
{
for (UINT j = 0; j < pShareDesc->cFiles; j++)
{
//
// Note that we always pass "false" for the bDirectory
// argument to AddFile(). Passing true causes the
// string "\*" to be appended to the filename stored
// in the collection. Since we're getting names from
// an existing namelist buffer, directories will already
// have the "\*" appended. We don't want to append a
// second instance.
//
if (!AddFile(hShare, pszFileName, false, bCopy))
{
return false; // memory allocation failure.
}
pszFileName += (lstrlen(pszFileName) + 1);
}
}
pShareDesc++;
}
return true;
}
bool
CscFilenameList::AddShare(
LPCTSTR pszShare,
HSHARE *phShare,
bool bCopy
)
{
bool bResult = true;
if (m_cShares == m_cAllocated)
bResult = GrowSharePtrList();
if (bResult)
{
bResult = false;
Share *pShare = new Share(pszShare, bCopy);
if (NULL != pShare)
{
m_rgpShares[m_cShares++] = pShare;
*phShare = HSHARE(pShare);
bResult = true;
}
}
return bResult;
}
bool
CscFilenameList::AddFile(
HSHARE& hShare,
LPCTSTR pszFile,
bool bDirectory,
bool bCopy
)
{
return hShare.m_pShare->AddFile(pszFile, bDirectory, bCopy);
}
//
// Given a full UNC path name, separate the share and file names with
// a nul character and return the address of the share and file name
// parts. Note that the buffer pointed to by pszFullPath is modified.
//
void
CscFilenameList::ParseFullPath(
LPTSTR pszFullPath,
LPTSTR *ppszShare,
LPTSTR *ppszFile
) const
{
*ppszShare = NULL;
*ppszFile = pszFullPath;
LPTSTR psz = pszFullPath;
if (*psz && *psz == TEXT('\\'))
{
psz++;
if (*psz && *psz == TEXT('\\'))
{
*ppszShare = pszFullPath; // Assume a share name.
*ppszFile = NULL;
psz++;
while(*psz && *psz != TEXT('\\'))
{
psz = CharNext(psz);
}
if (*psz)
psz = CharNext(psz);
while(*psz && *psz != TEXT('\\'))
{
psz = CharNext(psz);
}
if (*psz)
{
*ppszFile = CharNext(psz);
*psz = TEXT('\0');
}
}
}
}
bool
CscFilenameList::AddFile(
LPCTSTR pszFullPath,
bool bDirectory,
bool bCopy
)
{
bool bResult = false;
LPTSTR pszShare = NULL;
LPTSTR pszFile = NULL;
LPTSTR pszParsedPath = DupStr(pszFullPath);
if (NULL != pszParsedPath)
{
TCHAR szBackslash[] = TEXT("\\");
ParseFullPath(pszParsedPath, &pszShare, &pszFile);
if (NULL == pszFile || TEXT('\0') == *pszFile)
{
//
// Path was just a share name with no file or subdirectory.
//
pszFile = szBackslash;
}
if (NULL != pszShare)
{
bResult = AddFile(pszShare, pszFile, bDirectory, bCopy);
}
delete[] pszParsedPath;
}
return bResult;
}
bool
CscFilenameList::AddFile(
LPCTSTR pszShare,
LPCTSTR pszFile,
bool bDirectory,
bool bCopy
)
{
HSHARE hShare;
if (!GetShareHandle(pszShare, &hShare))
{
if (!AddShare(pszShare, &hShare, bCopy))
{
return false; // memory allocation failure.
}
}
return AddFile(hShare, pszFile, bDirectory, bCopy);
}
bool
CscFilenameList::RemoveFile(
HSHARE& hShare,
LPCTSTR pszFile
)
{
return hShare.m_pShare->RemoveFile(pszFile);
}
bool
CscFilenameList::RemoveFile(
LPCTSTR pszFullPath
)
{
bool bResult = false;
LPTSTR pszShare = NULL;
LPTSTR pszFile = NULL;
LPTSTR pszParsedPath = DupStr(pszFullPath);
if (NULL != pszParsedPath)
{
TCHAR szBackslash[] = TEXT("\\");
ParseFullPath(pszParsedPath, &pszShare, &pszFile);
if (NULL == pszFile || TEXT('\0') == *pszFile)
{
//
// Path was just a share name with no file or subdirectory.
//
pszFile = szBackslash;
}
if (NULL != pszShare)
{
bResult = RemoveFile(pszShare, pszFile);
}
delete[] pszParsedPath;
}
return bResult;
}
bool
CscFilenameList::RemoveFile(
LPCTSTR pszShare,
LPCTSTR pszFile
)
{
HSHARE hShare;
if (!GetShareHandle(pszShare, &hShare))
{
return false; // doesn't exist
}
return RemoveFile(hShare, pszFile);
}
LPCTSTR
CscFilenameList::GetShareName(
HSHARE& hShare
) const
{
return static_cast<LPCTSTR>(hShare.m_pShare->m_pszShareName);
}
int
CscFilenameList::GetShareCount(
void
) const
{
return m_cShares;
}
int
CscFilenameList::GetFileCount(
void
) const
{
int cFiles = 0;
ShareIter si = CreateShareIterator();
HSHARE hShare;
while(si.Next(&hShare))
{
cFiles += GetShareFileCount(hShare);
}
return cFiles;
}
int
CscFilenameList::GetShareFileCount(
HSHARE& hShare
) const
{
return hShare.m_pShare->m_cFiles;
}
bool
CscFilenameList::ShareExists(
LPCTSTR pszShare
) const
{
HSHARE hShare;
return GetShareHandle(pszShare, &hShare);
}
//
// Replacement for lstrcmpi that adds a little twist for the
// filename list.
// If the *pbExact argument [in] is false AND if the s1
// string argument is appended with "\*", it is assumed to be a
// directory name and all descendents of that directory produce a
// match. *pbExact is modified to indicate if the match was
// an exact match or a wildcard match as just described.
// If *pbExact is false on entry, the function works just like
// lstrcmpi except that the return value is true/false instead
// of <0, 0, >0.
//
bool
CscFilenameList::Compare(
LPCTSTR s1,
LPCTSTR s2,
bool *pbExact
)
{
LPCTSTR s1First = s1;
bool bMatch = false;
TraceAssert((NULL != pbExact));
while(*s1 || *s2)
{
//
// Do a case-insensitive comparison.
//
if (PtrToUlong(CharUpper((LPTSTR)(*s1))) == PtrToUlong(CharUpper((LPTSTR)(*s2))))
{
s1 = CharNext(s1);
s2 = CharNext(s2);
}
else
{
if (!(*pbExact))
{
//
// An exact match is not required. Now check for
// wildcard match.
//
if (TEXT('\0') == *s2 &&
TEXT('\\') == *s1 &&
TEXT('*') == *(s1+1))
{
//
// At end of key string provided by user.
// We have a match if the string being tested
// contains "\*" at current test location.
//
// i.e. "foo\bar" matches "foo\bar\*"
//
bMatch = true;
*pbExact = false;
}
else if (TEXT('*') == *s1)
{
//
// We hit a '*' in the stored string.
// Since we've matched up to this point, the
// user's string is an automatic match.
//
bMatch = TEXT('\0') == *(s1+1);
*pbExact = false;
}
}
goto return_result;
}
}
if (TEXT('\0') == *s1 && TEXT('\0') == *s2)
{
//
// Exact match.
//
*pbExact = bMatch = true;
goto return_result;
}
return_result:
return bMatch;
}
bool
CscFilenameList::FileExists(
HSHARE& hShare,
LPCTSTR pszFile,
bool bExact // Default == true
) const
{
FileIter fi = CreateFileIterator(hShare);
//
// Skip past any leading backslashes for matching purposes.
// File names (paths) stored in the filename list don't have
// leading backslashes. It's implied as the root directory.
//
while(*pszFile && TEXT('\\') == *pszFile)
pszFile = CharNext(pszFile);
LPCTSTR psz;
while(NULL != (psz = fi.Next()))
{
bool bExactResult = bExact;
if (Compare(psz, pszFile, &bExactResult)) // Modifies bExactResult.
{
return !bExact || (bExact && bExactResult);
}
}
return false;
}
bool
CscFilenameList::FileExists(
LPCTSTR pszShare,
LPCTSTR pszFile,
bool bExact // Default == true
) const
{
HSHARE hShare;
return (GetShareHandle(pszShare, &hShare) &&
FileExists(hShare, pszFile, bExact));
}
bool
CscFilenameList::FileExists(
LPCTSTR pszFullPath,
bool bExact // Default = true
) const
{
bool bResult = false;
LPTSTR pszShare = NULL;
LPTSTR pszFile = NULL;
LPTSTR pszParsedPath = DupStr(pszFullPath);
if (NULL != pszParsedPath)
{
ParseFullPath(pszParsedPath, &pszShare, &pszFile);
if (NULL != pszShare && NULL != pszFile)
{
bResult = FileExists(pszShare, pszFile, bExact);
}
delete[] pszParsedPath;
}
return bResult;
}
CscFilenameList::FileIter
CscFilenameList::CreateFileIterator(
HSHARE& hShare
) const
{
return FileIter(hShare.m_pShare);
}
CscFilenameList::ShareIter
CscFilenameList::CreateShareIterator(
void
) const
{
return ShareIter(*this);
}
bool
CscFilenameList::GetShareHandle(
LPCTSTR pszShare,
HSHARE *phShare
) const
{
Share *pShare = NULL;
for (int i = 0; i < m_cShares; i++)
{
pShare = m_rgpShares[i];
if (pShare->m_pszShareName.IsValid() && 0 == lstrcmpi(pszShare, pShare->m_pszShareName))
{
*phShare = HSHARE(pShare);
return true;
}
}
return false;
}
bool
CscFilenameList::GrowSharePtrList(
void
)
{
Share **rgpShares = new Share *[m_cAllocated + m_cGrow];
if (NULL != rgpShares)
{
if (NULL != m_rgpShares)
CopyMemory(rgpShares, m_rgpShares, m_cAllocated * sizeof(Share *));
delete[] m_rgpShares;
m_rgpShares = rgpShares;
m_cAllocated += m_cGrow;
}
return (NULL != rgpShares);
}
//
// Create a memory buffer to hold the contents of the name list.
// The buffer is formatted as described in the header of filelist.h.
//
PCSC_NAMELIST_HDR
CscFilenameList::CreateListBuffer(
void
) const
{
int i;
//
// Calculate the required buffer size and allocate buffer.
//
int cbOfsNames = sizeof(CSC_NAMELIST_HDR) +
sizeof(CSC_NAMELIST_SHARE_DESC) * m_cShares;
int cbBuffer = cbOfsNames;
for (i = 0; i < m_cShares; i++)
{
cbBuffer += m_rgpShares[i]->ByteCount();
}
LPBYTE pbBuffer = new BYTE[cbBuffer];
PCSC_NAMELIST_HDR pHdr = reinterpret_cast<PCSC_NAMELIST_HDR>(pbBuffer);
if (NULL != pbBuffer)
{
LPTSTR pszNames = reinterpret_cast<LPTSTR>(pbBuffer + cbOfsNames);
CSC_NAMELIST_SHARE_DESC *pShareDescs = reinterpret_cast<CSC_NAMELIST_SHARE_DESC *>(pbBuffer + sizeof(CSC_NAMELIST_HDR));
int cchNames = (cbBuffer - cbOfsNames) / sizeof(TCHAR);
//
// Write the share and file name strings.
//
for (i = 0; i < m_cShares; i++)
{
CSC_NAMELIST_SHARE_DESC *pDesc = pShareDescs + i;
Share *pShare = m_rgpShares[i];
int cch = pShare->Write(pbBuffer,
pDesc,
pszNames,
cchNames);
cchNames -= cch;
pszNames += cch;
}
//
// Fill in the buffer header.
//
pHdr->cbSize = cbBuffer;
pHdr->cShares = m_cShares;
}
return pHdr;
}
void
CscFilenameList::FreeListBuffer(
PCSC_NAMELIST_HDR pbNames
)
{
delete[] pbNames;
}
#ifdef FILELIST_TEST
void
CscFilenameList::Dump(
void
) const
{
_tprintf(TEXT("Dump share name list at 0x%08X\n"), (DWORD)this);
_tprintf(TEXT("\tm_cShares......: %d\n"), m_cShares);
_tprintf(TEXT("\tm_cAllocated...: %d\n"), m_cAllocated);
for (int i = 0; i < m_cShares; i++)
{
m_rgpShares[i]->Dump();
}
}
void
CscFilenameList::DumpListBuffer(
PCSC_NAMELIST_HDR pHdr
) const
{
LPBYTE pbBuffer = (LPBYTE)pHdr;
_tprintf(TEXT("Dump buffer at 0x%08X\n"), (DWORD)pbBuffer);
_tprintf(TEXT("hdr.cbSize......: %d\n"), pHdr->cbSize);
_tprintf(TEXT("hdr.flags.......: %d\n"), pHdr->flags);
_tprintf(TEXT("hdr.cShares.....: %d\n"), pHdr->cShares);
CSC_NAMELIST_SHARE_DESC *pDesc = (CSC_NAMELIST_SHARE_DESC *)(pbBuffer + sizeof(CSC_NAMELIST_HDR));
for (UINT i = 0; i < pHdr->cShares; i++)
{
_tprintf(TEXT("\tShare [%d] header\n"), i);
_tprintf(TEXT("\t\tcbOfsShareName..:%d\n"), pDesc->cbOfsShareName);
_tprintf(TEXT("\t\tcbOfsFileNames..:%d\n"), pDesc->cbOfsFileNames);
_tprintf(TEXT("\t\tcFiles..........:%d\n"), pDesc->cFiles);
LPTSTR pszName = (LPTSTR)(pbBuffer + pDesc->cbOfsShareName);
_tprintf(TEXT("\t\tShare name......: \"%s\"\n"), pszName);
pszName += lstrlen(pszName) + 1;
for (UINT j = 0; j < pDesc->cFiles; j++)
{
_tprintf(TEXT("\t\tFile[%3d] name...: \"%s\"\n"), j, pszName);
pszName += lstrlen(pszName) + 1;
}
pDesc++;
}
}
#endif // FILELIST_TEST
CscFilenameList::Share::Share(
LPCTSTR pszShare,
bool bCopy
) : m_pszShareName(pszShare, bCopy),
m_cFiles(0),
m_cAllocated(0),
m_cchFileNames(0),
m_cchShareName(lstrlen(pszShare) + 1),
m_rgpszFileNames(NULL)
{
}
CscFilenameList::Share::~Share(
void
)
{
delete[] m_rgpszFileNames;
}
bool
CscFilenameList::Share::AddFile(
LPCTSTR pszFile,
bool bDirectory,
bool bCopy
)
{
bool bResult = true;
TraceAssert((NULL != pszFile && TEXT('\0') != *pszFile));
if (NULL == pszFile || TEXT('\0') == *pszFile)
return false;
if (m_cFiles == m_cAllocated)
bResult = GrowFileNamePtrList();
if (bResult)
{
LPTSTR pszFileCopy = NULL;
if (bDirectory)
{
int cchFile = lstrlen(pszFile);
pszFileCopy = new TCHAR[cchFile + 3]; // length + "\*" + nul
if (NULL == pszFileCopy)
return false; // memory alloc failure.
//
// Append "\*" to a directory entry.
// This will allow us to do lookups on files that
// are descendants of a directory. See
// CscFilenameList::FileExists() for details.
//
lstrcpy(pszFileCopy, pszFile);
if (TEXT('\\') == *(pszFileCopy + cchFile - 1))
{
//
// Guard against pszFile already having a trailing backslash.
//
cchFile--;
}
lstrcpy(pszFileCopy + cchFile, TEXT("\\*"));
pszFile = pszFileCopy;
}
//
// Skip past any leading backslash.
//
while(*pszFile && TEXT('\\') == *pszFile)
pszFile = CharNext(pszFile);
NamePtr np(pszFile, bCopy);
if (bResult = np.IsValid())
{
m_rgpszFileNames[m_cFiles++] = np;
m_cchFileNames += (lstrlen(pszFile) + 1);
}
delete[] pszFileCopy;
}
return bResult;
}
bool
CscFilenameList::Share::RemoveFile(
LPCTSTR pszFile
)
{
TraceAssert((NULL != pszFile && TEXT('\0') != *pszFile));
if (NULL == pszFile || TEXT('\0') == *pszFile)
return false;
//
// Skip past any leading backslashes for matching purposes.
// File names (paths) stored in the filename list don't have
// leading backslashes. It's implied as the root directory.
//
while(*pszFile && TEXT('\\') == *pszFile)
pszFile = CharNext(pszFile);
for(int i = 0; i < m_cFiles; i++)
{
bool bExactResult = true;
if (Compare(m_rgpszFileNames[i], pszFile, &bExactResult)
&& bExactResult)
{
// Found an exact match. Move the last file into the
// current array location and decrement the count.
m_rgpszFileNames[i] = m_rgpszFileNames[--m_cFiles];
return true;
}
}
return false;
}
bool
CscFilenameList::Share::GrowFileNamePtrList(
void
)
{
CscFilenameList::NamePtr *rgpsz = new CscFilenameList::NamePtr[m_cAllocated + m_cGrow];
if (NULL != rgpsz)
{
m_cAllocated += m_cGrow;
if (NULL != m_rgpszFileNames)
{
for (int i = 0; i < m_cFiles; i++)
{
rgpsz[i] = m_rgpszFileNames[i];
}
}
delete[] m_rgpszFileNames;
m_rgpszFileNames = rgpsz;
}
return (NULL != rgpsz);
}
//
// Write the share name and file names to a text buffer.
//
int
CscFilenameList::Share::Write(
LPBYTE pbBufferStart, // Address of buffer start.
CSC_NAMELIST_SHARE_DESC *pShare, // Address of share descriptor.
LPTSTR pszBuffer, // Address of name buffer
int cchBuffer // Chars left in name buffer.
) const
{
pShare->cbOfsShareName = (DWORD)((LPBYTE)pszBuffer - pbBufferStart);
int cch = WriteName(pszBuffer, cchBuffer);
cchBuffer -= cch;
pszBuffer += cch;
pShare->cbOfsFileNames = (DWORD)((LPBYTE)pszBuffer - pbBufferStart);
cch += WriteFileNames(pszBuffer, cchBuffer, &pShare->cFiles);
return cch;
}
//
// Write the share name to a text buffer.
//
int
CscFilenameList::Share::WriteName(
LPTSTR pszBuffer,
int cchBuffer
) const
{
if (m_pszShareName.IsValid() && m_cchShareName <= cchBuffer)
{
lstrcpy(pszBuffer, m_pszShareName);
return m_cchShareName;
}
return 0;
}
//
// Write the file names to a text buffer.
//
int
CscFilenameList::Share::WriteFileNames(
LPTSTR pszBuffer,
int cchBuffer,
DWORD *pcFilesWritten // [out]. Count of files written.
) const
{
int cchWritten = 0;
DWORD cFilesWritten = 0;
if (m_cchFileNames <= cchBuffer)
{
for (int i = 0; i < m_cFiles; i++)
{
if (m_rgpszFileNames[i].IsValid())
{
lstrcpy(pszBuffer, m_rgpszFileNames[i]);
int cch = (lstrlen(m_rgpszFileNames[i]) + 1);
pszBuffer += cch;
cchWritten += cch;
cFilesWritten++;
}
}
}
if (NULL != pcFilesWritten)
{
*pcFilesWritten = cFilesWritten;
}
return cchWritten;
}
#ifdef FILELIST_TEST
void
CscFilenameList::Share::Dump(
void
) const
{
_tprintf(TEXT("Share \"%s\"\n"), (LPCTSTR)m_pszShareName ? (LPCTSTR)m_pszShareName : TEXT("<null>"));
_tprintf(TEXT("\tm_cFiles........: %d\n"), m_cFiles);
_tprintf(TEXT("\tm_cAllocated....: %d\n"), m_cAllocated);
_tprintf(TEXT("\tm_cchShareName..: %d\n"), m_cchShareName);
_tprintf(TEXT("\tm_cchFileNames..: %d\n"), m_cchFileNames);
for (int i = 0; i < m_cFiles; i++)
{
_tprintf(TEXT("\tFile[%3d].......: \"%s\"\n"), i, (LPCTSTR)m_rgpszFileNames[i] ? (LPCTSTR)m_rgpszFileNames[i] : TEXT("<null>"));
}
}
#endif // FILELIST_TEST
CscFilenameList::FileIter::FileIter(
const CscFilenameList::Share *pShare
) : m_pShare(pShare),
m_iFile(0)
{
}
CscFilenameList::FileIter::FileIter(
void
) : m_pShare(NULL),
m_iFile(0)
{
}
CscFilenameList::FileIter::FileIter(
const CscFilenameList::FileIter& rhs
)
{
*this = rhs;
}
CscFilenameList::FileIter&
CscFilenameList::FileIter::operator = (
const CscFilenameList::FileIter& rhs
)
{
if (this != &rhs)
{
m_pShare = rhs.m_pShare;
m_iFile = rhs.m_iFile;
}
return *this;
}
LPCTSTR
CscFilenameList::FileIter::Next(
void
)
{
if (0 < m_pShare->m_cFiles && m_iFile < m_pShare->m_cFiles)
return m_pShare->m_rgpszFileNames[m_iFile++];
return NULL;
}
void
CscFilenameList::FileIter::Reset(
void
)
{
m_iFile = 0;
}
CscFilenameList::ShareIter::ShareIter(
const CscFilenameList& fnl
) : m_pfnl(&fnl),
m_iShare(0)
{
}
CscFilenameList::ShareIter::ShareIter(
void
) : m_pfnl(NULL),
m_iShare(0)
{
}
CscFilenameList::ShareIter::ShareIter(
const CscFilenameList::ShareIter& rhs
)
{
*this = rhs;
}
CscFilenameList::ShareIter&
CscFilenameList::ShareIter::operator = (
const CscFilenameList::ShareIter& rhs
)
{
if (this != &rhs)
{
m_pfnl = rhs.m_pfnl;
m_iShare = rhs.m_iShare;
}
return *this;
}
bool
CscFilenameList::ShareIter::Next(
HSHARE *phShare
)
{
if (0 < m_pfnl->m_cShares && m_iShare < m_pfnl->m_cShares)
{
*phShare = HSHARE(m_pfnl->m_rgpShares[m_iShare++]);
return true;
}
return false;
}
void
CscFilenameList::ShareIter::Reset(
void
)
{
m_iShare = 0;
}
CscFilenameList::NamePtr::NamePtr(
LPCTSTR pszName,
bool bCopy
) : m_pszName(pszName),
m_bOwns(bCopy)
{
if (bCopy)
{
m_pszName = DupStr(pszName);
m_bOwns = true;
}
}
CscFilenameList::NamePtr::~NamePtr(
void
)
{
if (m_bOwns)
{
delete[] const_cast<LPTSTR>(m_pszName);
}
}
CscFilenameList::NamePtr::NamePtr(
CscFilenameList::NamePtr& rhs
)
{
*this = rhs;
}
CscFilenameList::NamePtr&
CscFilenameList::NamePtr::operator = (
CscFilenameList::NamePtr& rhs
)
{
if (this != &rhs)
{
if (m_bOwns)
delete[] (LPTSTR)m_pszName;
m_pszName = rhs.m_pszName;
m_bOwns = false;
if (rhs.m_bOwns)
{
//
// Assume ownership of the buffer.
//
rhs.m_bOwns = false;
m_bOwns = true;
}
}
return *this;
}
CscFilenameList::HSHARE::HSHARE(
void
) : m_pShare(NULL)
{
}
CscFilenameList::HSHARE::HSHARE(
const HSHARE& rhs
)
{
*this = rhs;
}
CscFilenameList::HSHARE&
CscFilenameList::HSHARE::operator = (
const CscFilenameList::HSHARE& rhs
)
{
if (this != &rhs)
{
m_pShare = rhs.m_pShare;
}
return *this;
}