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.

536 lines
15 KiB

  1. // AttrStrW.cpp : Implementation of CMLStrAttrWStr
  2. #include "private.h"
  3. #ifdef NEWMLSTR
  4. #include "attrstrw.h"
  5. #include "mlsbwalk.h"
  6. /////////////////////////////////////////////////////////////////////////////
  7. // CMLStrAttrWStr
  8. CMLStrAttrWStr::CMLStrAttrWStr(void) :
  9. m_pMLStr(NULL)
  10. {
  11. }
  12. CMLStrAttrWStr::~CMLStrAttrWStr(void)
  13. {
  14. VERIFY(SetClient(NULL)); // Clean m_pMLStr
  15. }
  16. STDMETHODIMP CMLStrAttrWStr::SetClient(IUnknown* pUnk)
  17. {
  18. ASSERT_THIS;
  19. ASSERT_READ_PTR_OR_NULL(pUnk);
  20. HRESULT hr = S_OK;
  21. // Release old client
  22. IMLangString* const pMLStr = m_pMLStr;
  23. if (pMLStr && SUCCEEDED(hr = StartEndConnectionMLStr(pMLStr, FALSE))) // End connection to MLStr
  24. {
  25. pMLStr->Release();
  26. m_pMLStr = NULL;
  27. }
  28. // Set new client
  29. if (SUCCEEDED(hr) && pUnk) // pUnk is given
  30. {
  31. ASSERT(!m_pMLStr);
  32. if (SUCCEEDED(hr = pUnk->QueryInterface(IID_IMLangString, (void**)&m_pMLStr)))
  33. {
  34. ASSERT_READ_PTR(m_pMLStr);
  35. if (FAILED(hr = StartEndConnectionMLStr(pUnk, TRUE))) // Start connection to MLStr
  36. {
  37. m_pMLStr->Release();
  38. m_pMLStr = NULL;
  39. }
  40. }
  41. }
  42. return hr;
  43. }
  44. HRESULT CMLStrAttrWStr::StartEndConnectionMLStr(IUnknown* const pUnk, BOOL fStart)
  45. {
  46. ASSERT_THIS;
  47. ASSERT_READ_PTR(pUnk);
  48. HRESULT hr;
  49. IConnectionPointContainer* pCPC;
  50. if (SUCCEEDED(hr = pUnk->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC)))
  51. {
  52. ASSERT_READ_PTR(pCPC);
  53. IConnectionPoint* pCP;
  54. if (SUCCEEDED(hr = pCPC->FindConnectionPoint(IID_IMLangStringNotifySink, &pCP)))
  55. {
  56. ASSERT_READ_PTR(pCP);
  57. if (fStart)
  58. hr = pCP->Advise((IMLStrAttr*)this, &m_dwMLStrCookie);
  59. else
  60. hr = pCP->Unadvise(m_dwMLStrCookie);
  61. pCP->Release();
  62. }
  63. pCPC->Release();
  64. }
  65. return hr;
  66. }
  67. STDMETHODIMP CMLStrAttrWStr::GetClient(IUnknown** ppUnk)
  68. {
  69. ASSERT_THIS;
  70. ASSERT_WRITE_PTR_OR_NULL(ppUnk);
  71. if (ppUnk)
  72. {
  73. IUnknown* const pUnk = m_pMLStr;
  74. *ppUnk = pUnk;
  75. if (pUnk)
  76. pUnk->AddRef();
  77. }
  78. return S_OK;
  79. }
  80. STDMETHODIMP CMLStrAttrWStr::QueryAttr(REFIID riid, LPARAM lParam, IUnknown** ppUnk, long* lConf)
  81. {
  82. return E_NOTIMPL; // CMLStrAttrWStr::QueryAttr()
  83. }
  84. STDMETHODIMP CMLStrAttrWStr::GetAttrInterface(IID* pIID, LPARAM* plParam)
  85. {
  86. return E_NOTIMPL; // CMLStrAttrWStr::GetAttrInterface()
  87. }
  88. STDMETHODIMP CMLStrAttrWStr::SetMLStr(long lDestPos, long lDestLen, IUnknown* pSrcMLStr, long lSrcPos, long lSrcLen)
  89. {
  90. return E_NOTIMPL; // CMLStrAttrWStr::SetMLStr()
  91. }
  92. STDMETHODIMP CMLStrAttrWStr::SetWStr(long lDestPos, long lDestLen, const WCHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  93. {
  94. ASSERT_THIS;
  95. ASSERT_READ_BLOCK(pszSrc, cchSrc);
  96. ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  97. ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  98. HRESULT hr = CheckThread();
  99. CLock Lock(TRUE, this, hr);
  100. long cchDestPos;
  101. long cchDestLen;
  102. long cchActual;
  103. long lActualLen;
  104. if (SUCCEEDED(hr) && (GetBufFlags() & MLSTR_WRITE))
  105. hr = E_INVALIDARG; // Not writable StrBuf; TODO: Replace StrBuf in this case if allowed
  106. if (SUCCEEDED(hr) &&
  107. SUCCEEDED(hr = PrepareMLStrBuf()) &&
  108. SUCCEEDED(hr = RegularizePosLen(&lDestPos, &lDestLen)) &&
  109. SUCCEEDED(hr = GetCCh(0, lDestPos, &cchDestPos)) &&
  110. SUCCEEDED(hr = GetCCh(cchDestPos, lDestLen, &cchDestLen)))
  111. {
  112. IMLangStringBufW* const pMLStrBufW = GetMLStrBufW();
  113. if (pMLStrBufW)
  114. {
  115. if (cchSrc > cchDestLen)
  116. {
  117. hr = pMLStrBufW->Insert(cchDestPos, cchSrc - cchDestLen, (pcchActual || plActualLen) ? &cchSrc : NULL);
  118. cchSrc += cchDestLen;
  119. }
  120. else if (cchSrc < cchDestLen)
  121. {
  122. hr = pMLStrBufW->Delete(cchDestPos, cchDestLen - cchSrc);
  123. }
  124. CMLStrBufWalkW BufWalk(pMLStrBufW, cchDestPos, cchSrc, (pcchActual || plActualLen));
  125. lActualLen = 0;
  126. while (BufWalk.Lock(hr))
  127. {
  128. long lLen;
  129. if (plActualLen)
  130. hr = CalcLenW(pszSrc, BufWalk.GetCCh(), &lLen);
  131. if (SUCCEEDED(hr))
  132. {
  133. lActualLen += lLen;
  134. ::memcpy(BufWalk.GetStr(), pszSrc, sizeof(WCHAR) * BufWalk.GetCCh());
  135. pszSrc += BufWalk.GetCCh();
  136. }
  137. BufWalk.Unlock(hr);
  138. }
  139. cchActual = BufWalk.GetDoneCCh();
  140. }
  141. else
  142. {
  143. IMLangStringBufA* const pMLStrBufA = GetMLStrBufA(); // Should succeed because PrepareMLStrBuf() above was succeeded
  144. const UINT uCodePage = GetCodePage();
  145. long cchSrcA;
  146. if (SUCCEEDED(hr = ConvWStrToAStr(pcchActual || plActualLen, uCodePage, pszSrc, cchSrc, NULL, 0, &cchSrcA, NULL, NULL)))
  147. {
  148. if (cchSrcA > cchDestLen)
  149. {
  150. hr = pMLStrBufA->Insert(cchDestPos, cchSrcA - cchDestLen, (pcchActual || plActualLen) ? &cchSrcA : NULL);
  151. cchSrcA += cchDestLen;
  152. }
  153. else if (cchSrcA < cchDestLen)
  154. {
  155. hr = pMLStrBufA->Delete(cchDestPos, cchDestLen - cchSrcA);
  156. }
  157. }
  158. CMLStrBufWalkA BufWalk(pMLStrBufA, cchDestPos, cchSrcA, (pcchActual || plActualLen));
  159. cchActual = 0;
  160. lActualLen = 0;
  161. while (BufWalk.Lock(hr))
  162. {
  163. long cchWrittenA;
  164. long cchWrittenW;
  165. long lWrittenLen;
  166. if (SUCCEEDED(hr = ConvWStrToAStr(pcchActual || plActualLen, uCodePage, pszSrc, cchSrc, BufWalk.GetStr(), BufWalk.GetCCh(), &cchWrittenA, &cchWrittenW, &lWrittenLen)))
  167. {
  168. pszSrc += cchWrittenW;
  169. cchSrc -= cchWrittenW;
  170. cchActual += cchWrittenW;
  171. lActualLen += lWrittenLen;
  172. }
  173. BufWalk.Unlock(hr, cchWrittenA);
  174. }
  175. }
  176. }
  177. if (SUCCEEDED(hr))
  178. {
  179. if (pcchActual)
  180. *pcchActual = cchActual;
  181. if (plActualLen)
  182. *plActualLen = lActualLen;
  183. }
  184. else
  185. {
  186. if (pcchActual)
  187. *pcchActual = 0;
  188. if (plActualLen)
  189. *plActualLen = 0;
  190. }
  191. return hr;
  192. }
  193. STDMETHODIMP CMLStrAttrWStr::SetStrBufW(long lDestPos, long lDestLen, IMLangStringBufW* pSrcBuf, long* pcchActual, long* plActualLen)
  194. {
  195. ASSERT_THIS;
  196. return SetStrBufCommon(this, lDestPos, lDestLen, 0, pSrcBuf, NULL, pcchActual, plActualLen);
  197. }
  198. STDMETHODIMP CMLStrAttrWStr::GetWStr(long lSrcPos, long lSrcLen, WCHAR* pszDest, long cchDest, long* pcchActual, long* plActualLen)
  199. {
  200. ASSERT_THIS;
  201. ASSERT_WRITE_BLOCK_OR_NULL(pszDest, cchDest);
  202. ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  203. ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  204. HRESULT hr = CheckThread();
  205. CLock Lock(FALSE, this, hr);
  206. long cchSrcPos;
  207. long cchSrcLen;
  208. long cchActual;
  209. long lActualLen;
  210. if (SUCCEEDED(hr) &&
  211. SUCCEEDED(hr = RegularizePosLen(&lSrcPos, &lSrcLen)) &&
  212. SUCCEEDED(hr = GetCCh(0, lSrcPos, &cchSrcPos)) &&
  213. SUCCEEDED(hr = GetCCh(cchSrcPos, lSrcLen, &cchSrcLen)))
  214. {
  215. IMLangStringBufW* const pMLStrBufW = GetMLStrBufW();
  216. IMLangStringBufA* const pMLStrBufA = GetMLStrBufA();
  217. if (pszDest)
  218. cchActual = min(cchSrcLen, cchDest);
  219. else
  220. cchActual = cchSrcLen;
  221. if (pMLStrBufW)
  222. {
  223. CMLStrBufWalkW BufWalk(pMLStrBufW, cchSrcPos, cchActual, (pcchActual || plActualLen));
  224. lActualLen = 0;
  225. while (BufWalk.Lock(hr))
  226. {
  227. long lLen;
  228. if (plActualLen)
  229. hr = CalcLenW(BufWalk.GetStr(), BufWalk.GetCCh(), &lLen);
  230. if (SUCCEEDED(hr))
  231. {
  232. lActualLen += lLen;
  233. if (pszDest)
  234. {
  235. ::memcpy(pszDest, BufWalk.GetStr(), sizeof(WCHAR) * BufWalk.GetCCh());
  236. pszDest += BufWalk.GetCCh();
  237. }
  238. }
  239. BufWalk.Unlock(hr);
  240. }
  241. cchActual = BufWalk.GetDoneCCh();
  242. }
  243. else if (pMLStrBufA)
  244. {
  245. CMLStrBufWalkA BufWalk(pMLStrBufA, cchSrcPos, cchActual, (pcchActual || plActualLen));
  246. cchActual = 0;
  247. lActualLen = 0;
  248. while ((!pszDest || cchDest > 0) && BufWalk.Lock(hr))
  249. {
  250. CHAR* const pszBuf = BufWalk.GetStr();
  251. long cchWrittenA;
  252. long cchWrittenW;
  253. long lWrittenLen;
  254. if (SUCCEEDED(hr = ConvAStrToWStr(GetCodePage(), pszBuf, BufWalk.GetCCh(), pszDest, cchDest, &cchWrittenA, &cchWrittenW, &lWrittenLen)))
  255. {
  256. lActualLen += lWrittenLen;
  257. cchActual += cchWrittenW;
  258. if (pszDest)
  259. {
  260. pszDest += cchWrittenW;
  261. cchDest -= cchWrittenW;
  262. }
  263. }
  264. BufWalk.Unlock(hr, cchWrittenA);
  265. }
  266. }
  267. else
  268. {
  269. ASSERT(cchActual == 0); // MLStrBuf is not available
  270. lActualLen = 0;
  271. }
  272. }
  273. if (SUCCEEDED(hr))
  274. {
  275. if (pcchActual)
  276. *pcchActual = cchActual;
  277. if (plActualLen)
  278. *plActualLen = lActualLen;
  279. }
  280. else
  281. {
  282. if (pcchActual)
  283. *pcchActual = 0;
  284. if (plActualLen)
  285. *plActualLen = 0;
  286. }
  287. return hr;
  288. }
  289. STDMETHODIMP CMLStrAttrWStr::GetStrBufW(long lSrcPos, long lSrcMaxLen, IMLangStringBufW** ppDestBuf, long* plDestLen)
  290. {
  291. ASSERT_THIS;
  292. ASSERT_WRITE_PTR_OR_NULL(ppDestBuf);
  293. ASSERT_WRITE_PTR_OR_NULL(plDestLen);
  294. HRESULT hr = CheckThread();
  295. CLock Lock(FALSE, this, hr);
  296. IMLangStringBufW* pMLStrBufW;
  297. if (SUCCEEDED(hr) &&
  298. SUCCEEDED(hr = RegularizePosLen(&lSrcPos, &lSrcMaxLen)) &&
  299. lSrcMaxLen <= 0)
  300. {
  301. hr = E_INVALIDARG;
  302. }
  303. if (SUCCEEDED(hr))
  304. {
  305. pMLStrBufW = GetMLStrBufW();
  306. if (!pMLStrBufW)
  307. hr = MLSTR_E_STRBUFNOTAVAILABLE;
  308. }
  309. if (SUCCEEDED(hr))
  310. {
  311. if (ppDestBuf)
  312. {
  313. pMLStrBufW->AddRef();
  314. *ppDestBuf = pMLStrBufW;
  315. }
  316. if (plDestLen)
  317. *plDestLen = lSrcMaxLen;
  318. }
  319. else
  320. {
  321. if (ppDestBuf)
  322. *ppDestBuf = NULL;
  323. if (plDestLen)
  324. *plDestLen = 0;
  325. }
  326. return hr;
  327. }
  328. STDMETHODIMP CMLStrAttrWStr::LockWStr(long lSrcPos, long lSrcLen, long lFlags, long cchRequest, WCHAR** ppszDest, long* pcchDest, long* plDestLen)
  329. {
  330. ASSERT_THIS;
  331. ASSERT_WRITE_PTR_OR_NULL(ppszDest);
  332. ASSERT_WRITE_PTR_OR_NULL(pcchDest);
  333. ASSERT_WRITE_PTR_OR_NULL(plDestLen);
  334. HRESULT hr = CheckThread();
  335. CLock Lock(lFlags & MLSTR_WRITE, this, hr);
  336. long cchSrcPos;
  337. long cchSrcLen;
  338. WCHAR* pszBuf = NULL;
  339. long cchBuf;
  340. long lLockLen;
  341. BOOL fDirectLock;
  342. if (SUCCEEDED(hr) && (!lFlags || (lFlags & ~GetBufFlags() & MLSTR_WRITE)))
  343. hr = E_INVALIDARG; // No flags specified, or not writable StrBuf; TODO: Replace StrBuf in this case if allowed
  344. if (!(lFlags & MLSTR_WRITE))
  345. cchRequest = 0;
  346. if (SUCCEEDED(hr) &&
  347. SUCCEEDED(hr = PrepareMLStrBuf()) &&
  348. SUCCEEDED(hr = RegularizePosLen(&lSrcPos, &lSrcLen)) &&
  349. SUCCEEDED(hr = GetCCh(0, lSrcPos, &cchSrcPos)) &&
  350. SUCCEEDED(hr = GetCCh(cchSrcPos, lSrcLen, &cchSrcLen)))
  351. {
  352. IMLangStringBufW* const pMLStrBufW = GetMLStrBufW();
  353. fDirectLock = (pMLStrBufW != 0);
  354. if (fDirectLock)
  355. {
  356. long cchInserted;
  357. long cchLockLen = cchSrcLen;
  358. if (cchRequest > cchSrcLen &&
  359. SUCCEEDED(hr = pMLStrBufW->Insert(cchSrcPos + cchSrcLen, cchRequest - cchSrcLen, &cchInserted)))
  360. {
  361. SetBufCCh(GetBufCCh() + cchInserted);
  362. cchLockLen += cchInserted;
  363. if (!pcchDest && cchLockLen < cchRequest)
  364. hr = E_OUTOFMEMORY; // Can't insert in StrBuf
  365. }
  366. if (SUCCEEDED(hr) &&
  367. SUCCEEDED(hr = pMLStrBufW->LockBuf(cchSrcPos, cchLockLen, &pszBuf, &cchBuf)) &&
  368. !pcchDest && cchBuf < max(cchSrcLen, cchRequest))
  369. {
  370. hr = E_OUTOFMEMORY; // Can't lock StrBuf
  371. }
  372. if (plDestLen && SUCCEEDED(hr))
  373. hr = CalcLenW(pszBuf, cchBuf, &lLockLen);
  374. }
  375. else
  376. {
  377. long cchSize;
  378. if (SUCCEEDED(hr = CalcBufSizeW(lSrcLen, &cchSize)))
  379. {
  380. cchBuf = max(cchSize, cchRequest);
  381. hr = MemAlloc(sizeof(*pszBuf) * cchBuf, (void**)&pszBuf);
  382. }
  383. if (SUCCEEDED(hr) && (lFlags & MLSTR_READ))
  384. hr = GetWStr(lSrcPos, lSrcLen, pszBuf, cchBuf, (pcchDest) ? &cchBuf : NULL, (plDestLen) ? &lLockLen : NULL);
  385. }
  386. }
  387. if (SUCCEEDED(hr) &&
  388. SUCCEEDED(hr = Lock.FallThrough()))
  389. {
  390. hr = GetLockInfo()->Lock((fDirectLock) ? UnlockWStrDirect : UnlockWStrIndirect, lFlags, 0, pszBuf, lSrcPos, lSrcLen, cchSrcPos, cchBuf);
  391. }
  392. if (SUCCEEDED(hr))
  393. {
  394. if (ppszDest)
  395. *ppszDest = pszBuf;
  396. if (pcchDest)
  397. *pcchDest = cchBuf;
  398. if (plDestLen)
  399. *plDestLen = lLockLen;
  400. }
  401. else
  402. {
  403. if (pszBuf)
  404. {
  405. if (fDirectLock)
  406. GetMLStrBufW()->UnlockBuf(pszBuf, 0, 0);
  407. else
  408. MemFree(pszBuf);
  409. }
  410. if (ppszDest)
  411. *ppszDest = NULL;
  412. if (pcchDest)
  413. *pcchDest = 0;
  414. if (plDestLen)
  415. *plDestLen = 0;
  416. }
  417. return hr;
  418. }
  419. STDMETHODIMP CMLStrAttrWStr::UnlockWStr(const WCHAR* pszSrc, long cchSrc, long* pcchActual, long* plActualLen)
  420. {
  421. ASSERT_THIS;
  422. ASSERT_READ_BLOCK(pszSrc, cchSrc);
  423. ASSERT_WRITE_PTR_OR_NULL(pcchActual);
  424. ASSERT_WRITE_PTR_OR_NULL(plActualLen);
  425. return UnlockStrCommon(pszSrc, cchSrc, pcchActual, plActualLen);
  426. }
  427. STDMETHODIMP CMLStrAttrWStr::OnRegisterAttr(IUnknown* pUnk)
  428. {
  429. return E_NOTIMPL; // CMLStrAttrWStr::OnRegisterAttr()
  430. }
  431. STDMETHODIMP CMLStrAttrWStr::OnUnregisterAttr(IUnknown* pUnk)
  432. {
  433. return E_NOTIMPL; // CMLStrAttrWStr::OnUnregisterAttr()
  434. }
  435. STDMETHODIMP CMLStrAttrWStr::OnRequestEdit(long lDestPos, long lDestLen, long lNewLen, REFIID riid, LPARAM lParam, IUnknown* pUnk)
  436. {
  437. return E_NOTIMPL; // CMLStrAttrWStr::OnRequestEdit()
  438. }
  439. STDMETHODIMP CMLStrAttrWStr::OnCanceledEdit(long lDestPos, long lDestLen, long lNewLen, REFIID riid, LPARAM lParam, IUnknown* pUnk)
  440. {
  441. return E_NOTIMPL; // CMLStrAttrWStr::OnCanceledEdit()
  442. }
  443. STDMETHODIMP CMLStrAttrWStr::OnChanged(long lDestPos, long lDestLen, long lNewLen, REFIID riid, LPARAM lParam, IUnknown* pUnk)
  444. {
  445. return E_NOTIMPL; // CMLStrAttrWStr::OnChanged()
  446. }
  447. #endif // NEWMLSTR