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.

787 lines
22 KiB

  1. // MLStrA.cpp : Implementation of CMLStrA
  2. #include "private.h"
  3. #ifndef NEWMLSTR
  4. #include "mlstr.h"
  5. #ifdef ASTRIMPL
  6. #include "mlswalk.h"
  7. #include "mlsbwalk.h"
  8. #endif
  9. /////////////////////////////////////////////////////////////////////////////
  10. // CMLStrA
  11. #ifdef ASTRIMPL
  12. CMLStrA::CMLStrA(void) :
  13. m_pMLCPs(NULL)
  14. {
  15. DllAddRef();
  16. }
  17. CMLStrA::~CMLStrA(void)
  18. {
  19. if (m_pMLCPs)
  20. m_pMLCPs->Release();
  21. DllRelease();
  22. }
  23. #endif
  24. STDMETHODIMP CMLStrA::Sync(BOOL fNoAccess)
  25. {
  26. ASSERT_THIS;
  27. return GetOwner()->Sync(fNoAccess);
  28. }
  29. STDMETHODIMP CMLStrA::GetLength(long* plLen)
  30. {
  31. ASSERT_THIS;
  32. return GetOwner()->GetLength(plLen);
  33. }
  34. STDMETHODIMP CMLStrA::SetMLStr(long lDestPos, long lDestLen, IUnknown* pSrcMLStr, long lSrcPos, long lSrcLen)
  35. {
  36. ASSERT_THIS;
  37. return GetOwner()->SetMLStr(lDestPos, lDestLen, pSrcMLStr, lSrcPos, lSrcLen);
  38. }
  39. STDMETHODIMP CMLStrA::GetMLStr(long lSrcPos, long lSrcLen, IUnknown* pUnkOuter, DWORD dwClsContext, const IID* piid, IUnknown** ppDestMLStr, long* plDestPos, long* plDestLen)
  40. {
  41. ASSERT_THIS;
  42. return GetOwner()->GetMLStr(lSrcPos, lSrcLen, pUnkOuter, dwClsContext, piid, ppDestMLStr, plDestPos, plDestLen);
  43. }
  44. STDMETHODIMP CMLStrA::SetAStr(long lDestPos, long lDestLen, UINT uCodePage, const CHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  45. {
  46. #ifdef ASTRIMPL
  47. ASSERT_THIS;
  48. ASSERT_READ_BLOCK(pszSrc, cchSrc);
  49. ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  50. ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  51. POWNER const pOwner = GetOwner();
  52. HRESULT hr = pOwner->CheckThread();
  53. CMLStr::CLock Lock(TRUE, pOwner, hr);
  54. long cchDestPos;
  55. long cchDestLen;
  56. long cchActual;
  57. long lActualLen;
  58. if (SUCCEEDED(hr) && (pOwner->GetBufFlags() & MLSTR_WRITE))
  59. hr = E_INVALIDARG; // Not writable StrBuf; TODO: Replace StrBuf in this case if allowed
  60. if (SUCCEEDED(hr) &&
  61. SUCCEEDED(hr = pOwner->PrepareMLStrBuf()) &&
  62. SUCCEEDED(hr = pOwner->RegularizePosLen(&lDestPos, &lDestLen)) &&
  63. SUCCEEDED(hr = pOwner->GetCCh(0, lDestPos, &cchDestPos)) &&
  64. SUCCEEDED(hr = pOwner->GetCCh(cchDestPos, lDestLen, &cchDestLen)))
  65. {
  66. IMLangStringBufA* const pMLStrBufA = pOwner->GetMLStrBufA();
  67. if (uCodePage == CP_ACP)
  68. uCodePage = g_uACP;
  69. if (pMLStrBufA && uCodePage == pOwner->GetCodePage())
  70. {
  71. if (cchSrc > cchDestLen)
  72. {
  73. hr = pMLStrBufA->Insert(cchDestPos, cchSrc - cchDestLen, (pcchActual || plActualLen) ? &cchSrc : NULL);
  74. cchSrc += cchDestLen;
  75. }
  76. else if (cchSrc < cchDestLen)
  77. {
  78. hr = pMLStrBufA->Delete(cchDestPos, cchDestLen - cchSrc);
  79. }
  80. CMLStrBufWalkA BufWalk(pMLStrBufA, cchDestPos, cchSrc, (pcchActual || plActualLen));
  81. lActualLen = 0;
  82. while (BufWalk.Lock(hr))
  83. {
  84. long lLen;
  85. if (plActualLen)
  86. hr = pOwner->CalcLenA(uCodePage, pszSrc, BufWalk.GetCCh(), &lLen);
  87. if (SUCCEEDED(hr))
  88. {
  89. lActualLen += lLen;
  90. ::memcpy(BufWalk.GetStr(), pszSrc, sizeof(CHAR) * BufWalk.GetCCh());
  91. pszSrc += BufWalk.GetCCh();
  92. }
  93. BufWalk.Unlock(hr);
  94. }
  95. cchActual = BufWalk.GetDoneCCh();
  96. }
  97. else
  98. {
  99. IMLangStringWStr* pMLStrW;
  100. if (SUCCEEDED(hr = pOwner->QueryInterface(IID_IMLangStringWStr, (void**)&pMLStrW)))
  101. {
  102. CMLStrWalkW StrWalk(pMLStrW, lDestPos, lDestLen, MLSTR_WRITE, (pcchActual || plActualLen));
  103. cchActual = 0;
  104. lActualLen = 0;
  105. while (StrWalk.Lock(hr))
  106. {
  107. long cchWrittenA;
  108. long lWrittenLen;
  109. if (SUCCEEDED(hr = pOwner->ConvAStrToWStr(uCodePage, pszSrc, cchSrc, StrWalk.GetStr(), StrWalk.GetCCh(), &cchWrittenA, NULL, &lWrittenLen)))
  110. {
  111. pszSrc += cchWrittenA;
  112. cchSrc -= cchWrittenA;
  113. cchActual += cchWrittenA;
  114. lActualLen += lWrittenLen;
  115. }
  116. StrWalk.Unlock(hr, lWrittenLen);
  117. }
  118. pMLStrW->Release();
  119. }
  120. }
  121. }
  122. if (SUCCEEDED(hr))
  123. {
  124. if (pcchActual)
  125. *pcchActual = cchActual;
  126. if (plActualLen)
  127. *plActualLen = lActualLen;
  128. }
  129. else
  130. {
  131. if (pcchActual)
  132. *pcchActual = 0;
  133. if (plActualLen)
  134. *plActualLen = 0;
  135. }
  136. return hr;
  137. #else
  138. return E_NOTIMPL; // !ASTRIMPL
  139. #endif
  140. }
  141. STDMETHODIMP CMLStrA::SetStrBufA(long lDestPos, long lDestLen, UINT uCodePage, IMLangStringBufA* pSrcBuf, long* pcchActual, long* plActualLen)
  142. {
  143. ASSERT_THIS;
  144. return GetOwner()->SetStrBufCommon(this, lDestPos, lDestLen, uCodePage, NULL, pSrcBuf, pcchActual, plActualLen);
  145. }
  146. STDMETHODIMP CMLStrA::GetAStr(long lSrcPos, long lSrcLen, UINT uCodePageIn, UINT* puCodePageOut, CHAR* pszDest, long cchDest, long* pcchActual, long* plActualLen)
  147. {
  148. ASSERT_THIS;
  149. ASSERT_WRITE_PTR_OR_NULL(puCodePageOut);
  150. ASSERT_WRITE_BLOCK_OR_NULL(pszDest, cchDest);
  151. ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  152. ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  153. POWNER const pOwner = GetOwner();
  154. HRESULT hr = pOwner->CheckThread();
  155. #ifdef ASTRIMPL
  156. CMLStr::CLock Lock(FALSE, pOwner, hr);
  157. #endif
  158. long cchSrcPos;
  159. long cchSrcLen;
  160. long cchActual;
  161. long lActualLen;
  162. #ifndef ASTRIMPL
  163. if (SUCCEEDED(hr = m_pOwner->CheckThread()) &&
  164. (m_pOwner->IsLocked() || puCodePageOut || uCodePageIn != m_pOwner->GetCodePage())) // !ASTRIMPL
  165. {
  166. hr = E_INVALIDARG;
  167. }
  168. #endif
  169. if (SUCCEEDED(hr) &&
  170. SUCCEEDED(hr = pOwner->RegularizePosLen(&lSrcPos, &lSrcLen)) &&
  171. SUCCEEDED(hr = pOwner->GetCCh(0, lSrcPos, &cchSrcPos)) &&
  172. SUCCEEDED(hr = pOwner->GetCCh(cchSrcPos, lSrcLen, &cchSrcLen)))
  173. {
  174. #ifdef ASTRIMPL
  175. IMLangStringBufA* const pMLStrBufA = pOwner->GetMLStrBufA();
  176. if (pszDest)
  177. cchActual = min(cchSrcLen, cchDest);
  178. else
  179. cchActual = cchSrcLen;
  180. if (uCodePageIn == CP_ACP)
  181. uCodePageIn = g_uACP;
  182. if (pMLStrBufA && (puCodePageOut || uCodePageIn == pOwner->GetCodePage()))
  183. {
  184. uCodePageIn = pOwner->GetCodePage();
  185. CMLStrBufWalkA BufWalk(pMLStrBufA, cchSrcPos, cchActual, (pcchActual || plActualLen));
  186. lActualLen = 0;
  187. while (BufWalk.Lock(hr))
  188. {
  189. long lLen;
  190. if (plActualLen)
  191. hr = pOwner->CalcLenA(uCodePageIn, BufWalk.GetStr(), BufWalk.GetCCh(), &lLen);
  192. if (SUCCEEDED(hr))
  193. {
  194. lActualLen += lLen;
  195. if (pszDest)
  196. {
  197. ::memcpy(pszDest, BufWalk.GetStr(), sizeof(CHAR) * BufWalk.GetCCh());
  198. pszDest += BufWalk.GetCCh();
  199. }
  200. }
  201. BufWalk.Unlock(hr);
  202. }
  203. cchActual = BufWalk.GetDoneCCh();
  204. }
  205. else
  206. {
  207. IMLangStringWStr* pMLStrW;
  208. if (SUCCEEDED(hr = pOwner->QueryInterface(IID_IMLangStringWStr, (void**)&pMLStrW)))
  209. {
  210. BOOL fDontHaveCodePageIn = (puCodePageOut != 0);
  211. CMLStrWalkW StrWalk(pMLStrW, lSrcPos, lSrcLen, (pcchActual || plActualLen));
  212. cchActual = 0;
  213. while (StrWalk.Lock(hr))
  214. {
  215. LCID locale;
  216. UINT uLocaleCodePage;
  217. DWORD dwLocaleCodePages;
  218. DWORD dwStrCodePages;
  219. long cchWritten;
  220. long lWrittenLen;
  221. if (fDontHaveCodePageIn &&
  222. SUCCEEDED(hr = pOwner->GetLocale(lSrcPos, lSrcLen, &locale, NULL, NULL)) &&
  223. SUCCEEDED(hr = ::LocaleToCodePage(locale, &uLocaleCodePage)) &&
  224. SUCCEEDED(hr = PrepareMLangCodePages()) &&
  225. SUCCEEDED(hr = GetMLangCodePages()->CodePageToCodePages(uLocaleCodePage, &dwLocaleCodePages)) &&
  226. SUCCEEDED(hr = GetMLangCodePages()->GetStrCodePages(StrWalk.GetStr(), StrWalk.GetCCh(), dwLocaleCodePages, &dwStrCodePages, NULL)))
  227. {
  228. fDontHaveCodePageIn = FALSE;
  229. hr = GetMLangCodePages()->CodePagesToCodePage(dwStrCodePages, uLocaleCodePage, &uCodePageIn);
  230. }
  231. if (SUCCEEDED(hr) &&
  232. SUCCEEDED(hr = pOwner->ConvWStrToAStr(pcchActual || plActualLen, uCodePageIn, StrWalk.GetStr(), StrWalk.GetCCh(), pszDest, cchDest, &cchWritten, NULL, &lWrittenLen)))
  233. {
  234. pszDest += cchWritten;
  235. cchDest -= cchWritten;
  236. cchActual += cchWritten;
  237. }
  238. StrWalk.Unlock(hr, lWrittenLen);
  239. }
  240. lActualLen = StrWalk.GetDoneLen();
  241. pMLStrW->Release();
  242. }
  243. }
  244. }
  245. #else
  246. if (pszDest)
  247. {
  248. hr = E_FAIL; // TODO: Not implemented in this version
  249. }
  250. else
  251. {
  252. cchActual = cchSrcLen;
  253. }
  254. }
  255. if (SUCCEEDED(hr) && plActualLen)
  256. hr = m_pOwner->CalcLenA(m_pOwner->GetCodePage(), 0, cchActual, &lActualLen);
  257. #endif
  258. if (SUCCEEDED(hr))
  259. {
  260. #ifdef ASTRIMPL
  261. if (puCodePageOut)
  262. *puCodePageOut = uCodePageIn;
  263. #endif
  264. if (pcchActual)
  265. *pcchActual = cchActual;
  266. if (plActualLen)
  267. *plActualLen = lActualLen;
  268. }
  269. else
  270. {
  271. if (puCodePageOut)
  272. *puCodePageOut = 0;
  273. if (pcchActual)
  274. *pcchActual = 0;
  275. if (plActualLen)
  276. *plActualLen = 0;
  277. }
  278. return hr;
  279. }
  280. STDMETHODIMP CMLStrA::GetStrBufA(long lSrcPos, long lSrcMaxLen, UINT* puDestCodePage, IMLangStringBufA** ppDestBuf, long* plDestLen)
  281. {
  282. #ifdef ASTRIMPL
  283. ASSERT_THIS;
  284. ASSERT_WRITE_PTR_OR_NULL(puDestCodePage);
  285. ASSERT_WRITE_PTR_OR_NULL(ppDestBuf);
  286. ASSERT_WRITE_PTR_OR_NULL(plDestLen);
  287. POWNER const pOwner = GetOwner();
  288. HRESULT hr = pOwner->CheckThread();
  289. CMLStr::CLock Lock(FALSE, pOwner, hr);
  290. IMLangStringBufA* pMLStrBufA;
  291. if (SUCCEEDED(hr) &&
  292. SUCCEEDED(hr = pOwner->RegularizePosLen(&lSrcPos, &lSrcMaxLen)) &&
  293. lSrcMaxLen <= 0)
  294. {
  295. hr = E_INVALIDARG;
  296. }
  297. if (SUCCEEDED(hr))
  298. {
  299. pMLStrBufA = pOwner->GetMLStrBufA();
  300. if (!pMLStrBufA)
  301. hr = MLSTR_E_STRBUFNOTAVAILABLE;
  302. }
  303. if (SUCCEEDED(hr))
  304. {
  305. if (puDestCodePage)
  306. *puDestCodePage = pOwner->GetCodePage();
  307. if (ppDestBuf)
  308. {
  309. pMLStrBufA->AddRef();
  310. *ppDestBuf = pMLStrBufA;
  311. }
  312. if (plDestLen)
  313. *plDestLen = lSrcMaxLen;
  314. }
  315. else
  316. {
  317. if (puDestCodePage)
  318. *puDestCodePage = 0;
  319. if (ppDestBuf)
  320. *ppDestBuf = NULL;
  321. if (plDestLen)
  322. *plDestLen = 0;
  323. }
  324. return hr;
  325. #else
  326. return E_NOTIMPL; // !ASTRIMPL
  327. #endif
  328. }
  329. STDMETHODIMP CMLStrA::LockAStr(long lSrcPos, long lSrcLen, long lFlags, UINT uCodePageIn, long cchRequest, UINT* puCodePageOut, CHAR** ppszDest, long* pcchDest, long* plDestLen)
  330. {
  331. #ifdef ASTRIMPL
  332. ASSERT_THIS;
  333. ASSERT_WRITE_PTR_OR_NULL(puCodePageOut);
  334. ASSERT_WRITE_PTR_OR_NULL(ppszDest);
  335. ASSERT_WRITE_PTR_OR_NULL(pcchDest);
  336. ASSERT_WRITE_PTR_OR_NULL(plDestLen);
  337. POWNER const pOwner = GetOwner();
  338. HRESULT hr = pOwner->CheckThread();
  339. CMLStr::CLock Lock(lFlags & MLSTR_WRITE, pOwner, hr);
  340. long cchSrcPos;
  341. long cchSrcLen;
  342. CHAR* pszBuf = NULL;
  343. long cchBuf;
  344. long lLockLen;
  345. BOOL fDirectLock;
  346. if (SUCCEEDED(hr) && (!lFlags || (lFlags & ~pOwner->GetBufFlags() & MLSTR_WRITE)))
  347. hr = E_INVALIDARG; // No flags specified, or not writable StrBuf; TODO: Replace StrBuf in this case if allowed
  348. if (!(lFlags & MLSTR_WRITE))
  349. cchRequest = 0;
  350. if (SUCCEEDED(hr) &&
  351. SUCCEEDED(hr = pOwner->PrepareMLStrBuf()) &&
  352. SUCCEEDED(hr = pOwner->RegularizePosLen(&lSrcPos, &lSrcLen)) &&
  353. SUCCEEDED(hr = pOwner->GetCCh(0, lSrcPos, &cchSrcPos)) &&
  354. SUCCEEDED(hr = pOwner->GetCCh(cchSrcPos, lSrcLen, &cchSrcLen)))
  355. {
  356. IMLangStringBufA* const pMLStrBufA = pOwner->GetMLStrBufA();
  357. fDirectLock = (pMLStrBufA && (puCodePageOut || uCodePageIn == pOwner->GetCodePage()));
  358. if (fDirectLock)
  359. {
  360. long cchInserted;
  361. long cchLockLen = cchSrcLen;
  362. if (puCodePageOut)
  363. hr = GetAStr(lSrcPos, lSrcLen, 0, &uCodePageIn, NULL, 0, NULL, NULL);
  364. if (SUCCEEDED(hr) &&
  365. cchRequest > cchSrcLen &&
  366. SUCCEEDED(hr = pMLStrBufA->Insert(cchSrcPos + cchSrcLen, cchRequest - cchSrcLen, &cchInserted)))
  367. {
  368. pOwner->SetBufCCh(pOwner->GetBufCCh() + cchInserted);
  369. cchLockLen += cchInserted;
  370. if (!pcchDest && cchLockLen < cchRequest)
  371. hr = E_OUTOFMEMORY; // Can't insert in StrBuf
  372. }
  373. if (SUCCEEDED(hr) &&
  374. SUCCEEDED(hr = pMLStrBufA->LockBuf(cchSrcPos, cchLockLen, &pszBuf, &cchBuf)) &&
  375. !pcchDest && cchBuf < max(cchSrcLen, cchRequest))
  376. {
  377. hr = E_OUTOFMEMORY; // Can't lock StrBuf
  378. }
  379. if (plDestLen && SUCCEEDED(hr))
  380. hr = pOwner->CalcLenA(uCodePageIn, pszBuf, cchBuf, &lLockLen);
  381. }
  382. else
  383. {
  384. long cchSize;
  385. if (SUCCEEDED(hr = pOwner->CalcBufSizeA(lSrcLen, &cchSize)))
  386. {
  387. cchBuf = max(cchSize, cchRequest);
  388. hr = pOwner->MemAlloc(sizeof(*pszBuf) * cchBuf, (void**)&pszBuf);
  389. }
  390. if (SUCCEEDED(hr) && ((lFlags & MLSTR_READ) || puCodePageOut))
  391. hr = GetAStr(lSrcPos, lSrcLen, uCodePageIn, (puCodePageOut) ? &uCodePageIn : NULL, (lFlags & MLSTR_READ) ? pszBuf : NULL, cchBuf, (pcchDest) ? &cchBuf : NULL, (plDestLen) ? &lLockLen : NULL);
  392. }
  393. }
  394. if (SUCCEEDED(hr) &&
  395. SUCCEEDED(hr = Lock.FallThrough()))
  396. {
  397. hr = pOwner->GetLockInfo()->Lock((fDirectLock) ? pOwner->UnlockAStrDirect : pOwner->UnlockAStrIndirect, lFlags, uCodePageIn, pszBuf, lSrcPos, lSrcLen, cchSrcPos, cchBuf);
  398. }
  399. if (SUCCEEDED(hr))
  400. {
  401. if (puCodePageOut)
  402. *puCodePageOut = uCodePageIn;
  403. if (ppszDest)
  404. *ppszDest = pszBuf;
  405. if (pcchDest)
  406. *pcchDest = cchBuf;
  407. if (plDestLen)
  408. *plDestLen = lLockLen;
  409. }
  410. else
  411. {
  412. if (pszBuf)
  413. {
  414. if (fDirectLock)
  415. pOwner->GetMLStrBufA()->UnlockBuf(pszBuf, 0, 0);
  416. else
  417. pOwner->MemFree(pszBuf);
  418. }
  419. if (puCodePageOut)
  420. *puCodePageOut = 0;
  421. if (ppszDest)
  422. *ppszDest = NULL;
  423. if (pcchDest)
  424. *pcchDest = 0;
  425. if (plDestLen)
  426. *plDestLen = 0;
  427. }
  428. return hr;
  429. #else
  430. return E_NOTIMPL; // !ASTRIMPL
  431. #endif
  432. }
  433. STDMETHODIMP CMLStrA::UnlockAStr(const CHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  434. {
  435. #ifdef ASTRIMPL
  436. ASSERT_THIS;
  437. ASSERT_READ_BLOCK(pszSrc, cchSrc);
  438. ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  439. ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  440. return GetOwner()->UnlockStrCommon(pszSrc, cchSrc, pcchActual, plActualLen);
  441. #else
  442. return E_NOTIMPL; // !ASTRIMPL
  443. #endif
  444. }
  445. STDMETHODIMP CMLStrA::SetLocale(long lDestPos, long lDestLen, LCID locale)
  446. {
  447. ASSERT_THIS;
  448. return GetOwner()->SetLocale(lDestPos, lDestLen, locale);
  449. }
  450. STDMETHODIMP CMLStrA::GetLocale(long lSrcPos, long lSrcMaxLen, LCID* plocale, long* plLocalePos, long* plLocaleLen)
  451. {
  452. ASSERT_THIS;
  453. return GetOwner()->GetLocale(lSrcPos, lSrcMaxLen, plocale, plLocalePos, plLocaleLen);
  454. }
  455. #else // NEWMLSTR
  456. #include "mlstr.h"
  457. /////////////////////////////////////////////////////////////////////////////
  458. // CMLStrA
  459. CMLStrA::CMLStrA(void) :
  460. m_pAttrAStr(NULL),
  461. m_pAttrLocale(NULL),
  462. m_dwAttrAStrCookie(NULL),
  463. m_dwAttrLocaleCookie(NULL)
  464. {
  465. DllAddRef();
  466. ::InitializeCriticalSection(&m_cs);
  467. }
  468. CMLStrA::~CMLStrA(void)
  469. {
  470. if (m_dwAttrLocaleCookie)
  471. GetOwner()->UnregisterAttr(m_dwAttrLocaleCookie);
  472. if (m_dwAttrAStrCookie)
  473. GetOwner()->UnregisterAttr(m_dwAttrAStrCookie);
  474. if (m_pAttrLocale)
  475. m_pAttrLocale->Release();
  476. if (m_pAttrAStr)
  477. m_pAttrAStr->Release();
  478. ::DeleteCriticalSection(&m_cs);
  479. DllRelease();
  480. }
  481. HRESULT CMLStrA::GetAttrAStrReal(IMLStrAttrAStr** ppAttr)
  482. {
  483. HRESULT hr = S_OK;
  484. ::EnterCriticalSection(&m_cs);
  485. if (!m_pAttrAStr)
  486. {
  487. IMLStrAttrAStr* pAttr;
  488. hr = ::CoCreateInstance(CLSID_CMLStrAttrAStr, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pAttr);
  489. if (SUCCEEDED(hr))
  490. hr = GetOwner()->RegisterAttr(pAttr, &m_dwAttrAStrCookie);
  491. if (SUCCEEDED(hr))
  492. {
  493. pAttr->Release();
  494. hr = GetOwner()->FindAttr(IID_IMLStrAttrAStr, 0, (IUnknown**)&pAttr);
  495. }
  496. if (SUCCEEDED(hr))
  497. m_pAttrAStr = pAttr;
  498. }
  499. if (ppAttr)
  500. *ppAttr = m_pAttrAStr;
  501. ::LeaveCriticalSection(&m_cs);
  502. return hr;
  503. }
  504. HRESULT CMLStrA::GetAttrLocaleReal(IMLStrAttrLocale** ppAttr)
  505. {
  506. HRESULT hr = S_OK;
  507. ::EnterCriticalSection(&m_cs);
  508. if (!m_pAttrLocale)
  509. {
  510. IMLStrAttrLocale* pAttr;
  511. hr = ::CoCreateInstance(CLSID_CMLStrAttrLocale, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pAttr);
  512. if (SUCCEEDED(hr))
  513. hr = GetOwner()->RegisterAttr(pAttr, &m_dwAttrLocaleCookie);
  514. if (SUCCEEDED(hr))
  515. {
  516. pAttr->Release();
  517. hr = GetOwner()->FindAttr(IID_IMLStrAttrLocale, 0, (IUnknown**)&pAttr);
  518. }
  519. if (SUCCEEDED(hr))
  520. m_pAttrLocale = pAttr;
  521. }
  522. if (ppAttr)
  523. *ppAttr = m_pAttrLocale;
  524. ::LeaveCriticalSection(&m_cs);
  525. return hr;
  526. }
  527. STDMETHODIMP CMLStrA::LockMLStr(long lPos, long lLen, DWORD dwFlags, DWORD* pdwCookie, long* plActualPos, long* plActualLen)
  528. {
  529. ASSERT_THIS;
  530. return GetOwner()->LockMLStr(lPos, lLen, dwFlags, pdwCookie, plActualPos, plActualLen);
  531. }
  532. STDMETHODIMP CMLStrA::UnlockMLStr(DWORD dwCookie)
  533. {
  534. ASSERT_THIS;
  535. return GetOwner()->UnlockMLStr(dwCookie);
  536. }
  537. STDMETHODIMP CMLStrA::GetLength(long* plLen)
  538. {
  539. ASSERT_THIS;
  540. return GetOwner()->GetLength(plLen);
  541. }
  542. STDMETHODIMP CMLStrA::SetMLStr(long lDestPos, long lDestLen, IUnknown* pSrcMLStr, long lSrcPos, long lSrcLen)
  543. {
  544. ASSERT_THIS;
  545. return GetOwner()->SetMLStr(lDestPos, lDestLen, pSrcMLStr, lSrcPos, lSrcLen);
  546. }
  547. STDMETHODIMP CMLStrA::RegisterAttr(IUnknown* pUnk, DWORD* pdwCookie)
  548. {
  549. ASSERT_THIS;
  550. return GetOwner()->RegisterAttr(pUnk, pdwCookie);
  551. }
  552. STDMETHODIMP CMLStrA::UnregisterAttr(DWORD dwCookie)
  553. {
  554. ASSERT_THIS;
  555. return GetOwner()->UnregisterAttr(dwCookie);
  556. }
  557. STDMETHODIMP CMLStrA::EnumAttr(IEnumUnknown** ppEnumUnk)
  558. {
  559. ASSERT_THIS;
  560. return GetOwner()->EnumAttr(ppEnumUnk);
  561. }
  562. STDMETHODIMP CMLStrA::FindAttr(REFIID riid, LPARAM lParam, IUnknown** ppUnk)
  563. {
  564. ASSERT_THIS;
  565. return GetOwner()->FindAttr(riid, lParam, ppUnk);
  566. }
  567. STDMETHODIMP CMLStrA::SetAStr(long lDestPos, long lDestLen, UINT uCodePage, const CHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  568. {
  569. ASSERT_THIS;
  570. IMLStrAttrAStr* pAttr;
  571. HRESULT hr = GetAttrAStr(&pAttr);
  572. if (SUCCEEDED(hr))
  573. hr = pAttr->SetAStr(lDestPos, lDestLen, uCodePage, pszSrc, cchSrc, pcchActual, plActualLen);
  574. return hr;
  575. }
  576. STDMETHODIMP CMLStrA::SetStrBufA(long lDestPos, long lDestLen, UINT uCodePage, IMLangStringBufA* pSrcBuf, long* pcchActual, long* plActualLen)
  577. {
  578. ASSERT_THIS;
  579. IMLStrAttrAStr* pAttr;
  580. HRESULT hr = GetAttrAStr(&pAttr);
  581. if (SUCCEEDED(hr))
  582. hr = pAttr->SetStrBufA(lDestPos, lDestLen, uCodePage, pSrcBuf, pcchActual, plActualLen);
  583. return hr;
  584. }
  585. STDMETHODIMP CMLStrA::GetAStr(long lSrcPos, long lSrcLen, UINT uCodePageIn, UINT* puCodePageOut, CHAR* pszDest, long cchDest, long* pcchActual, long* plActualLen)
  586. {
  587. ASSERT_THIS;
  588. IMLStrAttrAStr* pAttr;
  589. HRESULT hr = GetAttrAStr(&pAttr);
  590. if (SUCCEEDED(hr))
  591. hr = pAttr->GetAStr(lSrcPos, lSrcLen, uCodePageIn, puCodePageOut, pszDest, cchDest, pcchActual, plActualLen);
  592. return hr;
  593. }
  594. STDMETHODIMP CMLStrA::GetStrBufA(long lSrcPos, long lSrcMaxLen, UINT* puDestCodePage, IMLangStringBufA** ppDestBuf, long* plDestLen)
  595. {
  596. ASSERT_THIS;
  597. IMLStrAttrAStr* pAttr;
  598. HRESULT hr = GetAttrAStr(&pAttr);
  599. if (SUCCEEDED(hr))
  600. hr = pAttr->GetStrBufA(lSrcPos, lSrcMaxLen, puDestCodePage, ppDestBuf, plDestLen);
  601. return hr;
  602. }
  603. STDMETHODIMP CMLStrA::LockAStr(long lSrcPos, long lSrcLen, long lFlags, UINT uCodePageIn, long cchRequest, UINT* puCodePageOut, CHAR** ppszDest, long* pcchDest, long* plDestLen)
  604. {
  605. ASSERT_THIS;
  606. IMLStrAttrAStr* pAttr;
  607. HRESULT hr = GetAttrAStr(&pAttr);
  608. if (SUCCEEDED(hr))
  609. hr = pAttr->LockAStr(lSrcPos, lSrcLen, lFlags, uCodePageIn, cchRequest, puCodePageOut, ppszDest, pcchDest, plDestLen);
  610. return hr;
  611. }
  612. STDMETHODIMP CMLStrA::UnlockAStr(const CHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  613. {
  614. ASSERT_THIS;
  615. IMLStrAttrAStr* pAttr;
  616. HRESULT hr = GetAttrAStr(&pAttr);
  617. if (SUCCEEDED(hr))
  618. hr = pAttr->UnlockAStr(pszSrc, cchSrc, pcchActual, plActualLen);
  619. return hr;
  620. }
  621. STDMETHODIMP CMLStrA::SetLocale(long lDestPos, long lDestLen, LCID locale)
  622. {
  623. ASSERT_THIS;
  624. IMLStrAttrLocale* pAttr;
  625. HRESULT hr = GetAttrLocale(&pAttr);
  626. if (SUCCEEDED(hr))
  627. hr = pAttr->SetLong(lDestPos, lDestLen, (long)locale);
  628. return hr;
  629. }
  630. STDMETHODIMP CMLStrA::GetLocale(long lSrcPos, long lSrcMaxLen, LCID* plocale, long* plLocalePos, long* plLocaleLen)
  631. {
  632. ASSERT_THIS;
  633. IMLStrAttrLocale* pAttr;
  634. HRESULT hr = GetAttrLocale(&pAttr);
  635. if (SUCCEEDED(hr))
  636. hr = pAttr->GetLong(lSrcPos, lSrcMaxLen, (long*)plocale, plLocalePos, plLocaleLen);
  637. return hr;
  638. }
  639. #endif NEWMLSTR