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.

781 lines
20 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. SCardDlg
  5. Abstract:
  6. This file contains the outline implementation of the DLL exports
  7. for the Smartcard Common Dialogs
  8. Author:
  9. Chris Dudley 2/27/1997
  10. Environment:
  11. Win32, C++ w/Exceptions, MFC
  12. Revision History:
  13. Amanda Matlosz 07/09/1998 incorporated new select card,
  14. get pin and change pin dlgs.
  15. Notes:
  16. --*/
  17. /////////////////////////////////////////////////////////////////////////////
  18. //
  19. // Includes
  20. //
  21. #include "stdafx.h"
  22. #include <atlconv.cpp>
  23. #include "resource.h"
  24. #include "miscdef.h"
  25. #include "SCDlg.h"
  26. #include "ScSearch.h"
  27. #include "ScInsDlg.h"
  28. #include "chngpdlg.h"
  29. #include "ScUIDlg.h" // will someday be just <winscard.h>
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. /////////////////////////////////////////////////////////////////////////////
  36. // Forward Decls -- Helper functions defined @ eof
  37. void MString2CommaList(CString& str, LPWSTR szmString);
  38. void MString2CommaList(CString& str, LPSTR szmString);
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CSCardDlgApp
  41. BEGIN_MESSAGE_MAP(CSCardDlgApp, CWinApp)
  42. //{{AFX_MSG_MAP(CSCardDlgApp)
  43. // NOTE - the ClassWizard will add and remove mapping macros here.
  44. // DO NOT EDIT what you see in these blocks of generated code!
  45. //}}AFX_MSG_MAP
  46. END_MESSAGE_MAP()
  47. /*++
  48. CSCardDlgApp:
  49. Construction.
  50. Arguments:
  51. Return Value:
  52. Author:
  53. Chris Dudley 2/27/1997
  54. --*/
  55. CSCardDlgApp::CSCardDlgApp()
  56. {
  57. }
  58. /////////////////////////////////////////////////////////////////////////////
  59. //
  60. // The one CSCardDlgApp object
  61. //
  62. CSCardDlgApp theApp;
  63. /*++
  64. InitInstance:
  65. Override for the instance initializaion.
  66. Arguments:
  67. None
  68. Return Value:
  69. TRUE on success; FALSE otherwise resulting in DLL NOT be loaded.
  70. Author:
  71. Chris Dudley 2/27/1997
  72. --*/
  73. BOOL CSCardDlgApp::InitInstance()
  74. {
  75. BOOL fResult = FALSE;
  76. #ifdef ISOLATION_AWARE_ENABLED
  77. SHFusionInitializeFromModuleID (m_hInstance, 2);
  78. #endif
  79. // Disable all DLL notifications...Force exported API entry point.
  80. fResult = DisableThreadLibraryCalls(m_hInstance);
  81. _ASSERTE(fResult); // DisableThreadLibraryCalls failed; can't init dll
  82. return fResult;
  83. }
  84. int CSCardDlgApp::ExitInstance()
  85. {
  86. #ifdef ISOLATION_AWARE_ENABLED
  87. SHFusionUninitialize();
  88. #endif
  89. return CWinApp::ExitInstance();
  90. }
  91. /////////////////////////////////////////////////////////////////////////////
  92. //
  93. // Exported APIs from the DLL
  94. //
  95. /*++
  96. GetOpenCardName:
  97. This is the SDK v1.0 entry point routine to open the common dialog box.
  98. It has been retained for backwards compatibility; it is now a wrapper
  99. call for GetOpenCardNameEx().
  100. Arguments:
  101. pOCNA - Pointer to an ANSI open card name structure.
  102. -or-
  103. pOCNW - Popinter to a UNICODE open card name structure
  104. Return Value:
  105. A LONG value indicating the status of the requested action. Please
  106. see the Smartcard header files for additional information.
  107. Author:
  108. Chris Dudley 2/27/1997
  109. --*/
  110. LONG WINAPI GetOpenCardNameA(LPOPENCARDNAMEA pOCNA)
  111. {
  112. // Setup the correct module state information
  113. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  114. USES_CONVERSION;
  115. // Locals
  116. LONG lReturn = SCARD_S_SUCCESS;
  117. OPENCARDNAMEA_EX openCardNameEx;
  118. OPENCARD_SEARCH_CRITERIAA openCardSearchCriteria;
  119. try
  120. {
  121. // Check Params
  122. if (NULL == pOCNA)
  123. {
  124. throw (LONG)SCARD_E_INVALID_VALUE;
  125. }
  126. if (pOCNA->dwStructSize != sizeof(OPENCARDNAMEA))
  127. {
  128. throw (LONG)SCARD_E_INVALID_VALUE;
  129. }
  130. // Translate the OPENCARDNAME struct to OPENCARDNAME_EX
  131. ZeroMemory((PVOID)&openCardNameEx, sizeof(openCardNameEx));
  132. openCardNameEx.dwStructSize = sizeof(openCardNameEx);
  133. openCardNameEx.hwndOwner = pOCNA->hwndOwner;
  134. openCardNameEx.hSCardContext = pOCNA->hSCardContext;
  135. openCardNameEx.lpstrTitle = pOCNA->lpstrTitle;
  136. openCardNameEx.dwFlags = pOCNA->dwFlags;
  137. openCardNameEx.lpstrRdr = pOCNA->lpstrRdr;
  138. openCardNameEx.nMaxRdr = pOCNA->nMaxRdr;
  139. openCardNameEx.lpstrCard = pOCNA->lpstrCard;
  140. openCardNameEx.nMaxCard = pOCNA->nMaxCard;
  141. openCardNameEx.lpfnConnect = pOCNA->lpfnConnect;
  142. openCardNameEx.pvUserData = pOCNA->pvUserData;
  143. openCardNameEx.dwShareMode = pOCNA->dwShareMode;
  144. openCardNameEx.dwPreferredProtocols = pOCNA->dwPreferredProtocols;
  145. // Build a OPENCARD_SEARCH_CRITERIA struct
  146. ZeroMemory((PVOID)&openCardSearchCriteria, sizeof(openCardSearchCriteria));
  147. openCardSearchCriteria.dwStructSize = sizeof(openCardSearchCriteria);
  148. openCardSearchCriteria.lpstrGroupNames = pOCNA->lpstrGroupNames;
  149. openCardSearchCriteria.nMaxGroupNames = pOCNA->nMaxGroupNames;
  150. openCardSearchCriteria.rgguidInterfaces = pOCNA->rgguidInterfaces;
  151. openCardSearchCriteria.cguidInterfaces = pOCNA->cguidInterfaces;
  152. openCardSearchCriteria.lpstrCardNames = pOCNA->lpstrCardNames;
  153. openCardSearchCriteria.nMaxCardNames = pOCNA->nMaxCardNames;
  154. openCardSearchCriteria.lpfnCheck = pOCNA->lpfnCheck;
  155. openCardSearchCriteria.lpfnConnect = pOCNA->lpfnConnect;
  156. openCardSearchCriteria.lpfnDisconnect = pOCNA->lpfnDisconnect;
  157. openCardSearchCriteria.pvUserData = pOCNA->pvUserData;
  158. openCardSearchCriteria.dwShareMode = pOCNA->dwShareMode;
  159. openCardSearchCriteria.dwPreferredProtocols = pOCNA->dwPreferredProtocols;
  160. openCardNameEx.pOpenCardSearchCriteria = &openCardSearchCriteria;
  161. // Create a "search description" based on requested card names
  162. CString strPrompt;
  163. strPrompt.Empty();
  164. if (NULL != pOCNA->lpstrCardNames)
  165. {
  166. DWORD cNames = AnsiMStringCount(pOCNA->lpstrCardNames);
  167. if (1 == cNames)
  168. {
  169. strPrompt.Format(
  170. IDS_PROMPT_ONECARD,
  171. A2W(pOCNA->lpstrCardNames));
  172. }
  173. else if (1 < cNames)
  174. {
  175. CString strCommaList;
  176. MString2CommaList(strCommaList, pOCNA->lpstrCardNames);
  177. strPrompt.Format(
  178. IDS_PROMPT_CARDS,
  179. strCommaList);
  180. }
  181. }
  182. if (!strPrompt.IsEmpty())
  183. {
  184. openCardNameEx.lpstrSearchDesc = (LPCSTR)W2A(strPrompt);
  185. }
  186. // Call the updated routine
  187. lReturn = SCardUIDlgSelectCardA(&openCardNameEx);
  188. // Update the (const) return values of the OPENCARDNAME struct
  189. pOCNA->nMaxRdr = openCardNameEx.nMaxRdr;
  190. pOCNA->nMaxCard = openCardNameEx.nMaxCard;
  191. pOCNA->dwActiveProtocol = openCardNameEx.dwActiveProtocol;
  192. pOCNA->hCardHandle = openCardNameEx.hCardHandle;
  193. }
  194. catch (LONG hr)
  195. {
  196. lReturn = hr;
  197. TRACE_CATCH(_T("GetOpenCardNameA"),hr);
  198. }
  199. catch (...) {
  200. lReturn = (LONG) SCARD_E_UNEXPECTED;
  201. TRACE_CATCH_UNKNOWN(_T("GetOpenCardNameA"));
  202. }
  203. return lReturn;
  204. }
  205. LONG WINAPI GetOpenCardNameW(LPOPENCARDNAMEW pOCNW)
  206. {
  207. // Setup the correct module state information
  208. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  209. // Locals
  210. LONG lReturn = SCARD_S_SUCCESS;
  211. OPENCARDNAMEW_EX openCardNameEx;
  212. OPENCARD_SEARCH_CRITERIAW openCardSearchCriteria;
  213. try
  214. {
  215. // Check Params
  216. if (NULL == pOCNW)
  217. {
  218. throw (LONG)SCARD_E_INVALID_VALUE;
  219. }
  220. if (pOCNW->dwStructSize != sizeof(OPENCARDNAMEW))
  221. {
  222. throw (LONG)SCARD_E_INVALID_VALUE;
  223. }
  224. // Translate the OPENCARDNAME struct to OPENCARDNAME_EX
  225. ZeroMemory((PVOID)&openCardNameEx, sizeof(openCardNameEx));
  226. openCardNameEx.dwStructSize = sizeof(openCardNameEx);
  227. openCardNameEx.hwndOwner = pOCNW->hwndOwner;
  228. openCardNameEx.hSCardContext = pOCNW->hSCardContext;
  229. openCardNameEx.lpstrTitle = pOCNW->lpstrTitle;
  230. openCardNameEx.dwFlags = pOCNW->dwFlags;
  231. openCardNameEx.lpstrRdr = pOCNW->lpstrRdr;
  232. openCardNameEx.nMaxRdr = pOCNW->nMaxRdr;
  233. openCardNameEx.lpstrCard = pOCNW->lpstrCard;
  234. openCardNameEx.nMaxCard = pOCNW->nMaxCard;
  235. openCardNameEx.lpfnConnect = pOCNW->lpfnConnect;
  236. openCardNameEx.pvUserData = pOCNW->pvUserData;
  237. openCardNameEx.dwShareMode = pOCNW->dwShareMode;
  238. openCardNameEx.dwPreferredProtocols = pOCNW->dwPreferredProtocols;
  239. // Build a OPENCARD_SEARCH_CRITERIA struct
  240. ZeroMemory((PVOID)&openCardSearchCriteria, sizeof(openCardSearchCriteria));
  241. openCardSearchCriteria.dwStructSize = sizeof(openCardSearchCriteria);
  242. openCardSearchCriteria.lpstrGroupNames = pOCNW->lpstrGroupNames;
  243. openCardSearchCriteria.nMaxGroupNames = pOCNW->nMaxGroupNames;
  244. openCardSearchCriteria.rgguidInterfaces = pOCNW->rgguidInterfaces;
  245. openCardSearchCriteria.cguidInterfaces = pOCNW->cguidInterfaces;
  246. openCardSearchCriteria.lpstrCardNames = pOCNW->lpstrCardNames;
  247. openCardSearchCriteria.nMaxCardNames = pOCNW->nMaxCardNames;
  248. openCardSearchCriteria.lpfnCheck = pOCNW->lpfnCheck;
  249. openCardSearchCriteria.lpfnConnect = pOCNW->lpfnConnect;
  250. openCardSearchCriteria.lpfnDisconnect = pOCNW->lpfnDisconnect;
  251. openCardSearchCriteria.pvUserData = pOCNW->pvUserData;
  252. openCardSearchCriteria.dwShareMode = pOCNW->dwShareMode;
  253. openCardSearchCriteria.dwPreferredProtocols = pOCNW->dwPreferredProtocols;
  254. openCardNameEx.pOpenCardSearchCriteria = &openCardSearchCriteria;
  255. // Create a "search description" based on requested card names
  256. CString strPrompt;
  257. strPrompt.Empty();
  258. if (NULL != pOCNW->lpstrCardNames)
  259. {
  260. DWORD cNames = MStringCount(pOCNW->lpstrCardNames);
  261. if (1 == cNames)
  262. {
  263. strPrompt.Format(
  264. IDS_PROMPT_ONECARD,
  265. pOCNW->lpstrCardNames);
  266. }
  267. else if (1 < cNames)
  268. {
  269. CString strCommaList;
  270. MString2CommaList(strCommaList, pOCNW->lpstrCardNames);
  271. strPrompt.Format(
  272. IDS_PROMPT_CARDS,
  273. strCommaList);
  274. }
  275. }
  276. if (!strPrompt.IsEmpty())
  277. {
  278. openCardNameEx.lpstrSearchDesc = (LPCWSTR)strPrompt;
  279. }
  280. // Call the updated routine
  281. lReturn = SCardUIDlgSelectCardW(&openCardNameEx);
  282. // Update the (const) return values of the OPENCARDNAME struct
  283. pOCNW->nMaxRdr = openCardNameEx.nMaxRdr;
  284. pOCNW->nMaxCard = openCardNameEx.nMaxCard;
  285. pOCNW->dwActiveProtocol = openCardNameEx.dwActiveProtocol;
  286. pOCNW->hCardHandle = openCardNameEx.hCardHandle;
  287. }
  288. catch (LONG hr)
  289. {
  290. lReturn = hr;
  291. TRACE_CATCH(_T("GetOpenCardNameW"),hr);
  292. }
  293. catch (...) {
  294. lReturn = (LONG) SCARD_E_UNEXPECTED;
  295. TRACE_CATCH_UNKNOWN(_T("GetOpenCardNameW"));
  296. }
  297. return lReturn;
  298. }
  299. /*++
  300. LONG SCardDlgExtendedError:
  301. This is an old entry point for getting extended errors from the
  302. dialog. Please use the lLastError member of the OPENCARDNAME struct.
  303. Arguments:
  304. None.
  305. Return Value:
  306. None.
  307. Author:
  308. Chris Dudley 2/27/1997
  309. --*/
  310. LONG WINAPI SCardDlgExtendedError (void)
  311. {
  312. // Setup the correct module state information
  313. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  314. LONG lReturn = E_NOTIMPL;
  315. // NO LONGER IMPLEMENTED
  316. return lReturn;
  317. }
  318. /*++
  319. SCardUIDlgSelectCard:
  320. This is the entry point routine to open the common dialog box, introduced
  321. in the Microsoft Smart Card SDK v1.x.
  322. Arguments:
  323. pOCNA - Pointer to an ANSI open card name (ex) structure.
  324. -or-
  325. pOCNW - Pointer to a UNICODE open card name (ex) structure.
  326. Return Value:
  327. A LONG value indicating the status of the requested action. Please
  328. see the Smartcard header files for additional information.
  329. Author:
  330. Amanda Matlosz 6/11/98
  331. --*/
  332. LONG WINAPI SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pOCNA)
  333. {
  334. // Setup the correct module state information
  335. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  336. // Locals
  337. LONG lReturn = SCARD_S_SUCCESS;
  338. CWnd wndParent;
  339. BOOL fEnableUI = FALSE;
  340. INT_PTR nResponse = IDCANCEL;
  341. int nResult = 0;
  342. DWORD dwOKCards = 0;
  343. try
  344. {
  345. // Check Params
  346. if (!CheckOCN(pOCNA))
  347. {
  348. throw (LONG)SCARD_E_INVALID_VALUE;
  349. }
  350. // Determine names of all acceptable cards
  351. CTextMultistring mstrOKCards;
  352. ListAllOKCardNames(pOCNA, mstrOKCards);
  353. //
  354. // Do a silent search intially to determine # of suitable cards
  355. // currently available and/or connect to a card if min or no UI
  356. //
  357. lReturn = NoUISearch(pOCNA, &dwOKCards, (LPCSTR)mstrOKCards);
  358. //
  359. // If we haven't successfully selected a card and we can show UI,
  360. // raise the dialog
  361. //
  362. if (SCARD_S_SUCCESS != lReturn && !(pOCNA->dwFlags & SC_DLG_NO_UI))
  363. {
  364. // Now we can init the common dialog
  365. wndParent.Attach(pOCNA->hwndOwner);
  366. CScInsertDlg dlgCommon(&wndParent);
  367. #ifdef ISOLATION_AWARE_ENABLED
  368. CThemeContextActivator activator;
  369. #endif
  370. lReturn = dlgCommon.Initialize(pOCNA, dwOKCards, (LPCSTR)mstrOKCards);
  371. if(SCARD_S_SUCCESS != lReturn)
  372. {
  373. throw lReturn;
  374. }
  375. nResponse = dlgCommon.DoModal();
  376. // If cancel/closed return error
  377. switch (nResponse)
  378. {
  379. case IDOK: // absolutely sure of total success!
  380. break;
  381. case IDCANCEL:
  382. lReturn = dlgCommon.m_lLastError;
  383. if (0 == lReturn)
  384. lReturn = SCARD_W_CANCELLED_BY_USER; // not SCARD_E_CANCELLED
  385. break;
  386. default:
  387. _ASSERTE(FALSE);
  388. case -1:
  389. case IDABORT:
  390. lReturn = dlgCommon.m_lLastError;
  391. if (0 == lReturn)
  392. lReturn = SCARD_F_UNKNOWN_ERROR;
  393. break;
  394. }
  395. }
  396. }
  397. catch (LONG hr)
  398. {
  399. lReturn = hr;
  400. TRACE_CATCH(_T("SCardUIDlgSelectCardA"),hr);
  401. }
  402. catch (...) {
  403. lReturn = (LONG) SCARD_E_UNEXPECTED;
  404. TRACE_CATCH_UNKNOWN(_T("SCardUIDlgSelectCardA"));
  405. }
  406. if (NULL != wndParent.m_hWnd)
  407. {
  408. wndParent.Detach();
  409. }
  410. return lReturn;
  411. }
  412. LONG WINAPI SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pOCNW)
  413. {
  414. // Setup the correct module state information
  415. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  416. // Locals
  417. LONG lReturn = SCARD_S_SUCCESS;
  418. CWnd wndParent;
  419. BOOL fEnableUI = FALSE;
  420. INT_PTR nResponse = IDCANCEL;
  421. DWORD dwOKCards = 0;
  422. try
  423. {
  424. // Check Params
  425. if (!CheckOCN(pOCNW))
  426. {
  427. throw (LONG)SCARD_E_INVALID_VALUE;
  428. }
  429. // Determine names of all acceptable cards
  430. CTextMultistring mstrOKCards;
  431. ListAllOKCardNames(pOCNW, mstrOKCards);
  432. //
  433. // Do a silent search intially to determine # of suitable cards and/or
  434. // connect to a card according to display mode (min or no UI)
  435. //
  436. lReturn = NoUISearch(pOCNW, &dwOKCards, (LPCWSTR)mstrOKCards);
  437. //
  438. // If we haven't successfully selected a card and we can show UI,
  439. // raise the dialog
  440. //
  441. if (SCARD_S_SUCCESS != lReturn && !(pOCNW->dwFlags & SC_DLG_NO_UI))
  442. {
  443. // Now we can init the common dialog
  444. wndParent.Attach(pOCNW->hwndOwner);
  445. CScInsertDlg dlgCommon(&wndParent);
  446. #ifdef ISOLATION_AWARE_ENABLED
  447. CThemeContextActivator activator;
  448. #endif
  449. // Store Pointer and open dialog
  450. lReturn = dlgCommon.Initialize(pOCNW, dwOKCards, (LPCWSTR)mstrOKCards);
  451. if (SCARD_S_SUCCESS != lReturn)
  452. {
  453. throw (lReturn);
  454. }
  455. nResponse = dlgCommon.DoModal();
  456. // If cancel/closed return error
  457. switch (nResponse)
  458. {
  459. case IDOK: // absolutely sure of total success!
  460. break;
  461. case IDCANCEL:
  462. lReturn = SCARD_W_CANCELLED_BY_USER; // not SCARD_E_CANCELLED
  463. break;
  464. default:
  465. _ASSERTE(FALSE);
  466. case -1:
  467. case IDABORT:
  468. lReturn = dlgCommon.m_lLastError;
  469. if (0 == lReturn)
  470. lReturn = SCARD_F_UNKNOWN_ERROR;
  471. break;
  472. }
  473. }
  474. }
  475. catch (LONG lErr)
  476. {
  477. lReturn = lErr;
  478. TRACE_CATCH(_T("SCardUIDlgSelectCardW"),lReturn);
  479. }
  480. catch (...) {
  481. lReturn = (LONG) SCARD_E_UNEXPECTED;
  482. TRACE_CATCH_UNKNOWN(_T("SCardUIDlgSelectCardW"));
  483. }
  484. if (NULL != wndParent.m_hWnd)
  485. {
  486. wndParent.Detach();
  487. }
  488. return lReturn;
  489. }
  490. /*++
  491. SCardUIDlgGetPIN:
  492. Arguments:
  493. Return Value:
  494. A LONG value indicating the status of the requested action.
  495. Author:
  496. Amanda Matlosz 06/18/1998
  497. --*/
  498. LONG WINAPI SCardUIDlgGetPINA(LPPINPROMPT pPinPrompt)
  499. {
  500. // Setup the correct module state information
  501. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  502. INT_PTR nResponse = IDCANCEL; // result of DoModal.
  503. CWnd wndParent;
  504. wndParent.Attach(pPinPrompt->hwndOwner);
  505. CGetPinDlg dlgGetPin(&wndParent);
  506. if (dlgGetPin.SetAttributes(pPinPrompt))
  507. {
  508. #ifdef ISOLATION_AWARE_ENABLED
  509. CThemeContextActivator activator;
  510. #endif
  511. nResponse = dlgGetPin.DoModal();
  512. }
  513. if (NULL != wndParent.m_hWnd)
  514. {
  515. wndParent.Detach();
  516. }
  517. return (LONG)nResponse;
  518. }
  519. /*++
  520. SCardUIDlgChangePIN:
  521. Arguments:
  522. Return Value:
  523. A LONG value indicating the status of the requested action.
  524. Author:
  525. Amanda Matlosz 06/18/1998
  526. --*/
  527. LONG WINAPI SCardUIDlgChangePINA(LPCHANGEPIN pChangePin)
  528. {
  529. // Setup the correct module state information
  530. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  531. INT_PTR nResponse = IDCANCEL; // result of DoModal.
  532. CWnd wndParent;
  533. wndParent.Attach(pChangePin->hwndOwner);
  534. CChangePinDlg dlgChangePin(&wndParent);
  535. if (dlgChangePin.SetAttributes(pChangePin))
  536. {
  537. #ifdef ISOLATION_AWARE_ENABLED
  538. CThemeContextActivator activator;
  539. #endif
  540. nResponse = dlgChangePin.DoModal();
  541. }
  542. if (NULL != wndParent.m_hWnd)
  543. {
  544. wndParent.Detach();
  545. }
  546. return (LONG)nResponse;
  547. }
  548. ///////////////////////////////////////////////////////////////////////////////
  549. // Helper functions
  550. void MString2CommaList(CString& str, LPWSTR szmString)
  551. {
  552. str.Empty();
  553. if (NULL == szmString)
  554. {
  555. return;
  556. }
  557. LPCWSTR szm = szmString;
  558. szm = FirstString(szm);
  559. str = szm;
  560. for(szm = NextString(szm); NULL != szm; szm = NextString(szm))
  561. {
  562. str += ", ";
  563. str += szm;
  564. }
  565. }
  566. void MString2CommaList(CString& str, LPSTR szmString)
  567. {
  568. USES_CONVERSION;
  569. str.Empty();
  570. if (NULL == szmString)
  571. {
  572. return;
  573. }
  574. LPCSTR szm = szmString;
  575. str += A2W(szm);
  576. szm = szm + (sizeof(CHAR)*(strlen(szm)+1));
  577. while (NULL != szm && NULL != *szm)
  578. {
  579. str += ", ";
  580. str += A2W(szm);
  581. szm = szm + (sizeof(CHAR)*(strlen(szm)+1));
  582. }
  583. }