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.

645 lines
13 KiB

  1. /*
  2. * V A L I D A T E . C
  3. *
  4. * Functions used to validate parameters on standard MAPI object methods.
  5. *
  6. * Used in conjunction with macros found in VALIDATE.H.
  7. *
  8. * Copyright 1992-93 Microsoft Corporation. All Rights Reserved.
  9. */
  10. #include <_apipch.h>
  11. /*
  12. * FBadRgPropVal()
  13. *
  14. * Purpose:
  15. * Routine to attempt to validate all of the ptrs contained in an input
  16. * property value array, LPSPropVal
  17. */
  18. /*
  19. *BOOL
  20. *FBadPropVal( LPSPropValue lpPropVal)
  21. *{
  22. * ULONG ulPropType;
  23. * BOOL fLongMVProp = FALSE;
  24. * ULONG cbItemType = 0;
  25. * ULONG cMVVals;
  26. * LPVOID FAR *lppvMVArray;
  27. *
  28. * switch (ulPropType = PROP_TYPE(lpPropVal->ulPropTag))
  29. * {
  30. * case PT_STRING8:
  31. *
  32. * if (IsBadStringPtrA( lpPropVal->Value.lpszA, (UINT)-1 ))
  33. * {
  34. * return TRUE;
  35. * }
  36. *
  37. * break;
  38. *
  39. *
  40. *#ifdef WIN32
  41. * case PT_UNICODE:
  42. *
  43. * if (IsBadStringPtrW( lpPropVal->Value.lpszW, (UINT)-1 ))
  44. * {
  45. * return TRUE;
  46. * }
  47. * break;
  48. *#endif
  49. *
  50. *
  51. * case PT_BINARY:
  52. *
  53. * if (IsBadReadPtr( lpPropVal->Value.bin.lpb
  54. * , (UINT) lpPropVal->Value.bin.cb))
  55. * {
  56. * return TRUE;
  57. * }
  58. *
  59. * break;
  60. *
  61. * case PT_MV_I2: // 16 bit quantities
  62. *
  63. * cbItemType = sizeof(lpPropVal->Value.i);
  64. * break;
  65. *
  66. *
  67. * case PT_MV_UNICODE: // Arrays of strings
  68. * case PT_MV_STRING8:
  69. *
  70. * fLongMVProp = TRUE;
  71. *
  72. * // Now fall thru to the 32 bit quantity code below to size the
  73. * // top level array of ptrs
  74. *
  75. *
  76. * case PT_MV_LONG: // 32 bit quantities
  77. * case PT_MV_R4:
  78. *
  79. * cbItemType = sizeof(long);
  80. * break;
  81. *
  82. *
  83. * case PT_MV_BINARY: // Arrays of counted binary data
  84. *
  85. * fLongMVProp = TRUE;
  86. *
  87. * // Now fall thru to the 64 bit quantity code below to size the array
  88. * // of ULONG lengths / ULONG ptrs that comprise the top level stream
  89. *
  90. *
  91. * case PT_MV_DOUBLE: // 64 bit quantities
  92. * case PT_MV_CURRENCY:
  93. * case PT_MV_APPTIME:
  94. * case PT_MV_SYSTIME:
  95. * case PT_MV_I8:
  96. *
  97. * // Assert that all array elements for this case are the same size.
  98. * Assert( sizeof( double ) == sizeof( LARGE_INTEGER ));
  99. * cbItemType = sizeof( double );
  100. * break;
  101. *
  102. *
  103. * case PT_MV_CLSID: // 128 bit quantity
  104. *
  105. * cbItemType = sizeof( GUID );
  106. * break;
  107. *
  108. *
  109. * case PT_OBJECT:
  110. * case PT_NULL:
  111. * default:
  112. * if (ulPropType & MV_FLAG)
  113. * {
  114. * return TRUE; // Unknown multivalue prop is bad
  115. * }
  116. *
  117. * break;
  118. * }
  119. *
  120. * if (!(ulPropType & MV_FLAG))
  121. * {
  122. * return FALSE;
  123. * }
  124. *
  125. * // Try to validate the multivalue props
  126. *
  127. * // This code assumes that the count and ptr of every multivalue
  128. * // property are in the same place.
  129. * // Asserts check that the sizes of the grouped types above are
  130. * // matched
  131. *
  132. * cMVVals = lpPropVal->Value.MVl.cValues;
  133. * lppvMVArray = (LPVOID FAR *) (lpPropVal->Value.MVl.lpl);
  134. *
  135. * if (IsBadReadPtr( lppvMVArray, (UINT) (cMVVals * cbItemType)))
  136. * {
  137. * return TRUE;
  138. * }
  139. *
  140. * if (fLongMVProp)
  141. * {
  142. * // Go verify the array of pointers.
  143. * for ( ; cMVVals; cMVVals--, lppvMVArray++)
  144. * {
  145. * switch (ulPropType)
  146. * {
  147. *#ifdef WIN32
  148. * case PT_MV_UNICODE:
  149. *
  150. * if (IsBadStringPtrW( (LPCWSTR) (*lppvMVArray), (UINT) -1))
  151. * {
  152. * return TRUE;
  153. * }
  154. *
  155. * break;
  156. *#endif
  157. * case PT_MV_STRING8:
  158. *
  159. * if (IsBadStringPtrA( (LPCSTR) (*lppvMVArray), (UINT) -1))
  160. * {
  161. * return TRUE;
  162. * }
  163. *
  164. * break;
  165. *
  166. * case PT_MV_BINARY:
  167. *
  168. * if (IsBadReadPtr( ((SBinary FAR *)(*lppvMVArray))->lpb
  169. * , (UINT)
  170. * ((SBinary FAR *)(*lppvMVArray))->cb))
  171. * {
  172. * return TRUE;
  173. * }
  174. * break;
  175. * }
  176. * }
  177. * }
  178. *
  179. * return FALSE;
  180. *}
  181. */
  182. /*
  183. * FBadRgPropVal()
  184. *
  185. * Purpose:
  186. * Routine to attempt to validate all of the ptrs contained in an input
  187. * property value array, LPSPropVal
  188. */
  189. /*BOOL
  190. *FBadRgPropVal( LPSPropValue lpPropVal,
  191. * ULONG cValues)
  192. *{
  193. *
  194. * if (IsBadReadPtr( lpPropVal, sizeof(SPropValue) * (UINT) cValues))
  195. * {
  196. * return TRUE;
  197. * }
  198. *
  199. * // Warning! Modifies the function parameters (NOT what they point to!).
  200. * //
  201. * for ( ; cValues ; cValues--, lpPropVal++)
  202. * {
  203. * if (FBadPropVal( lpPropVal))
  204. * {
  205. * return TRUE;
  206. * }
  207. * }
  208. *
  209. * return FALSE;
  210. *}
  211. */
  212. /*
  213. * FBadRglpszA()
  214. *
  215. * Purpose:
  216. * Routine to attempt to validate all of the ptrs contained in an input
  217. * array of string8 pointers, LPSTR FAR *.
  218. */
  219. STDAPI_(BOOL)
  220. FBadRglpszA( LPSTR FAR *lppszA,
  221. ULONG cStrings)
  222. {
  223. if (IsBadReadPtr( lppszA, (UINT) (cStrings * sizeof(LPSTR FAR *))))
  224. {
  225. return TRUE;
  226. }
  227. /* Check for readability of each string in the array.
  228. *
  229. * WARNING!
  230. * Function pointers and counts are modified (NOT what they point to).
  231. */
  232. for (; cStrings; cStrings--, lppszA++)
  233. {
  234. if (IsBadStringPtrA( *lppszA, (UINT)-1 ))
  235. {
  236. return TRUE;
  237. }
  238. }
  239. return FALSE;
  240. }
  241. /*
  242. * FBadRglpszW()
  243. *
  244. * Purpose:
  245. * Routine to attempt to validate all of the ptrs contained in an input
  246. * array of UNICODE string pointers, LPSTR FAR *.
  247. */
  248. STDAPI_(BOOL)
  249. FBadRglpszW( LPWSTR FAR *lppszW,
  250. ULONG cStrings)
  251. {
  252. if (IsBadReadPtr( lppszW, (UINT) (cStrings * sizeof(LPWSTR FAR *))))
  253. {
  254. return TRUE;
  255. }
  256. // Check for readability of each string in the array.
  257. //
  258. // WARNING!
  259. // Function pointers and counts are modified (NOT what they point to).
  260. //
  261. for (; cStrings; cStrings--, lppszW++)
  262. {
  263. #ifdef MAC
  264. if (IsBadStringPtr( *lppszW, (UINT)-1 ))
  265. #else
  266. if (IsBadStringPtrW( *lppszW, (UINT)-1 ))
  267. #endif
  268. {
  269. return TRUE;
  270. }
  271. }
  272. return FALSE;
  273. }
  274. /*
  275. * FBadRowSet()
  276. *
  277. * Purpose:
  278. * Routine to validate all rows of properties in a row set.
  279. *
  280. * NOTE! A NULL row pointer is assumed to be a VALID entry in a row set.
  281. * A NULL row set pointer is assumed to be INVALID.
  282. */
  283. STDAPI_(BOOL)
  284. FBadRowSet( LPSRowSet lpRowSet)
  285. {
  286. LPSRow lpRow;
  287. ULONG cRows;
  288. if (IsBadReadPtr( lpRowSet, CbNewSRowSet(0)))
  289. return TRUE;
  290. if (IsBadWritePtr( lpRowSet, CbSRowSet(lpRowSet)))
  291. return TRUE;
  292. // Short cut
  293. if (!lpRowSet->cRows)
  294. return FALSE;
  295. // Check each row in the set.
  296. // cValues == 0 is valid if and only if lpProps == NULL
  297. //
  298. for ( lpRow = lpRowSet->aRow, cRows = lpRowSet->cRows
  299. ; cRows
  300. ; lpRow++, cRows--)
  301. {
  302. if ( IsBadReadPtr( lpRow, sizeof(*lpRow))
  303. #ifndef _WIN64
  304. || FBadRgPropVal( lpRow->lpProps, (int) (lpRow->cValues))
  305. #endif // _WIN64
  306. )
  307. {
  308. return TRUE;
  309. }
  310. }
  311. return FALSE;
  312. }
  313. /*
  314. * FBadRglpNameID()
  315. *
  316. * Purpose:
  317. * Routine to attempt to validate all of the ptrs contained in an input
  318. * array of MAPINAMEID pointers, LPMAPINAMEID FAR *.
  319. */
  320. STDAPI_(BOOL)
  321. FBadRglpNameID( LPMAPINAMEID FAR * lppNameId,
  322. ULONG cNames)
  323. {
  324. if (IsBadReadPtr( lppNameId, (UINT) (cNames * sizeof(LPMAPINAMEID FAR *))))
  325. {
  326. return TRUE;
  327. }
  328. // Check for readability of each string in the array.
  329. //
  330. for (; cNames; cNames--, lppNameId++)
  331. {
  332. LPMAPINAMEID lpName = *lppNameId;
  333. if (IsBadReadPtr(lpName, sizeof(MAPINAMEID)))
  334. {
  335. return TRUE;
  336. }
  337. if (IsBadReadPtr(lpName->lpguid, sizeof(GUID)))
  338. {
  339. return TRUE;
  340. }
  341. if (lpName->ulKind != MNID_ID && lpName->ulKind != MNID_STRING)
  342. {
  343. return TRUE;
  344. }
  345. if (lpName->ulKind == MNID_STRING)
  346. {
  347. if (IsBadStringPtrW( lpName->Kind.lpwstrName, (UINT)-1 ))
  348. {
  349. return TRUE;
  350. }
  351. }
  352. }
  353. return FALSE;
  354. }
  355. /* FBadEntryList moved to src\lo\msvalid. */
  356. /*============================================================================
  357. * The following functions are used to determine the validity of various
  358. * table-related structures. These functions should most definitely
  359. * be moved to proputil when it becomes a lib (or DLL).
  360. */
  361. /*============================================================================
  362. - FBadPropTag()
  363. -
  364. * Returns TRUE if the specified prop tag isn't one of the known
  365. * MAPI property types, FALSE otherwise.
  366. *
  367. *
  368. * Parameter:
  369. * ulPropTag in Proptag to validate.
  370. */
  371. STDAPI_(ULONG)
  372. FBadPropTag( ULONG ulPropTag )
  373. {
  374. // Just check the type
  375. switch ( PROP_TYPE(ulPropTag) & ~MV_FLAG )
  376. {
  377. default:
  378. return TRUE;
  379. case PT_UNSPECIFIED:
  380. case PT_NULL:
  381. case PT_I2:
  382. case PT_LONG:
  383. case PT_R4:
  384. case PT_DOUBLE:
  385. case PT_CURRENCY:
  386. case PT_APPTIME:
  387. case PT_ERROR:
  388. case PT_BOOLEAN:
  389. case PT_OBJECT:
  390. case PT_I8:
  391. case PT_STRING8:
  392. case PT_UNICODE:
  393. case PT_SYSTIME:
  394. case PT_CLSID:
  395. case PT_BINARY:
  396. return FALSE;
  397. }
  398. }
  399. /*============================================================================
  400. - FBadRow()
  401. -
  402. * Returns TRUE if the specified row contains invalid (PT_ERROR or
  403. * PT_NULL) columns or if any of those columns are invalid.
  404. *
  405. *
  406. * Parameter:
  407. * lprow in Row to validate.
  408. */
  409. STDAPI_(ULONG)
  410. FBadRow( LPSRow lprow )
  411. {
  412. LPSPropValue lpprop;
  413. LPSPropValue lppropT;
  414. if ( IsBadReadPtr(lprow, sizeof(SRow)) ||
  415. IsBadReadPtr(lprow->lpProps, (size_t)(lprow->cValues * sizeof(SPropValue))) )
  416. return TRUE;
  417. lpprop = lprow->lpProps + lprow->cValues;
  418. while ( lpprop-- > lprow->lpProps )
  419. {
  420. if ( FBadProp(lpprop) )
  421. return TRUE;
  422. lppropT = lpprop;
  423. while ( lppropT-- > lprow->lpProps )
  424. if ( lppropT->ulPropTag == lpprop->ulPropTag &&
  425. PROP_TYPE(lppropT->ulPropTag) != PT_ERROR &&
  426. PROP_TYPE(lppropT->ulPropTag) != PT_NULL )
  427. {
  428. DebugTrace( TEXT("FBadRow() - Row has multiple columns with same proptag!\n") );
  429. return TRUE;
  430. }
  431. }
  432. return FALSE;
  433. }
  434. /*============================================================================
  435. - FBadProp()
  436. -
  437. * Returns TRUE if the specified property is invalid.
  438. *
  439. *
  440. * Parameters:
  441. * lpprop in Property to validate.
  442. */
  443. STDAPI_(ULONG)
  444. FBadProp( LPSPropValue lpprop )
  445. {
  446. ULONG ulcb;
  447. LPVOID lpv;
  448. if ( IsBadReadPtr(lpprop, sizeof(SPropValue)) ||
  449. FBadPropTag(lpprop->ulPropTag) )
  450. return TRUE;
  451. switch ( PROP_TYPE(lpprop->ulPropTag) )
  452. {
  453. default:
  454. return FALSE;
  455. case PT_BINARY:
  456. ulcb = lpprop->Value.bin.cb;
  457. lpv = lpprop->Value.bin.lpb;
  458. break;
  459. case PT_STRING8:
  460. ulcb = sizeof(CHAR);
  461. lpv = lpprop->Value.lpszA;
  462. break;
  463. #ifndef WIN16
  464. case PT_UNICODE:
  465. ulcb = sizeof(WCHAR);
  466. lpv = lpprop->Value.lpszW;
  467. break;
  468. #endif
  469. case PT_CLSID:
  470. ulcb = sizeof(GUID);
  471. lpv = lpprop->Value.lpguid;
  472. break;
  473. case PT_MV_I2:
  474. case PT_MV_LONG:
  475. case PT_MV_R4:
  476. case PT_MV_DOUBLE:
  477. case PT_MV_CURRENCY:
  478. case PT_MV_I8:
  479. ulcb = UlPropSize(lpprop);
  480. lpv = lpprop->Value.MVi.lpi;
  481. break;
  482. case PT_MV_BINARY:
  483. {
  484. LPSBinary lpbin;
  485. if ( IsBadReadPtr(lpprop->Value.MVbin.lpbin,
  486. (size_t)(lpprop->Value.MVbin.cValues *
  487. sizeof(SBinary))) )
  488. return TRUE;
  489. lpbin = lpprop->Value.MVbin.lpbin + lpprop->Value.MVbin.cValues;
  490. while ( lpprop->Value.MVbin.lpbin < lpbin-- )
  491. if ( IsBadReadPtr(lpbin->lpb, (size_t)(lpbin->cb) ))
  492. return TRUE;
  493. return FALSE;
  494. }
  495. case PT_MV_STRING8:
  496. {
  497. LPCSTR FAR * lppsz;
  498. if ( IsBadReadPtr(lpprop->Value.MVszA.lppszA,
  499. (size_t)(lpprop->Value.MVszA.cValues * sizeof(LPSTR))) )
  500. return TRUE;
  501. lppsz = lpprop->Value.MVszA.lppszA + lpprop->Value.MVszA.cValues;
  502. while ( lpprop->Value.MVszA.lppszA < lppsz-- )
  503. // Need to break the code up this way for the Mac version
  504. if ( IsBadReadPtr(*lppsz, sizeof(CHAR)))
  505. return TRUE;
  506. return FALSE;
  507. }
  508. case PT_MV_UNICODE:
  509. {
  510. UNALIGNED LPWSTR FAR * lppsz;
  511. if ( IsBadReadPtr(lpprop->Value.MVszW.lppszW,
  512. (size_t)(lpprop->Value.MVszW.cValues * sizeof(LPWSTR))) )
  513. return TRUE;
  514. lppsz = lpprop->Value.MVszW.lppszW + lpprop->Value.MVszW.cValues;
  515. while ( lpprop->Value.MVszW.lppszW < lppsz-- )
  516. if ( IsBadReadPtr(*lppsz, sizeof(WCHAR)))
  517. return TRUE;
  518. return FALSE;
  519. }
  520. }
  521. return IsBadReadPtr(lpv, (size_t) ulcb);
  522. }
  523. /* FBadSortOrderSet moved to src\lo\MSVALID.C */
  524. /*============================================================================
  525. - FBadColumnSet()
  526. -
  527. * Returns TRUE if the specified column set is invalid. For use
  528. * with IMAPITable::SetColumns(), this function treats PT_ERROR columns
  529. * as invalid and PT_NULL columns as valid.
  530. *
  531. *
  532. * Parameter:
  533. * lpptaCols in Column set to validate.
  534. */
  535. STDAPI_(ULONG)
  536. FBadColumnSet( LPSPropTagArray lpptaCols )
  537. {
  538. UNALIGNED ULONG FAR * pulPropTag;
  539. if ( IsBadReadPtr(lpptaCols,CbNewSPropTagArray(0)) ||
  540. IsBadReadPtr(lpptaCols,CbSPropTagArray(lpptaCols)))
  541. {
  542. DebugTrace( TEXT("FBadColumnSet() - Bad column set structure\n") );
  543. return TRUE;
  544. }
  545. // maximum number of proptags we can calculate size for. raid 4460
  546. if ( lpptaCols->cValues > ((INT_MAX - offsetof( SPropTagArray, aulPropTag ))
  547. / sizeof( ULONG )))
  548. {
  549. DebugTrace( TEXT("FBadColumnSet(): Exceeded maximum number of tags\n") );
  550. return TRUE;
  551. }
  552. pulPropTag = lpptaCols->aulPropTag + lpptaCols->cValues;
  553. while ( pulPropTag-- > lpptaCols->aulPropTag )
  554. {
  555. // DCR 978: Disallow PT_ERROR columns.
  556. // DCR 715: Ignore PT_NULL columns and only allow columns
  557. // from initial column set.
  558. if ( PROP_TYPE(*pulPropTag) != PT_NULL &&
  559. (PROP_TYPE(*pulPropTag) == PT_ERROR ||
  560. FBadPropTag(*pulPropTag)) )
  561. {
  562. DebugTrace( TEXT("FBadColumnSet() - Bad column 0x%08lX\n"), *pulPropTag );
  563. return TRUE;
  564. }
  565. }
  566. return FALSE;
  567. }