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.

1013 lines
22 KiB

  1. //****************************************************************************
  2. //
  3. // Module: ULS.DLL
  4. // File: utils.cpp
  5. // Content: Miscellaneous utility functions and classes
  6. //
  7. // Copyright (c) Microsoft Corporation 1996-1997
  8. //
  9. //****************************************************************************
  10. #include "ulsp.h"
  11. //****************************************************************************
  12. // HRESULT
  13. // SetLPTSTR (LPTSTR *ppszName, LPCTSTR pszUserName)
  14. //
  15. // Purpose: Clone the provided string into a newly allocated buffer.
  16. //
  17. // Parameters:
  18. // ppszName The buffer to receive a newly allocated string buffer.
  19. // pszUserName The provided name string.
  20. //
  21. // Return Value:
  22. // S_OK success if the string can be cloned.
  23. // ILS_E_MEMORY if the string cannot be cloned.
  24. //****************************************************************************
  25. HRESULT
  26. SetLPTSTR (LPTSTR *ppszName, LPCTSTR pszUserName)
  27. {
  28. HRESULT hr;
  29. TCHAR *pszNew = My_strdup (pszUserName);
  30. if (pszNew != NULL)
  31. {
  32. // Free the old name
  33. //
  34. ::MemFree (*ppszName);
  35. *ppszName = pszNew;
  36. hr = S_OK;
  37. }
  38. else
  39. {
  40. hr = ILS_E_MEMORY;
  41. }
  42. return hr;
  43. }
  44. //****************************************************************************
  45. // HRESULT
  46. // SafeSetLPTSTR (LPTSTR *ppszName, LPCTSTR pszUserName)
  47. //
  48. // Purpose: Clone the provided string into a newly allocated buffer.
  49. // It is ok that the provided string is NULL.
  50. //
  51. // Parameters:
  52. // ppszName The buffer to receive a newly allocated string buffer.
  53. // pszUserName The provided name string.
  54. //
  55. // Return Value:
  56. // S_OK success if the string can be cloned.
  57. // ILS_E_MEMORY if the non-null string cannot be cloned.
  58. //****************************************************************************
  59. HRESULT
  60. SafeSetLPTSTR (LPTSTR *ppszName, LPCTSTR pszUserName)
  61. {
  62. if (pszUserName == NULL)
  63. {
  64. MemFree (*ppszName);
  65. *ppszName = NULL;
  66. return S_FALSE;
  67. }
  68. return SetLPTSTR (ppszName, pszUserName);
  69. }
  70. //****************************************************************************
  71. // HRESULT
  72. // SetOffsetString ( TCHAR **ppszDst, BYTE *pSrcBase, ULONG uSrcOffset )
  73. //
  74. // Purpose: Clone the provided string into a newly allocated buffer.
  75. // If the source string is null or empty, the destination string
  76. // will be null.
  77. //
  78. // Parameters:
  79. //
  80. // Return Value:
  81. // S_OK success if the string can be cloned.
  82. // S_FALSE the destination string is null
  83. // ILS_E_MEMORY if the string cannot be cloned.
  84. //****************************************************************************
  85. HRESULT
  86. SetOffsetString ( TCHAR **ppszDst, BYTE *pSrcBase, ULONG uSrcOffset )
  87. {
  88. HRESULT hr = S_FALSE;
  89. TCHAR *pszNew = NULL;
  90. if (uSrcOffset != INVALID_OFFSET)
  91. {
  92. TCHAR *pszSrc = (TCHAR *) (pSrcBase + uSrcOffset);
  93. if (*pszSrc != TEXT ('\0'))
  94. {
  95. pszNew = My_strdup (pszSrc);
  96. hr = (pszNew != NULL) ? S_OK : ILS_E_MEMORY;
  97. }
  98. }
  99. if (SUCCEEDED (hr))
  100. {
  101. ::MemFree (*ppszDst);
  102. *ppszDst = pszNew;
  103. }
  104. return hr;
  105. }
  106. //****************************************************************************
  107. // HRESULT
  108. // LPTSTR_to_BSTR (BSTR *pbstr, LPCTSTR psz)
  109. //
  110. // Purpose: Make a BSTR string from an LPTSTR string
  111. //
  112. // Parameters:
  113. // pbstr The buffer to receive a newly allocated BSTR string.
  114. // psz The LPTSTR string.
  115. //
  116. // Return Value:
  117. // S_OK success if the string can be cloned.
  118. // ILS_E_FAIL cannot convert the string to BSTR
  119. // ILS_E_MEMORY cannot allocate enough memory for the BSTR string.
  120. //****************************************************************************
  121. HRESULT
  122. LPTSTR_to_BSTR (BSTR *pbstr, LPCTSTR psz)
  123. {
  124. #ifndef _UNICODE
  125. BSTR bstr;
  126. int i;
  127. HRESULT hr;
  128. // compute the length of the required BSTR
  129. //
  130. i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
  131. if (i <= 0)
  132. {
  133. return ILS_E_FAIL;
  134. };
  135. // allocate the widestr, +1 for terminating null
  136. //
  137. bstr = SysAllocStringLen(NULL, i-1); // SysAllocStringLen adds 1
  138. if (bstr != NULL)
  139. {
  140. MultiByteToWideChar(CP_ACP, 0, psz, -1, (LPWSTR)bstr, i);
  141. ((LPWSTR)bstr)[i - 1] = 0;
  142. *pbstr = bstr;
  143. hr = S_OK;
  144. }
  145. else
  146. {
  147. hr = ILS_E_MEMORY;
  148. };
  149. return hr;
  150. #else
  151. BSTR bstr;
  152. bstr = SysAllocString(psz);
  153. if (bstr != NULL)
  154. {
  155. *pbstr = bstr;
  156. return S_OK;
  157. }
  158. else
  159. {
  160. return ILS_E_MEMORY;
  161. };
  162. #endif // _UNICODE
  163. }
  164. //****************************************************************************
  165. // HRESULT
  166. // BSTR_to_LPTSTR (LPTSTR *ppsz, BSTR bstr)
  167. //
  168. // Purpose: Make a LPTSTR string from an BSTR string
  169. //
  170. // Parameters:
  171. // ppsz The buffer to receive a newly allocated LPTSTR string.
  172. // bstr The BSTR string.
  173. //
  174. // Return Value:
  175. // S_OK success if the string can be cloned.
  176. // ILS_E_FAIL cannot convert the string to BSTR
  177. // ILS_E_MEMORY cannot allocate enough memory for the BSTR string.
  178. //****************************************************************************
  179. HRESULT
  180. BSTR_to_LPTSTR (LPTSTR *ppsz, BSTR bstr)
  181. {
  182. #ifndef _UNICODE
  183. LPTSTR psz;
  184. int i;
  185. HRESULT hr;
  186. // compute the length of the required BSTR
  187. //
  188. i = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)bstr, -1, NULL, 0, NULL, NULL);
  189. if (i <= 0)
  190. {
  191. return ILS_E_FAIL;
  192. };
  193. // allocate the widestr, +1 for terminating null
  194. //
  195. psz = (TCHAR *) ::MemAlloc (i * sizeof (TCHAR));
  196. if (psz != NULL)
  197. {
  198. WideCharToMultiByte(CP_ACP, 0, (LPWSTR)bstr, -1, psz, i, NULL, NULL);
  199. *ppsz = psz;
  200. hr = S_OK;
  201. }
  202. else
  203. {
  204. hr = ILS_E_MEMORY;
  205. };
  206. return hr;
  207. #else
  208. LPTSTR psz = NULL;
  209. HRESULT hr;
  210. hr = SetLPTSTR(&psz, (LPTSTR)bstr);
  211. if (hr == S_OK)
  212. {
  213. *ppsz = psz;
  214. };
  215. return hr;
  216. #endif // _UNICODE
  217. }
  218. //****************************************************************************
  219. // CList::CList (void)
  220. //
  221. // Purpose: Constructor for the CList class
  222. //
  223. // Parameters: None
  224. //****************************************************************************
  225. CList::CList (void)
  226. {
  227. pHead = NULL;
  228. pTail = NULL;
  229. return;
  230. }
  231. //****************************************************************************
  232. // CList::~CList (void)
  233. //
  234. // Purpose: Constructor for the CList class
  235. //
  236. // Parameters: None
  237. //****************************************************************************
  238. CList::~CList (void)
  239. {
  240. Flush();
  241. return;
  242. }
  243. //****************************************************************************
  244. // HRESULT
  245. // CList::Insert (LPVOID pv)
  246. //
  247. // Purpose: Insert an object at the beginning of the list
  248. //
  249. // Parameters: None
  250. //****************************************************************************
  251. HRESULT
  252. CList::Insert (LPVOID pv)
  253. {
  254. PNODE pNode;
  255. pNode = new NODE;
  256. if (pNode == NULL)
  257. {
  258. return ILS_E_MEMORY;
  259. };
  260. pNode->pNext = pHead;
  261. pNode->pv = pv;
  262. pHead = pNode;
  263. if (pTail == NULL)
  264. {
  265. // This is the first node
  266. //
  267. pTail = pNode;
  268. };
  269. return NOERROR;
  270. }
  271. //****************************************************************************
  272. // HRESULT
  273. // CList::Append (LPVOID pv)
  274. //
  275. // Purpose: Append an object to the end of the list
  276. //
  277. // Parameters: None
  278. //****************************************************************************
  279. HRESULT
  280. CList::Append (LPVOID pv)
  281. {
  282. PNODE pNode;
  283. pNode = new NODE;
  284. if (pNode == NULL)
  285. {
  286. return ILS_E_MEMORY;
  287. };
  288. pNode->pNext = NULL;
  289. pNode->pv = pv;
  290. if (pHead == NULL)
  291. {
  292. pHead = pNode;
  293. };
  294. if (pTail != NULL)
  295. {
  296. pTail->pNext = pNode;
  297. };
  298. pTail = pNode;
  299. return NOERROR;
  300. }
  301. //****************************************************************************
  302. // HRESULT
  303. // CList::Remove (LPVOID pv)
  304. //
  305. // Purpose: Append an object to the end of the list
  306. //
  307. // Parameters: None
  308. //****************************************************************************
  309. HRESULT
  310. CList::Remove (LPVOID pv)
  311. {
  312. PNODE pNode, pPrev;
  313. HRESULT hr;
  314. pNode = pHead;
  315. pPrev = NULL;
  316. while (pNode != NULL)
  317. {
  318. // Matching the requested node
  319. //
  320. if (pNode->pv == pv)
  321. {
  322. break; // found!!!
  323. };
  324. pPrev = pNode;
  325. pNode = pNode->pNext;
  326. };
  327. if (pNode != NULL)
  328. {
  329. // We found the node to remove
  330. // Update relevant pointer
  331. //
  332. if (pTail == pNode)
  333. {
  334. pTail = pPrev;
  335. };
  336. if (pPrev != NULL)
  337. {
  338. pPrev->pNext = pNode->pNext;
  339. }
  340. else
  341. {
  342. pHead = pNode->pNext;
  343. };
  344. delete pNode;
  345. hr = NOERROR;
  346. }
  347. else
  348. {
  349. hr = S_FALSE;
  350. };
  351. return hr;
  352. }
  353. //****************************************************************************
  354. // HRESULT
  355. // CList::Find (LPVOID pv)
  356. //
  357. // Purpose: Find an object in the list
  358. //
  359. // Parameters: None
  360. //****************************************************************************
  361. HRESULT
  362. CList::Find (LPVOID pv)
  363. {
  364. PNODE pNode;
  365. pNode = pHead;
  366. while (pNode != NULL)
  367. {
  368. // Matching the requested node
  369. //
  370. if (pNode->pv == pv)
  371. {
  372. break; // found!!!
  373. };
  374. pNode = pNode->pNext;
  375. };
  376. return (pNode != NULL ? NOERROR : S_FALSE);
  377. }
  378. //****************************************************************************
  379. // HRESULT
  380. // CList::FindStorage (LPVOID *ppv, LPVOID pv)
  381. //
  382. // Purpose: Find an object in the list and returns the object storage.
  383. // This call is useful for search-and-replace operations.
  384. //
  385. // Parameters: None
  386. //****************************************************************************
  387. HRESULT
  388. CList::FindStorage (LPVOID *ppv, LPVOID pv)
  389. {
  390. PNODE pNode;
  391. HRESULT hr;
  392. pNode = pHead;
  393. while (pNode != NULL)
  394. {
  395. // Matching the requested node
  396. //
  397. if (pNode->pv == pv)
  398. {
  399. break; // found!!!
  400. };
  401. pNode = pNode->pNext;
  402. };
  403. if (pNode != NULL)
  404. {
  405. *ppv = &(pNode->pv);
  406. hr = NOERROR;
  407. }
  408. else
  409. {
  410. *ppv = NULL;
  411. hr = S_FALSE;
  412. };
  413. return hr;
  414. }
  415. //****************************************************************************
  416. // HRESULT
  417. // CList::Enumerate (HANDLE *phEnum)
  418. //
  419. // Purpose: Start object enumeration
  420. //
  421. // Parameters: None
  422. //****************************************************************************
  423. HRESULT
  424. CList::Enumerate (HANDLE *phEnum)
  425. {
  426. *phEnum = (HANDLE)pHead;
  427. return NOERROR;
  428. }
  429. //****************************************************************************
  430. // HRESULT
  431. // CList::Next (HANDLE *phEnum, LPVOID *ppv)
  432. //
  433. // Purpose: Obtain the next enumerated object
  434. //
  435. // Parameters: None
  436. //****************************************************************************
  437. HRESULT
  438. CList::Next (HANDLE *phEnum, LPVOID *ppv)
  439. {
  440. PNODE pNext;
  441. HRESULT hr;
  442. pNext = (PNODE)*phEnum;
  443. if (pNext == NULL)
  444. {
  445. *ppv = NULL;
  446. hr = S_FALSE;
  447. }
  448. else
  449. {
  450. *ppv = pNext->pv;
  451. *phEnum = (HANDLE)(pNext->pNext);
  452. hr = NOERROR;
  453. };
  454. return hr;
  455. }
  456. //****************************************************************************
  457. // HRESULT
  458. // CList::NextStorage (HANDLE *phEnum, LPVOID *ppv)
  459. //
  460. // Purpose: Obtain the storage of the next enumerated object. This call is
  461. // useful for search-and-replace operations.
  462. //
  463. // Parameters: None
  464. //****************************************************************************
  465. HRESULT
  466. CList::NextStorage (HANDLE *phEnum, LPVOID *ppv)
  467. {
  468. PNODE pNext;
  469. HRESULT hr;
  470. pNext = (PNODE)*phEnum;
  471. if (pNext == NULL)
  472. {
  473. *ppv = NULL;
  474. hr = S_FALSE;
  475. }
  476. else
  477. {
  478. *ppv = &(pNext->pv);
  479. *phEnum = (HANDLE)(pNext->pNext);
  480. hr = NOERROR;
  481. };
  482. return hr;
  483. }
  484. //****************************************************************************
  485. // HRESULT
  486. // CList::Flush (void)
  487. //
  488. // Purpose: Flush all the nodes in the list
  489. //
  490. // Parameters: None
  491. //****************************************************************************
  492. HRESULT
  493. CList::Flush (void)
  494. {
  495. PNODE pNode;
  496. while (pHead != NULL)
  497. {
  498. pNode = pHead;
  499. pHead = pHead->pNext;
  500. delete pNode;
  501. };
  502. return NOERROR;
  503. }
  504. //****************************************************************************
  505. // HRESULT
  506. // CList::Clone (CList *pList, HANDLE *phEnum)
  507. //
  508. // Purpose: Flush all the nodes in the list
  509. //
  510. // Parameters: None
  511. //****************************************************************************
  512. HRESULT
  513. CList::Clone (CList *pList, HANDLE *phEnum)
  514. {
  515. PNODE pNode;
  516. HRESULT hr;
  517. // Only allow a null list to be cloned
  518. //
  519. if (pHead != NULL)
  520. {
  521. return ILS_E_FAIL;
  522. };
  523. // Traverse the source list
  524. //
  525. hr = S_OK; // lonchanc: in case of null list
  526. pNode = pList->pHead;
  527. while(pNode != NULL)
  528. {
  529. // Use append to maintain the order
  530. //
  531. hr = Append(pNode->pv);
  532. if (FAILED(hr))
  533. {
  534. break;
  535. };
  536. // Get the enumerator info
  537. //
  538. if ((phEnum != NULL) &&
  539. (*phEnum == (HANDLE)pNode))
  540. {
  541. *phEnum = (HANDLE)pTail;
  542. };
  543. pNode = pNode->pNext;
  544. };
  545. return hr;
  546. }
  547. //****************************************************************************
  548. // CEnumNames::CEnumNames (void)
  549. //
  550. // History:
  551. // Wed 17-Apr-1996 11:15:18 -by- Viroon Touranachun [viroont]
  552. // Created.
  553. //****************************************************************************
  554. CEnumNames::CEnumNames (void)
  555. {
  556. cRef = 0;
  557. pNext = NULL;
  558. pszNames = NULL;
  559. cbSize = 0;
  560. return;
  561. }
  562. //****************************************************************************
  563. // CEnumNames::~CEnumNames (void)
  564. //
  565. // History:
  566. // Wed 17-Apr-1996 11:15:18 -by- Viroon Touranachun [viroont]
  567. // Created.
  568. //****************************************************************************
  569. CEnumNames::~CEnumNames (void)
  570. {
  571. if (pszNames != NULL)
  572. {
  573. ::MemFree (pszNames);
  574. };
  575. return;
  576. }
  577. //****************************************************************************
  578. // STDMETHODIMP
  579. // CEnumNames::Init (LPTSTR pList, ULONG cNames)
  580. //
  581. // History:
  582. // Wed 17-Apr-1996 11:15:25 -by- Viroon Touranachun [viroont]
  583. // Created.
  584. //****************************************************************************
  585. STDMETHODIMP
  586. CEnumNames::Init (LPTSTR pList, ULONG cNames)
  587. {
  588. HRESULT hr = NOERROR;
  589. // If no list, do nothing
  590. //
  591. if (cNames != 0)
  592. {
  593. LPTSTR pNextSrc;
  594. ULONG i, cLen, cbSize;
  595. ASSERT(pList != NULL);
  596. // Calculate the list size
  597. //
  598. pNextSrc = pList;
  599. for (i = 0, cbSize = 0; i < cNames; i++)
  600. {
  601. cLen = lstrlen(pNextSrc)+1;
  602. pNextSrc += cLen;
  603. cbSize += cLen;
  604. };
  605. // Allocate the snapshot buffer with the specified length
  606. // plus one for doubly null-termination
  607. //
  608. pszNames = (TCHAR *) ::MemAlloc ((cbSize+1) * sizeof (TCHAR));
  609. if (pszNames != NULL)
  610. {
  611. // Snapshot the name list
  612. //
  613. CopyMemory(pszNames, pList, cbSize*sizeof(TCHAR));
  614. pszNames[cbSize] = '\0';
  615. pNext = pszNames;
  616. this->cbSize = cbSize+1;
  617. }
  618. else
  619. {
  620. hr = ILS_E_MEMORY;
  621. };
  622. };
  623. return hr;
  624. }
  625. //****************************************************************************
  626. // STDMETHODIMP
  627. // CEnumNames::QueryInterface (REFIID riid, void **ppv)
  628. //
  629. // History:
  630. // Wed 17-Apr-1996 11:15:31 -by- Viroon Touranachun [viroont]
  631. // Created.
  632. //****************************************************************************
  633. STDMETHODIMP
  634. CEnumNames::QueryInterface (REFIID riid, void **ppv)
  635. {
  636. if (riid == IID_IEnumIlsNames || riid == IID_IUnknown)
  637. {
  638. *ppv = (IEnumIlsNames *) this;
  639. AddRef();
  640. return S_OK;
  641. }
  642. else
  643. {
  644. *ppv = NULL;
  645. return ILS_E_NO_INTERFACE;
  646. };
  647. }
  648. //****************************************************************************
  649. // STDMETHODIMP_(ULONG)
  650. // CEnumNames::AddRef (void)
  651. //
  652. // History:
  653. // Wed 17-Apr-1996 11:15:37 -by- Viroon Touranachun [viroont]
  654. // Created.
  655. //****************************************************************************
  656. STDMETHODIMP_(ULONG)
  657. CEnumNames::AddRef (void)
  658. {
  659. DllLock();
  660. MyDebugMsg ((DM_REFCOUNT, "CEnumNames::AddRef: ref=%ld\r\n", cRef));
  661. ::InterlockedIncrement ((LONG *) &cRef);
  662. return cRef;
  663. }
  664. //****************************************************************************
  665. // STDMETHODIMP_(ULONG)
  666. // CEnumNames::Release (void)
  667. //
  668. // History:
  669. // Wed 17-Apr-1996 11:15:43 -by- Viroon Touranachun [viroont]
  670. // Created.
  671. //****************************************************************************
  672. STDMETHODIMP_(ULONG)
  673. CEnumNames::Release (void)
  674. {
  675. DllRelease();
  676. ASSERT (cRef > 0);
  677. MyDebugMsg ((DM_REFCOUNT, "CEnumNames::Release: ref=%ld\r\n", cRef));
  678. if (::InterlockedDecrement ((LONG *) &cRef) == 0)
  679. {
  680. delete this;
  681. return 0;
  682. }
  683. return cRef;
  684. }
  685. //****************************************************************************
  686. // STDMETHODIMP
  687. // CEnumNames::Next (ULONG cNames, BSTR *rgpbstrName, ULONG *pcFetched)
  688. //
  689. // History:
  690. // Wed 17-Apr-1996 11:15:49 -by- Viroon Touranachun [viroont]
  691. // Created.
  692. //****************************************************************************
  693. STDMETHODIMP
  694. CEnumNames::Next (ULONG cNames, BSTR *rgpbstrName, ULONG *pcFetched)
  695. {
  696. ULONG cCopied;
  697. HRESULT hr;
  698. // Validate the pointer
  699. //
  700. if (rgpbstrName == NULL)
  701. return ILS_E_POINTER;
  702. // Validate the parameters
  703. //
  704. if ((cNames == 0) ||
  705. ((cNames > 1) && (pcFetched == NULL)))
  706. return ILS_E_PARAMETER;
  707. // Check the enumeration index
  708. //
  709. cCopied = 0;
  710. if (pNext != NULL)
  711. {
  712. // Can copy if we still have more names
  713. //
  714. while ((cCopied < cNames) &&
  715. (*pNext != '\0'))
  716. {
  717. if (SUCCEEDED(LPTSTR_to_BSTR(&rgpbstrName[cCopied], pNext)))
  718. {
  719. cCopied++;
  720. };
  721. pNext += lstrlen(pNext)+1;
  722. };
  723. };
  724. // Determine the returned information based on other parameters
  725. //
  726. if (pcFetched != NULL)
  727. {
  728. *pcFetched = cCopied;
  729. };
  730. return (cNames == cCopied ? S_OK : S_FALSE);
  731. }
  732. //****************************************************************************
  733. // STDMETHODIMP
  734. // CEnumNames::Skip (ULONG cNames)
  735. //
  736. // History:
  737. // Wed 17-Apr-1996 11:15:56 -by- Viroon Touranachun [viroont]
  738. // Created.
  739. //****************************************************************************
  740. STDMETHODIMP
  741. CEnumNames::Skip (ULONG cNames)
  742. {
  743. ULONG cSkipped;
  744. // Validate the parameters
  745. //
  746. if (cNames == 0)
  747. return ILS_E_PARAMETER;
  748. // Check the enumeration index limit
  749. //
  750. cSkipped = 0;
  751. if (pNext != NULL)
  752. {
  753. // Can skip only if we still have more attributes
  754. //
  755. while ((cSkipped < cNames) &&
  756. (*pNext != '\0'))
  757. {
  758. pNext += lstrlen(pNext)+1;
  759. cSkipped++;
  760. };
  761. };
  762. return (cNames == cSkipped ? S_OK : S_FALSE);
  763. }
  764. //****************************************************************************
  765. // STDMETHODIMP
  766. // CEnumNames::Reset (void)
  767. //
  768. // History:
  769. // Wed 17-Apr-1996 11:16:02 -by- Viroon Touranachun [viroont]
  770. // Created.
  771. //****************************************************************************
  772. STDMETHODIMP
  773. CEnumNames::Reset (void)
  774. {
  775. pNext = pszNames;
  776. return S_OK;
  777. }
  778. //****************************************************************************
  779. // STDMETHODIMP
  780. // CEnumNames::Clone(IEnumIlsNames **ppEnum)
  781. //
  782. // History:
  783. // Wed 17-Apr-1996 11:16:11 -by- Viroon Touranachun [viroont]
  784. // Created.
  785. //****************************************************************************
  786. STDMETHODIMP
  787. CEnumNames::Clone(IEnumIlsNames **ppEnum)
  788. {
  789. CEnumNames *peun;
  790. HRESULT hr;
  791. // Validate parameters
  792. //
  793. if (ppEnum == NULL)
  794. {
  795. return ILS_E_POINTER;
  796. };
  797. *ppEnum = NULL;
  798. // Create an enumerator
  799. //
  800. peun = new CEnumNames;
  801. if (peun == NULL)
  802. return ILS_E_MEMORY;
  803. // Clone the information
  804. //
  805. hr = NOERROR;
  806. peun->cbSize = cbSize;
  807. if (cbSize != 0)
  808. {
  809. peun->pszNames = (TCHAR *) ::MemAlloc (cbSize * sizeof (TCHAR));
  810. if (peun->pszNames != NULL)
  811. {
  812. CopyMemory(peun->pszNames, pszNames, cbSize*sizeof(TCHAR));
  813. peun->pNext = peun->pszNames+(pNext-pszNames);
  814. }
  815. else
  816. {
  817. hr = ILS_E_MEMORY;
  818. };
  819. }
  820. else
  821. {
  822. peun->pNext = NULL;
  823. peun->pszNames = NULL;
  824. };
  825. if (SUCCEEDED(hr))
  826. {
  827. // Return the cloned enumerator
  828. //
  829. peun->AddRef();
  830. *ppEnum = peun;
  831. }
  832. else
  833. {
  834. delete peun;
  835. };
  836. return hr;
  837. }
  838. /* F L E G A L E M A I L S Z */
  839. /*-------------------------------------------------------------------------
  840. %%Function: FLegalEmailSz
  841. RobD created
  842. A legal email name contains only ANSI characters.
  843. "a-z, A-Z, numbers 0-9 and some common symbols"
  844. It cannot include extended characters or < > ( ) /
  845. loncahnc modified
  846. IsLegalEmailName ( TCHAR *pszName ).
  847. A legal email name contains RFC 822 compliant characters.
  848. -------------------------------------------------------------------------*/
  849. BOOL IsLegalEmailName ( TCHAR *pszName )
  850. {
  851. // Null string is not legal
  852. //
  853. if (pszName == NULL)
  854. return FALSE;
  855. TCHAR ch;
  856. while ((ch = *pszName++) != TEXT ('\0'))
  857. {
  858. switch (ch)
  859. {
  860. default:
  861. // Check if ch is in the range
  862. //
  863. if (ch > TEXT (' ') && ch <= TEXT ('~'))
  864. break;
  865. // Fall thru to error code
  866. //
  867. case TEXT ('('): case TEXT (')'):
  868. case TEXT ('<'): case TEXT ('>'):
  869. case TEXT ('['): case TEXT (']'):
  870. case TEXT ('/'): case TEXT ('\\'):
  871. case TEXT (','):
  872. case TEXT (';'):
  873. case TEXT (':'):
  874. case TEXT ('\"'):
  875. return FALSE;
  876. }
  877. } // while
  878. return TRUE;
  879. }