|
|
//+-------------------------------------------------------------------------
//
// 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) { LONG cch = lstrlen(psz) + 1; LPTSTR pszNew = new TCHAR[cch]; if (NULL != pszNew) { StringCchCopy(pszNew, cch, 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.
//
StringCchCopy(pszFileCopy, cchFile + 3, pszFile); if (TEXT('\\') == *(pszFileCopy + cchFile - 1)) { //
// Guard against pszFile already having a trailing backslash.
//
cchFile--; } StringCchCopy(pszFileCopy + cchFile, 3, 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) { StringCchCopy(pszBuffer, cchBuffer, 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()) { StringCchCopy(pszBuffer, cchBuffer, m_rgpszFileNames[i]); int cch = (lstrlen(m_rgpszFileNames[i]) + 1); pszBuffer += cch; cchBuffer -= 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; }
|