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.

972 lines
32 KiB

  1. /***********************************************************************
  2. *
  3. * DBGUTIL.C
  4. *
  5. * Debug utility functions
  6. *
  7. * Copyright 1992 - 1996 Microsoft Corporation. All Rights Reserved.
  8. *
  9. * Revision History:
  10. *
  11. * When Who What
  12. * -------- ------------------ ---------------------------------------
  13. * 11.13.95 Bruce Kelley Created
  14. *
  15. ***********************************************************************/
  16. #include <windows.h>
  17. #include <wab.h>
  18. #include "apitest.h"
  19. #include "dbgutil.h"
  20. #define _WAB_DBGUTIL_C
  21. PUCHAR PropTagName(ULONG ulPropTag);
  22. const TCHAR szNULL[] = "";
  23. extern SCODE WABFreeBuffer(LPVOID lpBuffer);
  24. VOID FAR CDECL DebugTrace(LPSTR lpszFmt, ...);
  25. /***************************************************************************
  26. Name : FreeBufferAndNull
  27. Purpose : Frees a MAPI buffer and NULLs the pointer
  28. Parameters: lppv = pointer to buffer pointer to free
  29. Returns : void
  30. Comment : Remember to pass in the pointer to the pointer. The
  31. compiler is not smart enough to tell if you are doing this
  32. right or not, but you will know at runtime!
  33. BUGBUG: Make this fastcall!
  34. ***************************************************************************/
  35. void __fastcall FreeBufferAndNull(LPVOID * lppv) {
  36. if (lppv) {
  37. if (*lppv) {
  38. SCODE sc;
  39. if (sc = WABFreeBuffer(*lppv)) {
  40. DebugTrace("WABFreeBuffer(%x) -> 0x%08x\n", *lppv, sc);
  41. }
  42. *lppv = NULL;
  43. }
  44. }
  45. }
  46. /***************************************************************************
  47. Name : ReleaseAndNull
  48. Purpose : Releases an object and NULLs the pointer
  49. Parameters: lppv = pointer to pointer to object to release
  50. Returns : void
  51. Comment : Remember to pass in the pointer to the pointer. The
  52. compiler is not smart enough to tell if you are doing this
  53. right or not, but you will know at runtime!
  54. BUGBUG: Make this fastcall!
  55. ***************************************************************************/
  56. void __fastcall ReleaseAndNull(LPVOID * lppv) {
  57. LPUNKNOWN * lppunk = (LPUNKNOWN *)lppv;
  58. if (lppunk) {
  59. if (*lppunk) {
  60. HRESULT hResult;
  61. if (hResult = (*lppunk)->lpVtbl->Release(*lppunk)) {
  62. DebugTrace("Release(%x) -> 0x%08x\n", *lppunk, GetScode(hResult));
  63. }
  64. *lppunk = NULL;
  65. }
  66. }
  67. }
  68. /***************************************************************************
  69. Name : PropTypeString
  70. Purpose : Map a proptype to a string
  71. Parameters: ulPropType = property type to map
  72. Returns : string pointer to name of prop type
  73. Comment :
  74. ***************************************************************************/
  75. LPTSTR PropTypeString(ULONG ulPropType) {
  76. switch (ulPropType) {
  77. case PT_UNSPECIFIED:
  78. return("PT_UNSPECIFIED");
  79. case PT_NULL:
  80. return("PT_NULL ");
  81. case PT_I2:
  82. return("PT_I2 ");
  83. case PT_LONG:
  84. return("PT_LONG ");
  85. case PT_R4:
  86. return("PT_R4 ");
  87. case PT_DOUBLE:
  88. return("PT_DOUBLE ");
  89. case PT_CURRENCY:
  90. return("PT_CURRENCY ");
  91. case PT_APPTIME:
  92. return("PT_APPTIME ");
  93. case PT_ERROR:
  94. return("PT_ERROR ");
  95. case PT_BOOLEAN:
  96. return("PT_BOOLEAN ");
  97. case PT_OBJECT:
  98. return("PT_OBJECT ");
  99. case PT_I8:
  100. return("PT_I8 ");
  101. case PT_STRING8:
  102. return("PT_STRING8 ");
  103. case PT_UNICODE:
  104. return("PT_UNICODE ");
  105. case PT_SYSTIME:
  106. return("PT_SYSTIME ");
  107. case PT_CLSID:
  108. return("PT_CLSID ");
  109. case PT_BINARY:
  110. return("PT_BINARY ");
  111. case PT_MV_I2:
  112. return("PT_MV_I2 ");
  113. case PT_MV_LONG:
  114. return("PT_MV_LONG ");
  115. case PT_MV_R4:
  116. return("PT_MV_R4 ");
  117. case PT_MV_DOUBLE:
  118. return("PT_MV_DOUBLE ");
  119. case PT_MV_CURRENCY:
  120. return("PT_MV_CURRENCY");
  121. case PT_MV_APPTIME:
  122. return("PT_MV_APPTIME ");
  123. case PT_MV_SYSTIME:
  124. return("PT_MV_SYSTIME ");
  125. case PT_MV_STRING8:
  126. return("PT_MV_STRING8 ");
  127. case PT_MV_BINARY:
  128. return("PT_MV_BINARY ");
  129. case PT_MV_UNICODE:
  130. return("PT_MV_UNICODE ");
  131. case PT_MV_CLSID:
  132. return("PT_MV_CLSID ");
  133. case PT_MV_I8:
  134. return("PT_MV_I8 ");
  135. default:
  136. return(" <unknown> ");
  137. }
  138. }
  139. /***************************************************************************
  140. Name : TraceMVPStrings
  141. Purpose : Debug trace a multivalued string property value
  142. Parameters: lpszCaption = caption string
  143. PropValue = property value to dump
  144. Returns : none
  145. Comment :
  146. ***************************************************************************/
  147. void _TraceMVPStrings(LPTSTR lpszCaption, SPropValue PropValue) {
  148. ULONG i;
  149. DebugTrace("-----------------------------------------------------\n");
  150. DebugTrace("%s", lpszCaption);
  151. switch (PROP_TYPE(PropValue.ulPropTag)) {
  152. case PT_ERROR:
  153. DebugTrace("Error value 0x%08x\n", PropValue.Value.err);
  154. break;
  155. case PT_MV_TSTRING:
  156. DebugTrace("%u values\n", PropValue.Value.MVSZ.cValues);
  157. if (PropValue.Value.MVSZ.cValues) {
  158. DebugTrace("- - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
  159. for (i = 0; i < PropValue.Value.MVSZ.cValues; i++) {
  160. DebugTrace("%u: \"%s\"\n", i, PropValue.Value.MVSZ.LPPSZ[i]);
  161. }
  162. DebugTrace("- - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
  163. }
  164. break;
  165. default:
  166. DebugTrace("TraceMVPStrings got incorrect property type %u for tag %x\n",
  167. PROP_TYPE(PropValue.ulPropTag), PropValue.ulPropTag);
  168. break;
  169. }
  170. }
  171. /***************************************************************************
  172. Name : DebugBinary
  173. Purpose : Debug dump an array of bytes
  174. Parameters: cb = number of bytes to dump
  175. lpb -> bytes to dump
  176. Returns : none
  177. Comment :
  178. ***************************************************************************/
  179. #define DEBUG_NUM_BINARY_LINES 2
  180. VOID DebugBinary(UINT cb, LPBYTE lpb) {
  181. UINT cbLines = 0;
  182. #if (DEBUG_NUM_BINARY_LINES != 0)
  183. UINT cbi;
  184. while (cb && cbLines < DEBUG_NUM_BINARY_LINES) {
  185. cbi = min(cb, 16);
  186. cb -= cbi;
  187. switch (cbi) {
  188. case 16:
  189. DebugTrace("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  190. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6], lpb[7],
  191. lpb[8], lpb[9], lpb[10], lpb[11], lpb[12], lpb[13], lpb[14],
  192. lpb[15]);
  193. break;
  194. case 1:
  195. DebugTrace("%02x\n", lpb[0]);
  196. break;
  197. case 2:
  198. DebugTrace("%02x %02x\n", lpb[0], lpb[1]);
  199. break;
  200. case 3:
  201. DebugTrace("%02x %02x %02x\n", lpb[0], lpb[1], lpb[2]);
  202. break;
  203. case 4:
  204. DebugTrace("%02x %02x %02x %02x\n", lpb[0], lpb[1], lpb[2], lpb[3]);
  205. break;
  206. case 5:
  207. DebugTrace("%02x %02x %02x %02x %02x\n", lpb[0], lpb[1], lpb[2], lpb[3],
  208. lpb[4]);
  209. break;
  210. case 6:
  211. DebugTrace("%02x %02x %02x %02x %02x %02x\n",
  212. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5]);
  213. break;
  214. case 7:
  215. DebugTrace("%02x %02x %02x %02x %02x %02x %02x\n",
  216. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6]);
  217. break;
  218. case 8:
  219. DebugTrace("%02x %02x %02x %02x %02x %02x %02x %02x\n",
  220. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6], lpb[7]);
  221. break;
  222. case 9:
  223. DebugTrace("%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  224. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6], lpb[7],
  225. lpb[8]);
  226. break;
  227. case 10:
  228. DebugTrace("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  229. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6], lpb[7],
  230. lpb[8], lpb[9]);
  231. break;
  232. case 11:
  233. DebugTrace("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  234. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6], lpb[7],
  235. lpb[8], lpb[9], lpb[10]);
  236. break;
  237. case 12:
  238. DebugTrace("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  239. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6], lpb[7],
  240. lpb[8], lpb[9], lpb[10], lpb[11]);
  241. break;
  242. case 13:
  243. DebugTrace("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  244. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6], lpb[7],
  245. lpb[8], lpb[9], lpb[10], lpb[11], lpb[12]);
  246. break;
  247. case 14:
  248. DebugTrace("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  249. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6], lpb[7],
  250. lpb[8], lpb[9], lpb[10], lpb[11], lpb[12], lpb[13]);
  251. break;
  252. case 15:
  253. DebugTrace("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  254. lpb[0], lpb[1], lpb[2], lpb[3], lpb[4], lpb[5], lpb[6], lpb[7],
  255. lpb[8], lpb[9], lpb[10], lpb[11], lpb[12], lpb[13], lpb[14]);
  256. break;
  257. }
  258. lpb += cbi;
  259. cbLines++;
  260. }
  261. if (cb) {
  262. DebugTrace("<etc.>"); //
  263. }
  264. #endif
  265. }
  266. #define MAX_TIME_DATE_STRING 64
  267. /***************************************************************************
  268. Name : FormatTime
  269. Purpose : Format a time string for the locale
  270. Parameters: lpst -> system time/date
  271. lptstr -> output buffer
  272. cchstr = size in chars of lpstr
  273. Returns : number of characters used/needed (including null)
  274. Comment : If cchstr < the return value, nothing will be written
  275. to lptstr.
  276. ***************************************************************************/
  277. UINT FormatTime(LPSYSTEMTIME lpst, LPTSTR lptstr, UINT cchstr) {
  278. return((UINT)GetTimeFormat(LOCALE_USER_DEFAULT,
  279. 0, lpst, NULL, lptstr, cchstr));
  280. }
  281. /***************************************************************************
  282. Name : FormatDate
  283. Purpose : Format a date string for the locale
  284. Parameters: lpst -> system time/date
  285. lptstr -> output buffer
  286. cchstr = size in chars of lpstr
  287. Returns : number of characters used/needed (including null)
  288. Comment : If cchstr < the return value, nothing will be written
  289. to lptstr.
  290. ***************************************************************************/
  291. UINT FormatDate(LPSYSTEMTIME lpst, LPTSTR lptstr, UINT cchstr) {
  292. return((UINT)GetDateFormat(LOCALE_USER_DEFAULT,
  293. 0, lpst, NULL, lptstr, cchstr));
  294. }
  295. /***************************************************************************
  296. Name : BuildDate
  297. Purpose : Put together a formated local date/time string from a MAPI
  298. style time/date value.
  299. Parameters: lptstr -> buffer to fill.
  300. cchstr = size of buffer (or zero if we want to know how
  301. big we need)
  302. DateTime = MAPI date/time value
  303. Returns : count of bytes in date/time string (including null)
  304. Comment : All MAPI times and Win32 FILETIMEs are in Universal Time and
  305. need to be converted to local time before being placed in the
  306. local date/time string.
  307. ***************************************************************************/
  308. UINT BuildDate(LPTSTR lptstr, UINT cchstr, FILETIME DateTime) {
  309. SYSTEMTIME st;
  310. FILETIME ftLocal;
  311. UINT cbRet = 0;
  312. if (! FileTimeToLocalFileTime((LPFILETIME)&DateTime, &ftLocal)) {
  313. DebugTrace("BuildDate: Invalid Date/Time\n");
  314. if (cchstr > (18 * sizeof(TCHAR))) {
  315. lstrcpy(lptstr, TEXT("Invalid Date/Time"));
  316. }
  317. } else {
  318. if (FileTimeToSystemTime(&ftLocal, &st)) {
  319. // Do the date first.
  320. cbRet = FormatDate(&st, lptstr, cchstr);
  321. // Do the time. Start at the null after
  322. // the date, but remember that we've used part
  323. // of the buffer, so the buffer is shorter now.
  324. if (cchstr) {
  325. lstrcat(lptstr, " "); // seperate date and time
  326. }
  327. cbRet+=1;
  328. cbRet += FormatTime(&st, lptstr + cbRet,
  329. cchstr ? cchstr - cbRet : 0);
  330. } else {
  331. DebugTrace("BuildDate: Invalid Date/Time\n");
  332. if (cchstr > (18 * sizeof(TCHAR))) {
  333. lstrcpy(lptstr, TEXT("Invalid Date/Time"));
  334. }
  335. }
  336. }
  337. return(cbRet);
  338. }
  339. /*
  340. * DebugTime
  341. *
  342. * Debug output of UTC filetime or MAPI time.
  343. *
  344. * All MAPI times and Win32 FILETIMEs are in Universal Time.
  345. *
  346. */
  347. void DebugTime(FILETIME Date, PUCHAR lpszFormat) {
  348. UCHAR lpszSubmitDate[MAX_TIME_DATE_STRING];
  349. BuildDate(lpszSubmitDate, sizeof(lpszSubmitDate), Date);
  350. DebugTrace(lpszFormat, lpszSubmitDate);
  351. }
  352. #define RETURN_PROP_CASE(pt) case PROP_ID(pt): return(#pt)
  353. /***************************************************************************
  354. Name : PropTagName
  355. Purpose : Associate a name with a property tag
  356. Parameters: ulPropTag = property tag
  357. Returns : none
  358. Comment : Add new Property ID's as they become known
  359. ***************************************************************************/
  360. PUCHAR PropTagName(ULONG ulPropTag) {
  361. static UCHAR szPropTag[35]; // see string on default
  362. switch (PROP_ID(ulPropTag)) {
  363. RETURN_PROP_CASE(PR_INITIALS);
  364. RETURN_PROP_CASE(PR_SURNAME);
  365. RETURN_PROP_CASE(PR_TITLE);
  366. RETURN_PROP_CASE(PR_TELEX_NUMBER);
  367. RETURN_PROP_CASE(PR_GIVEN_NAME);
  368. RETURN_PROP_CASE(PR_PRIMARY_TELEPHONE_NUMBER);
  369. RETURN_PROP_CASE(PR_PRIMARY_FAX_NUMBER);
  370. RETURN_PROP_CASE(PR_POSTAL_CODE);
  371. RETURN_PROP_CASE(PR_POSTAL_ADDRESS);
  372. RETURN_PROP_CASE(PR_POST_OFFICE_BOX);
  373. RETURN_PROP_CASE(PR_PAGER_TELEPHONE_NUMBER);
  374. RETURN_PROP_CASE(PR_OTHER_TELEPHONE_NUMBER);
  375. RETURN_PROP_CASE(PR_ORGANIZATIONAL_ID_NUMBER);
  376. RETURN_PROP_CASE(PR_OFFICE_LOCATION);
  377. RETURN_PROP_CASE(PR_LOCATION);
  378. RETURN_PROP_CASE(PR_LOCALITY);
  379. RETURN_PROP_CASE(PR_ISDN_NUMBER);
  380. RETURN_PROP_CASE(PR_GOVERNMENT_ID_NUMBER);
  381. RETURN_PROP_CASE(PR_GENERATION);
  382. RETURN_PROP_CASE(PR_DEPARTMENT_NAME);
  383. RETURN_PROP_CASE(PR_COUNTRY);
  384. RETURN_PROP_CASE(PR_COMPANY_NAME);
  385. RETURN_PROP_CASE(PR_COMMENT);
  386. RETURN_PROP_CASE(PR_CELLULAR_TELEPHONE_NUMBER);
  387. RETURN_PROP_CASE(PR_CAR_TELEPHONE_NUMBER);
  388. RETURN_PROP_CASE(PR_CALLBACK_TELEPHONE_NUMBER);
  389. RETURN_PROP_CASE(PR_BUSINESS2_TELEPHONE_NUMBER);
  390. RETURN_PROP_CASE(PR_BUSINESS_TELEPHONE_NUMBER);
  391. RETURN_PROP_CASE(PR_BUSINESS_FAX_NUMBER);
  392. RETURN_PROP_CASE(PR_ASSISTANT_TELEPHONE_NUMBER);
  393. RETURN_PROP_CASE(PR_ASSISTANT);
  394. RETURN_PROP_CASE(PR_ACCOUNT);
  395. RETURN_PROP_CASE(PR_TEMPLATEID);
  396. RETURN_PROP_CASE(PR_DETAILS_TABLE);
  397. RETURN_PROP_CASE(PR_SEARCH_KEY);
  398. RETURN_PROP_CASE(PR_LAST_MODIFICATION_TIME);
  399. RETURN_PROP_CASE(PR_CREATION_TIME);
  400. RETURN_PROP_CASE(PR_ENTRYID);
  401. RETURN_PROP_CASE(PR_RECORD_KEY);
  402. RETURN_PROP_CASE(PR_MAPPING_SIGNATURE);
  403. RETURN_PROP_CASE(PR_OBJECT_TYPE);
  404. RETURN_PROP_CASE(PR_ROWID);
  405. RETURN_PROP_CASE(PR_ADDRTYPE);
  406. RETURN_PROP_CASE(PR_DISPLAY_NAME);
  407. RETURN_PROP_CASE(PR_EMAIL_ADDRESS);
  408. RETURN_PROP_CASE(PR_DEPTH);
  409. RETURN_PROP_CASE(PR_ROW_TYPE);
  410. RETURN_PROP_CASE(PR_RADIO_TELEPHONE_NUMBER);
  411. RETURN_PROP_CASE(PR_HOME_TELEPHONE_NUMBER);
  412. RETURN_PROP_CASE(PR_INSTANCE_KEY);
  413. RETURN_PROP_CASE(PR_DISPLAY_TYPE);
  414. RETURN_PROP_CASE(PR_RECIPIENT_TYPE);
  415. RETURN_PROP_CASE(PR_CONTAINER_FLAGS);
  416. RETURN_PROP_CASE(PR_DEF_CREATE_DL);
  417. RETURN_PROP_CASE(PR_DEF_CREATE_MAILUSER);
  418. RETURN_PROP_CASE(PR_CONTACT_ADDRTYPES);
  419. RETURN_PROP_CASE(PR_CONTACT_DEFAULT_ADDRESS_INDEX);
  420. RETURN_PROP_CASE(PR_CONTACT_EMAIL_ADDRESSES);
  421. RETURN_PROP_CASE(PR_HOME_ADDRESS_CITY);
  422. RETURN_PROP_CASE(PR_HOME_ADDRESS_COUNTRY);
  423. RETURN_PROP_CASE(PR_HOME_ADDRESS_POSTAL_CODE);
  424. RETURN_PROP_CASE(PR_HOME_ADDRESS_STATE_OR_PROVINCE);
  425. RETURN_PROP_CASE(PR_HOME_ADDRESS_STREET);
  426. RETURN_PROP_CASE(PR_HOME_ADDRESS_POST_OFFICE_BOX);
  427. RETURN_PROP_CASE(PR_MIDDLE_NAME);
  428. RETURN_PROP_CASE(PR_NICKNAME);
  429. RETURN_PROP_CASE(PR_PERSONAL_HOME_PAGE);
  430. RETURN_PROP_CASE(PR_BUSINESS_HOME_PAGE);
  431. RETURN_PROP_CASE(PR_MHS_COMMON_NAME);
  432. RETURN_PROP_CASE(PR_SEND_RICH_INFO);
  433. RETURN_PROP_CASE(PR_TRANSMITABLE_DISPLAY_NAME);
  434. RETURN_PROP_CASE(PR_STATE_OR_PROVINCE);
  435. RETURN_PROP_CASE(PR_STREET_ADDRESS);
  436. default:
  437. wsprintf(szPropTag, "Unknown property tag 0x%x",
  438. PROP_ID(ulPropTag));
  439. return(szPropTag);
  440. }
  441. }
  442. /***************************************************************************
  443. Name : DebugPropTagArray
  444. Purpose : Displays MAPI property tags from a counted array
  445. Parameters: lpPropArray -> property array
  446. pszObject -> object string (ie "Message", "Recipient", etc)
  447. Returns : none
  448. Comment :
  449. ***************************************************************************/
  450. void _DebugPropTagArray(LPSPropTagArray lpPropArray, PUCHAR pszObject) {
  451. DWORD i;
  452. PUCHAR lpType;
  453. if (lpPropArray == NULL) {
  454. DebugTrace("Empty %s property tag array.\n", pszObject ? pszObject : szNULL);
  455. return;
  456. }
  457. DebugTrace("=======================================\n");
  458. DebugTrace("+ Enumerating %u %s property tags:\n", lpPropArray->cValues,
  459. pszObject ? pszObject : szNULL);
  460. for (i = 0; i < lpPropArray->cValues ; i++) {
  461. DebugTrace("---------------------------------------\n");
  462. #if FALSE
  463. DebugTrace("PropTag:0x%08x, ID:0x%04x, PT:0x%04x\n",
  464. lpPropArray->aulPropTag[i],
  465. lpPropArray->aulPropTag[i] >> 16,
  466. lpPropArray->aulPropTag[i] & 0xffff);
  467. #endif
  468. switch (lpPropArray->aulPropTag[i] & 0xffff) {
  469. case PT_STRING8:
  470. lpType = "STRING8";
  471. break;
  472. case PT_LONG:
  473. lpType = "LONG";
  474. break;
  475. case PT_I2:
  476. lpType = "I2";
  477. break;
  478. case PT_ERROR:
  479. lpType = "ERROR";
  480. break;
  481. case PT_BOOLEAN:
  482. lpType = "BOOLEAN";
  483. break;
  484. case PT_R4:
  485. lpType = "R4";
  486. break;
  487. case PT_DOUBLE:
  488. lpType = "DOUBLE";
  489. break;
  490. case PT_CURRENCY:
  491. lpType = "CURRENCY";
  492. break;
  493. case PT_APPTIME:
  494. lpType = "APPTIME";
  495. break;
  496. case PT_SYSTIME:
  497. lpType = "SYSTIME";
  498. break;
  499. case PT_UNICODE:
  500. lpType = "UNICODE";
  501. break;
  502. case PT_CLSID:
  503. lpType = "CLSID";
  504. break;
  505. case PT_BINARY:
  506. lpType = "BINARY";
  507. break;
  508. case PT_I8:
  509. lpType = "PT_I8";
  510. break;
  511. case PT_MV_I2:
  512. lpType = "MV_I2";
  513. break;
  514. case PT_MV_LONG:
  515. lpType = "MV_LONG";
  516. break;
  517. case PT_MV_R4:
  518. lpType = "MV_R4";
  519. break;
  520. case PT_MV_DOUBLE:
  521. lpType = "MV_DOUBLE";
  522. break;
  523. case PT_MV_CURRENCY:
  524. lpType = "MV_CURRENCY";
  525. break;
  526. case PT_MV_APPTIME:
  527. lpType = "MV_APPTIME";
  528. break;
  529. case PT_MV_SYSTIME:
  530. lpType = "MV_SYSTIME";
  531. break;
  532. case PT_MV_BINARY:
  533. lpType = "MV_BINARY";
  534. break;
  535. case PT_MV_STRING8:
  536. lpType = "MV_STRING8";
  537. break;
  538. case PT_MV_UNICODE:
  539. lpType = "MV_UNICODE";
  540. break;
  541. case PT_MV_CLSID:
  542. lpType = "MV_CLSID";
  543. break;
  544. case PT_MV_I8:
  545. lpType = "MV_I8";
  546. break;
  547. case PT_NULL:
  548. lpType = "NULL";
  549. break;
  550. case PT_OBJECT:
  551. lpType = "OBJECT";
  552. break;
  553. default:
  554. DebugTrace("<Unknown Property Type>");
  555. break;
  556. }
  557. DebugTrace("%s\t%s\n", PropTagName(lpPropArray->aulPropTag[i]), lpType);
  558. }
  559. }
  560. /***************************************************************************
  561. Name : DebugProperties
  562. Purpose : Displays MAPI properties in a property list
  563. Parameters: lpProps -> property list
  564. cProps = count of properties
  565. pszObject -> object string (ie "Message", "Recipient", etc)
  566. Returns : none
  567. Comment : Add new Property ID's as they become known
  568. ***************************************************************************/
  569. void _DebugProperties(LPSPropValue lpProps, DWORD cProps, PUCHAR pszObject) {
  570. DWORD i, j;
  571. DebugTrace("=======================================\n");
  572. DebugTrace("+ Enumerating %u %s properties:\n", cProps,
  573. pszObject ? pszObject : szNULL);
  574. for (i = 0; i < cProps ; i++) {
  575. DebugTrace("---------------------------------------\n");
  576. #if FALSE
  577. DebugTrace("PropTag:0x%08x, ID:0x%04x, PT:0x%04x\n",
  578. lpProps[i].ulPropTag,
  579. lpProps[i].ulPropTag >> 16,
  580. lpProps[i].ulPropTag & 0xffff);
  581. #endif
  582. DebugTrace("%s\n", PropTagName(lpProps[i].ulPropTag));
  583. switch (lpProps[i].ulPropTag & 0xffff) {
  584. case PT_STRING8:
  585. if (lstrlen(lpProps[i].Value.lpszA) < 1024) {
  586. DebugTrace("STRING8 Value:\"%s\"\n", lpProps[i].Value.lpszA);
  587. } else {
  588. DebugTrace("STRING8 Value is too long to display\n");
  589. }
  590. break;
  591. case PT_LONG:
  592. DebugTrace("LONG Value:%u\n", lpProps[i].Value.l);
  593. break;
  594. case PT_I2:
  595. DebugTrace("I2 Value:%u\n", lpProps[i].Value.i);
  596. break;
  597. case PT_ERROR:
  598. DebugTrace("ERROR Value: 0x%08x\n", lpProps[i].Value.err);
  599. break;
  600. case PT_BOOLEAN:
  601. DebugTrace("BOOLEAN Value:%s\n", lpProps[i].Value.b ?
  602. "TRUE" : "FALSE");
  603. break;
  604. case PT_R4:
  605. DebugTrace("R4 Value\n");
  606. break;
  607. case PT_DOUBLE:
  608. DebugTrace("DOUBLE Value\n");
  609. break;
  610. case PT_CURRENCY:
  611. DebugTrace("CURRENCY Value\n");
  612. break;
  613. case PT_APPTIME:
  614. DebugTrace("APPTIME Value\n");
  615. break;
  616. case PT_SYSTIME:
  617. DebugTime(lpProps[i].Value.ft, "SYSTIME Value:%s\n");
  618. break;
  619. case PT_UNICODE:
  620. DebugTrace("UNICODE Value\n");
  621. break;
  622. case PT_CLSID:
  623. DebugTrace("CLSID Value\n");
  624. break;
  625. case PT_BINARY:
  626. DebugTrace("BINARY Value %u bytes:\n", lpProps[i].Value.bin.cb);
  627. DebugBinary(lpProps[i].Value.bin.cb, lpProps[i].Value.bin.lpb);
  628. break;
  629. case PT_I8:
  630. DebugTrace("LARGE_INTEGER Value\n");
  631. break;
  632. case PT_MV_I2:
  633. DebugTrace("MV_I2 Value\n");
  634. break;
  635. case PT_MV_LONG:
  636. DebugTrace("MV_LONG Value\n");
  637. break;
  638. case PT_MV_R4:
  639. DebugTrace("MV_R4 Value\n");
  640. break;
  641. case PT_MV_DOUBLE:
  642. DebugTrace("MV_DOUBLE Value\n");
  643. break;
  644. case PT_MV_CURRENCY:
  645. DebugTrace("MV_CURRENCY Value\n");
  646. break;
  647. case PT_MV_APPTIME:
  648. DebugTrace("MV_APPTIME Value\n");
  649. break;
  650. case PT_MV_SYSTIME:
  651. DebugTrace("MV_SYSTIME Value\n");
  652. break;
  653. case PT_MV_BINARY:
  654. DebugTrace("MV_BINARY with %u values\n", lpProps[i].Value.MVbin.cValues);
  655. for (j = 0; j < lpProps[i].Value.MVbin.cValues; j++) {
  656. DebugTrace("BINARY Value %u: %u bytes\n", j, lpProps[i].Value.MVbin.lpbin[j].cb);
  657. DebugBinary(lpProps[i].Value.MVbin.lpbin[j].cb, lpProps[i].Value.MVbin.lpbin[j].lpb);
  658. }
  659. break;
  660. case PT_MV_STRING8:
  661. DebugTrace("MV_STRING8 with %u values\n", lpProps[i].Value.MVszA.cValues);
  662. for (j = 0; j < lpProps[i].Value.MVszA.cValues; j++) {
  663. if (lstrlen(lpProps[i].Value.MVszA.lppszA[j]) < 1024) {
  664. DebugTrace("STRING8 Value:\"%s\"\n", lpProps[i].Value.MVszA.lppszA[j]);
  665. } else {
  666. DebugTrace("STRING8 Value is too long to display\n");
  667. }
  668. }
  669. break;
  670. case PT_MV_UNICODE:
  671. DebugTrace("MV_UNICODE Value\n");
  672. break;
  673. case PT_MV_CLSID:
  674. DebugTrace("MV_CLSID Value\n");
  675. break;
  676. case PT_MV_I8:
  677. DebugTrace("MV_I8 Value\n");
  678. break;
  679. case PT_NULL:
  680. DebugTrace("NULL Value\n");
  681. break;
  682. case PT_OBJECT:
  683. DebugTrace("OBJECT Value\n");
  684. break;
  685. default:
  686. DebugTrace("Unknown Property Type\n");
  687. break;
  688. }
  689. }
  690. }
  691. /***************************************************************************
  692. Name : DebugADRLIST
  693. Purpose : Displays structure of an ADRLIST including properties
  694. Parameters: lpAdrList -> ADRLSIT to show
  695. lpszTitle = string to identify this dump
  696. Returns : none
  697. Comment :
  698. ***************************************************************************/
  699. void _DebugADRLIST(LPADRLIST lpAdrList, LPTSTR lpszTitle) {
  700. ULONG i;
  701. TCHAR szTitle[250];
  702. for (i = 0; i < lpAdrList->cEntries; i++) {
  703. wsprintf(szTitle, "%s : Entry %u", lpszTitle, i);
  704. _DebugProperties(lpAdrList->aEntries[i].rgPropVals,
  705. lpAdrList->aEntries[i].cValues, szTitle);
  706. }
  707. }
  708. /***************************************************************************
  709. Name : DebugObjectProps
  710. Purpose : Displays MAPI properties of an object
  711. Parameters: lpObject -> object to dump
  712. Label = string to identify this prop dump
  713. Returns : none
  714. Comment :
  715. ***************************************************************************/
  716. void _DebugObjectProps(LPMAPIPROP lpObject, LPTSTR Label) {
  717. DWORD cProps = 0;
  718. LPSPropValue lpProps = NULL;
  719. HRESULT hr = hrSuccess;
  720. SCODE sc = SUCCESS_SUCCESS;
  721. hr = lpObject->lpVtbl->GetProps(lpObject, NULL, 0, &cProps, &lpProps);
  722. switch (sc = GetScode(hr)) {
  723. case SUCCESS_SUCCESS:
  724. break;
  725. case MAPI_W_ERRORS_RETURNED:
  726. DebugTrace("GetProps -> Errors Returned\n");
  727. break;
  728. default:
  729. DebugTrace("GetProps -> Error 0x%x\n", sc);
  730. return;
  731. }
  732. _DebugProperties(lpProps, cProps, Label);
  733. FreeBufferAndNull(&lpProps);
  734. }
  735. /*
  736. * Destroys an SRowSet structure.
  737. */
  738. STDAPI_(void)
  739. FreeProws(LPSRowSet prows)
  740. {
  741. ULONG irow;
  742. if (!prows)
  743. return;
  744. for (irow = 0; irow < prows->cRows; ++irow)
  745. WABFreeBuffer(prows->aRow[irow].lpProps);
  746. WABFreeBuffer(prows);
  747. }
  748. /***************************************************************************
  749. Name : DebugMapiTable
  750. Purpose : Displays structure of a MAPITABLE including properties
  751. Parameters: lpTable -> MAPITABLE to display
  752. Returns : none
  753. Comment : Don't sort the columns or rows here. This routine should
  754. not produce side effects in the table.
  755. ***************************************************************************/
  756. void _DebugMapiTable(LPMAPITABLE lpTable) {
  757. UCHAR szTemp[30]; // plenty for "ROW %u"
  758. ULONG ulCount;
  759. WORD wIndex;
  760. LPSRowSet lpsRow = NULL;
  761. ULONG ulCurrentRow = (ULONG)-1;
  762. ULONG ulNum, ulDen, lRowsSeeked;
  763. DebugTrace("=======================================\n");
  764. DebugTrace("+ Dump of MAPITABLE at 0x%x:\n", lpTable);
  765. DebugTrace("---------------------------------------\n");
  766. // How big is the table?
  767. lpTable->lpVtbl->GetRowCount(lpTable, 0, &ulCount);
  768. DebugTrace("Table contains %u rows\n", ulCount);
  769. // Save the current position in the table
  770. lpTable->lpVtbl->QueryPosition(lpTable, &ulCurrentRow, &ulNum, &ulDen);
  771. // Display the properties for each row in the table
  772. for (wIndex = 0; wIndex < ulCount; wIndex++) {
  773. // Get the next row
  774. lpTable->lpVtbl->QueryRows(lpTable, 1, 0, &lpsRow);
  775. if (lpsRow) {
  776. // Assert(lpsRow->cRows == 1); // should have exactly one row
  777. wsprintf(szTemp, "ROW %u", wIndex);
  778. DebugProperties(lpsRow->aRow[0].lpProps,
  779. lpsRow->aRow[0].cValues, szTemp);
  780. FreeProws(lpsRow);
  781. }
  782. }
  783. // Restore the current position for the table
  784. if (ulCurrentRow != (ULONG)-1) {
  785. lpTable->lpVtbl->SeekRow(lpTable, BOOKMARK_BEGINNING, ulCurrentRow,
  786. &lRowsSeeked);
  787. }
  788. }
  789. /*
  790. * DebugTrace -- printf to the debugger console or debug output file
  791. * Takes printf style arguments.
  792. * Expects newline characters at the end of the string.
  793. */
  794. VOID FAR CDECL DebugTrace(LPSTR lpszFmt, ...) {
  795. va_list marker;
  796. TCHAR String[1100];
  797. va_start(marker, lpszFmt);
  798. wvsprintf(String, lpszFmt, marker);
  799. OutputDebugString(String);
  800. }