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.

623 lines
16 KiB

  1. // AttrStr.cpp : Implementation of CMLStrAttrStrCommonAttrStrCommon
  2. #include "private.h"
  3. #ifdef NEWMLSTR
  4. #include "attrstr.h"
  5. #include "mlsbwalk.h"
  6. /////////////////////////////////////////////////////////////////////////////
  7. // CMLStrAttrStrCommon
  8. CMLStrAttrStrCommon::CMLStrAttrStrCommon(void) :
  9. m_pMLStrBufW(NULL),
  10. m_pMLStrBufA(NULL),
  11. m_lBufFlags(0),
  12. m_cchBuf(0),
  13. m_locale(0),
  14. m_LockInfo(this)
  15. {
  16. m_dwThreadID = ::GetCurrentThreadId();
  17. }
  18. CMLStrAttrStrCommon::~CMLStrAttrStrCommon(void)
  19. {
  20. if (m_pMLStrBufW)
  21. m_pMLStrBufW->Release();
  22. if (m_pMLStrBufA)
  23. m_pMLStrBufA->Release();
  24. }
  25. HRESULT CMLStrAttrStrCommon::SetStrBufCommon(void* pMLStrX, long lDestPos, long lDestLen, UINT uCodePage, IMLangStringBufW* pSrcBufW, IMLangStringBufA* pSrcBufA, long* pcchActual, long* plActualLen)
  26. {
  27. ASSERT_THIS;
  28. ASSERT_READ_PTR_OR_NULL(pSrcBufW);
  29. ASSERT_READ_PTR_OR_NULL(pSrcBufA);
  30. ASSERT(!pSrcBufW || !pSrcBufA); // Either one or both should be NULL
  31. ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  32. ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  33. HRESULT hr = CheckThread();
  34. CLock Lock(TRUE, this, hr);
  35. long lBufFlags = 0; // '= 0' for in case of both of pSrcBufW and pSrcBufA are NULL
  36. long cchBuf = 0;
  37. long cchDestPos;
  38. long cchDestLen;
  39. long lActualLen = 0;
  40. if (SUCCEEDED(hr) &&
  41. (!pSrcBufW || SUCCEEDED(hr = pSrcBufW->GetStatus(&lBufFlags, &cchBuf))) &&
  42. (!pSrcBufA || SUCCEEDED(hr = pSrcBufA->GetStatus(&lBufFlags, &cchBuf))) &&
  43. SUCCEEDED(hr = RegularizePosLen(&lDestPos, &lDestLen)) &&
  44. SUCCEEDED(hr = GetCCh(0, lDestPos, &cchDestPos)) &&
  45. SUCCEEDED(hr = GetCCh(cchDestPos, lDestLen, &cchDestLen)))
  46. {
  47. if (!cchDestPos && cchDestLen == GetBufCCh()) // Replacing entire string
  48. {
  49. IMLangStringBufW* const pOldBufW = GetMLStrBufW();
  50. IMLangStringBufA* const pOldBufA = GetMLStrBufA();
  51. if (pOldBufW)
  52. pOldBufW->Release();
  53. else if (pOldBufA)
  54. pOldBufA->Release();
  55. if (pSrcBufW)
  56. pSrcBufW->AddRef();
  57. else if (pSrcBufA)
  58. pSrcBufA->AddRef();
  59. SetMLStrBufW(pSrcBufW);
  60. SetMLStrBufA(pSrcBufA);
  61. SetCodePage(uCodePage);
  62. SetBufFlags(lBufFlags);
  63. SetBufCCh(cchBuf);
  64. if (plActualLen)
  65. hr = GetLen(0, GetBufCCh(), &lActualLen);
  66. }
  67. else
  68. {
  69. if (pSrcBufW)
  70. {
  71. CMLStrBufWalkW BufWalk(pSrcBufW, 0, cchBuf, (pcchActual || plActualLen));
  72. while (BufWalk.Lock(hr))
  73. {
  74. long cchSet;
  75. long lSetLen;
  76. hr = ((IMLangStringWStr*)pMLStrX)->SetWStr(lDestPos, lDestLen, BufWalk.GetStr(), BufWalk.GetCCh(), &cchSet, (plActualLen) ? &lSetLen : NULL);
  77. lActualLen += lSetLen;
  78. BufWalk.Unlock(hr, cchSet);
  79. }
  80. cchBuf = BufWalk.GetDoneCCh();
  81. pSrcBufW->Release();
  82. }
  83. else if (pSrcBufA && pMLStrX)
  84. {
  85. CMLStrBufWalkA BufWalk(pSrcBufA, 0, cchBuf, (pcchActual || plActualLen));
  86. while (BufWalk.Lock(hr))
  87. {
  88. long cchSet;
  89. long lSetLen;
  90. hr = ((IMLangStringAStr*)pMLStrX)->SetAStr(lDestPos, lDestLen, uCodePage, BufWalk.GetStr(), BufWalk.GetCCh(), &cchSet, (plActualLen) ? &lSetLen : NULL);
  91. lActualLen += lSetLen;
  92. BufWalk.Unlock(hr, cchSet);
  93. }
  94. cchBuf = BufWalk.GetDoneCCh();
  95. pSrcBufA->Release();
  96. }
  97. else
  98. {
  99. hr = GetMLStrAttr()->SetMLStr(lDestPos, lDestLen, NULL, 0, 0);
  100. }
  101. }
  102. }
  103. if (SUCCEEDED(hr))
  104. {
  105. if (pcchActual)
  106. *pcchActual = cchBuf;
  107. if (plActualLen)
  108. *plActualLen = lActualLen;
  109. }
  110. else
  111. {
  112. if (pcchActual)
  113. *pcchActual = 0;
  114. if (plActualLen)
  115. *plActualLen = 0;
  116. }
  117. return hr;
  118. }
  119. HRESULT CMLStrAttrStrCommon::UnlockWStrDirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  120. {
  121. HRESULT hr;
  122. IMLangStringBufW* const pMLStrBufW = GetMLStrBufW();
  123. const long cchLockLen = GetLockInfo()->GetCChLen(pKey);
  124. if (SUCCEEDED(hr = pMLStrBufW->UnlockBuf((WCHAR*)pszSrc, 0, cchSrc)) &&
  125. (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE))
  126. {
  127. if (cchSrc < cchLockLen)
  128. {
  129. if (SUCCEEDED(hr = pMLStrBufW->Delete(GetLockInfo()->GetCChPos(pKey) + cchSrc, cchLockLen - cchSrc)))
  130. SetBufCCh(GetBufCCh() - (cchLockLen - cchSrc));
  131. }
  132. if (SUCCEEDED(hr) && plActualLen)
  133. hr = CalcLenW((WCHAR*)pszSrc, cchSrc, plActualLen);
  134. if (pcchActual)
  135. *pcchActual = cchSrc;
  136. }
  137. return hr;
  138. }
  139. HRESULT CMLStrAttrStrCommon::UnlockWStrIndirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  140. {
  141. HRESULT hr = S_OK;
  142. if (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE)
  143. {
  144. CComQIPtr<IMLStrAttrWStr, &IID_IMLStrAttrWStr> pAttrWStr(GetMLStrAttr());
  145. ASSERT(pAttrWStr);
  146. hr = pAttrWStr->SetWStr(GetLockInfo()->GetPos(pKey), GetLockInfo()->GetLen(pKey), (WCHAR*)pszSrc, cchSrc, pcchActual, plActualLen);
  147. }
  148. ASSIGN_IF_FAILED(hr, MemFree((void*)pszSrc));
  149. return hr;
  150. }
  151. HRESULT CMLStrAttrStrCommon::UnlockAStrDirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  152. {
  153. HRESULT hr;
  154. IMLangStringBufA* const pMLStrBufA = GetMLStrBufA();
  155. const long cchLockLen = GetLockInfo()->GetCChLen(pKey);
  156. if (SUCCEEDED(hr = pMLStrBufA->UnlockBuf((CHAR*)pszSrc, 0, cchSrc)) &&
  157. (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE))
  158. {
  159. if (cchSrc < cchLockLen)
  160. {
  161. if (SUCCEEDED(hr = pMLStrBufA->Delete(GetLockInfo()->GetCChPos(pKey) + cchSrc, cchLockLen - cchSrc)))
  162. SetBufCCh(GetBufCCh() - (cchLockLen - cchSrc));
  163. }
  164. if (SUCCEEDED(hr) && plActualLen)
  165. hr = CalcLenA(GetCodePage(), (CHAR*)pszSrc, cchSrc, plActualLen);
  166. if (pcchActual)
  167. *pcchActual = cchSrc;
  168. }
  169. return hr;
  170. }
  171. HRESULT CMLStrAttrStrCommon::UnlockAStrIndirect(void* pKey, const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  172. {
  173. HRESULT hr = S_OK;
  174. if (GetLockInfo()->GetFlags(pKey) & MLSTR_WRITE)
  175. {
  176. CComQIPtr<IMLStrAttrAStr, &IID_IMLStrAttrAStr> pAttrAStr(GetMLStrAttr());
  177. ASSERT(pAttrAStr);
  178. hr = pAttrAStr->SetAStr(GetLockInfo()->GetPos(pKey), GetLockInfo()->GetLen(pKey), GetLockInfo()->GetCodePage(pKey), (CHAR*)pszSrc, cchSrc, pcchActual, plActualLen);
  179. }
  180. ASSIGN_IF_FAILED(hr, MemFree((void*)pszSrc));
  181. return hr;
  182. }
  183. HRESULT CMLStrAttrStrCommon::UnlockStrCommon(const void* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  184. {
  185. HRESULT hr = CheckThread();
  186. void* pLockKey;
  187. long lSrcLen;
  188. if (SUCCEEDED(hr))
  189. hr = GetLockInfo()->Find(pszSrc, cchSrc, &pLockKey);
  190. if (SUCCEEDED(hr))
  191. hr = GetLockInfo()->Unlock(pLockKey, pszSrc, cchSrc, (pcchActual) ? &cchSrc : NULL, (plActualLen) ? &lSrcLen : NULL);
  192. if (SUCCEEDED(hr))
  193. {
  194. if (pcchActual)
  195. *pcchActual = cchSrc;
  196. if (plActualLen)
  197. *plActualLen = lSrcLen;
  198. }
  199. else
  200. {
  201. if (pcchActual)
  202. *pcchActual = 0;
  203. if (plActualLen)
  204. *plActualLen = 0;
  205. }
  206. return hr;
  207. }
  208. HRESULT CMLStrAttrStrCommon::PrepareMLStrBuf(void)
  209. {
  210. if (GetMLStrBufW() || GetMLStrBufA())
  211. return S_OK;
  212. IMLangStringBufW* pBuf = new CMLStrAttrStrCommon::CMLStrBufStandardW;
  213. if (pBuf)
  214. {
  215. SetMLStrBufW(pBuf);
  216. return S_OK;
  217. }
  218. else
  219. {
  220. return E_OUTOFMEMORY;
  221. }
  222. }
  223. HRESULT CMLStrAttrStrCommon::RegularizePosLen(long* plPos, long* plLen)
  224. {
  225. HRESULT hr;
  226. long lStrLen;
  227. if (SUCCEEDED(hr = GetLen(0, GetBufCCh(), &lStrLen)))
  228. hr = ::RegularizePosLen(lStrLen, plPos, plLen);
  229. return hr;
  230. }
  231. HRESULT CMLStrAttrStrCommon::GetCCh(long cchOffset, long lLen, long* pcchLen)
  232. {
  233. if (GetMLStrBufW())
  234. {
  235. if (pcchLen)
  236. *pcchLen = lLen; // The number of characters is equal to the length
  237. return S_OK;
  238. }
  239. else if (GetMLStrBufA())
  240. {
  241. HRESULT hr = S_OK;
  242. CMLStrBufWalkA BufWalk(GetMLStrBufA(), cchOffset, GetBufCCh() - cchOffset);
  243. while (lLen > 0 && BufWalk.Lock(hr))
  244. {
  245. for (LPCSTR pszTemp = BufWalk.GetStr(); lLen > 0 && *pszTemp; lLen--)
  246. pszTemp = ::CharNextExA((WORD)GetCodePage(), pszTemp, 0);
  247. if (!*pszTemp)
  248. lLen = 0; // String terminated
  249. BufWalk.Unlock(hr);
  250. }
  251. if (pcchLen)
  252. {
  253. if (SUCCEEDED(hr))
  254. *pcchLen = BufWalk.GetDoneCCh();
  255. else
  256. *pcchLen = 0;
  257. }
  258. return hr;
  259. }
  260. else
  261. {
  262. if (pcchLen)
  263. *pcchLen = 0; // No string
  264. return S_OK;
  265. }
  266. }
  267. HRESULT CMLStrAttrStrCommon::GetLen(long cchOffset, long cchLen, long* plLen)
  268. {
  269. if (GetMLStrBufW())
  270. {
  271. if (plLen)
  272. *plLen = cchLen; // The length is equal to the number of characters
  273. return S_OK;
  274. }
  275. else if (GetMLStrBufA())
  276. {
  277. HRESULT hr = S_OK;
  278. long lDoneLen = 0;
  279. CMLStrBufWalkA BufWalk(GetMLStrBufA(), cchOffset, cchLen);
  280. while (BufWalk.Lock(hr))
  281. {
  282. long lTempLen;
  283. hr = CalcLenA(GetCodePage(), BufWalk.GetStr(), BufWalk.GetCCh(), &lTempLen);
  284. if (hr == S_FALSE)
  285. cchLen = 0; // String terminated
  286. lDoneLen += lTempLen;
  287. BufWalk.Unlock(hr);
  288. }
  289. if (plLen)
  290. {
  291. if (SUCCEEDED(hr))
  292. *plLen = lDoneLen;
  293. else
  294. *plLen = 0;
  295. }
  296. return hr;
  297. }
  298. else
  299. {
  300. if (plLen)
  301. *plLen = 0; // No string
  302. return S_OK;
  303. }
  304. }
  305. HRESULT CMLStrAttrStrCommon::CalcLenA(UINT uCodePage, const CHAR* psz, long cchLen, long* plLen)
  306. {
  307. long lLen = 0;
  308. const CHAR* const pszEnd = psz + cchLen;
  309. for (; psz < pszEnd && *psz; lLen++)
  310. {
  311. const CHAR* const pszNew = ::CharNextExA((WORD)uCodePage, psz, 0);
  312. if (pszNew > pszEnd) // Overrun out of buffer
  313. break;
  314. psz = pszNew;
  315. }
  316. if (plLen)
  317. *plLen = lLen;
  318. if (*psz)
  319. return S_OK;
  320. else
  321. return S_FALSE;
  322. }
  323. HRESULT CMLStrAttrStrCommon::CalcCChA(UINT uCodePage, const CHAR* psz, long lLen, long* pcchLen)
  324. {
  325. const CHAR* const pszStart = psz;
  326. for (; lLen > 0 && *psz; lLen--)
  327. psz = ::CharNextExA((WORD)uCodePage, psz, 0);
  328. if (pcchLen)
  329. *pcchLen = psz - pszStart;
  330. if (*psz)
  331. return S_OK;
  332. else
  333. return S_FALSE;
  334. }
  335. HRESULT CMLStrAttrStrCommon::ConvAStrToWStr(UINT uCodePage, const CHAR* pszSrc, long cchSrc, WCHAR* pszDest, long cchDest, long* pcchActualA, long* pcchActualW, long* plActualLen)
  336. {
  337. HRESULT hr = S_OK;
  338. long lWrittenLen;
  339. long cchWrittenA;
  340. long cchWrittenW = ::MultiByteToWideChar(uCodePage, 0, pszSrc, cchSrc, pszDest, (pszDest) ? cchDest : 0);
  341. if (!cchWrittenW)
  342. hr = E_FAIL; // NLS failed
  343. if ((pcchActualA || plActualLen) && SUCCEEDED(hr))
  344. hr = CalcLenW(pszDest, cchWrittenW, &lWrittenLen); // BOGUS: pszDest may be NULL
  345. if (pcchActualA && SUCCEEDED(hr))
  346. hr = CalcCChA(uCodePage, pszSrc, lWrittenLen, &cchWrittenA);
  347. if (SUCCEEDED(hr))
  348. {
  349. if (pcchActualA)
  350. *pcchActualA = cchWrittenA;
  351. if (pcchActualW)
  352. *pcchActualW = cchWrittenW;
  353. if (plActualLen)
  354. *plActualLen = lWrittenLen;
  355. }
  356. else
  357. {
  358. if (pcchActualA)
  359. *pcchActualA = 0;
  360. if (pcchActualW)
  361. *pcchActualW = 0;
  362. if (plActualLen)
  363. *plActualLen = 0;
  364. }
  365. return hr;
  366. }
  367. HRESULT CMLStrAttrStrCommon::ConvWStrToAStr(BOOL fCanStopAtMiddle, UINT uCodePage, const WCHAR* pszSrc, long cchSrc, CHAR* pszDest, long cchDest, long* pcchActualA, long* pcchActualW, long* plActualLen)
  368. {
  369. HRESULT hr = S_OK;
  370. long lWrittenLen;
  371. long cchWrittenW;
  372. long cchWrittenA = ::WideCharToMultiByte(uCodePage, (fCanStopAtMiddle) ? 0 : WC_DEFAULTCHAR, pszSrc, cchSrc, pszDest, (pszDest) ? cchDest : 0, NULL, NULL);
  373. if (!cchWrittenA)
  374. hr = E_FAIL; // NLS failed
  375. if ((pcchActualW || plActualLen) && SUCCEEDED(hr))
  376. {
  377. if (pszDest)
  378. hr = CalcLenA(uCodePage, pszDest, cchWrittenA, &lWrittenLen);
  379. else
  380. hr = E_NOTIMPL; // Can't retrieve pcchActualW and plActualLen
  381. }
  382. if (pcchActualW && SUCCEEDED(hr))
  383. hr = CalcCChW(pszSrc, lWrittenLen, &cchWrittenW);
  384. if (SUCCEEDED(hr))
  385. {
  386. if (pcchActualA)
  387. *pcchActualA = cchWrittenA;
  388. if (pcchActualW)
  389. *pcchActualW = cchWrittenW;
  390. if (plActualLen)
  391. *plActualLen = lWrittenLen;
  392. }
  393. else
  394. {
  395. if (pcchActualA)
  396. *pcchActualA = 0;
  397. if (pcchActualW)
  398. *pcchActualW = 0;
  399. if (plActualLen)
  400. *plActualLen = 0;
  401. }
  402. return hr;
  403. }
  404. /////////////////////////////////////////////////////////////////////////////
  405. // CMLStrAttrStrCommon::CLockInfo
  406. HRESULT CMLStrAttrStrCommon::CLockInfo::UnlockAll(void)
  407. {
  408. if (m_pLockArray)
  409. {
  410. for (int n = 0; n < MAX_LOCK_COUNT; n++)
  411. {
  412. if (m_pLockArray[n].m_psz)
  413. Unlock(&m_pLockArray[n], m_pLockArray[n].m_psz, m_pLockArray[n].m_cchLen, NULL, NULL);
  414. }
  415. }
  416. return S_OK;
  417. }
  418. HRESULT CMLStrAttrStrCommon::CLockInfo::Lock(PFNUNLOCKPROC pfnUnlockProc, long lFlags, UINT uCodePage, void* psz, long lPos, long lLen, long cchPos, long cchLen)
  419. {
  420. HRESULT hr = S_OK;
  421. int nIndex;
  422. if (!m_pLockArray)
  423. {
  424. m_pLockArray = new CLockInfoEntry[MAX_LOCK_COUNT];
  425. if (m_pLockArray)
  426. {
  427. for (nIndex = 0; nIndex < MAX_LOCK_COUNT; nIndex++)
  428. m_pLockArray[nIndex].m_psz = NULL;
  429. }
  430. else
  431. {
  432. hr = E_OUTOFMEMORY;
  433. }
  434. }
  435. if (SUCCEEDED(hr))
  436. {
  437. for (nIndex = 0; nIndex < MAX_LOCK_COUNT; nIndex++)
  438. {
  439. if (!m_pLockArray[nIndex].m_psz)
  440. break;
  441. }
  442. if (nIndex >= MAX_LOCK_COUNT)
  443. hr = MLSTR_E_TOOMANYNESTOFLOCK;
  444. }
  445. if (SUCCEEDED(hr))
  446. {
  447. m_pLockArray[nIndex].m_psz = psz;
  448. m_pLockArray[nIndex].m_pfnUnlockProc = pfnUnlockProc;
  449. m_pLockArray[nIndex].m_lFlags = lFlags;
  450. m_pLockArray[nIndex].m_uCodePage = uCodePage;
  451. m_pLockArray[nIndex].m_lPos = lPos;
  452. m_pLockArray[nIndex].m_lLen = lLen;
  453. m_pLockArray[nIndex].m_cchPos = cchPos;
  454. m_pLockArray[nIndex].m_cchLen = cchLen;
  455. }
  456. return hr;
  457. }
  458. HRESULT CMLStrAttrStrCommon::CLockInfo::Find(const void* psz, long, void** ppKey)
  459. {
  460. HRESULT hr = S_OK;
  461. int nIndex;
  462. if (m_pLockArray)
  463. {
  464. for (nIndex = 0; nIndex < MAX_LOCK_COUNT; nIndex++)
  465. {
  466. if (psz == m_pLockArray[nIndex].m_psz)
  467. break;
  468. }
  469. }
  470. if (!m_pLockArray || nIndex >= MAX_LOCK_COUNT)
  471. hr = E_INVALIDARG;
  472. if (ppKey)
  473. {
  474. if (SUCCEEDED(hr))
  475. *ppKey = &m_pLockArray[nIndex];
  476. else
  477. *ppKey = NULL;
  478. }
  479. return hr;
  480. }
  481. HRESULT CMLStrAttrStrCommon::CLockInfo::Unlock(void* pKey, const void* psz, long cch, long* pcchActual, long* plActualLen)
  482. {
  483. CLockInfoEntry* const pEntry = (CLockInfoEntry*)pKey;
  484. HRESULT hr;
  485. if (!(pEntry->m_lFlags & MLSTR_WRITE))
  486. {
  487. cch = 0;
  488. if (plActualLen)
  489. *plActualLen = 0;
  490. }
  491. hr = (m_pCommon->*(pEntry->m_pfnUnlockProc))(pKey, psz, cch, pcchActual, plActualLen);
  492. if (SUCCEEDED(hr))
  493. hr = EndLock(pEntry->m_lFlags & MLSTR_WRITE);
  494. pEntry->m_psz = NULL; // Remove from lock array anyway
  495. if (FAILED(hr))
  496. {
  497. if (pcchActual)
  498. *pcchActual = 0;
  499. if (plActualLen)
  500. *plActualLen = 0;
  501. }
  502. return hr;
  503. }
  504. /////////////////////////////////////////////////////////////////////////////
  505. // CMLStrAttrStrCommon::CMLStrBufStandardW
  506. long CMLStrAttrStrCommon::CMLStrBufStandardW::RoundBufSize(long cchStr)
  507. {
  508. for (int n = 8; n < 12; n++)
  509. {
  510. if (cchStr < (1L << n))
  511. break;
  512. }
  513. const long cchTick = (1L << (n - 4));
  514. return (cchStr + cchTick - 1) / cchTick * cchTick;
  515. }
  516. #endif // NEWMLSTR