Leaked source code of windows server 2003
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.

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