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.

507 lines
13 KiB

  1. #include <pch.hxx>
  2. #include <shlwapi.h>
  3. #include "xpcomm.h"
  4. #include "propbckt.h"
  5. void FreePropVariant(LPPROPVARIANT pProp);
  6. HRESULT DupPropVariant(LPPROPVARIANT pPropDst, LPCPROPVARIANT pPropSrc, BOOL fFree);
  7. HRESULT InsertPropNode(LPCSTR pszProp, int iProp, PROPNODE **ppNode, int *pcNode, int *pcNodeBuf);
  8. MSOEACCTAPI CreatePropertyBucket(IPropertyBucket **ppPropBckt)
  9. {
  10. CPropertyBucket *pBckt;
  11. Assert(ppPropBckt != NULL);
  12. pBckt = new CPropertyBucket;
  13. *ppPropBckt = (IPropertyBucket *)pBckt;
  14. return(pBckt == NULL ? E_OUTOFMEMORY : S_OK);
  15. }
  16. CPropertyBucket::CPropertyBucket(void)
  17. {
  18. m_cRef = 1;
  19. InitializeCriticalSection(&m_cs);
  20. m_pNodeId = NULL;
  21. m_cNodeId = 0;
  22. m_cNodeIdBuf = 0;
  23. m_pNodeSz = NULL;
  24. m_cNodeSz = 0;
  25. m_cNodeSzBuf = 0;
  26. m_pProp = 0;
  27. m_cProp = 0;
  28. m_cPropBuf = 0;
  29. }
  30. CPropertyBucket::~CPropertyBucket(void)
  31. {
  32. int i;
  33. PROPNODE *pNode;
  34. LPPROPVARIANT pProp;
  35. DeleteCriticalSection(&m_cs);
  36. if (m_pNodeId != NULL)
  37. MemFree(m_pNodeId);
  38. if (m_pNodeSz != NULL)
  39. {
  40. for (i = 0, pNode = m_pNodeSz; i < m_cNodeSz; i++, pNode++)
  41. {
  42. Assert(pNode->psz != NULL);
  43. MemFree(pNode->psz);
  44. }
  45. MemFree(m_pNodeSz);
  46. }
  47. if (m_pProp != NULL)
  48. {
  49. for (i = 0, pProp = m_pProp; i < m_cProp; i++, pProp++)
  50. FreePropVariant(pProp);
  51. MemFree(m_pProp);
  52. }
  53. }
  54. STDMETHODIMP CPropertyBucket::QueryInterface(REFIID riid, LPVOID *ppv)
  55. {
  56. if (ppv == NULL)
  57. return(E_INVALIDARG);
  58. if (IID_IUnknown == riid)
  59. {
  60. *ppv = (IUnknown *)this;
  61. }
  62. else if (IID_IPropertyBucket == riid)
  63. {
  64. *ppv = (IPropertyBucket *)this;
  65. }
  66. else
  67. {
  68. *ppv = NULL;
  69. return(E_NOINTERFACE);
  70. }
  71. ((IUnknown *)*ppv)->AddRef();
  72. return(S_OK);
  73. }
  74. STDMETHODIMP_(ULONG) CPropertyBucket::AddRef(void)
  75. {
  76. return((ULONG)InterlockedIncrement(&m_cRef));
  77. }
  78. STDMETHODIMP_(ULONG) CPropertyBucket::Release(void)
  79. {
  80. LONG cRef = InterlockedDecrement(&m_cRef);
  81. if (0 == cRef)
  82. delete this;
  83. return((ULONG)cRef);
  84. }
  85. LPPROPVARIANT CPropertyBucket::GetPropVariant(LPCSTR pszProp)
  86. {
  87. BOOL fSz;
  88. PROPID id;
  89. PROPNODE *pNode, *pNodeT;
  90. int x, left, right, d, cNode;
  91. Assert(pszProp != NULL);
  92. fSz = !IsPropId(pszProp);
  93. if (fSz)
  94. {
  95. pNode = m_pNodeSz;
  96. cNode = m_cNodeSz;
  97. }
  98. else
  99. {
  100. id = SzToPropId(pszProp);
  101. pNode = m_pNodeId;
  102. cNode = m_cNodeId;
  103. }
  104. if (pNode != NULL)
  105. {
  106. Assert(cNode > 0);
  107. left = 0;
  108. right = cNode - 1;
  109. do
  110. {
  111. x = (left + right) / 2;
  112. Assert(x >= 0);
  113. Assert(x < cNode);
  114. pNodeT = &pNode[x];
  115. d = fSz ? lstrcmp(pszProp, pNodeT->psz) : (id - pNodeT->id);
  116. if (d == 0)
  117. {
  118. Assert(pNodeT->iProp < m_cProp);
  119. return(&m_pProp[pNodeT->iProp]);
  120. }
  121. else if (d < 0)
  122. {
  123. right = x - 1;
  124. }
  125. else
  126. {
  127. left = x + 1;
  128. }
  129. }
  130. while (right >= left);
  131. }
  132. return(NULL);
  133. }
  134. // TODO: move to msoert
  135. void FreePropVariant(LPPROPVARIANT pProp)
  136. {
  137. Assert(pProp != NULL);
  138. switch (pProp->vt)
  139. {
  140. // Since pProp is a union, this MemFree will work for all
  141. case VT_LPSTR:
  142. case VT_LPWSTR:
  143. case VT_CLSID:
  144. case VT_CF:
  145. if (pProp->pszVal != NULL)
  146. MemFree(pProp->pszVal);
  147. break;
  148. case VT_BSTR:
  149. if (pProp->bstrVal != NULL)
  150. SysFreeString(pProp->bstrVal);
  151. break;
  152. case VT_BLOB:
  153. if (pProp->blob.pBlobData != NULL)
  154. MemFree(pProp->blob.pBlobData);
  155. break;
  156. case VT_STREAM:
  157. if (pProp->pStream != NULL)
  158. pProp->pStream->Release();
  159. break;
  160. case VT_STORAGE:
  161. if (pProp->pStorage != NULL)
  162. pProp->pStorage->Release();
  163. break;
  164. }
  165. }
  166. // TODO: move to msoert
  167. HRESULT DupPropVariant(LPPROPVARIANT pPropDst, LPCPROPVARIANT pPropSrc, BOOL fFree)
  168. {
  169. HRESULT hr = S_OK;
  170. LPSTR psz = NULL;
  171. LPWSTR pwsz = NULL;
  172. LPBYTE pb;
  173. hr = S_OK;
  174. switch (pPropSrc->vt)
  175. {
  176. case VT_LPSTR:
  177. if (pPropSrc->pszVal != NULL)
  178. {
  179. IF_NULLEXIT(psz = PszDupA(pPropSrc->pszVal));
  180. if (fFree)
  181. FreePropVariant(pPropDst);
  182. pPropDst->pszVal = psz;
  183. }
  184. else
  185. {
  186. if (fFree)
  187. FreePropVariant(pPropDst);
  188. pPropDst->pszVal = NULL;
  189. }
  190. break;
  191. case VT_LPWSTR:
  192. if (pPropSrc->pwszVal != NULL)
  193. {
  194. IF_NULLEXIT(pwsz = PszDupW(pPropSrc->pwszVal));
  195. if (fFree)
  196. FreePropVariant(pPropDst);
  197. pPropDst->pwszVal = pwsz;
  198. }
  199. else
  200. {
  201. if (fFree)
  202. FreePropVariant(pPropDst);
  203. pPropDst->pwszVal = NULL;
  204. }
  205. break;
  206. case VT_BLOB:
  207. if (pPropSrc->blob.pBlobData != NULL)
  208. {
  209. Assert(pPropSrc->blob.cbSize > 0);
  210. IF_NULLEXIT(MemAlloc((void **)&pb, pPropSrc->blob.cbSize));
  211. if (fFree)
  212. FreePropVariant(pPropDst);
  213. CopyMemory(pb, pPropSrc->blob.pBlobData, pPropSrc->blob.cbSize);
  214. pPropDst->blob.pBlobData = pb;
  215. pPropDst->blob.cbSize = pPropSrc->blob.cbSize;
  216. }
  217. else
  218. {
  219. if (fFree)
  220. FreePropVariant(pPropDst);
  221. Assert(pPropSrc->blob.cbSize == 0);
  222. pPropDst->blob.cbSize = 0;
  223. pPropDst->blob.pBlobData = NULL;
  224. }
  225. break;
  226. case VT_UI1:
  227. pPropDst->bVal = pPropSrc->bVal;
  228. break;
  229. case VT_I2:
  230. case VT_UI2:
  231. case VT_BOOL:
  232. Assert(sizeof(pPropDst->uiVal) >= sizeof(pPropDst->boolVal));
  233. pPropDst->uiVal = pPropSrc->uiVal;
  234. break;
  235. case VT_I4:
  236. case VT_UI4:
  237. case VT_ERROR:
  238. case VT_R4:
  239. Assert(sizeof(pPropDst->ulVal) >= sizeof(pPropDst->scode));
  240. Assert(sizeof(pPropDst->ulVal) >= sizeof(pPropDst->fltVal));
  241. pPropDst->ulVal = pPropSrc->ulVal;
  242. break;
  243. case VT_I8:
  244. case VT_UI8:
  245. case VT_R8:
  246. case VT_CY:
  247. case VT_DATE:
  248. case VT_FILETIME:
  249. Assert(sizeof(pPropDst->uhVal) >= sizeof(pPropDst->dblVal));
  250. Assert(sizeof(pPropDst->uhVal) >= sizeof(pPropDst->cyVal));
  251. Assert(sizeof(pPropDst->uhVal) >= sizeof(pPropDst->date));
  252. Assert(sizeof(pPropDst->uhVal) >= sizeof(pPropDst->filetime));
  253. pPropDst->uhVal = pPropSrc->uhVal;
  254. break;
  255. default:
  256. AssertSz(FALSE, "nyi");
  257. IF_FAILEXIT(hr = E_FAIL);
  258. break;
  259. }
  260. exit:
  261. if (SUCCEEDED(hr))
  262. pPropDst->vt = pPropSrc->vt;
  263. return(hr);
  264. }
  265. HRESULT ComparePropVariant(LPPROPVARIANT pProp1, LPCPROPVARIANT pProp2)
  266. {
  267. HRESULT hr;
  268. BYTE *pb1, *pb2;
  269. ULONG i;
  270. hr = S_OK;
  271. if (pProp1->vt == pProp2->vt)
  272. {
  273. switch (pProp1->vt)
  274. {
  275. case VT_LPSTR:
  276. if (0 == lstrcmp(pProp1->pszVal, pProp2->pszVal))
  277. hr = S_NO_CHANGE;
  278. break;
  279. case VT_LPWSTR:
  280. if (0 == StrCmpW(pProp1->pwszVal, pProp2->pwszVal))
  281. hr = S_NO_CHANGE;
  282. break;
  283. case VT_BLOB:
  284. if (pProp1->blob.cbSize == pProp2->blob.cbSize)
  285. {
  286. pb1 = pProp1->blob.pBlobData;
  287. pb2 = pProp2->blob.pBlobData;
  288. if (pb1 == NULL)
  289. {
  290. Assert(pb2 == NULL);
  291. hr = S_NO_CHANGE;
  292. }
  293. else
  294. {
  295. Assert(pb2 != NULL);
  296. for (i = 0; i < pProp1->blob.cbSize; i++)
  297. {
  298. if (*pb1 != *pb2)
  299. break;
  300. pb1++;
  301. pb2++;
  302. }
  303. if (i == pProp1->blob.cbSize)
  304. hr = S_NO_CHANGE;
  305. }
  306. }
  307. break;
  308. case VT_UI4:
  309. if (pProp1->ulVal == pProp2->ulVal)
  310. hr = S_NO_CHANGE;
  311. break;
  312. default:
  313. break;
  314. }
  315. }
  316. return(hr);
  317. }
  318. STDMETHODIMP CPropertyBucket::GetProperty(LPCSTR pszProp, LPPROPVARIANT pVar, DWORD dwReserved)
  319. {
  320. HRESULT hr;
  321. LPPROPVARIANT pProp;
  322. if (pszProp == NULL ||
  323. pVar == NULL ||
  324. dwReserved != 0)
  325. return(E_INVALIDARG);
  326. EnterCriticalSection(&m_cs);
  327. pProp = GetPropVariant(pszProp);
  328. if (pProp != NULL)
  329. hr = DupPropVariant(pVar, pProp, FALSE);
  330. else
  331. hr = E_PROP_NOT_FOUND;
  332. LeaveCriticalSection(&m_cs);
  333. return(hr);
  334. }
  335. #define CALLOCPROP 32
  336. #define CALLOCNODE 16
  337. STDMETHODIMP CPropertyBucket::SetProperty(LPCSTR pszProp, LPCPROPVARIANT pVar, DWORD dwReserved)
  338. {
  339. HRESULT hr = S_OK;
  340. LPPROPVARIANT pProp;
  341. UINT cAlloc;
  342. PROPNODE *pNode;
  343. if (pszProp == NULL || pVar == NULL || dwReserved != 0)
  344. return TraceResult(E_INVALIDARG);
  345. EnterCriticalSection(&m_cs);
  346. pProp = GetPropVariant(pszProp);
  347. if (pProp != NULL)
  348. {
  349. if (pProp->vt != pVar->vt)
  350. {
  351. hr = E_INVALID_PROP_TYPE;
  352. }
  353. else
  354. {
  355. hr = ComparePropVariant(pProp, pVar);
  356. if (hr != S_NO_CHANGE)
  357. IF_FAILEXIT(hr = DupPropVariant(pProp, pVar, TRUE));
  358. }
  359. }
  360. else
  361. {
  362. if (m_cProp == m_cPropBuf)
  363. {
  364. cAlloc = m_cPropBuf + CALLOCPROP;
  365. IF_NULLEXIT(MemRealloc((void **)&m_pProp, sizeof(PROPVARIANT) * cAlloc));
  366. m_cPropBuf = cAlloc;
  367. ZeroMemory(&m_pProp[m_cProp], sizeof(PROPVARIANT) * CALLOCPROP);
  368. }
  369. pProp = &m_pProp[m_cProp];
  370. IF_FAILEXIT(hr = DupPropVariant(pProp, pVar, FALSE));
  371. if (IsPropId(pszProp))
  372. hr = InsertPropNode(pszProp, m_cProp, &m_pNodeId, &m_cNodeId, &m_cNodeIdBuf);
  373. else
  374. hr = InsertPropNode(pszProp, m_cProp, &m_pNodeSz, &m_cNodeSz, &m_cNodeSzBuf);
  375. m_cProp++;
  376. }
  377. exit:
  378. LeaveCriticalSection(&m_cs);
  379. return(hr);
  380. }
  381. HRESULT InsertPropNode(LPCSTR pszProp, int iProp, PROPNODE **ppNode, int *pcNode, int *pcNodeBuf)
  382. {
  383. int iNode, cAlloc, d;
  384. BOOL fSz;
  385. LPSTR psz;
  386. PROPNODE *pNodeT;
  387. HRESULT hr = S_OK;
  388. if (*pcNode == *pcNodeBuf)
  389. {
  390. cAlloc = *pcNodeBuf + CALLOCNODE;
  391. IF_NULLEXIT(MemRealloc((void **)ppNode, sizeof(PROPNODE) * cAlloc));
  392. *pcNodeBuf = cAlloc;
  393. ZeroMemory(&(*ppNode)[*pcNode], sizeof(PROPNODE) * CALLOCNODE);
  394. }
  395. if (fSz = !IsPropId(pszProp))
  396. {
  397. IF_NULLEXIT(psz = StringDup(pszProp));
  398. }
  399. else
  400. {
  401. psz = (LPSTR)pszProp;
  402. }
  403. pNodeT = *ppNode;
  404. for (iNode = 0; iNode < *pcNode; iNode++)
  405. {
  406. d = fSz ? lstrcmp(pszProp, pNodeT->psz) : (PtrToUlong(pszProp) - pNodeT->id);
  407. Assert(d != 0);
  408. if (d < 0)
  409. break;
  410. pNodeT++;
  411. }
  412. cAlloc = *pcNode - iNode;
  413. if (cAlloc > 0)
  414. MoveMemory(pNodeT + 1, pNodeT, cAlloc * sizeof(PROPNODE));
  415. pNodeT->psz = psz;
  416. pNodeT->iProp = iProp;
  417. (*pcNode)++;
  418. exit:
  419. return hr;
  420. }