Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1188 lines
25 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: filelist.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //////////////////////////////////////////////////////////////////////////////
  11. /* File: filelist.cpp
  12. Description: Simplifies the transmission of a list of share and
  13. associated file names between components of the CSC UI. See
  14. description in filelist.h for details.
  15. Classes:
  16. CscFilenameList
  17. CscFilenameList::HSHARE
  18. CscFilenameList::ShareIter
  19. CscFilenameList::FileIter
  20. Note: This module was written to be used by any part of the CSCUI,
  21. not just the viewer. Therefore, I don't assume that the
  22. new operator will throw an exception on allocation failures.
  23. I don't like all the added code to detect allocation failures
  24. but it's not reasonable to expect code in the other components
  25. to become exception-aware with respect to "new" failures.
  26. Revision History:
  27. Date Description Programmer
  28. -------- --------------------------------------------------- ----------
  29. 11/28/97 Initial creation. BrianAu
  30. */
  31. ///////////////////////////////////////////////////////////////////////////////
  32. #include "pch.h"
  33. #pragma hdrstop
  34. #include "filelist.h"
  35. #ifdef FILELIST_TEST
  36. #include <stdio.h>
  37. #include <tchar.h>
  38. #endif
  39. static LPTSTR DupStr(LPCTSTR psz)
  40. {
  41. LPTSTR pszNew = new TCHAR[lstrlen(psz) + 1];
  42. if (NULL != pszNew)
  43. {
  44. lstrcpy(pszNew, psz);
  45. }
  46. return pszNew;
  47. }
  48. int CscFilenameList::m_cGrow = 4;
  49. int CscFilenameList::Share::m_cGrow = 10;
  50. CscFilenameList::CscFilenameList(
  51. void
  52. ) : m_cShares(0),
  53. m_cAllocated(0),
  54. m_rgpShares(NULL),
  55. m_bValid(true)
  56. {
  57. }
  58. CscFilenameList::CscFilenameList(
  59. PCSC_NAMELIST_HDR pbNames,
  60. bool bCopy
  61. ) : m_cShares(0),
  62. m_cAllocated(0),
  63. m_rgpShares(NULL),
  64. m_bValid(true)
  65. {
  66. m_bValid = LoadFromBuffer(pbNames, bCopy);
  67. }
  68. CscFilenameList::~CscFilenameList(
  69. void
  70. )
  71. {
  72. for (int i = 0; i < m_cShares; i++)
  73. {
  74. delete m_rgpShares[i];
  75. }
  76. delete[] m_rgpShares;
  77. }
  78. bool
  79. CscFilenameList::LoadFromBuffer(
  80. PCSC_NAMELIST_HDR pHdr,
  81. bool bCopy
  82. )
  83. {
  84. LPBYTE pbBuffer = reinterpret_cast<LPBYTE>(pHdr);
  85. CSC_NAMELIST_SHARE_DESC *pShareDesc = (CSC_NAMELIST_SHARE_DESC *)(pbBuffer + sizeof(CSC_NAMELIST_HDR));
  86. for (UINT i = 0; i < pHdr->cShares; i++)
  87. {
  88. LPCTSTR pszShareName = (LPCTSTR)(pbBuffer + pShareDesc->cbOfsShareName);
  89. LPCTSTR pszFileName = (LPCTSTR)(pbBuffer + pShareDesc->cbOfsFileNames);
  90. HSHARE hShare;
  91. if (!AddShare(pszShareName, &hShare, bCopy))
  92. {
  93. return false; // memory allocation failure.
  94. }
  95. else
  96. {
  97. for (UINT j = 0; j < pShareDesc->cFiles; j++)
  98. {
  99. //
  100. // Note that we always pass "false" for the bDirectory
  101. // argument to AddFile(). Passing true causes the
  102. // string "\*" to be appended to the filename stored
  103. // in the collection. Since we're getting names from
  104. // an existing namelist buffer, directories will already
  105. // have the "\*" appended. We don't want to append a
  106. // second instance.
  107. //
  108. if (!AddFile(hShare, pszFileName, false, bCopy))
  109. {
  110. return false; // memory allocation failure.
  111. }
  112. pszFileName += (lstrlen(pszFileName) + 1);
  113. }
  114. }
  115. pShareDesc++;
  116. }
  117. return true;
  118. }
  119. bool
  120. CscFilenameList::AddShare(
  121. LPCTSTR pszShare,
  122. HSHARE *phShare,
  123. bool bCopy
  124. )
  125. {
  126. bool bResult = true;
  127. if (m_cShares == m_cAllocated)
  128. bResult = GrowSharePtrList();
  129. if (bResult)
  130. {
  131. bResult = false;
  132. Share *pShare = new Share(pszShare, bCopy);
  133. if (NULL != pShare)
  134. {
  135. m_rgpShares[m_cShares++] = pShare;
  136. *phShare = HSHARE(pShare);
  137. bResult = true;
  138. }
  139. }
  140. return bResult;
  141. }
  142. bool
  143. CscFilenameList::AddFile(
  144. HSHARE& hShare,
  145. LPCTSTR pszFile,
  146. bool bDirectory,
  147. bool bCopy
  148. )
  149. {
  150. return hShare.m_pShare->AddFile(pszFile, bDirectory, bCopy);
  151. }
  152. //
  153. // Given a full UNC path name, separate the share and file names with
  154. // a nul character and return the address of the share and file name
  155. // parts. Note that the buffer pointed to by pszFullPath is modified.
  156. //
  157. void
  158. CscFilenameList::ParseFullPath(
  159. LPTSTR pszFullPath,
  160. LPTSTR *ppszShare,
  161. LPTSTR *ppszFile
  162. ) const
  163. {
  164. *ppszShare = NULL;
  165. *ppszFile = pszFullPath;
  166. LPTSTR psz = pszFullPath;
  167. if (*psz && *psz == TEXT('\\'))
  168. {
  169. psz++;
  170. if (*psz && *psz == TEXT('\\'))
  171. {
  172. *ppszShare = pszFullPath; // Assume a share name.
  173. *ppszFile = NULL;
  174. psz++;
  175. while(*psz && *psz != TEXT('\\'))
  176. {
  177. psz = CharNext(psz);
  178. }
  179. if (*psz)
  180. psz = CharNext(psz);
  181. while(*psz && *psz != TEXT('\\'))
  182. {
  183. psz = CharNext(psz);
  184. }
  185. if (*psz)
  186. {
  187. *ppszFile = CharNext(psz);
  188. *psz = TEXT('\0');
  189. }
  190. }
  191. }
  192. }
  193. bool
  194. CscFilenameList::AddFile(
  195. LPCTSTR pszFullPath,
  196. bool bDirectory,
  197. bool bCopy
  198. )
  199. {
  200. bool bResult = false;
  201. LPTSTR pszShare = NULL;
  202. LPTSTR pszFile = NULL;
  203. LPTSTR pszParsedPath = DupStr(pszFullPath);
  204. if (NULL != pszParsedPath)
  205. {
  206. TCHAR szBackslash[] = TEXT("\\");
  207. ParseFullPath(pszParsedPath, &pszShare, &pszFile);
  208. if (NULL == pszFile || TEXT('\0') == *pszFile)
  209. {
  210. //
  211. // Path was just a share name with no file or subdirectory.
  212. //
  213. pszFile = szBackslash;
  214. }
  215. if (NULL != pszShare)
  216. {
  217. bResult = AddFile(pszShare, pszFile, bDirectory, bCopy);
  218. }
  219. delete[] pszParsedPath;
  220. }
  221. return bResult;
  222. }
  223. bool
  224. CscFilenameList::AddFile(
  225. LPCTSTR pszShare,
  226. LPCTSTR pszFile,
  227. bool bDirectory,
  228. bool bCopy
  229. )
  230. {
  231. HSHARE hShare;
  232. if (!GetShareHandle(pszShare, &hShare))
  233. {
  234. if (!AddShare(pszShare, &hShare, bCopy))
  235. {
  236. return false; // memory allocation failure.
  237. }
  238. }
  239. return AddFile(hShare, pszFile, bDirectory, bCopy);
  240. }
  241. bool
  242. CscFilenameList::RemoveFile(
  243. HSHARE& hShare,
  244. LPCTSTR pszFile
  245. )
  246. {
  247. return hShare.m_pShare->RemoveFile(pszFile);
  248. }
  249. bool
  250. CscFilenameList::RemoveFile(
  251. LPCTSTR pszFullPath
  252. )
  253. {
  254. bool bResult = false;
  255. LPTSTR pszShare = NULL;
  256. LPTSTR pszFile = NULL;
  257. LPTSTR pszParsedPath = DupStr(pszFullPath);
  258. if (NULL != pszParsedPath)
  259. {
  260. TCHAR szBackslash[] = TEXT("\\");
  261. ParseFullPath(pszParsedPath, &pszShare, &pszFile);
  262. if (NULL == pszFile || TEXT('\0') == *pszFile)
  263. {
  264. //
  265. // Path was just a share name with no file or subdirectory.
  266. //
  267. pszFile = szBackslash;
  268. }
  269. if (NULL != pszShare)
  270. {
  271. bResult = RemoveFile(pszShare, pszFile);
  272. }
  273. delete[] pszParsedPath;
  274. }
  275. return bResult;
  276. }
  277. bool
  278. CscFilenameList::RemoveFile(
  279. LPCTSTR pszShare,
  280. LPCTSTR pszFile
  281. )
  282. {
  283. HSHARE hShare;
  284. if (!GetShareHandle(pszShare, &hShare))
  285. {
  286. return false; // doesn't exist
  287. }
  288. return RemoveFile(hShare, pszFile);
  289. }
  290. LPCTSTR
  291. CscFilenameList::GetShareName(
  292. HSHARE& hShare
  293. ) const
  294. {
  295. return static_cast<LPCTSTR>(hShare.m_pShare->m_pszShareName);
  296. }
  297. int
  298. CscFilenameList::GetShareCount(
  299. void
  300. ) const
  301. {
  302. return m_cShares;
  303. }
  304. int
  305. CscFilenameList::GetFileCount(
  306. void
  307. ) const
  308. {
  309. int cFiles = 0;
  310. ShareIter si = CreateShareIterator();
  311. HSHARE hShare;
  312. while(si.Next(&hShare))
  313. {
  314. cFiles += GetShareFileCount(hShare);
  315. }
  316. return cFiles;
  317. }
  318. int
  319. CscFilenameList::GetShareFileCount(
  320. HSHARE& hShare
  321. ) const
  322. {
  323. return hShare.m_pShare->m_cFiles;
  324. }
  325. bool
  326. CscFilenameList::ShareExists(
  327. LPCTSTR pszShare
  328. ) const
  329. {
  330. HSHARE hShare;
  331. return GetShareHandle(pszShare, &hShare);
  332. }
  333. //
  334. // Replacement for lstrcmpi that adds a little twist for the
  335. // filename list.
  336. // If the *pbExact argument [in] is false AND if the s1
  337. // string argument is appended with "\*", it is assumed to be a
  338. // directory name and all descendents of that directory produce a
  339. // match. *pbExact is modified to indicate if the match was
  340. // an exact match or a wildcard match as just described.
  341. // If *pbExact is false on entry, the function works just like
  342. // lstrcmpi except that the return value is true/false instead
  343. // of <0, 0, >0.
  344. //
  345. bool
  346. CscFilenameList::Compare(
  347. LPCTSTR s1,
  348. LPCTSTR s2,
  349. bool *pbExact
  350. )
  351. {
  352. LPCTSTR s1First = s1;
  353. bool bMatch = false;
  354. TraceAssert((NULL != pbExact));
  355. while(*s1 || *s2)
  356. {
  357. //
  358. // Do a case-insensitive comparison.
  359. //
  360. if (PtrToUlong(CharUpper((LPTSTR)(*s1))) == PtrToUlong(CharUpper((LPTSTR)(*s2))))
  361. {
  362. s1 = CharNext(s1);
  363. s2 = CharNext(s2);
  364. }
  365. else
  366. {
  367. if (!(*pbExact))
  368. {
  369. //
  370. // An exact match is not required. Now check for
  371. // wildcard match.
  372. //
  373. if (TEXT('\0') == *s2 &&
  374. TEXT('\\') == *s1 &&
  375. TEXT('*') == *(s1+1))
  376. {
  377. //
  378. // At end of key string provided by user.
  379. // We have a match if the string being tested
  380. // contains "\*" at current test location.
  381. //
  382. // i.e. "foo\bar" matches "foo\bar\*"
  383. //
  384. bMatch = true;
  385. *pbExact = false;
  386. }
  387. else if (TEXT('*') == *s1)
  388. {
  389. //
  390. // We hit a '*' in the stored string.
  391. // Since we've matched up to this point, the
  392. // user's string is an automatic match.
  393. //
  394. bMatch = TEXT('\0') == *(s1+1);
  395. *pbExact = false;
  396. }
  397. }
  398. goto return_result;
  399. }
  400. }
  401. if (TEXT('\0') == *s1 && TEXT('\0') == *s2)
  402. {
  403. //
  404. // Exact match.
  405. //
  406. *pbExact = bMatch = true;
  407. goto return_result;
  408. }
  409. return_result:
  410. return bMatch;
  411. }
  412. bool
  413. CscFilenameList::FileExists(
  414. HSHARE& hShare,
  415. LPCTSTR pszFile,
  416. bool bExact // Default == true
  417. ) const
  418. {
  419. FileIter fi = CreateFileIterator(hShare);
  420. //
  421. // Skip past any leading backslashes for matching purposes.
  422. // File names (paths) stored in the filename list don't have
  423. // leading backslashes. It's implied as the root directory.
  424. //
  425. while(*pszFile && TEXT('\\') == *pszFile)
  426. pszFile = CharNext(pszFile);
  427. LPCTSTR psz;
  428. while(NULL != (psz = fi.Next()))
  429. {
  430. bool bExactResult = bExact;
  431. if (Compare(psz, pszFile, &bExactResult)) // Modifies bExactResult.
  432. {
  433. return !bExact || (bExact && bExactResult);
  434. }
  435. }
  436. return false;
  437. }
  438. bool
  439. CscFilenameList::FileExists(
  440. LPCTSTR pszShare,
  441. LPCTSTR pszFile,
  442. bool bExact // Default == true
  443. ) const
  444. {
  445. HSHARE hShare;
  446. return (GetShareHandle(pszShare, &hShare) &&
  447. FileExists(hShare, pszFile, bExact));
  448. }
  449. bool
  450. CscFilenameList::FileExists(
  451. LPCTSTR pszFullPath,
  452. bool bExact // Default = true
  453. ) const
  454. {
  455. bool bResult = false;
  456. LPTSTR pszShare = NULL;
  457. LPTSTR pszFile = NULL;
  458. LPTSTR pszParsedPath = DupStr(pszFullPath);
  459. if (NULL != pszParsedPath)
  460. {
  461. ParseFullPath(pszParsedPath, &pszShare, &pszFile);
  462. if (NULL != pszShare && NULL != pszFile)
  463. {
  464. bResult = FileExists(pszShare, pszFile, bExact);
  465. }
  466. delete[] pszParsedPath;
  467. }
  468. return bResult;
  469. }
  470. CscFilenameList::FileIter
  471. CscFilenameList::CreateFileIterator(
  472. HSHARE& hShare
  473. ) const
  474. {
  475. return FileIter(hShare.m_pShare);
  476. }
  477. CscFilenameList::ShareIter
  478. CscFilenameList::CreateShareIterator(
  479. void
  480. ) const
  481. {
  482. return ShareIter(*this);
  483. }
  484. bool
  485. CscFilenameList::GetShareHandle(
  486. LPCTSTR pszShare,
  487. HSHARE *phShare
  488. ) const
  489. {
  490. Share *pShare = NULL;
  491. for (int i = 0; i < m_cShares; i++)
  492. {
  493. pShare = m_rgpShares[i];
  494. if (pShare->m_pszShareName.IsValid() && 0 == lstrcmpi(pszShare, pShare->m_pszShareName))
  495. {
  496. *phShare = HSHARE(pShare);
  497. return true;
  498. }
  499. }
  500. return false;
  501. }
  502. bool
  503. CscFilenameList::GrowSharePtrList(
  504. void
  505. )
  506. {
  507. Share **rgpShares = new Share *[m_cAllocated + m_cGrow];
  508. if (NULL != rgpShares)
  509. {
  510. if (NULL != m_rgpShares)
  511. CopyMemory(rgpShares, m_rgpShares, m_cAllocated * sizeof(Share *));
  512. delete[] m_rgpShares;
  513. m_rgpShares = rgpShares;
  514. m_cAllocated += m_cGrow;
  515. }
  516. return (NULL != rgpShares);
  517. }
  518. //
  519. // Create a memory buffer to hold the contents of the name list.
  520. // The buffer is formatted as described in the header of filelist.h.
  521. //
  522. PCSC_NAMELIST_HDR
  523. CscFilenameList::CreateListBuffer(
  524. void
  525. ) const
  526. {
  527. int i;
  528. //
  529. // Calculate the required buffer size and allocate buffer.
  530. //
  531. int cbOfsNames = sizeof(CSC_NAMELIST_HDR) +
  532. sizeof(CSC_NAMELIST_SHARE_DESC) * m_cShares;
  533. int cbBuffer = cbOfsNames;
  534. for (i = 0; i < m_cShares; i++)
  535. {
  536. cbBuffer += m_rgpShares[i]->ByteCount();
  537. }
  538. LPBYTE pbBuffer = new BYTE[cbBuffer];
  539. PCSC_NAMELIST_HDR pHdr = reinterpret_cast<PCSC_NAMELIST_HDR>(pbBuffer);
  540. if (NULL != pbBuffer)
  541. {
  542. LPTSTR pszNames = reinterpret_cast<LPTSTR>(pbBuffer + cbOfsNames);
  543. CSC_NAMELIST_SHARE_DESC *pShareDescs = reinterpret_cast<CSC_NAMELIST_SHARE_DESC *>(pbBuffer + sizeof(CSC_NAMELIST_HDR));
  544. int cchNames = (cbBuffer - cbOfsNames) / sizeof(TCHAR);
  545. //
  546. // Write the share and file name strings.
  547. //
  548. for (i = 0; i < m_cShares; i++)
  549. {
  550. CSC_NAMELIST_SHARE_DESC *pDesc = pShareDescs + i;
  551. Share *pShare = m_rgpShares[i];
  552. int cch = pShare->Write(pbBuffer,
  553. pDesc,
  554. pszNames,
  555. cchNames);
  556. cchNames -= cch;
  557. pszNames += cch;
  558. }
  559. //
  560. // Fill in the buffer header.
  561. //
  562. pHdr->cbSize = cbBuffer;
  563. pHdr->cShares = m_cShares;
  564. }
  565. return pHdr;
  566. }
  567. void
  568. CscFilenameList::FreeListBuffer(
  569. PCSC_NAMELIST_HDR pbNames
  570. )
  571. {
  572. delete[] pbNames;
  573. }
  574. #ifdef FILELIST_TEST
  575. void
  576. CscFilenameList::Dump(
  577. void
  578. ) const
  579. {
  580. _tprintf(TEXT("Dump share name list at 0x%08X\n"), (DWORD)this);
  581. _tprintf(TEXT("\tm_cShares......: %d\n"), m_cShares);
  582. _tprintf(TEXT("\tm_cAllocated...: %d\n"), m_cAllocated);
  583. for (int i = 0; i < m_cShares; i++)
  584. {
  585. m_rgpShares[i]->Dump();
  586. }
  587. }
  588. void
  589. CscFilenameList::DumpListBuffer(
  590. PCSC_NAMELIST_HDR pHdr
  591. ) const
  592. {
  593. LPBYTE pbBuffer = (LPBYTE)pHdr;
  594. _tprintf(TEXT("Dump buffer at 0x%08X\n"), (DWORD)pbBuffer);
  595. _tprintf(TEXT("hdr.cbSize......: %d\n"), pHdr->cbSize);
  596. _tprintf(TEXT("hdr.flags.......: %d\n"), pHdr->flags);
  597. _tprintf(TEXT("hdr.cShares.....: %d\n"), pHdr->cShares);
  598. CSC_NAMELIST_SHARE_DESC *pDesc = (CSC_NAMELIST_SHARE_DESC *)(pbBuffer + sizeof(CSC_NAMELIST_HDR));
  599. for (UINT i = 0; i < pHdr->cShares; i++)
  600. {
  601. _tprintf(TEXT("\tShare [%d] header\n"), i);
  602. _tprintf(TEXT("\t\tcbOfsShareName..:%d\n"), pDesc->cbOfsShareName);
  603. _tprintf(TEXT("\t\tcbOfsFileNames..:%d\n"), pDesc->cbOfsFileNames);
  604. _tprintf(TEXT("\t\tcFiles..........:%d\n"), pDesc->cFiles);
  605. LPTSTR pszName = (LPTSTR)(pbBuffer + pDesc->cbOfsShareName);
  606. _tprintf(TEXT("\t\tShare name......: \"%s\"\n"), pszName);
  607. pszName += lstrlen(pszName) + 1;
  608. for (UINT j = 0; j < pDesc->cFiles; j++)
  609. {
  610. _tprintf(TEXT("\t\tFile[%3d] name...: \"%s\"\n"), j, pszName);
  611. pszName += lstrlen(pszName) + 1;
  612. }
  613. pDesc++;
  614. }
  615. }
  616. #endif // FILELIST_TEST
  617. CscFilenameList::Share::Share(
  618. LPCTSTR pszShare,
  619. bool bCopy
  620. ) : m_pszShareName(pszShare, bCopy),
  621. m_cFiles(0),
  622. m_cAllocated(0),
  623. m_cchFileNames(0),
  624. m_cchShareName(lstrlen(pszShare) + 1),
  625. m_rgpszFileNames(NULL)
  626. {
  627. }
  628. CscFilenameList::Share::~Share(
  629. void
  630. )
  631. {
  632. delete[] m_rgpszFileNames;
  633. }
  634. bool
  635. CscFilenameList::Share::AddFile(
  636. LPCTSTR pszFile,
  637. bool bDirectory,
  638. bool bCopy
  639. )
  640. {
  641. bool bResult = true;
  642. TraceAssert((NULL != pszFile && TEXT('\0') != *pszFile));
  643. if (NULL == pszFile || TEXT('\0') == *pszFile)
  644. return false;
  645. if (m_cFiles == m_cAllocated)
  646. bResult = GrowFileNamePtrList();
  647. if (bResult)
  648. {
  649. LPTSTR pszFileCopy = NULL;
  650. if (bDirectory)
  651. {
  652. int cchFile = lstrlen(pszFile);
  653. pszFileCopy = new TCHAR[cchFile + 3]; // length + "\*" + nul
  654. if (NULL == pszFileCopy)
  655. return false; // memory alloc failure.
  656. //
  657. // Append "\*" to a directory entry.
  658. // This will allow us to do lookups on files that
  659. // are descendants of a directory. See
  660. // CscFilenameList::FileExists() for details.
  661. //
  662. lstrcpy(pszFileCopy, pszFile);
  663. if (TEXT('\\') == *(pszFileCopy + cchFile - 1))
  664. {
  665. //
  666. // Guard against pszFile already having a trailing backslash.
  667. //
  668. cchFile--;
  669. }
  670. lstrcpy(pszFileCopy + cchFile, TEXT("\\*"));
  671. pszFile = pszFileCopy;
  672. }
  673. //
  674. // Skip past any leading backslash.
  675. //
  676. while(*pszFile && TEXT('\\') == *pszFile)
  677. pszFile = CharNext(pszFile);
  678. NamePtr np(pszFile, bCopy);
  679. if (bResult = np.IsValid())
  680. {
  681. m_rgpszFileNames[m_cFiles++] = np;
  682. m_cchFileNames += (lstrlen(pszFile) + 1);
  683. }
  684. delete[] pszFileCopy;
  685. }
  686. return bResult;
  687. }
  688. bool
  689. CscFilenameList::Share::RemoveFile(
  690. LPCTSTR pszFile
  691. )
  692. {
  693. TraceAssert((NULL != pszFile && TEXT('\0') != *pszFile));
  694. if (NULL == pszFile || TEXT('\0') == *pszFile)
  695. return false;
  696. //
  697. // Skip past any leading backslashes for matching purposes.
  698. // File names (paths) stored in the filename list don't have
  699. // leading backslashes. It's implied as the root directory.
  700. //
  701. while(*pszFile && TEXT('\\') == *pszFile)
  702. pszFile = CharNext(pszFile);
  703. for(int i = 0; i < m_cFiles; i++)
  704. {
  705. bool bExactResult = true;
  706. if (Compare(m_rgpszFileNames[i], pszFile, &bExactResult)
  707. && bExactResult)
  708. {
  709. // Found an exact match. Move the last file into the
  710. // current array location and decrement the count.
  711. m_rgpszFileNames[i] = m_rgpszFileNames[--m_cFiles];
  712. return true;
  713. }
  714. }
  715. return false;
  716. }
  717. bool
  718. CscFilenameList::Share::GrowFileNamePtrList(
  719. void
  720. )
  721. {
  722. CscFilenameList::NamePtr *rgpsz = new CscFilenameList::NamePtr[m_cAllocated + m_cGrow];
  723. if (NULL != rgpsz)
  724. {
  725. m_cAllocated += m_cGrow;
  726. if (NULL != m_rgpszFileNames)
  727. {
  728. for (int i = 0; i < m_cFiles; i++)
  729. {
  730. rgpsz[i] = m_rgpszFileNames[i];
  731. }
  732. }
  733. delete[] m_rgpszFileNames;
  734. m_rgpszFileNames = rgpsz;
  735. }
  736. return (NULL != rgpsz);
  737. }
  738. //
  739. // Write the share name and file names to a text buffer.
  740. //
  741. int
  742. CscFilenameList::Share::Write(
  743. LPBYTE pbBufferStart, // Address of buffer start.
  744. CSC_NAMELIST_SHARE_DESC *pShare, // Address of share descriptor.
  745. LPTSTR pszBuffer, // Address of name buffer
  746. int cchBuffer // Chars left in name buffer.
  747. ) const
  748. {
  749. pShare->cbOfsShareName = (DWORD)((LPBYTE)pszBuffer - pbBufferStart);
  750. int cch = WriteName(pszBuffer, cchBuffer);
  751. cchBuffer -= cch;
  752. pszBuffer += cch;
  753. pShare->cbOfsFileNames = (DWORD)((LPBYTE)pszBuffer - pbBufferStart);
  754. cch += WriteFileNames(pszBuffer, cchBuffer, &pShare->cFiles);
  755. return cch;
  756. }
  757. //
  758. // Write the share name to a text buffer.
  759. //
  760. int
  761. CscFilenameList::Share::WriteName(
  762. LPTSTR pszBuffer,
  763. int cchBuffer
  764. ) const
  765. {
  766. if (m_pszShareName.IsValid() && m_cchShareName <= cchBuffer)
  767. {
  768. lstrcpy(pszBuffer, m_pszShareName);
  769. return m_cchShareName;
  770. }
  771. return 0;
  772. }
  773. //
  774. // Write the file names to a text buffer.
  775. //
  776. int
  777. CscFilenameList::Share::WriteFileNames(
  778. LPTSTR pszBuffer,
  779. int cchBuffer,
  780. DWORD *pcFilesWritten // [out]. Count of files written.
  781. ) const
  782. {
  783. int cchWritten = 0;
  784. DWORD cFilesWritten = 0;
  785. if (m_cchFileNames <= cchBuffer)
  786. {
  787. for (int i = 0; i < m_cFiles; i++)
  788. {
  789. if (m_rgpszFileNames[i].IsValid())
  790. {
  791. lstrcpy(pszBuffer, m_rgpszFileNames[i]);
  792. int cch = (lstrlen(m_rgpszFileNames[i]) + 1);
  793. pszBuffer += cch;
  794. cchWritten += cch;
  795. cFilesWritten++;
  796. }
  797. }
  798. }
  799. if (NULL != pcFilesWritten)
  800. {
  801. *pcFilesWritten = cFilesWritten;
  802. }
  803. return cchWritten;
  804. }
  805. #ifdef FILELIST_TEST
  806. void
  807. CscFilenameList::Share::Dump(
  808. void
  809. ) const
  810. {
  811. _tprintf(TEXT("Share \"%s\"\n"), (LPCTSTR)m_pszShareName ? (LPCTSTR)m_pszShareName : TEXT("<null>"));
  812. _tprintf(TEXT("\tm_cFiles........: %d\n"), m_cFiles);
  813. _tprintf(TEXT("\tm_cAllocated....: %d\n"), m_cAllocated);
  814. _tprintf(TEXT("\tm_cchShareName..: %d\n"), m_cchShareName);
  815. _tprintf(TEXT("\tm_cchFileNames..: %d\n"), m_cchFileNames);
  816. for (int i = 0; i < m_cFiles; i++)
  817. {
  818. _tprintf(TEXT("\tFile[%3d].......: \"%s\"\n"), i, (LPCTSTR)m_rgpszFileNames[i] ? (LPCTSTR)m_rgpszFileNames[i] : TEXT("<null>"));
  819. }
  820. }
  821. #endif // FILELIST_TEST
  822. CscFilenameList::FileIter::FileIter(
  823. const CscFilenameList::Share *pShare
  824. ) : m_pShare(pShare),
  825. m_iFile(0)
  826. {
  827. }
  828. CscFilenameList::FileIter::FileIter(
  829. void
  830. ) : m_pShare(NULL),
  831. m_iFile(0)
  832. {
  833. }
  834. CscFilenameList::FileIter::FileIter(
  835. const CscFilenameList::FileIter& rhs
  836. )
  837. {
  838. *this = rhs;
  839. }
  840. CscFilenameList::FileIter&
  841. CscFilenameList::FileIter::operator = (
  842. const CscFilenameList::FileIter& rhs
  843. )
  844. {
  845. if (this != &rhs)
  846. {
  847. m_pShare = rhs.m_pShare;
  848. m_iFile = rhs.m_iFile;
  849. }
  850. return *this;
  851. }
  852. LPCTSTR
  853. CscFilenameList::FileIter::Next(
  854. void
  855. )
  856. {
  857. if (0 < m_pShare->m_cFiles && m_iFile < m_pShare->m_cFiles)
  858. return m_pShare->m_rgpszFileNames[m_iFile++];
  859. return NULL;
  860. }
  861. void
  862. CscFilenameList::FileIter::Reset(
  863. void
  864. )
  865. {
  866. m_iFile = 0;
  867. }
  868. CscFilenameList::ShareIter::ShareIter(
  869. const CscFilenameList& fnl
  870. ) : m_pfnl(&fnl),
  871. m_iShare(0)
  872. {
  873. }
  874. CscFilenameList::ShareIter::ShareIter(
  875. void
  876. ) : m_pfnl(NULL),
  877. m_iShare(0)
  878. {
  879. }
  880. CscFilenameList::ShareIter::ShareIter(
  881. const CscFilenameList::ShareIter& rhs
  882. )
  883. {
  884. *this = rhs;
  885. }
  886. CscFilenameList::ShareIter&
  887. CscFilenameList::ShareIter::operator = (
  888. const CscFilenameList::ShareIter& rhs
  889. )
  890. {
  891. if (this != &rhs)
  892. {
  893. m_pfnl = rhs.m_pfnl;
  894. m_iShare = rhs.m_iShare;
  895. }
  896. return *this;
  897. }
  898. bool
  899. CscFilenameList::ShareIter::Next(
  900. HSHARE *phShare
  901. )
  902. {
  903. if (0 < m_pfnl->m_cShares && m_iShare < m_pfnl->m_cShares)
  904. {
  905. *phShare = HSHARE(m_pfnl->m_rgpShares[m_iShare++]);
  906. return true;
  907. }
  908. return false;
  909. }
  910. void
  911. CscFilenameList::ShareIter::Reset(
  912. void
  913. )
  914. {
  915. m_iShare = 0;
  916. }
  917. CscFilenameList::NamePtr::NamePtr(
  918. LPCTSTR pszName,
  919. bool bCopy
  920. ) : m_pszName(pszName),
  921. m_bOwns(bCopy)
  922. {
  923. if (bCopy)
  924. {
  925. m_pszName = DupStr(pszName);
  926. m_bOwns = true;
  927. }
  928. }
  929. CscFilenameList::NamePtr::~NamePtr(
  930. void
  931. )
  932. {
  933. if (m_bOwns)
  934. {
  935. delete[] const_cast<LPTSTR>(m_pszName);
  936. }
  937. }
  938. CscFilenameList::NamePtr::NamePtr(
  939. CscFilenameList::NamePtr& rhs
  940. )
  941. {
  942. *this = rhs;
  943. }
  944. CscFilenameList::NamePtr&
  945. CscFilenameList::NamePtr::operator = (
  946. CscFilenameList::NamePtr& rhs
  947. )
  948. {
  949. if (this != &rhs)
  950. {
  951. if (m_bOwns)
  952. delete[] (LPTSTR)m_pszName;
  953. m_pszName = rhs.m_pszName;
  954. m_bOwns = false;
  955. if (rhs.m_bOwns)
  956. {
  957. //
  958. // Assume ownership of the buffer.
  959. //
  960. rhs.m_bOwns = false;
  961. m_bOwns = true;
  962. }
  963. }
  964. return *this;
  965. }
  966. CscFilenameList::HSHARE::HSHARE(
  967. void
  968. ) : m_pShare(NULL)
  969. {
  970. }
  971. CscFilenameList::HSHARE::HSHARE(
  972. const HSHARE& rhs
  973. )
  974. {
  975. *this = rhs;
  976. }
  977. CscFilenameList::HSHARE&
  978. CscFilenameList::HSHARE::operator = (
  979. const CscFilenameList::HSHARE& rhs
  980. )
  981. {
  982. if (this != &rhs)
  983. {
  984. m_pShare = rhs.m_pShare;
  985. }
  986. return *this;
  987. }