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