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.

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