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.

1762 lines
48 KiB

  1. /*
  2. * VALCOPY.C
  3. *
  4. * Utility functions for validating, copying, and (yeech) relocating
  5. * complex MAPI structures.
  6. *
  7. * For each data type there are three functions:
  8. * ScCountXXX address-checks and calculates the size
  9. * ScCopyXXX copies to a contiguous block of memory, which
  10. * must be pre-allocated
  11. * ScRelocXXX adjusts pointers, assuming that a structure in a
  12. * contiguous block of memory has been moved
  13. *
  14. * Data types supported:
  15. * NOTIFICATION (and array of), in ScCountNotifications etc.
  16. * SPropValue (and array of), in ScCountProps etc.
  17. *
  18. * //$ SIZE Returning the byte count from ScRelocXXX may not be necessary.
  19. */
  20. #include <_apipch.h>
  21. #if defined (_AMD64_) || defined (_IA64_)
  22. #define AlignProp(_cb) Align8(_cb)
  23. #else
  24. #define AlignProp(_cb) (_cb)
  25. #endif
  26. #define ALIGN_RISC 8
  27. #define ALIGN_X86 1
  28. // Pointer manipulation macros for use in the Reloc functions
  29. #ifdef WIN16
  30. #define SEG(_fp) HIWORD((DWORD)_fp)
  31. #define OFF(_fp) LOWORD((DWORD)_fp)
  32. #define PvRelocPv(_p,_baseOld,_baseNew) \
  33. ((LPVOID)MAKELONG(OFF(_p) - OFF(_baseOld) + OFF(_baseNew), SEG(_baseNew)))
  34. #else
  35. #define PvRelocPv(_p,_baseOld,_baseNew) \
  36. ((LPVOID)((LPBYTE)(_p) - (LPBYTE)(_baseOld) + (LPBYTE)(_baseNew)))
  37. #endif
  38. #ifdef NOTIFICATIONS // save this for notifications
  39. STDAPI_(SCODE)
  40. ScCountNotifications(int cntf, LPNOTIFICATION rgntf, ULONG FAR *pcb)
  41. {
  42. ULONG cb;
  43. ULONG cbT;
  44. LPNOTIFICATION pntf;
  45. SCODE sc = S_OK;
  46. // validate parameters
  47. AssertSz(!cntf || !IsBadReadPtr(rgntf, sizeof(NOTIFICATION) * cntf),
  48. TEXT("rgntf fails address check"));
  49. AssertSz(!pcb || !IsBadWritePtr(pcb, sizeof(ULONG)),
  50. TEXT("pcb fails address check"));
  51. for (cb = 0, pntf = rgntf; cntf--; ++pntf)
  52. {
  53. if (IsBadReadPtr(pntf, sizeof(NOTIFICATION)))
  54. {
  55. DebugTraceArg(ScCountNotification, TEXT("pntf fails address check"));
  56. goto badNotif;
  57. }
  58. cb += sizeof(NOTIFICATION);
  59. switch (HIWORD(pntf->ulEventType))
  60. {
  61. case (fnevExtended >> 16):
  62. // case (fnevSpooler >> 16):
  63. // fnevSpooler and fnevExtended both use the EXTENDED_NOTIFICATION
  64. // structure for their parameters
  65. if (pntf->info.ext.cb &&
  66. IsBadReadPtr(pntf->info.ext.pbEventParameters, (UINT)pntf->info.ext.cb))
  67. {
  68. DebugTraceArg(ScCountNotification, TEXT("ext.pbEventParameters fails address check"));
  69. goto badNotif;
  70. }
  71. cb += AlignProp(pntf->info.ext.cb);
  72. break;
  73. case 0:
  74. {
  75. switch (LOWORD(pntf->ulEventType))
  76. {
  77. case (USHORT)fnevCriticalError:
  78. {
  79. ERROR_NOTIFICATION FAR *perr = &pntf->info.err;
  80. if ( IsBadReadPtr( perr->lpEntryID, (UINT)perr->cbEntryID ) )
  81. {
  82. DebugTraceArg( ScCountNotification, TEXT("lpEntryID fails address check") );
  83. goto badNotif;
  84. }
  85. cb += AlignProp(((UINT)perr->cbEntryID));
  86. if (perr->lpMAPIError)
  87. {
  88. cb += AlignProp(sizeof( MAPIERROR ));
  89. #if defined(_WINNT) && !defined(MAC)
  90. if (perr->ulFlags & MAPI_UNICODE)
  91. {
  92. //$ No error check in WIN16
  93. if (IsBadStringPtrW((LPWSTR)perr->lpMAPIError->lpszError, INFINITE))
  94. {
  95. DebugTraceArg(ScCountNotification, TEXT("err.MapiError.lpszError (UNICODE) fails address check"));
  96. goto badNotif;
  97. }
  98. cb += AlignProp(((lstrlenW((LPWSTR)perr->lpMAPIError->lpszError) + 1)
  99. * sizeof(WCHAR)));
  100. if ( perr->lpMAPIError->lpszComponent )
  101. {
  102. if (IsBadStringPtrW((LPWSTR)perr->lpMAPIError->lpszComponent, INFINITE))
  103. {
  104. DebugTraceArg(ScCountNotification, TEXT("err.MapiError.lpszComponent (UNICODE) fails address check"));
  105. goto badNotif;
  106. }
  107. cb += AlignProp(((lstrlenW((LPWSTR)perr->lpMAPIError->lpszComponent) + 1)
  108. * sizeof(WCHAR)));
  109. }
  110. }
  111. else
  112. #endif
  113. {
  114. if (IsBadStringPtrA((LPSTR)perr->lpMAPIError->lpszError, INFINITE))
  115. {
  116. DebugTraceArg(ScCountNotification, TEXT("err.MapiError.lpszError (ASCII) fails address check"));
  117. goto badNotif;
  118. }
  119. cb += AlignProp((lstrlenA((LPSTR)perr->lpMAPIError->lpszError) + 1));
  120. if ( perr->lpMAPIError->lpszComponent )
  121. {
  122. if (IsBadStringPtrA((LPSTR)perr->lpMAPIError->lpszComponent, INFINITE))
  123. {
  124. DebugTraceArg(ScCountNotification, TEXT("err.MapiError.lpszError (ASCII) fails address check"));
  125. goto badNotif;
  126. }
  127. cb += AlignProp((lstrlenA((LPSTR)perr->lpMAPIError->lpszComponent) + 1));
  128. }
  129. }
  130. }
  131. break;
  132. }
  133. case (USHORT)fnevNewMail:
  134. {
  135. NEWMAIL_NOTIFICATION FAR *pnew = &pntf->info.newmail;
  136. if (IsBadReadPtr(pnew->lpEntryID, (UINT)pnew->cbEntryID))
  137. {
  138. DebugTraceArg(ScCountNotification, TEXT("lpEntryID fails address check"));
  139. goto badNotif;
  140. }
  141. cb += AlignProp(((UINT)pnew->cbEntryID));
  142. if (IsBadReadPtr(pnew->lpParentID, (UINT)pnew->cbParentID))
  143. {
  144. DebugTraceArg(ScCountNotification, TEXT("lpParentID fails address check"));
  145. goto badNotif;
  146. }
  147. cb += AlignProp(((UINT)pnew->cbParentID));
  148. if (pnew->lpszMessageClass)
  149. {
  150. if (pnew->ulFlags & MAPI_UNICODE)
  151. {
  152. #if defined(_WINNT) && !defined(MAC)
  153. //$ No error check in WIN16
  154. if (IsBadStringPtrW((LPWSTR)pnew->lpszMessageClass, INFINITE))
  155. {
  156. DebugTraceArg(ScCountNotification, TEXT("newmail.lpszMessageClass (UNICODE) fails address check"));
  157. goto badNotif;
  158. }
  159. #endif
  160. cb += AlignProp(((lstrlenW((LPWSTR)pnew->lpszMessageClass) + 1)
  161. * sizeof(WCHAR)));
  162. }
  163. else
  164. {
  165. if (IsBadStringPtrA((LPSTR)pnew->lpszMessageClass, INFINITE))
  166. {
  167. DebugTraceArg(ScCountNotification, TEXT("newmail.lpszMessageClass (ASCII) fails address check"));
  168. goto badNotif;
  169. }
  170. cb += AlignProp((lstrlenA((LPSTR)pnew->lpszMessageClass) + 1));
  171. }
  172. }
  173. break;
  174. }
  175. case (USHORT)fnevObjectCreated:
  176. case (USHORT)fnevObjectDeleted:
  177. case (USHORT)fnevObjectModified:
  178. case (USHORT)fnevObjectMoved:
  179. case (USHORT)fnevObjectCopied:
  180. case (USHORT)fnevSearchComplete:
  181. {
  182. OBJECT_NOTIFICATION FAR *pobj = &pntf->info.obj;
  183. if (pobj->cbEntryID)
  184. {
  185. if (IsBadReadPtr(pobj->lpEntryID, (UINT)pobj->cbEntryID))
  186. {
  187. DebugTraceArg(ScCountNotifications, TEXT("obj.lpEntryID fails address check"));
  188. goto badNotif;
  189. }
  190. cb += AlignProp(pobj->cbEntryID);
  191. }
  192. if (pobj->cbParentID)
  193. {
  194. if (IsBadReadPtr(pobj->lpParentID, (UINT)pobj->cbParentID))
  195. {
  196. DebugTraceArg(ScCountNotifications, TEXT("obj.lpParentID fails address check"));
  197. goto badNotif;
  198. }
  199. cb += AlignProp(pobj->cbParentID);
  200. }
  201. if (pobj->cbOldID)
  202. {
  203. if (IsBadReadPtr(pobj->lpOldID, (UINT)pobj->cbOldID))
  204. {
  205. DebugTraceArg(ScCountNotifications, TEXT("obj.lpOldID fails address check"));
  206. goto badNotif;
  207. }
  208. cb += AlignProp(pobj->cbOldID);
  209. }
  210. if (pobj->cbOldParentID)
  211. {
  212. if (IsBadReadPtr(pobj->lpOldParentID, (UINT)pobj->cbOldParentID))
  213. {
  214. DebugTraceArg(ScCountNotifications, TEXT("obj.lpOldParentID fails address check"));
  215. goto badNotif;
  216. }
  217. cb += AlignProp(pobj->cbOldParentID);
  218. }
  219. if (pobj->lpPropTagArray)
  220. {
  221. if (IsBadReadPtr(pobj->lpPropTagArray, sizeof(ULONG)) ||
  222. IsBadReadPtr(pobj->lpPropTagArray,
  223. offsetof(SPropTagArray, aulPropTag) +
  224. (UINT)pobj->lpPropTagArray->cValues * sizeof(ULONG)))
  225. {
  226. DebugTraceArg(ScCountNotifications, TEXT("obj.lpPropTagArray fails address check"));
  227. goto badNotif;
  228. }
  229. cb += AlignProp(offsetof(SPropTagArray, aulPropTag) +
  230. pobj->lpPropTagArray->cValues * sizeof(ULONG));
  231. }
  232. break;
  233. }
  234. case (USHORT)fnevTableModified:
  235. {
  236. TABLE_NOTIFICATION FAR *ptn = &pntf->info.tab;
  237. UINT n = (UINT) ptn->ulTableEvent;
  238. if (n != TABLE_CHANGED &&
  239. n != TABLE_RELOAD &&
  240. n != TABLE_ERROR &&
  241. n != TABLE_ROW_ADDED &&
  242. n != TABLE_ROW_DELETED &&
  243. n != TABLE_ROW_MODIFIED &&
  244. n != TABLE_SORT_DONE &&
  245. n != TABLE_RESTRICT_DONE &&
  246. n != TABLE_SETCOL_DONE)
  247. {
  248. DebugTraceArg(ScCountNotifications, TEXT("invalid tab.ulTableEvent"));
  249. goto badNotif;
  250. }
  251. if (ptn->propIndex.ulPropTag)
  252. {
  253. if (sc = ScCountProps(1, &ptn->propIndex, &cbT))
  254. goto ret;
  255. cb += cbT;
  256. }
  257. if (ptn->propPrior.ulPropTag)
  258. {
  259. if (sc = ScCountProps(1, &ptn->propPrior, &cbT))
  260. goto ret;
  261. cb += cbT;
  262. }
  263. if (ptn->row.cValues)
  264. {
  265. if (sc = ScCountProps((int)ptn->row.cValues, ptn->row.lpProps,
  266. &cbT))
  267. goto ret;
  268. cb += cbT;
  269. }
  270. else if (ptn->row.lpProps)
  271. {
  272. DebugTraceArg(ScCountNotifications, TEXT("non-NULL row.lpProps with zero row.cValues in table notification"));
  273. goto badNotif;
  274. }
  275. break;
  276. }
  277. case (USHORT)fnevStatusObjectModified:
  278. {
  279. STATUS_OBJECT_NOTIFICATION FAR *pstat = &pntf->info.statobj;
  280. if (pstat->cbEntryID)
  281. {
  282. if (IsBadReadPtr(pstat->lpEntryID, (UINT)pstat->cbEntryID))
  283. {
  284. DebugTraceArg(ScCountNotifications, TEXT("statobj.lpEntryID fails address check"));
  285. goto badNotif;
  286. }
  287. cb += AlignProp(pstat->cbEntryID);
  288. }
  289. if (pstat->cValues)
  290. {
  291. if (sc = ScCountProps((int)pstat->cValues,
  292. pstat->lpPropVals, &cbT))
  293. goto ret;
  294. cb += cbT;
  295. }
  296. break;
  297. }
  298. default:
  299. DebugTraceArg(ScCountNotification, TEXT("invalid ulEventType"));
  300. goto badNotif;
  301. }
  302. break;
  303. }
  304. default:
  305. DebugTraceArg(ScCountNotification, TEXT("invalid ulEventType"));
  306. goto badNotif;
  307. }
  308. }
  309. if (pcb)
  310. *pcb = cb;
  311. ret:
  312. DebugTraceSc(ScCountNotifications, sc);
  313. return sc;
  314. badNotif:
  315. // trace already issued
  316. return E_INVALIDARG;
  317. }
  318. STDAPI_(SCODE)
  319. ScCopyNotifications(int cntf, LPNOTIFICATION rgntf, LPVOID pvDst,
  320. ULONG FAR *pcb)
  321. {
  322. LPBYTE pb = pvDst;
  323. ULONG cb = 0;
  324. ULONG cbT;
  325. LPNOTIFICATION pntf;
  326. LPNOTIFICATION pntfDst;
  327. SCODE sc = S_OK;
  328. // validate parameters
  329. AssertSz(!cntf || !IsBadReadPtr(rgntf, sizeof(NOTIFICATION) * cntf),
  330. TEXT("rgntf fails address check"));
  331. AssertSz(!cntf || !IsBadWritePtr(pvDst, sizeof(NOTIFICATION) * cntf),
  332. TEXT("pvDst fails address check"));
  333. AssertSz(!pcb || !IsBadWritePtr(pcb, sizeof(ULONG)),
  334. TEXT("pcb fails address check"));
  335. cb = cntf * sizeof(NOTIFICATION);
  336. MemCopy(pvDst, rgntf, (UINT)cb);
  337. pb = (LPBYTE)pvDst + cb;
  338. for (pntf = rgntf, pntfDst = (LPNOTIFICATION)pvDst;
  339. cntf--;
  340. ++pntf, ++pntfDst)
  341. {
  342. switch (HIWORD(pntf->ulEventType))
  343. {
  344. case (fnevExtended >> 16):
  345. // case (fnevSpooler >> 16):
  346. if (pntf->info.ext.cb)
  347. {
  348. pntfDst->info.ext.pbEventParameters = pb;
  349. cbT = pntf->info.ext.cb;
  350. MemCopy(pb, pntf->info.ext.pbEventParameters, (UINT)cbT);
  351. pb += AlignProp(cbT);
  352. cb += AlignProp(cbT);
  353. }
  354. break;
  355. case 0:
  356. {
  357. switch (LOWORD(pntf->ulEventType))
  358. {
  359. case (USHORT)fnevCriticalError:
  360. {
  361. ERROR_NOTIFICATION FAR *perr = &pntf->info.err;
  362. if ( perr->cbEntryID )
  363. {
  364. pntfDst->info.err.lpEntryID = (LPENTRYID)pb;
  365. cbT = perr->cbEntryID;
  366. MemCopy(pb, perr->lpEntryID, (UINT)cbT);
  367. pb += AlignProp(cbT);
  368. cb += AlignProp(cbT);
  369. }
  370. if ( perr->lpMAPIError )
  371. {
  372. pntfDst->info.err.lpMAPIError = (LPMAPIERROR)pb;
  373. cbT = sizeof(MAPIERROR);
  374. MemCopy( pb, perr->lpMAPIError, sizeof( MAPIERROR ) );
  375. pb += AlignProp(cbT);
  376. cb += AlignProp(cbT);
  377. if (perr->lpMAPIError->lpszError)
  378. {
  379. #ifdef _WINNT
  380. if (perr->ulFlags & MAPI_UNICODE)
  381. {
  382. cbT = (lstrlenW((LPWSTR)perr->lpMAPIError->lpszError)
  383. + 1) * sizeof(WCHAR);
  384. }
  385. else
  386. #endif
  387. {
  388. cbT = lstrlenA((LPSTR)perr->lpMAPIError->lpszError) + 1;
  389. }
  390. pntfDst->info.err.lpMAPIError->lpszError = (LPSTR)pb;
  391. MemCopy(pb, perr->lpMAPIError->lpszError, (UINT)cbT);
  392. pb += AlignProp(cbT);
  393. cb += AlignProp(cbT);
  394. }
  395. if (perr->lpMAPIError->lpszComponent)
  396. {
  397. #ifdef _WINNT
  398. if (perr->ulFlags & MAPI_UNICODE)
  399. {
  400. cbT = (lstrlenW((LPWSTR)perr->lpMAPIError->lpszComponent)
  401. + 1) * sizeof(WCHAR);
  402. }
  403. else
  404. #endif
  405. {
  406. cbT = lstrlenA((LPSTR)perr->lpMAPIError->lpszComponent) + 1;
  407. }
  408. pntfDst->info.err.lpMAPIError->lpszComponent = pb;
  409. MemCopy(pb, perr->lpMAPIError->lpszComponent, (UINT)cbT);
  410. pb += AlignProp(cbT);
  411. cb += AlignProp(cbT);
  412. }
  413. }
  414. break;
  415. }
  416. case (USHORT)fnevNewMail:
  417. {
  418. NEWMAIL_NOTIFICATION FAR *pnew = &pntf->info.newmail;
  419. if (pnew->cbEntryID)
  420. {
  421. pntfDst->info.newmail.lpEntryID = (LPENTRYID)pb;
  422. cbT = pnew->cbEntryID;
  423. MemCopy(pb, pnew->lpEntryID, (UINT)cbT);
  424. pb += AlignProp(cbT);
  425. cb += AlignProp(cbT);
  426. }
  427. if (pnew->cbParentID)
  428. {
  429. pntfDst->info.newmail.lpParentID = (LPENTRYID)pb;
  430. cbT = pnew->cbParentID;
  431. MemCopy(pb, pnew->lpParentID, (UINT)cbT);
  432. pb += AlignProp(cbT);
  433. cb += AlignProp(cbT);
  434. }
  435. if (pnew->lpszMessageClass)
  436. {
  437. if (pnew->ulFlags & MAPI_UNICODE)
  438. cbT = (lstrlenW((LPWSTR)pnew->lpszMessageClass) + 1)
  439. * sizeof(WCHAR);
  440. else
  441. cbT = lstrlenA((LPSTR)pnew->lpszMessageClass) + 1;
  442. pntfDst->info.newmail.lpszMessageClass = (LPTSTR)pb;
  443. MemCopy(pb, pnew->lpszMessageClass, (UINT)cbT);
  444. pb += AlignProp(cbT);
  445. cb += AlignProp(cbT);
  446. }
  447. break;
  448. }
  449. case (USHORT)fnevObjectCreated:
  450. case (USHORT)fnevObjectDeleted:
  451. case (USHORT)fnevObjectModified:
  452. case (USHORT)fnevObjectMoved:
  453. case (USHORT)fnevObjectCopied:
  454. case (USHORT)fnevSearchComplete:
  455. {
  456. OBJECT_NOTIFICATION FAR *pobj = &pntf->info.obj;
  457. if (pobj->cbEntryID)
  458. {
  459. pntfDst->info.obj.lpEntryID = (LPENTRYID)pb;
  460. cbT = pobj->cbEntryID;
  461. MemCopy(pb, pobj->lpEntryID, (UINT)cbT);
  462. pb += AlignProp(cbT);
  463. cb += AlignProp(cbT);
  464. }
  465. if (pobj->cbParentID)
  466. {
  467. pntfDst->info.obj.lpParentID = (LPENTRYID)pb;
  468. cbT = pobj->cbParentID;
  469. MemCopy(pb, pobj->lpParentID, (UINT)cbT);
  470. pb += AlignProp(cbT);
  471. cb += AlignProp(cbT);
  472. }
  473. if (pobj->cbOldID)
  474. {
  475. pntfDst->info.obj.lpOldID = (LPENTRYID)pb;
  476. cbT = pobj->cbOldID;
  477. MemCopy(pb, pobj->lpOldID, (UINT)cbT);
  478. pb += AlignProp(cbT);
  479. cb += AlignProp(cbT);
  480. }
  481. if (pobj->cbOldParentID)
  482. {
  483. pntfDst->info.obj.lpOldParentID = (LPENTRYID)pb;
  484. cbT = pobj->cbOldParentID;
  485. MemCopy(pb, pobj->lpOldParentID, (UINT)cbT);
  486. pb += AlignProp(cbT);
  487. cb += AlignProp(cbT);
  488. }
  489. if (pobj->lpPropTagArray)
  490. {
  491. cbT = offsetof(SPropTagArray, aulPropTag) +
  492. pobj->lpPropTagArray->cValues * sizeof(ULONG);
  493. pntfDst->info.obj.lpPropTagArray = (LPSPropTagArray)pb;
  494. MemCopy(pb, pobj->lpPropTagArray, (UINT)cbT);
  495. pb += AlignProp(cbT);
  496. cb += AlignProp(cbT);
  497. }
  498. break;
  499. }
  500. case (USHORT)fnevTableModified:
  501. {
  502. TABLE_NOTIFICATION FAR *ptn = &pntf->info.tab;
  503. if (ptn->propIndex.ulPropTag)
  504. {
  505. // Wastes 16 bytes when the property doesn't have a tail
  506. if (sc = ScCopyProps(1, &ptn->propIndex, pb, &cbT))
  507. goto ret;
  508. //
  509. // This was once a straight structure assignment. However, on RISC platforms
  510. // if pntfDst is not on an 8-byte boundary, this raises a Datatype
  511. // Misalignment Exception. Changed this to a memcpy in order to not worry
  512. // about alignment and not cause any extra exception handling.
  513. //
  514. memcpy(&(pntfDst->info.tab.propIndex), (LPSPropValue)pb, sizeof(SPropValue));
  515. pb += AlignProp(cbT);
  516. cb += AlignProp(cbT);
  517. }
  518. if (ptn->propPrior.ulPropTag)
  519. {
  520. // Wastes 16 bytes when the property doesn't have a tail
  521. if (sc = ScCopyProps(1, &ptn->propPrior, pb, &cbT))
  522. goto ret;
  523. //
  524. // This was once a straight structure assignment. However, on RISC platforms
  525. // if pntfDst is not on an 8-byte boundary, this raises a Datatype
  526. // Misalignment Exception. Changed this to a memcpy in order to not worry
  527. // about alignment and not cause any extra exception handling.
  528. //
  529. memcpy(&(pntfDst->info.tab.propPrior), (LPSPropValue)pb, sizeof(SPropValue));
  530. pb += AlignProp(cbT);
  531. cb += AlignProp(cbT);
  532. }
  533. if (ptn->row.cValues)
  534. {
  535. pntfDst->info.tab.row.lpProps = (LPSPropValue)pb;
  536. if (sc = ScCopyProps((int)ptn->row.cValues, ptn->row.lpProps, pb, &cbT))
  537. goto ret;
  538. pb += AlignProp(cbT);
  539. cb += AlignProp(cbT);
  540. }
  541. break;
  542. }
  543. case (USHORT)fnevStatusObjectModified:
  544. {
  545. STATUS_OBJECT_NOTIFICATION FAR *pstat = &pntf->info.statobj;
  546. if (pstat->cbEntryID)
  547. {
  548. pntfDst->info.statobj.lpEntryID = (LPENTRYID)pb;
  549. cbT = pstat->cbEntryID;
  550. MemCopy(pb, pstat->lpEntryID, (UINT)cbT);
  551. pb += AlignProp(cbT);
  552. cb += AlignProp(cbT);
  553. }
  554. if (pstat->cValues)
  555. {
  556. pntfDst->info.statobj.lpPropVals = (LPSPropValue)pb;
  557. if (sc = ScCopyProps((int)pstat->cValues,
  558. pstat->lpPropVals, pb, &cbT))
  559. goto ret;
  560. pb += cbT;
  561. cb += cbT;
  562. }
  563. break;
  564. }
  565. default:
  566. DebugTraceArg(ScCopyNotification, TEXT("invalid ulEventType"));
  567. goto badNotif;
  568. }
  569. break;
  570. }
  571. default:
  572. DebugTraceArg(ScCopyNotification, TEXT("invalid ulEventType"));
  573. goto badNotif;
  574. }
  575. }
  576. if (pcb)
  577. *pcb = (ULONG)cb;
  578. ret:
  579. DebugTraceSc(ScCopyNotifications, sc);
  580. return sc;
  581. badNotif:
  582. // trace already issued
  583. return E_INVALIDARG;
  584. #undef COPY
  585. }
  586. STDAPI_(SCODE)
  587. ScRelocNotifications(int cntf, LPNOTIFICATION rgntf, LPVOID pvBaseOld,
  588. LPVOID pvBaseNew, ULONG FAR *pcb)
  589. {
  590. ULONG cb;
  591. ULONG cbT;
  592. LPNOTIFICATION pntf;
  593. SCODE sc = S_OK;
  594. AssertSz(!cntf || !IsBadReadPtr(rgntf, sizeof(NOTIFICATION) * cntf),
  595. TEXT("rgntf fails address check"));
  596. AssertSz(pvBaseOld, TEXT("pvBaseOld fails address check"));
  597. AssertSz(!IsBadWritePtr(pvBaseNew, sizeof(LPVOID)),
  598. TEXT("pvBaseNew fails address check"));
  599. AssertSz(!pcb || !IsBadWritePtr(pcb, sizeof(ULONG)),
  600. TEXT("pcb fails address check"));
  601. cb = cntf * sizeof(NOTIFICATION);
  602. for (pntf = rgntf; cntf--; ++pntf)
  603. {
  604. switch (HIWORD(pntf->ulEventType))
  605. {
  606. case (fnevExtended >> 16):
  607. // case (fnevSpooler >> 16):
  608. if (pntf->info.ext.cb)
  609. {
  610. pntf->info.ext.pbEventParameters =
  611. PvRelocPv(pntf->info.ext.pbEventParameters, pvBaseOld,
  612. pvBaseNew);
  613. cb += AlignProp(pntf->info.ext.cb);
  614. }
  615. break;
  616. case 0:
  617. {
  618. switch (LOWORD(pntf->ulEventType))
  619. {
  620. case (USHORT)fnevCriticalError:
  621. {
  622. ERROR_NOTIFICATION FAR *perr = &pntf->info.err;
  623. if ( perr->lpEntryID )
  624. {
  625. perr->lpEntryID = PvRelocPv( perr->lpEntryID, pvBaseOld,
  626. pvBaseNew );
  627. cb += AlignProp( (UINT)perr->cbEntryID );
  628. }
  629. if ( perr->lpMAPIError )
  630. {
  631. perr->lpMAPIError = PvRelocPv( perr->lpMAPIError, pvBaseOld,
  632. pvBaseNew );
  633. if (perr->lpMAPIError->lpszError)
  634. {
  635. perr->lpMAPIError->lpszError = PvRelocPv(
  636. perr->lpMAPIError->lpszError, pvBaseOld,
  637. pvBaseNew );
  638. #ifdef _WINNT
  639. if (perr->ulFlags & MAPI_UNICODE)
  640. cb += AlignProp((lstrlenW((LPWSTR)perr->lpMAPIError->lpszError)
  641. + 1) * sizeof(WCHAR));
  642. else
  643. #endif
  644. cb += AlignProp(lstrlenA((LPSTR)perr->lpMAPIError->lpszError) + 1);
  645. }
  646. if (perr->lpMAPIError->lpszComponent)
  647. {
  648. perr->lpMAPIError->lpszComponent = PvRelocPv(
  649. perr->lpMAPIError->lpszComponent, pvBaseOld,
  650. pvBaseNew );
  651. #ifdef _WINNT
  652. if (perr->ulFlags & MAPI_UNICODE)
  653. cb += AlignProp((lstrlenW((LPWSTR)perr->lpMAPIError->lpszComponent) + 1)
  654. * sizeof(WCHAR));
  655. else
  656. #endif
  657. cb += AlignProp(lstrlenA((LPSTR)perr->lpMAPIError->lpszComponent) + 1);
  658. }
  659. }
  660. }
  661. case (USHORT)fnevNewMail:
  662. {
  663. NEWMAIL_NOTIFICATION FAR *pnew = &pntf->info.newmail;
  664. if (pnew->lpEntryID)
  665. {
  666. pnew->lpEntryID = PvRelocPv(pnew->lpEntryID, pvBaseOld,
  667. pvBaseNew);
  668. cb += AlignProp((UINT)pnew->cbEntryID);
  669. }
  670. if (pnew->lpParentID)
  671. {
  672. pnew->lpParentID = PvRelocPv(pnew->lpParentID, pvBaseOld,
  673. pvBaseNew);
  674. cb += AlignProp((UINT)pnew->cbParentID);
  675. }
  676. if (pnew->lpszMessageClass)
  677. {
  678. pnew->lpszMessageClass = PvRelocPv(pnew->lpszMessageClass,
  679. pvBaseOld, pvBaseNew);
  680. if (pnew->ulFlags & MAPI_UNICODE)
  681. cbT = (lstrlenW((LPWSTR)pnew->lpszMessageClass) + 1)
  682. * sizeof(WCHAR);
  683. else
  684. cbT = lstrlenA((LPSTR)pnew->lpszMessageClass) + 1;
  685. cb += AlignProp(cbT);
  686. }
  687. break;
  688. }
  689. case (USHORT)fnevObjectCreated:
  690. case (USHORT)fnevObjectDeleted:
  691. case (USHORT)fnevObjectModified:
  692. case (USHORT)fnevObjectMoved:
  693. case (USHORT)fnevObjectCopied:
  694. case (USHORT)fnevSearchComplete:
  695. {
  696. OBJECT_NOTIFICATION FAR *pobj = &pntf->info.obj;
  697. if (pobj->lpEntryID)
  698. {
  699. pobj->lpEntryID = PvRelocPv(pobj->lpEntryID, pvBaseOld,
  700. pvBaseNew);
  701. cb += AlignProp(pobj->cbEntryID);
  702. }
  703. if (pobj->lpParentID)
  704. {
  705. pobj->lpParentID = PvRelocPv(pobj->lpParentID, pvBaseOld,
  706. pvBaseNew);
  707. cb += AlignProp(pobj->cbParentID);
  708. }
  709. if (pobj->lpOldID)
  710. {
  711. pobj->lpOldID = PvRelocPv(pobj->lpOldID, pvBaseOld,
  712. pvBaseNew);
  713. cb += AlignProp(pobj->cbOldID);
  714. }
  715. if (pobj->lpOldParentID)
  716. {
  717. pobj->lpOldParentID = PvRelocPv(pobj->lpOldParentID, pvBaseOld,
  718. pvBaseNew);
  719. cb += AlignProp(pobj->cbOldParentID);
  720. }
  721. if (pobj->lpPropTagArray)
  722. {
  723. pobj->lpPropTagArray = PvRelocPv(pobj->lpPropTagArray,
  724. pvBaseOld, pvBaseNew);
  725. cb += offsetof(SPropTagArray, aulPropTag) +
  726. pobj->lpPropTagArray->cValues * sizeof(ULONG);
  727. }
  728. break;
  729. }
  730. case (USHORT)fnevTableModified:
  731. {
  732. TABLE_NOTIFICATION FAR *ptn = &pntf->info.tab;
  733. Assert (FIsAligned (&ptn->propIndex));
  734. if (ptn->propIndex.ulPropTag)
  735. {
  736. if (sc = ScRelocProps(1, &ptn->propIndex, pvBaseOld,
  737. pvBaseNew, &cbT))
  738. goto ret;
  739. cb += cbT;
  740. }
  741. Assert (FIsAligned (&ptn->propPrior));
  742. if (ptn->propPrior.ulPropTag)
  743. {
  744. if (sc = ScRelocProps(1, &ptn->propPrior, pvBaseOld,
  745. pvBaseNew, &cbT))
  746. goto ret;
  747. cb += cbT;
  748. }
  749. if (ptn->row.cValues)
  750. {
  751. Assert (FIsAligned (ptn->row.lpProps));
  752. ptn->row.lpProps = PvRelocPv(ptn->row.lpProps,
  753. pvBaseOld, pvBaseNew);
  754. if (sc = ScRelocProps((int)ptn->row.cValues, ptn->row.lpProps,
  755. pvBaseOld, pvBaseNew, &cbT))
  756. goto ret;
  757. cb += cbT;
  758. }
  759. break;
  760. }
  761. case (USHORT)fnevStatusObjectModified:
  762. {
  763. STATUS_OBJECT_NOTIFICATION FAR *pstat = &pntf->info.statobj;
  764. if (pstat->lpEntryID)
  765. {
  766. pstat->lpEntryID = PvRelocPv(pstat->lpEntryID, pvBaseOld,
  767. pvBaseNew);
  768. // Whoa, this is not sufficient to buffer the size of
  769. // the entryid. If the entryid is not aligned, then the
  770. // the properties that follow will not be aligned either.
  771. //
  772. Assert (FIsAligned (pstat->lpEntryID));
  773. cb += AlignProp(pstat->cbEntryID);
  774. }
  775. if (pstat->cValues)
  776. {
  777. pstat->lpPropVals = PvRelocPv(pstat->lpPropVals,
  778. pvBaseOld, pvBaseNew);
  779. Assert (FIsAligned (pstat->lpPropVals));
  780. if (sc = ScRelocProps((int)pstat->cValues, pstat->lpPropVals,
  781. pvBaseOld, pvBaseNew, &cbT))
  782. goto ret;
  783. cb += cbT;
  784. }
  785. break;
  786. }
  787. default:
  788. DebugTraceArg(ScRelocNotification, TEXT("invalid ulEventType"));
  789. goto badNotif;
  790. }
  791. break;
  792. }
  793. default:
  794. DebugTraceArg(ScRelocNotification, TEXT("invalid ulEventType"));
  795. goto badNotif;
  796. }
  797. }
  798. if (pcb)
  799. *pcb = cb;
  800. ret:
  801. DebugTraceSc(ScRelocNotifications, sc);
  802. return sc;
  803. badNotif:
  804. // trace already issued
  805. return E_INVALIDARG;
  806. }
  807. #endif // NOTIFICATIONS
  808. STDAPI_(LPSPropValue)
  809. LpValFindProp( ULONG ulPropTag, ULONG cprop, LPSPropValue rgprop)
  810. {
  811. // Mutate the property tag to a property ID
  812. ulPropTag = PROP_ID(ulPropTag);
  813. while (cprop--)
  814. {
  815. Assert( !IsBadReadPtr( rgprop, sizeof(SPropValue)));
  816. if (PROP_ID(rgprop->ulPropTag) == ulPropTag)
  817. {
  818. return rgprop;
  819. }
  820. rgprop++;
  821. }
  822. // No match was found so return NULL.
  823. return NULL;
  824. }
  825. /*
  826. * ScCountPropsEx()
  827. *
  828. * Internal routine that computes the size required
  829. * to hold a given propval array based on specified alignment
  830. */
  831. SCODE
  832. ScCountPropsEx(int cprop, LPSPropValue rgprop, ULONG ulAlign, ULONG FAR *pcb)
  833. {
  834. LPSPropValue pprop;
  835. ULONG cb = 0;
  836. ULONG cbMV;
  837. int iValue;
  838. #define Align(_cb) ((ULONG)( ((DWORD_PTR) ((_cb) + (ulAlign-1))) & ~(((DWORD_PTR) ulAlign-1))))
  839. // validate parameters
  840. AssertSz(ulAlign && ulAlign <= ALIGN_RISC,
  841. TEXT("invalid alignment value"));
  842. AssertSz(!pcb || !IsBadWritePtr(pcb, sizeof(ULONG)),
  843. TEXT("pcb fails address check"));
  844. //$ SIZE Some of the multi-valued cases could be collapsed if we don't
  845. //$ mind assuming that the counts and pointers are in the same place.
  846. if ( (rgprop && !cprop)
  847. || IsBadReadPtr(rgprop, cprop*sizeof(SPropValue)))
  848. {
  849. DebugTraceArg(ScCountProps, TEXT("rgprop fails address check"));
  850. return MAPI_E_INVALID_PARAMETER;
  851. }
  852. for (pprop = rgprop; cprop--; ++pprop)
  853. {
  854. ULONG ulID = PROP_ID(pprop->ulPropTag);
  855. ULONG ulType = PROP_TYPE(pprop->ulPropTag);
  856. // Check for valid PROP_ID
  857. if ( (ulID == PROP_ID_INVALID)
  858. || ((ulType == PT_NULL) && (ulID != PROP_ID_NULL))
  859. || ((ulID == PROP_ID_NULL) && (ulType != PT_NULL) && (ulType != PT_ERROR)))
  860. return MAPI_E_INVALID_PARAMETER;
  861. // Check for valid PROP_TYPE and count memory consumed
  862. cb += sizeof(SPropValue);
  863. switch ( PROP_TYPE(pprop->ulPropTag) )
  864. {
  865. case PT_UNSPECIFIED:
  866. default:
  867. DebugTrace( TEXT("ScCountProps: Unknown property type %s (index %d)\n"), SzDecodeUlPropTag(pprop->ulPropTag), pprop - rgprop);
  868. return MAPI_E_INVALID_PARAMETER;
  869. case PT_I2:
  870. case PT_LONG:
  871. case PT_R4:
  872. case PT_APPTIME:
  873. case PT_DOUBLE:
  874. case PT_BOOLEAN:
  875. case PT_CURRENCY:
  876. case PT_SYSTIME:
  877. case PT_I8:
  878. case PT_ERROR:
  879. case PT_OBJECT:
  880. case PT_NULL:
  881. break;
  882. case PT_CLSID:
  883. if (IsBadReadPtr(pprop->Value.lpguid, sizeof(GUID)))
  884. goto badProp;
  885. cb += Align(sizeof(GUID));
  886. break;
  887. case PT_BINARY:
  888. //$Hack: IsBadReadPtr works funny under Win16.
  889. //$Hack: It doesn't handle the case of 0 cb, and
  890. //$Hack: non-0 lpb.
  891. if (pprop->Value.bin.cb && IsBadReadPtr( pprop->Value.bin.lpb
  892. , (UINT) (pprop->Value.bin.cb)))
  893. goto badProp;
  894. cb += Align(pprop->Value.bin.cb);
  895. break;
  896. case PT_STRING8:
  897. if (IsBadStringPtrA(pprop->Value.lpszA, INFINITE))
  898. goto badProp;
  899. cb += Align((lstrlenA( pprop->Value.lpszA ) + 1) * sizeof(CHAR));
  900. break;
  901. case PT_UNICODE:
  902. #if defined(WIN32) && !defined(MAC)
  903. //$ No validation code available on Win16
  904. if (IsBadStringPtrW(pprop->Value.lpszW, INFINITE))
  905. goto badProp;
  906. #endif
  907. cb += Align((lstrlenW( pprop->Value.lpszW ) + 1) * sizeof(WCHAR));
  908. break;
  909. // Note! MVxxx.cValues may NOT be zero (DCR 2789).
  910. case PT_MV_I2:
  911. if ( !(cbMV = pprop->Value.MVi.cValues * sizeof(short int))
  912. || IsBadReadPtr(pprop->Value.MVi.lpi, (UINT) cbMV))
  913. goto badProp;
  914. cb += Align(cbMV);
  915. break;
  916. case PT_MV_LONG:
  917. if ( !(cbMV = pprop->Value.MVl.cValues * sizeof(LONG))
  918. || IsBadReadPtr(pprop->Value.MVl.lpl, (UINT) cbMV))
  919. goto badProp;
  920. cb += Align(cbMV);
  921. break;
  922. case PT_MV_R4:
  923. if ( !(cbMV = pprop->Value.MVflt.cValues * sizeof(float))
  924. || IsBadReadPtr(pprop->Value.MVflt.lpflt, (UINT) cbMV))
  925. goto badProp;
  926. cb += Align(cbMV);
  927. break;
  928. case PT_MV_APPTIME:
  929. if ( !(cbMV = pprop->Value.MVat.cValues * sizeof(double))
  930. || IsBadReadPtr(pprop->Value.MVat.lpat, (UINT) cbMV))
  931. goto badProp;
  932. cb += cbMV;
  933. break;
  934. case PT_MV_DOUBLE:
  935. if ( !(cbMV = pprop->Value.MVdbl.cValues * sizeof(double))
  936. || IsBadReadPtr(pprop->Value.MVdbl.lpdbl, (UINT) cbMV))
  937. goto badProp;
  938. cb += cbMV;
  939. break;
  940. case PT_MV_CURRENCY:
  941. if ( !(cbMV = pprop->Value.MVcur.cValues * sizeof(CURRENCY))
  942. || IsBadReadPtr(pprop->Value.MVcur.lpcur, (UINT) cbMV))
  943. goto badProp;
  944. cb += cbMV;
  945. break;
  946. case PT_MV_SYSTIME:
  947. if ( !(cbMV = pprop->Value.MVft.cValues * sizeof(FILETIME))
  948. || IsBadReadPtr(pprop->Value.MVft.lpft, (UINT) cbMV))
  949. goto badProp;
  950. cb += cbMV;
  951. break;
  952. case PT_MV_CLSID:
  953. if ( !(cbMV = pprop->Value.MVguid.cValues * sizeof(GUID))
  954. || IsBadReadPtr(pprop->Value.MVguid.lpguid, (UINT) cbMV))
  955. goto badProp;
  956. cb += cbMV;
  957. break;
  958. case PT_MV_I8:
  959. if ( !(cbMV = pprop->Value.MVli.cValues * sizeof(LARGE_INTEGER))
  960. || IsBadReadPtr(pprop->Value.MVli.lpli, (UINT) cbMV))
  961. goto badProp;
  962. cb += cbMV;
  963. break;
  964. case PT_MV_BINARY:
  965. if ( !(cbMV = pprop->Value.MVbin.cValues * sizeof(SBinary))
  966. || IsBadReadPtr(pprop->Value.MVbin.lpbin, (UINT) cbMV))
  967. goto badProp;
  968. Assert(Align(cbMV) == cbMV);
  969. cb += cbMV;
  970. for ( iValue = 0;
  971. (ULONG)iValue < pprop->Value.MVbin.cValues;
  972. iValue++ )
  973. {
  974. if (IsBadReadPtr(pprop->Value.MVbin.lpbin[iValue].lpb,
  975. (UINT)pprop->Value.MVbin.lpbin[iValue].cb))
  976. goto badProp;
  977. cb += Align(pprop->Value.MVbin.lpbin[iValue].cb);
  978. }
  979. break;
  980. case PT_MV_STRING8:
  981. if ( !(cbMV = pprop->Value.MVszA.cValues * sizeof(LPVOID))
  982. || IsBadReadPtr(pprop->Value.MVszA.lppszA, (UINT) cbMV))
  983. goto badProp;
  984. cb += cbMV;
  985. for ( iValue = 0;
  986. (ULONG)iValue < pprop->Value.MVszA.cValues;
  987. iValue++ )
  988. {
  989. if (IsBadStringPtrA(pprop->Value.MVszA.lppszA[iValue],
  990. INFINITE))
  991. goto badProp;
  992. cb += lstrlenA(pprop->Value.MVszA.lppszA[iValue]) + 1;
  993. }
  994. cb = Align(cb);
  995. break;
  996. case PT_MV_UNICODE:
  997. if ( !(cbMV = pprop->Value.MVszW.cValues * sizeof(LPVOID))
  998. || IsBadReadPtr(pprop->Value.MVszW.lppszW, (UINT) cbMV))
  999. goto badProp;
  1000. cb += cbMV;
  1001. for ( iValue = 0;
  1002. (ULONG)iValue < pprop->Value.MVszW.cValues;
  1003. iValue++ )
  1004. {
  1005. #if defined(WIN32) && !defined(MAC)
  1006. //$ No validation on Win16
  1007. if (IsBadStringPtrW(pprop->Value.MVszW.lppszW[iValue], INFINITE))
  1008. goto badProp;
  1009. #endif
  1010. cb += (lstrlenW(pprop->Value.MVszW.lppszW[iValue]) + 1)
  1011. * sizeof(WCHAR);
  1012. }
  1013. cb = Align(cb);
  1014. break;
  1015. }
  1016. }
  1017. if (pcb)
  1018. {
  1019. Assert(!IsBadWritePtr(pcb, sizeof(ULONG)));
  1020. *pcb = cb;
  1021. }
  1022. return S_OK;
  1023. badProp:
  1024. DebugTrace( TEXT("ScCountProps: Unreadable property %s (index %d)\n"), SzDecodeUlPropTag(pprop->ulPropTag), pprop - rgprop);
  1025. return MAPI_E_INVALID_PARAMETER;
  1026. #undef Align
  1027. }
  1028. STDAPI_(SCODE)
  1029. ScCountProps(int cprop, LPSPropValue rgprop, ULONG FAR *pcb)
  1030. {
  1031. #if defined (_AMD64_) || defined(_IA64_)
  1032. return ScCountPropsEx( cprop, rgprop, ALIGN_RISC, pcb );
  1033. #else
  1034. return ScCountPropsEx( cprop, rgprop, ALIGN_X86, pcb );
  1035. #endif
  1036. }
  1037. STDAPI_(SCODE)
  1038. ScCopyProps(int cprop, LPSPropValue rgprop, LPVOID pvDst, ULONG FAR *pcb)
  1039. {
  1040. LPSPropValue pprop;
  1041. LPSPropValue ppropDst;
  1042. ULONG cb;
  1043. ULONG cbMV;
  1044. LPBYTE pb;
  1045. UINT cbT;
  1046. int iValue;
  1047. // validate parameters
  1048. AssertSz(!cprop || !IsBadReadPtr(rgprop, sizeof(SPropValue) * cprop),
  1049. TEXT("rgprop fails address check"));
  1050. AssertSz(!cprop || !IsBadWritePtr(pvDst, sizeof(SPropValue) * cprop),
  1051. TEXT("pvDst fails address check"));
  1052. AssertSz(!pcb || !IsBadWritePtr(pcb, sizeof(ULONG)),
  1053. TEXT("pcb fails address check"));
  1054. //$ SIZE Some of the multi-valued cases could be collapsed if we don't
  1055. //$ mind assuming that the counts and pointers are in the same place.
  1056. cb = cprop * sizeof(SPropValue);
  1057. MemCopy(pvDst, rgprop, (UINT)cb);
  1058. pb = (LPBYTE)pvDst + cb;
  1059. for (pprop = rgprop, ppropDst = pvDst; cprop--; ++pprop, ++ppropDst)
  1060. {
  1061. // Tricky: common code after the switch increments pb and cb
  1062. // by the amount copied. If no increment is necessary, the case
  1063. // uses 'continue' rather than 'break' to exit the switch, thus
  1064. // skipping the increment -- AND any other code which may be
  1065. // added after the switch.
  1066. switch ( PROP_TYPE(pprop->ulPropTag) )
  1067. {
  1068. default:
  1069. DebugTrace( TEXT("ScCopyProps: Unknown property type %s (index %d)\n"), SzDecodeUlPropTag(pprop->ulPropTag), pprop - rgprop);
  1070. return E_INVALIDARG;
  1071. case PT_I2:
  1072. case PT_LONG:
  1073. case PT_R4:
  1074. case PT_APPTIME:
  1075. case PT_DOUBLE:
  1076. case PT_BOOLEAN:
  1077. case PT_CURRENCY:
  1078. case PT_SYSTIME:
  1079. case PT_I8:
  1080. case PT_ERROR:
  1081. case PT_OBJECT:
  1082. case PT_NULL:
  1083. continue; // nothing to add
  1084. case PT_CLSID:
  1085. ppropDst->Value.lpguid = (LPGUID) pb;
  1086. cbT = sizeof(GUID);
  1087. MemCopy(pb, (LPBYTE) pprop->Value.lpguid, cbT);
  1088. break;
  1089. case PT_BINARY:
  1090. ppropDst->Value.bin.lpb = pb;
  1091. cbT = (UINT)pprop->Value.bin.cb;
  1092. MemCopy(pb, pprop->Value.bin.lpb, cbT);
  1093. break;
  1094. case PT_STRING8:
  1095. ppropDst->Value.lpszA = (LPSTR)pb;
  1096. cbT = lstrlenA( pprop->Value.lpszA ) + 1;
  1097. MemCopy(pb, pprop->Value.lpszA, cbT);
  1098. break;
  1099. case PT_UNICODE:
  1100. ppropDst->Value.lpszW = (LPWSTR)pb;
  1101. cbT = (lstrlenW( pprop->Value.lpszW ) + 1) * sizeof(WCHAR);
  1102. MemCopy(pb, pprop->Value.lpszW, cbT);
  1103. break;
  1104. case PT_MV_I2:
  1105. ppropDst->Value.MVi.lpi = (short int FAR *)pb;
  1106. cbT = (UINT)pprop->Value.MVi.cValues * sizeof(short int);
  1107. MemCopy(pb, pprop->Value.MVi.lpi, cbT);
  1108. break;
  1109. case PT_MV_LONG:
  1110. ppropDst->Value.MVl.lpl = (LONG FAR *)pb;
  1111. cbT = (UINT)pprop->Value.MVl.cValues * sizeof(LONG);
  1112. MemCopy(pb, pprop->Value.MVl.lpl, cbT);
  1113. break;
  1114. case PT_MV_R4:
  1115. ppropDst->Value.MVflt.lpflt = (float FAR *)pb;
  1116. cbT = (UINT)pprop->Value.MVflt.cValues * sizeof(float);
  1117. MemCopy(pb, pprop->Value.MVflt.lpflt, cbT);
  1118. break;
  1119. case PT_MV_APPTIME:
  1120. ppropDst->Value.MVat.lpat = (double FAR *)pb;
  1121. cbT = (UINT)pprop->Value.MVat.cValues * sizeof(double);
  1122. MemCopy(pb, pprop->Value.MVat.lpat, cbT);
  1123. break;
  1124. case PT_MV_DOUBLE:
  1125. ppropDst->Value.MVdbl.lpdbl = (double FAR *)pb;
  1126. cbT = (UINT)pprop->Value.MVdbl.cValues * sizeof(double);
  1127. MemCopy(pb, pprop->Value.MVdbl.lpdbl, cbT);
  1128. break;
  1129. case PT_MV_CURRENCY:
  1130. ppropDst->Value.MVcur.lpcur = (CURRENCY FAR *)pb;
  1131. cbT = (UINT)pprop->Value.MVcur.cValues * sizeof(CURRENCY);
  1132. MemCopy(pb, pprop->Value.MVcur.lpcur, cbT);
  1133. break;
  1134. case PT_MV_SYSTIME:
  1135. ppropDst->Value.MVft.lpft = (FILETIME FAR *)pb;
  1136. cbT = (UINT)pprop->Value.MVft.cValues * sizeof(FILETIME);
  1137. MemCopy(pb, pprop->Value.MVft.lpft, cbT);
  1138. break;
  1139. case PT_MV_CLSID:
  1140. ppropDst->Value.MVguid.lpguid = (GUID FAR *)pb;
  1141. cbT = (UINT)pprop->Value.MVguid.cValues * sizeof(GUID);
  1142. MemCopy(pb, pprop->Value.MVguid.lpguid, cbT);
  1143. break;
  1144. case PT_MV_I8:
  1145. ppropDst->Value.MVli.lpli = (LARGE_INTEGER FAR *)pb;
  1146. cbT = (UINT)pprop->Value.MVli.cValues * sizeof(LARGE_INTEGER);
  1147. MemCopy(pb, pprop->Value.MVli.lpli, cbT);
  1148. break;
  1149. case PT_MV_BINARY:
  1150. ppropDst->Value.MVbin.lpbin = (SBinary *) pb;
  1151. cbMV = pprop->Value.MVbin.cValues * sizeof(SBinary);
  1152. pb += cbMV;
  1153. cb += cbMV;
  1154. for (iValue = 0;
  1155. (ULONG)iValue < pprop->Value.MVbin.cValues;
  1156. iValue++)
  1157. {
  1158. ppropDst->Value.MVbin.lpbin[iValue].lpb = pb;
  1159. cbT = (UINT)pprop->Value.MVbin.lpbin[iValue].cb;
  1160. ppropDst->Value.MVbin.lpbin[iValue].cb = (ULONG)cbT;
  1161. MemCopy(pb, pprop->Value.MVbin.lpbin[iValue].lpb, cbT);
  1162. cbT = AlignProp(cbT);
  1163. cb += cbT;
  1164. pb += cbT;
  1165. }
  1166. continue; // already updated, don't do it again
  1167. case PT_MV_STRING8:
  1168. ppropDst->Value.MVszA.lppszA = (LPSTR *) pb;
  1169. cbMV = pprop->Value.MVszA.cValues * sizeof(LPSTR);
  1170. pb += cbMV;
  1171. cb += cbMV;
  1172. for (iValue = 0;
  1173. (ULONG)iValue < pprop->Value.MVszA.cValues;
  1174. iValue++)
  1175. {
  1176. ppropDst->Value.MVszA.lppszA[iValue] = (LPSTR)pb;
  1177. cbT = lstrlenA(pprop->Value.MVszA.lppszA[iValue]) + 1;
  1178. MemCopy(pb, pprop->Value.MVszA.lppszA[iValue], cbT);
  1179. pb += cbT;
  1180. cb += cbT;
  1181. }
  1182. cbT = (UINT)AlignProp(cb);
  1183. pb += cbT - cb;
  1184. cb = cbT;
  1185. continue; // already updated, don't do it again
  1186. case PT_MV_UNICODE:
  1187. ppropDst->Value.MVszW.lppszW = (LPWSTR *) pb;
  1188. cbMV = pprop->Value.MVszW.cValues * sizeof(LPWSTR);
  1189. pb += cbMV;
  1190. cb += cbMV;
  1191. for (iValue = 0;
  1192. (ULONG)iValue < pprop->Value.MVszW.cValues;
  1193. iValue++)
  1194. {
  1195. ppropDst->Value.MVszW.lppszW[iValue] = (LPWSTR)pb;
  1196. cbT = (lstrlenW(pprop->Value.MVszW.lppszW[iValue]) + 1)
  1197. * sizeof(WCHAR);
  1198. MemCopy(pb, pprop->Value.MVszW.lppszW[iValue], cbT);
  1199. pb += cbT;
  1200. cb += cbT;
  1201. }
  1202. cbT = (UINT)AlignProp(cb);
  1203. pb += cbT - cb;
  1204. cb = cbT;
  1205. continue; // already updated, don't do it again
  1206. }
  1207. // Advance pointer and total count by the amount copied
  1208. cbT = AlignProp(cbT);
  1209. pb += cbT;
  1210. cb += cbT;
  1211. }
  1212. if (pcb)
  1213. {
  1214. Assert(!IsBadWritePtr(pcb, sizeof(ULONG)));
  1215. *pcb = cb;
  1216. }
  1217. return S_OK;
  1218. }
  1219. #ifdef NOTIFICATIONS
  1220. STDAPI_(SCODE)
  1221. ScRelocProps( int cprop,
  1222. LPSPropValue rgprop,
  1223. LPVOID pvBaseOld,
  1224. LPVOID pvBaseNew,
  1225. ULONG FAR *pcb)
  1226. {
  1227. LPSPropValue pprop;
  1228. ULONG cb;
  1229. UINT cbT;
  1230. LPVOID pvT;
  1231. int iValue;
  1232. BOOL fBaseNewValid = !IsBadReadPtr (pvBaseNew, sizeof (LPVOID));
  1233. // validate parameters
  1234. AssertSz(!cprop || !IsBadWritePtr(rgprop, sizeof(SPropValue) * cprop),
  1235. TEXT("rgprop fails address check"));
  1236. AssertSz(!pcb || !IsBadWritePtr(pcb, sizeof(ULONG)),
  1237. TEXT("pcb fails address check"));
  1238. // The old behavior of this code assumed that pvBaseNew was a usable
  1239. // pointer and that there would be no relocation to or from an unusable
  1240. // pointer. We've changed this so that you may relocate to or from an
  1241. // unusable pointer -- but logic to figure out whether to use the
  1242. // original or new pointer to fixup internal pointers was added.
  1243. // What we mean by this is that things like strlens and mv prop arrays
  1244. // need to be computed based on where the data ** CURRENTLY ** lives.
  1245. // The old rules allowed us to assume that the NEW location was always
  1246. // the right place. The new rules make us figure it out based on the
  1247. // validity of the two pointers pvBaseNew/Old, that are passed in.
  1248. //
  1249. // In order to preserve the old behavior, we try to use the new pointer
  1250. // (the one that was always used before) as the basis for internal
  1251. // pointer fixup. If it is bad (for example if we are relocating from
  1252. // something to zero), we will use the old pointer.
  1253. //
  1254. // A new wrinkle in the behavior of this code is a return of
  1255. // MAPI_E_INVALID_PARAMETER if both addresses appear invalid. This is
  1256. // to help protect this code for the mv or strlen case (though all
  1257. // other cases would have worked OK).
  1258. if (!fBaseNewValid && IsBadReadPtr (pvBaseOld, sizeof (LPVOID)))
  1259. {
  1260. DebugTrace ( TEXT("pvBaseOld and pvBaseNew failed address check"));
  1261. DebugTraceSc (ScRelocProps, MAPI_E_INVALID_PARAMETER);
  1262. return MAPI_E_INVALID_PARAMETER;
  1263. }
  1264. //$ SIZE Some of the multi-valued cases could be collapsed if we don't
  1265. //$ mind assuming that the counts and pointers are in the same place.
  1266. cb = cprop * sizeof(SPropValue);
  1267. for (pprop = rgprop; cprop--; ++pprop)
  1268. {
  1269. // Tricky: common code after the switch increments cb.
  1270. // If no increment is necessary, the case
  1271. // uses 'continue' rather than 'break' to exit the switch, thus
  1272. // skipping the increment -- AND any other code which may be
  1273. // added after the switch.
  1274. switch ( PROP_TYPE(pprop->ulPropTag) )
  1275. {
  1276. default:
  1277. DebugTrace( TEXT("ScRelocProps: Unknown property type %s")
  1278. TEXT(" (index %d)\n"),
  1279. SzDecodeUlPropTag(pprop->ulPropTag), pprop - rgprop);
  1280. return E_INVALIDARG;
  1281. case PT_I2:
  1282. case PT_LONG:
  1283. case PT_R4:
  1284. case PT_APPTIME:
  1285. case PT_DOUBLE:
  1286. case PT_BOOLEAN:
  1287. case PT_CURRENCY:
  1288. case PT_SYSTIME:
  1289. case PT_I8:
  1290. case PT_ERROR:
  1291. case PT_OBJECT:
  1292. case PT_NULL:
  1293. continue; // nothing to add or relocate
  1294. case PT_CLSID:
  1295. pprop->Value.lpguid = PvRelocPv(pprop->Value.lpguid,
  1296. pvBaseOld, pvBaseNew);
  1297. cbT = sizeof(GUID);
  1298. break;
  1299. case PT_BINARY:
  1300. pprop->Value.bin.lpb = PvRelocPv(pprop->Value.bin.lpb,
  1301. pvBaseOld, pvBaseNew);
  1302. cbT = (UINT)pprop->Value.bin.cb;
  1303. break;
  1304. case PT_STRING8:
  1305. // If we're assuming that the old pointer is OK (this
  1306. // means that we determined that the new one is not OK),
  1307. // save the current lpszA value in a temp variable. After
  1308. // the relocation, if the reverse is true, we'll put the
  1309. // relocated lpszA value into the temp variable.
  1310. //
  1311. // We then use the strlen of the string we hope the temp
  1312. // variable is pointing to, in order to compute the amount
  1313. // of space in the blob which is occupied by the string.
  1314. if (!fBaseNewValid)
  1315. pvT = pprop->Value.lpszA;
  1316. pprop->Value.lpszA = PvRelocPv(pprop->Value.lpszA,
  1317. pvBaseOld, pvBaseNew);
  1318. if (fBaseNewValid)
  1319. pvT = pprop->Value.lpszA;
  1320. cbT = lstrlenA((LPSTR)pvT) + 1;
  1321. break;
  1322. case PT_UNICODE:
  1323. // If we're assuming that the old pointer is OK (this
  1324. // means that we determined that the new one is not OK),
  1325. // save the current lpszW value in a temp variable. After
  1326. // the relocation, if the reverse is true, we'll put the
  1327. // relocated lpszW value into the temp variable.
  1328. //
  1329. // We then use the strlen of the string we hope the temp
  1330. // variable is pointing to, in order to compute the amount
  1331. // of space in the blob which is occupied by the string.
  1332. if (!fBaseNewValid)
  1333. pvT = pprop->Value.lpszW;
  1334. pprop->Value.lpszW = PvRelocPv(pprop->Value.lpszW,
  1335. pvBaseOld, pvBaseNew);
  1336. if (fBaseNewValid)
  1337. pvT = pprop->Value.lpszW;
  1338. cbT = (lstrlenW((LPWSTR)pvT) + 1) * sizeof(WCHAR);
  1339. break;
  1340. case PT_MV_I2:
  1341. pprop->Value.MVi.lpi = PvRelocPv(pprop->Value.MVi.lpi,
  1342. pvBaseOld, pvBaseNew);
  1343. cbT = (UINT)pprop->Value.MVi.cValues * sizeof(short int);
  1344. break;
  1345. case PT_MV_LONG:
  1346. pprop->Value.MVl.lpl = PvRelocPv(pprop->Value.MVl.lpl,
  1347. pvBaseOld, pvBaseNew);
  1348. cbT = (UINT)pprop->Value.MVl.cValues * sizeof(LONG);
  1349. break;
  1350. case PT_MV_R4:
  1351. pprop->Value.MVflt.lpflt = PvRelocPv(pprop->Value.MVflt.lpflt,
  1352. pvBaseOld, pvBaseNew);
  1353. cbT = (UINT)pprop->Value.MVflt.cValues * sizeof(float);
  1354. break;
  1355. case PT_MV_APPTIME:
  1356. pprop->Value.MVat.lpat = PvRelocPv(pprop->Value.MVat.lpat,
  1357. pvBaseOld, pvBaseNew);
  1358. cbT = (UINT)pprop->Value.MVat.cValues * sizeof(double);
  1359. break;
  1360. case PT_MV_DOUBLE:
  1361. pprop->Value.MVdbl.lpdbl = PvRelocPv(pprop->Value.MVdbl.lpdbl,
  1362. pvBaseOld, pvBaseNew);
  1363. cbT = (UINT)pprop->Value.MVdbl.cValues * sizeof(double);
  1364. break;
  1365. case PT_MV_CURRENCY:
  1366. pprop->Value.MVcur.lpcur = PvRelocPv(pprop->Value.MVcur.lpcur,
  1367. pvBaseOld, pvBaseNew);
  1368. cbT = (UINT)pprop->Value.MVcur.cValues * sizeof(CURRENCY);
  1369. break;
  1370. case PT_MV_SYSTIME:
  1371. pprop->Value.MVft.lpft = PvRelocPv(pprop->Value.MVft.lpft,
  1372. pvBaseOld, pvBaseNew);
  1373. cbT = (UINT)pprop->Value.MVft.cValues * sizeof(FILETIME);
  1374. break;
  1375. case PT_MV_CLSID:
  1376. pprop->Value.MVguid.lpguid = PvRelocPv(pprop->Value.MVguid.lpguid,
  1377. pvBaseOld, pvBaseNew);
  1378. cbT = (UINT)pprop->Value.MVguid.cValues * sizeof(GUID);
  1379. break;
  1380. case PT_MV_I8:
  1381. pprop->Value.MVli.lpli = PvRelocPv(pprop->Value.MVli.lpli,
  1382. pvBaseOld, pvBaseNew);
  1383. cbT = (UINT)pprop->Value.MVli.cValues * sizeof(LARGE_INTEGER);
  1384. break;
  1385. case PT_MV_BINARY:
  1386. {
  1387. LPSBinary lpsbT = pprop->Value.MVbin.lpbin;
  1388. pprop->Value.MVbin.lpbin = PvRelocPv(lpsbT, pvBaseOld, pvBaseNew);
  1389. // We've already set up a temporary variable to point to the
  1390. // pvBaseOld memory location. If pvBaseNew was OK, then we'll
  1391. // redirect the temp variable to the relocated memory before
  1392. // using it to correct the pointers in the MVbin array.
  1393. if (fBaseNewValid)
  1394. lpsbT = pprop->Value.MVbin.lpbin;
  1395. for (iValue = 0;
  1396. (ULONG)iValue < pprop->Value.MVbin.cValues;
  1397. iValue++)
  1398. {
  1399. lpsbT[iValue].lpb = PvRelocPv(lpsbT[iValue].lpb, pvBaseOld, pvBaseNew);
  1400. cb += (UINT)AlignProp(lpsbT[iValue].cb);
  1401. }
  1402. continue; // already updated, don't do it again
  1403. }
  1404. case PT_MV_STRING8:
  1405. {
  1406. LPSTR * lppszT = pprop->Value.MVszA.lppszA;
  1407. pprop->Value.MVszA.lppszA = PvRelocPv(lppszT, pvBaseOld, pvBaseNew);
  1408. // We've already set up a temporary variable to point to the
  1409. // pvBaseOld memory location. If pvBaseNew was OK, then we'll
  1410. // redirect the temp variable to the relocated memory before
  1411. // using it to correct the pointers in the MVszA array.
  1412. if (fBaseNewValid)
  1413. lppszT = pprop->Value.MVszA.lppszA;
  1414. for (iValue = 0;
  1415. (ULONG)iValue < pprop->Value.MVszA.cValues;
  1416. iValue++)
  1417. {
  1418. // If we're assuming that the old pointer is OK (this
  1419. // means that we determined that the new one is not OK),
  1420. // save the current lppszT value in a temp variable. After
  1421. // the relocation, if the reverse is true, we'll put the
  1422. // relocated lppszT value into the temp variable.
  1423. //
  1424. // We then use the strlen of the string we hope the temp
  1425. // variable is pointing to, in order to compute the amount
  1426. // of space in the blob which is occupied by the string.
  1427. if (!fBaseNewValid)
  1428. pvT = lppszT[iValue];
  1429. lppszT[iValue] = PvRelocPv(lppszT[iValue], pvBaseOld, pvBaseNew);
  1430. if (fBaseNewValid)
  1431. pvT = lppszT[iValue];
  1432. cb += lstrlenA((LPSTR)pvT) + 1;
  1433. }
  1434. cb = AlignProp(cb);
  1435. continue; // already updated, don't do it again
  1436. }
  1437. case PT_MV_UNICODE:
  1438. {
  1439. LPWSTR * lppszwT = pprop->Value.MVszW.lppszW;
  1440. pprop->Value.MVszW.lppszW = PvRelocPv(lppszwT, pvBaseOld, pvBaseNew);
  1441. // We've already set up a temporary variable to point to the
  1442. // pvBaseOld memory location. If pvBaseNew was OK, then we'll
  1443. // redirect the temp variable to the relocated memory before
  1444. // using it to correct the pointers in the MVszW array.
  1445. if (fBaseNewValid)
  1446. lppszwT = pprop->Value.MVszW.lppszW;
  1447. for (iValue = 0;
  1448. (ULONG)iValue < pprop->Value.MVszW.cValues;
  1449. iValue++)
  1450. {
  1451. // If we're assuming that the old pointer is OK (this
  1452. // means that we determined that the new one is not OK),
  1453. // save the current lppszwT value in a temp variable. After
  1454. // the relocation, if the reverse is true, we'll put the
  1455. // relocated lppszwT value into the temp variable.
  1456. //
  1457. // We then use the strlen of the string we hope the temp
  1458. // variable is pointing to, in order to compute the amount
  1459. // of space in the blob which is occupied by the string.
  1460. if (!fBaseNewValid)
  1461. pvT = lppszwT[iValue];
  1462. lppszwT[iValue] = PvRelocPv(lppszwT[iValue], pvBaseOld, pvBaseNew);
  1463. if (fBaseNewValid)
  1464. pvT = lppszwT[iValue];
  1465. cb += (lstrlenW(lppszwT[iValue]) + 1) * sizeof(WCHAR);
  1466. }
  1467. cb = AlignProp(cb);
  1468. continue; // already updated, don't do it again
  1469. }
  1470. }
  1471. // Advance total count
  1472. cb += AlignProp(cbT);
  1473. }
  1474. if (pcb)
  1475. {
  1476. Assert(!IsBadWritePtr(pcb, sizeof(ULONG)));
  1477. *pcb = cb;
  1478. }
  1479. return S_OK;
  1480. }
  1481. #endif
  1482. /*
  1483. * Wrapper function to just duplicate a property value array
  1484. * into a single block of MAPI memory.
  1485. */
  1486. STDAPI_(SCODE)
  1487. ScDupPropset(int cprop, LPSPropValue rgprop, LPALLOCATEBUFFER palloc,
  1488. LPSPropValue FAR *prgprop)
  1489. {
  1490. ULONG cb;
  1491. SCODE sc;
  1492. // validate parameters
  1493. AssertSz(!cprop || !IsBadReadPtr(rgprop, sizeof(SPropValue) * cprop),
  1494. TEXT("rgprop fails address check"));
  1495. AssertSz(!IsBadCodePtr((FARPROC)palloc), TEXT("palloc fails address check"));
  1496. AssertSz(!IsBadWritePtr(prgprop, sizeof(LPSPropValue)),
  1497. TEXT("prgprop fails address check"));
  1498. // Find out how much memory we need
  1499. if (sc = ScCountProps(cprop, rgprop, &cb))
  1500. goto ret;
  1501. // Obtain memory
  1502. if (sc = (*palloc)(cb, (LPVOID *)prgprop))
  1503. goto ret;
  1504. // Copy the properties
  1505. if (sc = ScCopyProps(cprop, rgprop, *prgprop, &cb))
  1506. goto ret;
  1507. ret:
  1508. DebugTraceSc(ScDupPropset, sc);
  1509. return sc;
  1510. }