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.

1931 lines
60 KiB

  1. #include "wabtest.h"
  2. #include <assert.h>
  3. #include "resource.h"
  4. #include "..\luieng.dll\luieng.h"
  5. extern LUIOUT LUIOut;
  6. extern BOOL bLUIInit;
  7. #ifdef WAB
  8. extern LPWABOBJECT lpWABObject; //Global handle to session
  9. #endif
  10. #ifdef PAB
  11. MAPIINIT_0 mapiinit = {
  12. MAPI_INIT_VERSION,
  13. MAPI_MULTITHREAD_NOTIFICATIONS
  14. };
  15. #endif //PAB
  16. PropTableEntry PropTable[] = {
  17. PR_7BIT_DISPLAY_NAME, "PR_7BIT_DISPLAY_NAME", 0,
  18. PR_ACCOUNT, "PR_ACCOUNT", 0,
  19. PR_ADDRTYPE, "PR_ADDRTYPE", 0,
  20. PR_ALTERNATE_RECIPIENT, "PR_ALTERNATE_RECIPIENT", 0,
  21. PR_ASSISTANT, "PR_ASSISTANT", 0,
  22. PR_ASSISTANT_TELEPHONE_NUMBER, "PR_ASSISTANT_TELEPHONE_NUMBER", 0,
  23. PR_BEEPER_TELEPHONE_NUMBER, "PR_BEEPER_TELEPHONE_NUMBER", 0,
  24. PR_BIRTHDAY, "PR_BIRTHDAY", 0,
  25. PR_BUSINESS_ADDRESS_CITY, "PR_BUSINESS_ADDRESS_CITY", 0,
  26. PR_BUSINESS_ADDRESS_COUNTRY, "PR_BUSINESS_ADDRESS_COUNTRY", 0,
  27. PR_BUSINESS_ADDRESS_POST_OFFICE_BOX, "PR_BUSINESS_ADDRESS_POST_OFFICE_BOX", 0,
  28. PR_BUSINESS_ADDRESS_POSTAL_CODE, "PR_BUSINESS_ADDRESS_POSTAL_CODE", 0,
  29. PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE, "PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE", 0,
  30. PR_BUSINESS_ADDRESS_STREET, "PR_BUSINESS_ADDRESS_STREET", 0,
  31. PR_BUSINESS_FAX_NUMBER, "PR_BUSINESS_FAX_NUMBER", 0,
  32. PR_BUSINESS_HOME_PAGE, "PR_BUSINESS_HOME_PAGE", 0,
  33. PR_BUSINESS_TELEPHONE_NUMBER, "PR_BUSINESS_TELEPHONE_NUMBER", 0,
  34. PR_BUSINESS2_TELEPHONE_NUMBER, "PR_BUSINESS2_TELEPHONE_NUMBER", 0,
  35. PR_CALLBACK_TELEPHONE_NUMBER, "PR_CALLBACK_TELEPHONE_NUMBER", 0,
  36. PR_CAR_TELEPHONE_NUMBER, "PR_CAR_TELEPHONE_NUMBER", 0,
  37. PR_CELLULAR_TELEPHONE_NUMBER, "PR_CELLULAR_TELEPHONE_NUMBER", 0,
  38. PR_CHILDRENS_NAMES, "PR_CHILDRENS_NAMES", 0,
  39. PR_COMMENT, "PR_COMMENT", 0,
  40. PR_COMPANY_MAIN_PHONE_NUMBER, "PR_COMPANY_MAIN_PHONE_NUMBER", 0,
  41. PR_COMPANY_NAME, "PR_COMPANY_NAME", 0,
  42. PR_COMPUTER_NETWORK_NAME, "PR_COMPUTER_NETWORK_NAME", 0,
  43. PR_CONTACT_ADDRTYPES, "PR_CONTACT_ADDRTYPES", 0,
  44. PR_CONTACT_DEFAULT_ADDRESS_INDEX, "PR_CONTACT_DEFAULT_ADDRESS_INDEX", 0,
  45. PR_CONTACT_EMAIL_ADDRESSES, "PR_CONTACT_EMAIL_ADDRESSES", 0,
  46. PR_CONTACT_ENTRYIDS, "PR_CONTACT_ENTRYIDS", 0,
  47. PR_CONTACT_VERSION, "PR_CONTACT_VERSION", 0,
  48. PR_CONVERSION_PROHIBITED, "PR_CONVERSION_PROHIBITED", 0,
  49. PR_COUNTRY, "PR_COUNTRY", 0,
  50. PR_CUSTOMER_ID, "PR_CUSTOMER_ID", 0,
  51. PR_DEPARTMENT_NAME, "PR_DEPARTMENT_NAME", 0,
  52. PR_DISCLOSE_RECIPIENTS, "PR_DISCLOSE_RECIPIENTS", 0,
  53. PR_DISPLAY_NAME, "PR_DISPLAY_NAME", 0,
  54. PR_DISPLAY_NAME_PREFIX, "PR_DISPLAY_NAME_PREFIX", 0,
  55. PR_EMAIL_ADDRESS, "PR_EMAIL_ADDRESS", 0,
  56. PR_ENTRYID, "PR_ENTRYID", 0,
  57. PR_FTP_SITE, "PR_FTP_SITE", 0,
  58. PR_GENDER, "PR_GENDER", 0,
  59. PR_GENERATION, "PR_GENERATION", 0,
  60. PR_GIVEN_NAME, "PR_GIVEN_NAME", 0,
  61. PR_GOVERNMENT_ID_NUMBER, "PR_GOVERNMENT_ID_NUMBER", 0,
  62. PR_HOBBIES, "PR_HOBBIES", 0,
  63. PR_HOME_ADDRESS_CITY, "PR_HOME_ADDRESS_CITY", 0,
  64. PR_HOME_ADDRESS_COUNTRY, "PR_HOME_ADDRESS_COUNTRY", 0,
  65. PR_HOME_ADDRESS_POST_OFFICE_BOX, "PR_HOME_ADDRESS_POST_OFFICE_BOX", 0,
  66. PR_HOME_ADDRESS_POSTAL_CODE, "PR_HOME_ADDRESS_POSTAL_CODE", 0,
  67. PR_HOME_ADDRESS_STATE_OR_PROVINCE, "PR_HOME_ADDRESS_STATE_OR_PROVINCE", 0,
  68. PR_HOME_ADDRESS_STREET, "PR_HOME_ADDRESS_STREET", 0,
  69. PR_HOME_FAX_NUMBER, "PR_HOME_FAX_NUMBER", 0,
  70. PR_HOME_TELEPHONE_NUMBER, "PR_HOME_TELEPHONE_NUMBER", 0,
  71. PR_HOME2_TELEPHONE_NUMBER, "PR_HOME2_TELEPHONE_NUMBER", 0,
  72. PR_INITIALS, "PR_INITIALS", 0,
  73. PR_ISDN_NUMBER, "PR_ISDN_NUMBER", 0,
  74. PR_KEYWORD, "PR_KEYWORD", 0,
  75. PR_LANGUAGE, "PR_LANGUAGE", 0,
  76. PR_LOCALITY, "PR_LOCALITY", 0,
  77. PR_LOCATION, "PR_LOCATION", 0,
  78. PR_MAIL_PERMISSION, "PR_MAIL_PERMISSION", 0,
  79. PR_MANAGER_NAME, "PR_MANAGER_NAME", 0,
  80. PR_MHS_COMMON_NAME, "PR_MHS_COMMON_NAME", 0,
  81. PR_MIDDLE_NAME, "PR_MIDDLE_NAME", 0,
  82. PR_MOBILE_TELEPHONE_NUMBER, "PR_MOBILE_TELEPHONE_NUMBER", 0,
  83. PR_NICKNAME, "PR_NICKNAME", 0,
  84. PR_OBJECT_TYPE, "PR_OBJECT_TYPE", 0,
  85. PR_OFFICE_LOCATION, "PR_OFFICE_LOCATION", 0,
  86. PR_OFFICE_TELEPHONE_NUMBER, "PR_OFFICE_TELEPHONE_NUMBER", 0,
  87. PR_OFFICE2_TELEPHONE_NUMBER, "PR_OFFICE2_TELEPHONE_NUMBER", 0,
  88. PR_ORGANIZATIONAL_ID_NUMBER, "PR_ORGANIZATIONAL_ID_NUMBER", 0,
  89. PR_ORIGINAL_DISPLAY_NAME, "PR_ORIGINAL_DISPLAY_NAME", 0,
  90. PR_ORIGINAL_ENTRYID, "PR_ORIGINAL_ENTRYID", 0,
  91. PR_ORIGINAL_SEARCH_KEY, "PR_ORIGINAL_SEARCH_KEY", 0,
  92. PR_OTHER_ADDRESS_CITY, "PR_OTHER_ADDRESS_CITY", 0,
  93. PR_OTHER_ADDRESS_COUNTRY, "PR_OTHER_ADDRESS_COUNTRY", 0,
  94. PR_OTHER_ADDRESS_POST_OFFICE_BOX, "PR_OTHER_ADDRESS_POST_OFFICE_BOX", 0,
  95. PR_OTHER_ADDRESS_POSTAL_CODE, "PR_OTHER_ADDRESS_POSTAL_CODE", 0,
  96. PR_OTHER_ADDRESS_STATE_OR_PROVINCE, "PR_OTHER_ADDRESS_STATE_OR_PROVINCE", 0,
  97. PR_OTHER_ADDRESS_STREET,"PR_OTHER_ADDRESS_STREET", 0,
  98. PR_OTHER_TELEPHONE_NUMBER, "PR_OTHER_TELEPHONE_NUMBER", 0,
  99. PR_PAGER_TELEPHONE_NUMBER, "PR_PAGER_TELEPHONE_NUMBER", 0,
  100. PR_PERSONAL_HOME_PAGE, "PR_PERSONAL_HOME_PAGE", 0,
  101. PR_POST_OFFICE_BOX, "PR_POST_OFFICE_BOX", 0,
  102. PR_POSTAL_ADDRESS, "PR_POSTAL_ADDRESS", 0,
  103. PR_POSTAL_CODE, "PR_POSTAL_CODE", 0,
  104. PR_PREFERRED_BY_NAME, "PR_PREFERRED_BY_NAME", 0,
  105. PR_PRIMARY_FAX_NUMBER, "PR_PRIMARY_FAX_NUMBER", 0,
  106. PR_PRIMARY_TELEPHONE_NUMBER, "PR_PRIMARY_TELEPHONE_NUMBER", 0,
  107. PR_PROFESSION, "PR_PROFESSION", 0,
  108. PR_RADIO_TELEPHONE_NUMBER, "PR_RADIO_TELEPHONE_NUMBER", 0,
  109. PR_SEND_RICH_INFO, "PR_SEND_RICH_INFO", 0,
  110. PR_SPOUSE_NAME, "PR_SPOUSE_NAME", 0,
  111. PR_STATE_OR_PROVINCE, "PR_STATE_OR_PROVINCE", 0,
  112. PR_STREET_ADDRESS, "PR_STREET_ADDRESS", 0,
  113. PR_SURNAME, "PR_SURNAME", 0,
  114. PR_TELEX_NUMBER, "PR_TELEX_NUMBER", 0,
  115. PR_TITLE, "PR_TITLE", 0,
  116. PR_TRANSMITABLE_DISPLAY_NAME, "PR_TRANSMITABLE_DISPLAY_NAME", 0,
  117. PR_TTYTDD_PHONE_NUMBER, "PR_TTYTDD_PHONE_NUMBER", 0,
  118. PR_USER_CERTIFICATE, "PR_USER_CERTIFICATE", 0,
  119. PR_WEDDING_ANNIVERSARY, "PR_WEDDING_ANNIVERSARY", 0,
  120. PR_USER_X509_CERTIFICATE, "PR_USER_X509_CERTIFICATE", 0,
  121. (ULONG)0, "End of Table", 0
  122. };
  123. HRESULT OpenPABID( IN LPADRBOOK lpAdrBook,
  124. OUT ULONG *lpcbEidPAB,
  125. OUT LPENTRYID *lppEidPAB,
  126. OUT LPABCONT *lppPABCont,
  127. OUT ULONG *lpulObjType)
  128. {
  129. HRESULT hr = hrSuccess;
  130. int retval = TRUE;
  131. *lpulObjType = 0;
  132. if ( (NULL == lpcbEidPAB) ||
  133. (NULL == lppEidPAB) ||
  134. (NULL == lppPABCont) )
  135. return(FALSE);
  136. *lpcbEidPAB = 0;
  137. *lppEidPAB = NULL;
  138. *lppPABCont = NULL;
  139. //
  140. // Get the PAB
  141. //
  142. hr = lpAdrBook->GetPAB(
  143. OUT lpcbEidPAB,
  144. OUT lppEidPAB);
  145. if (HR_FAILED(hr)) {
  146. retval = FALSE;
  147. goto out;
  148. }
  149. if (0 == *lpcbEidPAB) //There is no PAB associated with this profile
  150. {
  151. LUIOut(L2, "Call to GetPAB FAILED. No PAB associated with this profile");
  152. retval = FALSE;
  153. goto out;
  154. }
  155. //
  156. // Open the PAB Container
  157. //
  158. hr = lpAdrBook->OpenEntry(
  159. IN *lpcbEidPAB,
  160. IN *lppEidPAB,
  161. IN NULL, //interface
  162. IN MAPI_MODIFY, //flags
  163. OUT lpulObjType,
  164. OUT (LPUNKNOWN *) lppPABCont);
  165. if (0 == *lpulObjType) {
  166. retval = FALSE;
  167. goto out;
  168. }
  169. out:
  170. return(retval);
  171. }
  172. #ifdef PAB
  173. BOOL MapiInitLogon(OUT LPMAPISESSION * lppMAPISession)
  174. {
  175. HRESULT hr = hrSuccess;
  176. SCODE sc = SUCCESS_SUCCESS;
  177. int retval=TRUE;
  178. char szProfileName[SML_BUF];
  179. hr = MAPIInitialize(IN & mapiinit);
  180. if (hr)
  181. {
  182. if (FAILED (GetScode(hr))) {
  183. LUIOut(L1,"Could not initialize MAPI\n");
  184. retval=FALSE;
  185. }
  186. }
  187. szProfileName[0]='\0';
  188. GetPrivateProfileString("Misc","Profile","",szProfileName,SML_BUF,"c:\\pabtests.ini");
  189. sc = MAPILogonEx(
  190. IN 0, //window handle
  191. IN szProfileName, //Profile Name
  192. IN NULL, //Password
  193. IN MAPI_NEW_SESSION |
  194. MAPI_EXTENDED |
  195. MAPI_LOGON_UI |
  196. MAPI_EXPLICIT_PROFILE |
  197. MAPI_ALLOW_OTHERS |
  198. MAPI_NO_MAIL, //Flags
  199. OUT lppMAPISession); //Session Pointer address
  200. if (FAILED(sc))
  201. {
  202. hr = ResultFromScode(sc);
  203. LUIOut(L1,"Could not start MAPI Session");
  204. retval=FALSE;
  205. }
  206. return retval;
  207. }
  208. #endif //PAB
  209. BOOL GetPropsFromIniBufEntry(LPSTR EntryBuf,ULONG cValues, char (*EntProp)[BIG_BUF])
  210. {
  211. //char szTemp[BIG_BUF];
  212. int j=0;
  213. if (EntryBuf) {
  214. for (int i = 0; i < (int)cValues; i++) {
  215. if ((*EntryBuf) == '"') {
  216. EntryBuf++;
  217. }
  218. j=0;
  219. while ((*EntryBuf)&&((*EntryBuf) != '"')&&(j< BIG_BUF-1)) {
  220. EntProp[i][j]= *EntryBuf;
  221. j++; EntryBuf++;
  222. }
  223. EntProp[i][j]='\0';
  224. if (*EntryBuf) EntryBuf++;
  225. if ((*EntryBuf)&&((*EntryBuf) == ',')) EntryBuf++;
  226. }
  227. return TRUE;
  228. }
  229. else {
  230. for (int i = 0; i < (int)cValues; i++) {
  231. EntProp[i][0]=0;
  232. }
  233. return FALSE;
  234. }
  235. }
  236. HRESULT HrCreateEntryListFromID(
  237. IN LPWABOBJECT lpLocalWABObject,
  238. IN ULONG cbeid, // count of bytes in Entry ID
  239. IN LPENTRYID lpeid, // pointer to Entry ID
  240. OUT LPENTRYLIST FAR *lppEntryList) // pointer to address variable of Entry
  241. // list
  242. {
  243. HRESULT hr = NOERROR;
  244. SCODE sc = 0;
  245. LPVOID lpvSBinaryArray = NULL;
  246. LPVOID lpvSBinary = NULL;
  247. LPVOID lpv = NULL;
  248. if (NULL == lppEntryList) return(FALSE);
  249. *lppEntryList = NULL;
  250. #ifdef PAB
  251. sc = MAPIAllocateBuffer(cbeid, &lpv);
  252. #endif
  253. #ifdef WAB
  254. sc = lpLocalWABObject->AllocateBuffer(cbeid, &lpv);
  255. #endif
  256. if(FAILED(sc))
  257. {
  258. hr = ResultFromScode(sc);
  259. goto cleanup;
  260. }
  261. // Copy entry ID
  262. CopyMemory(lpv, lpeid, cbeid);
  263. #ifdef PAB
  264. sc = MAPIAllocateBuffer(sizeof(SBinary), &lpvSBinary);
  265. #endif
  266. #ifdef WAB
  267. sc = lpLocalWABObject->AllocateBuffer(sizeof(SBinary), &lpvSBinary);
  268. #endif
  269. if(FAILED(sc))
  270. {
  271. hr = ResultFromScode(sc);
  272. goto cleanup;
  273. }
  274. // Initialize SBinary structure
  275. ZeroMemory(lpvSBinary, sizeof(SBinary));
  276. ((LPSBinary)lpvSBinary)->cb = cbeid;
  277. ((LPSBinary)lpvSBinary)->lpb = (LPBYTE)lpv;
  278. #ifdef PAB
  279. sc = MAPIAllocateBuffer(sizeof(SBinaryArray), &lpvSBinaryArray);
  280. #endif
  281. #ifdef WAB
  282. sc = lpLocalWABObject->AllocateBuffer(sizeof(SBinaryArray), &lpvSBinaryArray);
  283. #endif
  284. if(FAILED(sc))
  285. {
  286. hr = ResultFromScode(sc);
  287. goto cleanup;
  288. }
  289. // Initialize SBinaryArray structure
  290. ZeroMemory(lpvSBinaryArray, sizeof(SBinaryArray));
  291. ((SBinaryArray *)lpvSBinaryArray)->cValues = 1;
  292. ((SBinaryArray *)lpvSBinaryArray)->lpbin = (LPSBinary)lpvSBinary;
  293. *lppEntryList = (LPENTRYLIST)lpvSBinaryArray;
  294. cleanup:
  295. if (HR_FAILED(hr))
  296. {
  297. #ifdef PAB
  298. if (lpv)
  299. MAPIFreeBuffer(lpv);
  300. if (lpvSBinary)
  301. MAPIFreeBuffer(lpvSBinary);
  302. if (lpvSBinaryArray)
  303. MAPIFreeBuffer(lpvSBinaryArray);
  304. #endif
  305. #ifdef WAB
  306. if (lpv)
  307. lpLocalWABObject->FreeBuffer(lpv);
  308. if (lpvSBinary)
  309. lpLocalWABObject->FreeBuffer(lpvSBinary);
  310. if (lpvSBinaryArray)
  311. lpLocalWABObject->FreeBuffer(lpvSBinaryArray);
  312. #endif
  313. }
  314. return(hr);
  315. }
  316. HRESULT HrCreateEntryListFromRows(
  317. IN LPWABOBJECT lpLocalWABObject,
  318. IN LPSRowSet far* lppRows,
  319. OUT LPENTRYLIST FAR *lppEntryList) // pointer to address variable of Entry
  320. // list
  321. { LPSRowSet lpRows = *lppRows;
  322. HRESULT hr = NOERROR;
  323. SCODE sc = 0;
  324. SBinaryArray* lpvSBinaryArray = NULL;
  325. ULONG Rows = lpRows->cRows;
  326. unsigned int PropIndex;
  327. ULONG cb;
  328. LPENTRYID lpb;
  329. if (NULL == lppEntryList) return(FALSE);
  330. *lppEntryList = NULL;
  331. if (lpRows) {
  332. // Allocate the SBinaryArray
  333. sc = lpLocalWABObject->AllocateBuffer(sizeof(SBinaryArray), (void**)&lpvSBinaryArray);
  334. if(FAILED(sc))
  335. {
  336. LUIOut(L2, "HrCreateEntryListFromRows: Unable to allocate memory for the SBinaryArray.");
  337. hr = ResultFromScode(sc);
  338. goto cleanup;
  339. }
  340. // Initialize SBinaryArray structure
  341. ZeroMemory(lpvSBinaryArray, sizeof(SBinaryArray));
  342. lpvSBinaryArray->cValues = Rows;
  343. // Allocate the SBinary structures
  344. sc = lpLocalWABObject->AllocateBuffer((Rows*sizeof(SBinary)), (void**)&lpvSBinaryArray->lpbin);
  345. if(FAILED(sc))
  346. {
  347. LUIOut(L2, "HrCreateEntryListFromRows: Unable to allocate memory for the SBinary structures.");
  348. hr = ResultFromScode(sc);
  349. goto cleanup;
  350. }
  351. // Initialize SBinary structure
  352. ZeroMemory(lpvSBinaryArray->lpbin, (Rows*sizeof(SBinary)));
  353. FindPropinRow(&lpRows->aRow[0], // Find which column has the EID
  354. PR_ENTRYID,
  355. &PropIndex);
  356. // Walk through the rows, allocate the lpb and copy over each cbeid and lpb into the entrylist
  357. for (ULONG Row = 0; Row < Rows; Row++) {
  358. cb = lpRows->aRow[Row].lpProps[PropIndex].Value.bin.cb,
  359. lpb = (ENTRYID*)lpRows->aRow[Row].lpProps[PropIndex].Value.bin.lpb,
  360. sc = lpLocalWABObject->AllocateBuffer(cb, (void**)&(lpvSBinaryArray->lpbin[Row].lpb));
  361. if(FAILED(sc))
  362. {
  363. LUIOut(L2, "HrCreateEntryListFromRows: Unable to allocate memory for the SBinary->lpb.");
  364. hr = ResultFromScode(sc);
  365. goto cleanup;
  366. }
  367. // Copy entry ID
  368. lpvSBinaryArray->lpbin[Row].cb = cb;
  369. CopyMemory(lpvSBinaryArray->lpbin[Row].lpb, lpb, cb);
  370. }
  371. *lppEntryList = (LPENTRYLIST)lpvSBinaryArray;
  372. return TRUE;
  373. }
  374. return FALSE;
  375. cleanup:
  376. if (HR_FAILED(hr))
  377. {
  378. for (ULONG Kill=0; Kill<Rows; Kill++) {
  379. if (lpvSBinaryArray->lpbin[Kill].lpb)
  380. lpLocalWABObject->FreeBuffer(lpvSBinaryArray->lpbin[Kill].lpb);
  381. lpvSBinaryArray->lpbin[Kill].lpb = NULL;
  382. }
  383. if (lpvSBinaryArray->lpbin)
  384. lpLocalWABObject->FreeBuffer(lpvSBinaryArray->lpbin);
  385. if (lpvSBinaryArray)
  386. lpLocalWABObject->FreeBuffer(lpvSBinaryArray);
  387. }
  388. return(hr);
  389. }
  390. BOOL FreeEntryList(IN LPWABOBJECT lpLocalWABObject,
  391. IN LPENTRYLIST *lppEntryList) // pointer to address variable of Entry
  392. // list
  393. { LPENTRYLIST lpEntryList = *lppEntryList;
  394. if (lpEntryList == NULL) return FALSE;
  395. for (ULONG Row = 0; Row < lpEntryList->cValues; Row++) {
  396. if (lpEntryList->lpbin[Row].lpb)
  397. lpLocalWABObject->FreeBuffer(lpEntryList->lpbin[Row].lpb);
  398. }
  399. if (lpEntryList->lpbin)
  400. lpLocalWABObject->FreeBuffer(lpEntryList->lpbin);
  401. if (lpEntryList)
  402. lpLocalWABObject->FreeBuffer(lpEntryList);
  403. *lppEntryList = NULL;
  404. return TRUE;
  405. }
  406. BOOL FreeRows(IN LPWABOBJECT lpLocalWABObject,
  407. IN LPSRowSet far* lppRows)
  408. { LPSRowSet lpRows = *lppRows;
  409. #ifdef WAB
  410. if (lpRows) {
  411. for (ULONG Kill = 0; Kill < lpRows->cRows; Kill++)
  412. lpLocalWABObject->FreeBuffer(lpRows->aRow[Kill].lpProps);
  413. lpLocalWABObject->FreeBuffer(lpRows);
  414. *lppRows = NULL;
  415. #endif
  416. return TRUE;
  417. }
  418. return FALSE;
  419. }
  420. BOOL DisplayRows(IN LPSRowSet lpRows)
  421. { ULONG Rows, Columns;
  422. WORD* Key;
  423. if (lpRows) {
  424. Rows = lpRows->cRows;
  425. LUIOut(L2, "%u rows found.", Rows);
  426. for (ULONG Row = 0; Row < Rows; Row++) {
  427. Columns = lpRows->aRow[Row].cValues;
  428. LUIOut(L3, "Row %u contains %u columns.", Row, Columns);
  429. for (ULONG Column = 0; Column < Columns; Column++) {
  430. switch(lpRows->aRow[Row].lpProps[Column].ulPropTag) {
  431. case PR_ADDRTYPE:
  432. LUIOut(L3, "Column %u: PR_ADDRTYPE = %s", Column, lpRows->aRow[Row].lpProps[Column].Value.LPSZ);
  433. break;
  434. case PR_DISPLAY_NAME:
  435. LUIOut(L3, "Column %u: PR_DISPLAY_NAME = %s", Column, lpRows->aRow[Row].lpProps[Column].Value.LPSZ);
  436. break;
  437. case PR_DISPLAY_TYPE:
  438. switch(lpRows->aRow[Row].lpProps[Column].Value.l) {
  439. case DT_AGENT:
  440. LUIOut(L3, "Column %u: PR_DISPLAY_TYPE = DT_AGENT", Column);
  441. break;
  442. case DT_DISTLIST:
  443. LUIOut(L3, "Column %u: PR_DISPLAY_TYPE = DT_DISTLIST", Column);
  444. break;
  445. case DT_FORUM:
  446. LUIOut(L3, "Column %u: PR_DISPLAY_TYPE = DT_FORUM", Column);
  447. break;
  448. case DT_MAILUSER:
  449. LUIOut(L3, "Column %u: PR_DISPLAY_TYPE = DT_MAILUSER", Column);
  450. break;
  451. case DT_ORGANIZATION:
  452. LUIOut(L3, "Column %u: PR_DISPLAY_TYPE = DT_ORGANIZATION", Column);
  453. break;
  454. case DT_PRIVATE_DISTLIST:
  455. LUIOut(L3, "Column %u: PR_DISPLAY_TYPE = DT_PRIVATE_DISTLIST", Column);
  456. break;
  457. case DT_REMOTE_MAILUSER:
  458. LUIOut(L3, "Column %u: PR_DISPLAY_TYPE = DT_REMOTE_MAILUSER", Column);
  459. break;
  460. default:
  461. LUIOut(L3, "Column %u: PR_DISPLAY_TYPE = UNKNOWN!! [0x%x]", Column,
  462. lpRows->aRow[Row].lpProps[Column].Value.l);
  463. }
  464. break;
  465. case PR_ENTRYID:
  466. LUIOut(L3, "Column %u: PR_ENTRYID", Column);
  467. break;
  468. case PR_INSTANCE_KEY:
  469. Key = (WORD*)lpRows->aRow[Row].lpProps[Column].Value.bin.lpb;
  470. LUIOut(L3, "Column %u: PR_INSTANCE_KEY = 0x%x%x%x%x%x%x%x%x", Column,
  471. Key[0],Key[2],Key[4],Key[6],Key[8],Key[10],Key[12],Key[14]);
  472. break;
  473. case PR_OBJECT_TYPE:
  474. switch(lpRows->aRow[Row].lpProps[Column].Value.l) {
  475. case MAPI_ABCONT:
  476. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_ABCONT", Column);
  477. break;
  478. case MAPI_ADDRBOOK:
  479. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_ADDRBOOK", Column);
  480. break;
  481. case MAPI_ATTACH:
  482. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_ATTACH", Column);
  483. break;
  484. case MAPI_DISTLIST:
  485. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_DISTLIST", Column);
  486. break;
  487. case MAPI_FOLDER:
  488. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_FOLDER", Column);
  489. break;
  490. case MAPI_FORMINFO:
  491. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_FORMINFO", Column);
  492. break;
  493. case MAPI_MAILUSER:
  494. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_MAILUSER", Column);
  495. break;
  496. case MAPI_MESSAGE:
  497. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_MESSAGE", Column);
  498. break;
  499. case MAPI_PROFSECT:
  500. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_PROFSECT", Column);
  501. break;
  502. case MAPI_STATUS:
  503. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_STATUS", Column);
  504. break;
  505. case MAPI_STORE:
  506. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = MAPI_STORE", Column);
  507. break;
  508. default:
  509. LUIOut(L3, "Column %u: PR_OBJECT_TYPE = UNKNOWN!! [0x%x]", Column,
  510. lpRows->aRow[Row].lpProps[Column].Value.l);
  511. }
  512. break;
  513. case PR_RECORD_KEY:
  514. LUIOut(L3, "Column %u: PR_RECORD_KEY", Column);
  515. break;
  516. default:
  517. LUIOut(L3, "Column %u: Property tag UNKNOWN!! [0x%x]", Column,
  518. lpRows->aRow[Row].lpProps[Column].ulPropTag);
  519. }
  520. }
  521. }
  522. return TRUE;
  523. }
  524. return FALSE;
  525. }
  526. BOOL ValidateAdrList(LPADRLIST lpAdrList, ULONG cEntries)
  527. {
  528. int i = 0;
  529. int idx = 0;
  530. int cMaxProps = 0;
  531. for(i=0; i<(int) cEntries; ++i)
  532. {
  533. cMaxProps = (int)lpAdrList->aEntries[i].cValues;
  534. //Check to see if Email Address Type exists
  535. idx=0;
  536. while(lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_ADDRTYPE )
  537. {
  538. idx++;
  539. if(idx == cMaxProps) {
  540. LUIOut(L4, "PR_ADDRTYPE was not found in the lpAdrList");
  541. return FALSE;
  542. }
  543. }
  544. //Check to see if Email Address exists
  545. idx=0;
  546. while(lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_OBJECT_TYPE )
  547. {
  548. idx++;
  549. if(idx == cMaxProps) {
  550. LUIOut(L4, "PR_OBJECT_TYPE was not found in the lpAdrList");
  551. return FALSE;
  552. }
  553. }
  554. //Check to see if Email Address exists
  555. idx=0;
  556. while(lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_DISPLAY_TYPE )
  557. {
  558. idx++;
  559. if(idx == cMaxProps) {
  560. LUIOut(L4, "PR_DISPLAY_TYPE was not found in the lpAdrList");
  561. return FALSE;
  562. }
  563. }
  564. //Check to see if Display Name exists
  565. idx=0;
  566. while(lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_DISPLAY_NAME )
  567. {
  568. idx++;
  569. if(idx == cMaxProps) {
  570. LUIOut(L4, "PR_DISPLAY_NAME was not found in the lpAdrList");
  571. return FALSE;
  572. }
  573. }
  574. LUIOut(L4,"Display Name: %s",lpAdrList->aEntries[i].rgPropVals[idx].Value.LPSZ);
  575. //Check to see if EntryID exists
  576. idx=0;
  577. while(lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_ENTRYID )
  578. {
  579. idx++;
  580. if(idx == cMaxProps) {
  581. LUIOut(L4, "PR_ENTRYID was not found in the lpAdrList");
  582. return FALSE;
  583. }
  584. }
  585. }
  586. return TRUE;
  587. }
  588. //
  589. // PROCEDURE: VerifyResolvedAdrList
  590. // DESCRIPTION: Walk through a lpAdrList looking for PR_DISPLAY_NAME, PR_EMAIL_ADDRESS,
  591. // PR_ADDRTYPE, PR_ENTRYID, and PR_OBJECT_TYPE. Each EID is sanity checked
  592. // (lpb != NULL and cb != 0) and valid EIDs are passed to OpenEntry with
  593. // a MailUser interface specified. If OpenEntry succedes, we assume the EID
  594. // is a valid MailUser ID.
  595. //
  596. // PARAMETERS: LPADRLIST lpAdrList
  597. // char* lpszInput - can be NULL to bypass match checking
  598. //
  599. BOOL VerifyResolvedAdrList(LPADRLIST lpAdrList, char* lpszInput)
  600. {
  601. extern LPADRBOOK glbllpAdrBook;
  602. int i = 0, idx = 0, cMaxProps = 0;
  603. BOOL Found = FALSE, retval = TRUE, localretval = TRUE;
  604. ULONG cEntries = lpAdrList->cEntries;
  605. ULONG cbLookupEID, ulObjType;
  606. LPENTRYID lpLookupEID;
  607. HRESULT hr;
  608. LPUNKNOWN lpUnk=NULL;
  609. LPADRBOOK lpAdrBook;
  610. LPCIID lpcIID;
  611. LPVOID Reserved1=NULL;
  612. DWORD Reserved2=0;
  613. // LPWABOBJECT lpWABObject2;
  614. /* kludge to work around multiple wabopen/release bug, storing adrbook ptr
  615. in a global variable
  616. hr = WABOpen(&lpAdrBook, &lpWABObject2, Reserved1, Reserved2);
  617. if (hr != S_OK) {
  618. LUIOut(L4, "WABOpen FAILED. Couldn't obtain IAdrBook.");
  619. retval = FALSE;
  620. }
  621. */
  622. #ifdef WAB
  623. lpAdrBook = glbllpAdrBook;
  624. lpAdrBook->AddRef();
  625. #endif //WAB
  626. // Walk through each AdrList entry
  627. for(i=0; ((i<(int) lpAdrList->cEntries) && (!Found)); ++i) {
  628. LUIOut(L3, "Searching Entry #%i out of %i", i+1, cEntries);
  629. cMaxProps = (int)lpAdrList->aEntries[i].cValues;
  630. //Check to see if Display Name exists
  631. idx=0; localretval = TRUE;
  632. while((lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_DISPLAY_NAME )
  633. && localretval) {
  634. idx++;
  635. if(idx == cMaxProps) {
  636. LUIOut(L4, "PR_DISPLAY_NAME was not found in lpAdrList entry #%i",i);
  637. localretval = FALSE; retval = FALSE;
  638. goto skip;
  639. }
  640. }
  641. LUIOut(L4,"Display Name: %s",lpAdrList->aEntries[i].rgPropVals[idx].Value.LPSZ);
  642. if (lpszInput) {
  643. if (!lstrcmp(lpAdrList->aEntries[i].rgPropVals[idx].Value.LPSZ,lpszInput)) {
  644. LUIOut(L3, "Found the entry we just added");
  645. Found = TRUE;
  646. }
  647. else {
  648. LUIOut(L3, "Did not find the entry we just added");
  649. retval = FALSE;
  650. }
  651. }
  652. //Check to see if EntryID exists
  653. LUIOut(L3, "Verifying a PR_ENTRYID entry exists in the PropertyTagArray");
  654. idx=0; localretval = TRUE;
  655. while((lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_ENTRYID )
  656. && localretval) {
  657. idx++;
  658. if(idx == cMaxProps) {
  659. LUIOut(L4, "PR_ENTRYID was not found in the lpAdrList");
  660. localretval = FALSE; retval = FALSE;
  661. goto skip;
  662. }
  663. }
  664. if (idx < cMaxProps) {
  665. // Store EID for call to OpenEntry
  666. lpLookupEID = (ENTRYID*)lpAdrList->aEntries[i].rgPropVals[idx].Value.bin.lpb;
  667. cbLookupEID = lpAdrList->aEntries[i].rgPropVals[idx].Value.bin.cb;
  668. if ((cbLookupEID == 0) || (lpLookupEID == NULL)) {
  669. LUIOut(L4, "EntryID found, but is NULL or has size = 0. Test FAILED");
  670. retval = FALSE;
  671. goto skip;
  672. }
  673. else LUIOut(L4, "EntryID found and appears to be valid (not NULL and >0 size).");
  674. // Try calling OpenEntry on the returned EID specifying a mailuser interface
  675. LUIOut(L4, "Calling OpenEntry on the EntryID");
  676. lpcIID = &IID_IMailUser;
  677. hr = lpAdrBook->OpenEntry(cbLookupEID, lpLookupEID, lpcIID,
  678. MAPI_BEST_ACCESS, &ulObjType, &lpUnk);
  679. switch(hr) {
  680. case S_OK:
  681. if ((lpUnk) && (ulObjType==MAPI_MAILUSER))
  682. LUIOut(L4, "OpenEntry call succeded on this EntryID and returned a valid object pointer and type.");
  683. else {
  684. LUIOut(L4, "OpenEntry call succeded on this EntryID but returned an invalid object pointer or incorrect type. Test FAILED");
  685. retval = FALSE;
  686. }
  687. break;
  688. case MAPI_E_NOT_FOUND:
  689. LUIOut(L4, "OpenEntry returned MAPI_E_NOT_FOUND for this EntryID. Test FAILED");
  690. retval = FALSE;
  691. break;
  692. case MAPI_E_UNKNOWN_ENTRYID:
  693. LUIOut(L4, "OpenEntry returned MAPI_E_UNKNOWN_ENTRYID for this EntryID. Test FAILED");
  694. retval = FALSE;
  695. break;
  696. case MAPI_E_NO_ACCESS:
  697. LUIOut(L4, "OpenEntry returned MAPI_E_NO_ACCESS for this EntryID. Test FAILED");
  698. retval = FALSE;
  699. break;
  700. default:
  701. LUIOut(L4, "OpenEntry returned unknown result code (0x%x) for this EntryID. Test FAILED", hr);
  702. retval = FALSE;
  703. lpUnk = NULL;
  704. break;
  705. }
  706. }
  707. //Check to see if PR_EMAIL_ADDRESS exists
  708. LUIOut(L3, "Verifying a PR_EMAIL_ADDRESS entry exists in the PropertyTagArray");
  709. idx=0; localretval = TRUE;
  710. while((lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_EMAIL_ADDRESS )
  711. && localretval) {
  712. idx++;
  713. if(idx == cMaxProps) {
  714. LUIOut(L4, "PR_EMAIL_ADDRESS was not found in the lpAdrList");
  715. localretval = FALSE; //retval = FALSE;
  716. }
  717. }
  718. if (idx < cMaxProps) {
  719. LUIOut(L4,"Email Address: %s",lpAdrList->aEntries[i].rgPropVals[idx].Value.LPSZ);
  720. }
  721. //Check to see if PR_ADDRTYPE exists
  722. LUIOut(L3, "Verifying a PR_ADDRTYPE entry exists in the PropertyTagArray");
  723. idx=0; localretval = TRUE;
  724. while((lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_ADDRTYPE )
  725. && localretval) {
  726. idx++;
  727. if(idx == cMaxProps) {
  728. LUIOut(L4, "PR_ADDRTYPE was not found in the lpAdrList");
  729. localretval = FALSE; //retval = FALSE;
  730. }
  731. }
  732. if (idx < cMaxProps) {
  733. LUIOut(L4,"Address Type: %s",lpAdrList->aEntries[i].rgPropVals[idx].Value.LPSZ);
  734. }
  735. //Check to see if PR_OBJECT_TYPE exists
  736. LUIOut(L3, "Verifying a PR_OBJECT_TYPE entry exists in the PropertyTagArray");
  737. idx=0; localretval = TRUE;
  738. while((lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_OBJECT_TYPE )
  739. && localretval) {
  740. idx++;
  741. if(idx == cMaxProps) {
  742. LUIOut(L4, "PR_OBJECT_TYPE was not found in the lpAdrList");
  743. localretval = FALSE; retval = FALSE;
  744. }
  745. }
  746. if (idx < cMaxProps) {
  747. switch (lpAdrList->aEntries[i].rgPropVals[idx].Value.l) {
  748. case MAPI_MAILUSER:
  749. LUIOut(L4, "Object Type: MAPI_MAILUSER");
  750. break;
  751. case MAPI_DISTLIST:
  752. LUIOut(L4, "Object Type: MAPI_DISTLIST");
  753. break;
  754. default:
  755. LUIOut(L4,"Object Type not MAILUSER or DISTLIST. Test FAILED");
  756. }
  757. }
  758. skip: // skip the current entry and continue through the lpAdrList
  759. if (lpUnk) lpUnk->Release(); //Release the object returned from OpenEntry
  760. }
  761. if (lpAdrBook) lpAdrBook->Release();
  762. //if (lpWABObject2) lpWABObject->Release();
  763. return(retval);
  764. }
  765. BOOL DisplayAdrList(LPADRLIST lpAdrList, ULONG cEntries)
  766. {
  767. int i = 0;
  768. int idx = 0;
  769. int cMaxProps = 0;
  770. BOOL Found, retval = TRUE;
  771. for(i=0; i<(int) cEntries; ++i) {
  772. LUIOut(L3, "Searching Entry #%i out of %i", i+1, cEntries);
  773. cMaxProps = (int)lpAdrList->aEntries[i].cValues;
  774. /*
  775. //Check to see if Email Address Type exists
  776. idx=0; Found = TRUE;
  777. while(Found && lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_ADDRTYPE ) {
  778. idx++;
  779. if(idx == cMaxProps) {
  780. LUIOut(L4, "PR_ADDRTYPE was not found in the lpAdrList");
  781. Found = FALSE;
  782. }
  783. }
  784. if (Found) LUIOut(L4,"Address Type: %s",lpAdrList->aEntries[i].rgPropVals[idx].Value.LPSZ);
  785. //Check to see if Email Address exists
  786. idx=0; Found = TRUE;
  787. while(Found && lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_OBJECT_TYPE ) {
  788. idx++;
  789. if(idx == cMaxProps) {
  790. LUIOut(L4, "PR_OBJECT_TYPE was not found in the lpAdrList");
  791. Found = FALSE;
  792. }
  793. }
  794. if (Found) LUIOut(L4,"Object Type: %s",lpAdrList->aEntries[i].rgPropVals[idx].Value.LPSZ);
  795. //Check to see if display type exists
  796. idx=0; Found = TRUE;
  797. while(Found && lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_DISPLAY_TYPE ) {
  798. idx++;
  799. if(idx == cMaxProps) {
  800. LUIOut(L4, "PR_DISPLAY_TYPE was not found in the lpAdrList");
  801. Found = FALSE;
  802. }
  803. }
  804. if (Found) LUIOut(L4,"Display Type: %s",lpAdrList->aEntries[i].rgPropVals[idx].Value.LPSZ);
  805. */
  806. //Check to see if Display Name exists
  807. idx=0; Found = TRUE;
  808. while(Found && lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_DISPLAY_NAME ) {
  809. idx++;
  810. if(idx == cMaxProps) {
  811. LUIOut(L4, "PR_DISPLAY_NAME was not found in the lpAdrList");
  812. Found = FALSE;
  813. }
  814. }
  815. if (Found) LUIOut(L4,"Display Name: %s",lpAdrList->aEntries[i].rgPropVals[idx].Value.LPSZ);
  816. //Check to see if EntryID exists
  817. idx=0; Found = TRUE;
  818. while(Found && lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_ENTRYID ) {
  819. idx++;
  820. if(idx == cMaxProps) {
  821. LUIOut(L4, "PR_ENTRYID was not found in the lpAdrList");
  822. Found = FALSE;
  823. }
  824. }
  825. if (Found) LUIOut(L4,"Entry ID Found");
  826. //Check to see if Recipient Type exists
  827. idx=0; Found = TRUE;
  828. while(Found && lpAdrList->aEntries[i].rgPropVals[idx].ulPropTag != PR_RECIPIENT_TYPE ) {
  829. idx++;
  830. if(idx == cMaxProps) {
  831. LUIOut(L4, "PR_RECIPIENT_TYPE was not found in the lpAdrList");
  832. Found = FALSE;
  833. }
  834. }
  835. if (Found) {
  836. switch((ULONG)lpAdrList->aEntries[i].rgPropVals[idx].Value.l) {
  837. case MAPI_TO: {
  838. LUIOut(L4, "Recipient Type: [TO:]");
  839. break;
  840. }
  841. case MAPI_CC: {
  842. LUIOut(L4, "Recipient Type: [CC:]");
  843. break;
  844. }
  845. case MAPI_BCC: {
  846. LUIOut(L4, "Recipient Type: [BCC:]");
  847. break;
  848. }
  849. default: {
  850. LUIOut(L4, "Recipient Type: [UNKNOWN]. Test FAILED");
  851. }
  852. }
  853. }
  854. }
  855. return retval;
  856. }
  857. BOOL LogIt(HRESULT hr, int Level,char * LogString)
  858. {
  859. switch (Level) {
  860. case 0:
  861. if (HR_FAILED(hr)) {
  862. LUIOut(LFAIL, "%s",LogString);
  863. return FALSE;
  864. }
  865. else LUIOut(LPASS,"%s",LogString);
  866. return TRUE;
  867. case 1:
  868. if (HR_FAILED(hr)) {
  869. LUIOut(LFAIL1, "%s",LogString);
  870. return FALSE;
  871. }
  872. else LUIOut(LPASS1,"%s",LogString);
  873. return TRUE;
  874. case 2:
  875. if (HR_FAILED(hr)) {
  876. LUIOut(LFAIL2, "%s",LogString);
  877. return FALSE;
  878. }
  879. else LUIOut(LPASS2,"%s",LogString);
  880. return TRUE;
  881. case 3:
  882. if (HR_FAILED(hr)) {
  883. LUIOut(LFAIL3, "%s",LogString);
  884. return FALSE;
  885. }
  886. else LUIOut(LPASS3,"%s",LogString);
  887. return TRUE;
  888. case 4:
  889. if (HR_FAILED(hr)) {
  890. LUIOut(LFAIL4, "%s",LogString);
  891. return FALSE;
  892. }
  893. else LUIOut(LPASS4,"%s",LogString);
  894. return TRUE;
  895. default: break;
  896. }
  897. if (HR_FAILED(hr)) {
  898. LUIOut(LFAIL2, "%s",LogString);
  899. return FALSE;
  900. }
  901. else LUIOut(LPASS2,"%s",LogString);
  902. return TRUE;
  903. }
  904. //
  905. // PROCEDURE: AllocateAdrList
  906. // DESCRIPTION: Uses either MAPI or WAB allocaters to allocate an lpAdrList
  907. //
  908. // PARAMETERS: LPWABOBJECT lpLocalWABObject - ptr to opened WABObject
  909. // int nEntries - how many AdrEntries to allocate
  910. // int nProps - how many properties per AdrEntry
  911. // LPADRLIST * lppAdrList - where to return the allocated ptr
  912. //
  913. BOOL AllocateAdrList(IN LPWABOBJECT lpLocalWABObject, IN int nEntries, IN int nProps, OUT LPADRLIST * lppAdrList) {
  914. BOOL retval = TRUE;
  915. SCODE sc;
  916. *lppAdrList = NULL;
  917. #ifdef PAB
  918. if (! (sc = MAPIAllocateBuffer(sizeof(ADRLIST) + (nEntries * sizeof(ADRENTRY)),
  919. (void **)lppAdrList))) {
  920. (*lppAdrList)->cEntries = nEntries;
  921. for (int entry = 0; entry < nEntries; entry++) {
  922. (*lppAdrList)->aEntries[entry].ulReserved1 = 0;
  923. (*lppAdrList)->aEntries[entry].cValues = nProps;
  924. sc = MAPIAllocateBuffer((nProps * sizeof(SPropValue)),
  925. (void **)(&(*lppAdrList)->aEntries[entry].rgPropVals));
  926. if (sc != S_OK) retval = FALSE;
  927. }
  928. }
  929. else retval = FALSE;
  930. //
  931. // Should do cleanup here for a partial allocation that fails
  932. //
  933. #endif //PAB
  934. #ifdef WAB
  935. if (! (sc = lpLocalWABObject->AllocateBuffer(sizeof(ADRLIST) + (nEntries * sizeof(ADRENTRY)),
  936. (void **)lppAdrList))) {
  937. (*lppAdrList)->cEntries = nEntries;
  938. for (int entry = 0; entry < nEntries; entry++) {
  939. (*lppAdrList)->aEntries[entry].ulReserved1 = 0;
  940. (*lppAdrList)->aEntries[entry].cValues = nProps;
  941. sc = lpLocalWABObject->AllocateBuffer((nProps * sizeof(SPropValue)),
  942. (void **)(&(*lppAdrList)->aEntries[entry].rgPropVals));
  943. if (sc != S_OK) retval = FALSE;
  944. }
  945. }
  946. else retval = FALSE;
  947. //
  948. // Should do cleanup here for a partial allocation that fails
  949. //
  950. #endif //WAB
  951. return retval;
  952. }
  953. //
  954. // PROCEDURE: GrowAdrList
  955. // DESCRIPTION: Takes an existing lpAdrList, allocates a new, larger lpAdrList
  956. // , copies over the old entries and allocates new entries, returning
  957. // a pointer to the new AdrList in lpAdrList.
  958. //
  959. // PARAMETERS: int nEntries - how many AdrEntries to allocate in new list
  960. // int nProps - how many properties per new AdrEntry
  961. // LPADRLIST * lppAdrList - where to return the allocated ptr
  962. //
  963. BOOL GrowAdrList(IN UINT nEntries, IN UINT nProps, OUT LPADRLIST * lppAdrList) {
  964. BOOL retval = TRUE;
  965. SCODE sc;
  966. LPADRLIST lpTempAdrList;
  967. unsigned int entry;
  968. if ((!lppAdrList) || ((*lppAdrList)->cEntries>=nEntries))
  969. return FALSE;
  970. #ifdef PAB
  971. if (! (sc = MAPIAllocateBuffer(sizeof(ADRLIST) + (nEntries * sizeof(ADRENTRY)),
  972. (void **)&lpTempAdrList))) {
  973. lpTempAdrList->cEntries = nEntries;
  974. // Copy over old entries
  975. entry = (*lppAdrList)->cEntries;
  976. memcpy(lpTempAdrList, *lppAdrList, (entry * sizeof(ADRENTRY)));
  977. // Allocate new entries
  978. for (; entry < nEntries; entry++) {
  979. lpTempAdrList->aEntries[entry].ulReserved1 = 0;
  980. lpTempAdrList->aEntries[entry].cValues = nProps;
  981. sc = MAPIAllocateBuffer((nProps * sizeof(SPropValue)),
  982. (void **)(&lpTempAdrList->aEntries[entry].rgPropVals));
  983. if (sc != S_OK) retval = FALSE;
  984. }
  985. FreeAdrList(lppAdrList);
  986. *lppAdrList = lpTempAdrList;
  987. }
  988. else retval = FALSE;
  989. //
  990. // Should do cleanup here for a partial allocation that fails
  991. //
  992. #endif //PAB
  993. #ifdef WAB
  994. if (! (sc = lpWABObject->AllocateBuffer(sizeof(ADRLIST) + (nEntries * sizeof(ADRENTRY)),
  995. (void **)&lpTempAdrList))) {
  996. // Copy over old entries
  997. entry = (*lppAdrList)->cEntries;
  998. memcpy(lpTempAdrList, *lppAdrList, (sizeof(ADRLIST)+(entry * sizeof(ADRENTRY))));
  999. lpTempAdrList->cEntries = nEntries;
  1000. // Allocate new entries
  1001. for (; entry < nEntries; entry++) {
  1002. lpTempAdrList->aEntries[entry].ulReserved1 = 0;
  1003. lpTempAdrList->aEntries[entry].cValues = nProps;
  1004. sc = lpWABObject->AllocateBuffer((nProps * sizeof(SPropValue)),
  1005. (void **)(&lpTempAdrList->aEntries[entry].rgPropVals));
  1006. if (sc != S_OK) retval = FALSE;
  1007. }
  1008. FreePartAdrList(lppAdrList);
  1009. *lppAdrList = lpTempAdrList;
  1010. }
  1011. else retval = FALSE;
  1012. //
  1013. // Should do cleanup here for a partial allocation that fails
  1014. //
  1015. #endif //WAB
  1016. return retval;
  1017. }
  1018. //
  1019. // PROCEDURE: FreeAdrList
  1020. // DESCRIPTION: Uses either MAPI or WAB de-allocaters to walk and free an lpAdrList
  1021. //
  1022. // PARAMETERS: LPWABOBJECT lpLocalWABObject - ptr to opened WABObject
  1023. // LPADRLIST * lppAdrList - where the lpAdrList to free is stored
  1024. //
  1025. BOOL FreeAdrList(IN LPWABOBJECT lpLocalWABObject, IN LPADRLIST * lppAdrList) {
  1026. LPADRLIST lpAdrList = NULL;
  1027. UINT idx;
  1028. if (lppAdrList) lpAdrList = *lppAdrList;
  1029. #ifdef PAB
  1030. if (lpAdrList) {
  1031. for (idx = 0; idx < lpAdrList->cEntries; idx++)
  1032. MAPIFreeBuffer(lpAdrList->aEntries[idx].rgPropVals);
  1033. MAPIFreeBuffer(lpAdrList);
  1034. *lppAdrList=NULL;
  1035. }
  1036. #endif //PAB
  1037. #ifdef WAB
  1038. if (lpAdrList) {
  1039. for (idx = 0; idx < lpAdrList->cEntries; idx++)
  1040. lpLocalWABObject->FreeBuffer(lpAdrList->aEntries[idx].rgPropVals);
  1041. lpLocalWABObject->FreeBuffer(lpAdrList);
  1042. *lppAdrList=NULL;
  1043. }
  1044. #endif //WAB
  1045. return TRUE;
  1046. }
  1047. //
  1048. // PROCEDURE: FreePartAdrList
  1049. // DESCRIPTION: Uses either MAPI or WAB de-allocaters to free an lpAdrList
  1050. // but not the associated properties.
  1051. //
  1052. // PARAMETERS: LPADRLIST * lppAdrList - where the lpAdrList to free is stored
  1053. //
  1054. BOOL FreePartAdrList(IN LPADRLIST * lppAdrList) {
  1055. LPADRLIST lpAdrList = NULL;
  1056. if (lppAdrList) lpAdrList = *lppAdrList;
  1057. #ifdef PAB
  1058. if (lpAdrList) {
  1059. MAPIFreeBuffer(lpAdrList);
  1060. lpAdrList=NULL;
  1061. }
  1062. #endif //PAB
  1063. #ifdef WAB
  1064. if (lpAdrList) {
  1065. lpWABObject->FreeBuffer(lpAdrList);
  1066. lpAdrList=NULL;
  1067. }
  1068. #endif //WAB
  1069. return TRUE;
  1070. }
  1071. //
  1072. // PROCEDURE: FindProp
  1073. // DESCRIPTION: Walks through the properties of an AdrEntry and returns the index
  1074. // of the requested property tag.
  1075. //
  1076. // PARAMETERS: LPADRENTRY lpAdrEntry - Entry to search through
  1077. // ULONG ulPropTag - Property tag to look for
  1078. // unsigned int* lpnFoundIndex - Ptr to output variable where the found index
  1079. // value is to be stored.
  1080. //
  1081. // RETURNS: TRUE if succesfull.
  1082. //
  1083. BOOL FindProp(IN LPADRENTRY lpAdrEntry, IN ULONG ulPropTag, OUT unsigned int* lpnFoundIndex) {
  1084. if ((!lpAdrEntry) || (!ulPropTag) || (!lpnFoundIndex)) return(FALSE);
  1085. for (unsigned int Counter1 = 0; Counter1 < lpAdrEntry->cValues; Counter1++) {
  1086. if (lpAdrEntry->rgPropVals[Counter1].ulPropTag == ulPropTag) {
  1087. *lpnFoundIndex = Counter1;
  1088. return(TRUE);
  1089. }
  1090. }
  1091. return(FALSE);
  1092. }
  1093. //
  1094. // PROCEDURE: FindPropinRow
  1095. // DESCRIPTION: Walks through the properties of an SRowSet and returns the index
  1096. // of the requested property tag.
  1097. //
  1098. // PARAMETERS: LPSRow lpRow - Row to search through
  1099. // ULONG ulPropTag - Property tag to look for
  1100. // unsigned int* lpnFoundIndex - Ptr to output variable where the found index
  1101. // value is to be stored.
  1102. //
  1103. // RETURNS: TRUE if succesfull.
  1104. //
  1105. BOOL FindPropinRow(IN LPSRow lpRow, IN ULONG ulPropTag, OUT unsigned int* lpnFoundIndex) {
  1106. if ((!lpRow) || (!ulPropTag) || (!lpnFoundIndex)) return(FALSE);
  1107. for (ULONG Column = 0; Column < lpRow->cValues; Column++) {
  1108. if (lpRow->lpProps[Column].ulPropTag == ulPropTag) {
  1109. *lpnFoundIndex = Column;
  1110. return(TRUE);
  1111. }
  1112. }
  1113. return(FALSE);
  1114. }
  1115. //
  1116. // PROCEDURE: ParseIniBuffer
  1117. // DESCRIPTION: Walks through a buffer read from an ini file which contains
  1118. // several strings separated by quotation marks and copies the
  1119. // requested string to the users buffer.
  1120. //
  1121. // PARAMETERS: LPSTR lpszIniBuffer
  1122. // UINT uSelect - which string (in order left to right starting with 1 ) to return
  1123. // LPSTR lpszReturnBuffer - pre-alocated by caller and dumb (assumes enough space)
  1124. //
  1125. BOOL ParseIniBuffer(LPSTR lpszIniBuffer, UINT uSelect, LPSTR lpszReturnBuffer) {
  1126. UINT Selected = 0;
  1127. // while (*(lpszIniBuffer++) != '"'); // Advance to first entry
  1128. // lpszIniBuffer++;
  1129. Selected++; // Now pointing at 1st letter of first item
  1130. while(uSelect != Selected++) {
  1131. while (*(lpszIniBuffer++) != '"'); // Advance to end of this entry
  1132. while (*(lpszIniBuffer++) != '"'); // Advance to beginning of next entry
  1133. // Now we are pointing at the 1st letter of the desired entry so copy
  1134. }
  1135. while((*(lpszIniBuffer) != '"') && (*(lpszIniBuffer) != '\0')) {
  1136. *(lpszReturnBuffer++) = *lpszIniBuffer++;
  1137. }
  1138. *lpszReturnBuffer = '\0'; // Add the terminator
  1139. return(TRUE);
  1140. }
  1141. //
  1142. // PROCEDURE: PropError
  1143. // DESCRIPTION: Compares the passed in property type with PT_ERROR returning TRUE is error is found
  1144. //
  1145. // PARAMETERS: ulPropTag - Tag to compare
  1146. // cValues - # of entries returned from GetProps
  1147. //
  1148. BOOL PropError(ULONG ulPropTag, ULONG cValues) {
  1149. BOOL retval = FALSE;
  1150. #ifdef DISTLISTS
  1151. for(ULONG Counter = 0; Counter < cValues; Counter++) {
  1152. if (PROP_TYPE(ulPropTag) == PT_ERROR) retval = TRUE;
  1153. }
  1154. #endif
  1155. return retval;
  1156. }
  1157. //
  1158. // PROCEDURE: DeleteWABFile
  1159. // DESCRIPTION: Reads the registry to determine the location of the WAB file,
  1160. // and deletes the file.
  1161. //
  1162. // PARAMETERS: none
  1163. //
  1164. BOOL DeleteWABFile () {
  1165. BOOL retval = TRUE;
  1166. long lretval;
  1167. HKEY hKey;
  1168. char KeyAddress[] = "Software\\Microsoft\\WAB\\Wab File Name";
  1169. DWORD dType, dSize = 256;
  1170. char achData[256];
  1171. if (!MyRegOpenKeyEx(HKEY_CURRENT_USER,
  1172. KeyAddress,
  1173. KEY_QUERY_VALUE,
  1174. &hKey)) {
  1175. LUIOut(L2, "MyRegOpenKeyEx call failed");
  1176. retval = FALSE;
  1177. return(retval);
  1178. }
  1179. lretval = RegQueryValueEx(hKey, // handle of key to query
  1180. NULL, // address of name of value to query
  1181. (LPDWORD)NULL, // reserved
  1182. &dType, // address of buffer for value type
  1183. (LPBYTE)achData, // address of data buffer
  1184. &dSize // address of data buffer size
  1185. );
  1186. if (lretval != ERROR_SUCCESS) {
  1187. LUIOut(L2, "RegQueryValueEx call failed with error code %u", lretval);
  1188. retval = FALSE;
  1189. return(retval);
  1190. }
  1191. LUIOut(L2, "Deleting WAB file: %s", achData);
  1192. RegCloseKey(hKey);
  1193. if (!DeleteFile(achData)) {
  1194. LUIOut(L3, "Delete FAILED. Could not locate or delete file.");
  1195. retval = FALSE;
  1196. }
  1197. return(retval);
  1198. }
  1199. //
  1200. // PROCEDURE: MyRegOpenKeyEx
  1201. // DESCRIPTION: Walks through a null terminated string, such as "\Software\Microsoft\WAB"
  1202. // openning each key until it reaches the end and returns that open key (closing
  1203. // the interim keys along the way). The caller must close the returned HKEY.
  1204. //
  1205. // PARAMETERS: StartKey - one of the predefined "open" keys to root at
  1206. // szAddress - null terminated string specifcying the path to the key to be opened
  1207. // RegSec - the security access required (i.e. KEY_READ)
  1208. // lpReturnKey - address of HKEY where final opened key is stored
  1209. //
  1210. BOOL MyRegOpenKeyEx(HKEY StartKey, char* szAddress, REGSAM RegSec, HKEY* lpReturnKey) {
  1211. HKEY workkey1, workkey2, *lpOpenKey=&workkey1, *lpNewKey=&workkey2;
  1212. char workbuffer[256], *lpAddr = szAddress, *lpWork = workbuffer;
  1213. BOOL Started = FALSE, Done = FALSE;
  1214. long lretval;
  1215. if (!szAddress) return FALSE;
  1216. while (!Done) {
  1217. if (*lpAddr == '\\') lpAddr++; //skip over the initial backslash if it exists
  1218. while((*(lpAddr) != '\\') && (*(lpAddr) != '\0')) {
  1219. *(lpWork++) = *lpAddr++;
  1220. }
  1221. *lpWork = '\0'; // Add the terminator
  1222. if (*(lpAddr) == '\0') Done = TRUE;
  1223. lpWork = workbuffer;
  1224. if (!Started) {
  1225. //
  1226. // First, special case the starting key (predefined/open key root)
  1227. //
  1228. lretval = RegOpenKeyEx( StartKey,
  1229. lpWork,
  1230. DWORD(0),
  1231. RegSec,
  1232. lpOpenKey);
  1233. Started = TRUE;
  1234. }
  1235. else {
  1236. lretval = RegOpenKeyEx( *lpOpenKey,
  1237. lpWork,
  1238. DWORD(0),
  1239. RegSec,
  1240. lpNewKey);
  1241. RegCloseKey(*lpOpenKey);
  1242. *lpOpenKey = *lpNewKey;
  1243. }
  1244. if (lretval != ERROR_SUCCESS) {
  1245. LUIOut(L2, "RegOpenKeyEx call failed with error code 0x%x", lretval);
  1246. return(FALSE);
  1247. }
  1248. }
  1249. *lpReturnKey = *lpNewKey;
  1250. return(TRUE);
  1251. }
  1252. //
  1253. // PROCEDURE: CreateMultipleEntries
  1254. // DESCRIPTION: Creates multiple entries in the WAB using the display name stored in the
  1255. // pabtests.ini file CreateEntriesStress section.
  1256. //
  1257. // PARAMETERS: NumEntriesIn - how many entries to create. If 0, then the value is read
  1258. // from the same CreateEntriesStress section.
  1259. // lpPerfData - address of a dword data type to hold the average time in milliseconds
  1260. // required during SaveChanges. If NULL perf data is not accumulated.
  1261. //
  1262. BOOL CreateMultipleEntries(IN UINT NumEntriesIn, DWORD* lpPerfData)
  1263. {
  1264. ULONG ulFlags = 0;
  1265. HRESULT hr = hrSuccess;
  1266. SCODE sc = SUCCESS_SUCCESS;
  1267. int retval=TRUE;
  1268. DWORD StartTime, StopTime;
  1269. LPADRBOOK lpAdrBook = NULL;
  1270. LPABCONT lpABCont= NULL;
  1271. ULONG cbEidPAB = 0;
  1272. LPENTRYID lpEidPAB = NULL;
  1273. char EntProp[10][BIG_BUF]; //MAX_PROP
  1274. ULONG cValues = 0, ulObjType=NULL;
  1275. int i=0,k=0;
  1276. char EntryBuf[MAX_BUF];
  1277. char szDLTag[SML_BUF];
  1278. unsigned int NumEntries, counter, StrLen;
  1279. LPMAILUSER lpMailUser=NULL,lpDistList=NULL;
  1280. SPropValue PropValue[3] = {0}; // This value is 3 because we
  1281. // will be setting 3 properties:
  1282. // EmailAddress, DisplayName and
  1283. // AddressType.
  1284. LPSPropValue lpSPropValueAddress = NULL;
  1285. LPSPropValue lpSPropValueDL = NULL;
  1286. SizedSPropTagArray(1,SPTArrayAddress) = {1, {PR_DEF_CREATE_MAILUSER} };
  1287. SizedSPropTagArray(1,SPTArrayDL) = {1, {PR_DEF_CREATE_DL} };
  1288. if (!GetAB(OUT &lpAdrBook)) {
  1289. retval = FALSE;
  1290. goto out;
  1291. }
  1292. // Call IAddrBook::OpenEntry to get the root container to PAB - MAPI
  1293. assert(lpAdrBook != NULL);
  1294. hr = OpenPABID( IN lpAdrBook, OUT &cbEidPAB,
  1295. OUT &lpEidPAB,OUT &lpABCont, OUT &ulObjType);
  1296. // hr = lpAdrBook->OpenEntry(0, NULL, NULL,MAPI_MODIFY,&ulObjType, (LPUNKNOWN *) &lpABCont);
  1297. if (HR_FAILED(hr)) {
  1298. LUIOut(L2,"IAddrBook->OpenEntry Failed");
  1299. retval=FALSE;
  1300. goto out;
  1301. }
  1302. // Wipe perfdata if we're tracking this
  1303. if (lpPerfData) *lpPerfData = (DWORD)0;
  1304. //
  1305. // Try to create a MailUser entry in the container
  1306. //
  1307. // Need to get the template ID so we call GetProps with PR_DEF_CREATE_MAILUSER
  1308. assert(lpABCont != NULL);
  1309. hr = lpABCont->GetProps( IN (LPSPropTagArray) &SPTArrayAddress,
  1310. IN 0, //Flags
  1311. OUT &cValues,
  1312. OUT &lpSPropValueAddress);
  1313. if ((HR_FAILED(hr))||(PropError(lpSPropValueAddress->ulPropTag, cValues))) {
  1314. LUIOut(L3,"GetProps FAILED for Default MailUser template");
  1315. retval=FALSE;
  1316. goto out;
  1317. }
  1318. // The returned value of PR_DEF_CREATE_MAILUSER is an
  1319. // EntryID which can be passed to CreateEntry
  1320. //
  1321. // Retrieve user info from ini file
  1322. cValues = 3; //# of props we are setting
  1323. lstrcpy(szDLTag,"Address1");
  1324. GetPrivateProfileString("CreateEntriesStress",szDLTag,"",EntryBuf,MAX_BUF,INIFILENAME);
  1325. GetPropsFromIniBufEntry(EntryBuf,cValues,EntProp);
  1326. StrLen = (strlen(EntProp[0]));
  1327. _itoa(0,(char*)&EntProp[0][StrLen],10);
  1328. EntProp[0][StrLen+1]= '\0';
  1329. NumEntries = (NumEntriesIn > 0) ?
  1330. NumEntriesIn:GetPrivateProfileInt("CreateEntriesStress","NumCopies",0,INIFILENAME);
  1331. if (NumEntries > 100)
  1332. LUIOut(L2, "Adding %u MailUser entries to the WAB. This may take several minutes.", NumEntries);
  1333. for (counter = 0; counter < NumEntries; counter++) {
  1334. // LUIOut(L3, "Calling IABContainer->CreateEntry with the EID from GetProps");
  1335. hr = lpABCont->CreateEntry( IN lpSPropValueAddress->Value.bin.cb,
  1336. IN (LPENTRYID) lpSPropValueAddress->Value.bin.lpb,
  1337. IN 0,
  1338. OUT (LPMAPIPROP *) &lpMailUser);
  1339. if (HR_FAILED(hr)) {
  1340. LUIOut(L3,"CreateEntry failed for PR_DEF_CREATE_MAILUSER");
  1341. retval=FALSE;
  1342. goto out;
  1343. }
  1344. //
  1345. // Then set the properties
  1346. //
  1347. PropValue[0].ulPropTag = PR_DISPLAY_NAME;
  1348. PropValue[1].ulPropTag = PR_ADDRTYPE;
  1349. PropValue[2].ulPropTag = PR_EMAIL_ADDRESS;
  1350. _itoa(counter,(char*)&EntProp[0][StrLen],10);
  1351. // LUIOut(L2,"MailUser Entry to Add: %s",EntProp[0]);
  1352. for (i=0; i<(int)cValues;i++)
  1353. PropValue[i].Value.LPSZ = (LPTSTR)EntProp[i];
  1354. hr = lpMailUser->SetProps(IN cValues,
  1355. IN PropValue,
  1356. IN NULL);
  1357. if (HR_FAILED(hr)) {
  1358. LUIOut(L3,"MailUser->SetProps call FAILED for %s properties",PropValue[0].Value.LPSZ);
  1359. retval=FALSE;
  1360. goto out;
  1361. }
  1362. // else LUIOut(L3,"MailUser->SetProps call PASSED for %s properties",PropValue[0].Value.LPSZ);
  1363. StartTime = GetTickCount();
  1364. hr = lpMailUser->SaveChanges(IN KEEP_OPEN_READWRITE); //flags
  1365. StopTime = GetTickCount();
  1366. /* if (lpPerfData) {
  1367. if ((StopTime-StartTime) > *lpPerfData)
  1368. *lpPerfData = (StopTime - StartTime);
  1369. }
  1370. */
  1371. if (lpPerfData) {
  1372. *lpPerfData += (StopTime - StartTime);
  1373. }
  1374. if (HR_FAILED(hr)) {
  1375. LUIOut(L3,"MailUser->SaveChanges FAILED");
  1376. retval=FALSE;
  1377. goto out;
  1378. }
  1379. // else LUIOut(L3,"MailUser->SaveChanges PASSED, entry added to PAB/WAB");
  1380. if (lpMailUser) {
  1381. lpMailUser->Release();
  1382. lpMailUser = NULL;
  1383. }
  1384. }
  1385. if (lpPerfData)
  1386. *lpPerfData /= NumEntries;
  1387. out:
  1388. #ifdef PAB
  1389. if (lpEid)
  1390. MAPIFreeBuffer(lpEid);
  1391. if (lpEidPAB)
  1392. MAPIFreeBuffer(lpEidPAB);
  1393. if (lpSPropValueAddress)
  1394. MAPIFreeBuffer(lpSPropValueAddress);
  1395. if (lpSPropValueDL)
  1396. MAPIFreeBuffer(lpSPropValueDL);
  1397. #endif
  1398. #ifdef WAB
  1399. if (lpEidPAB)
  1400. lpWABObject->FreeBuffer(lpEidPAB);
  1401. if (lpSPropValueAddress)
  1402. lpWABObject->FreeBuffer(lpSPropValueAddress);
  1403. if (lpSPropValueDL)
  1404. lpWABObject->FreeBuffer(lpSPropValueDL);
  1405. #endif
  1406. if (lpMailUser)
  1407. lpMailUser->Release();
  1408. if (lpDistList)
  1409. lpDistList->Release();
  1410. if (lpABCont)
  1411. lpABCont->Release();
  1412. if (lpAdrBook)
  1413. lpAdrBook->Release();
  1414. #ifdef PAB
  1415. if (lpMAPISession)
  1416. lpMAPISession->Release();
  1417. MAPIUninitialize();
  1418. #endif
  1419. #ifdef WAB
  1420. if (lpWABObject) {
  1421. lpWABObject->Release();
  1422. lpWABObject = NULL;
  1423. }
  1424. #endif
  1425. return retval;
  1426. }
  1427. void GenerateRandomPhoneNumber(char **lppPhone) {
  1428. #define FORMATSIZE 15 // Size of formatted phone# + terminator i.e. (206)-882-8080
  1429. #define MAXNUMSIZE (FORMATSIZE + 32)
  1430. unsigned int Offset = 0;
  1431. extern BOOL Seeded;
  1432. *lppPhone = (char*)LocalAlloc(LMEM_FIXED, MAXNUMSIZE*sizeof(char));
  1433. (*lppPhone)[0] = '\0'; // Set the first char to a terminator
  1434. // seed the random number generator with the current time
  1435. if (!Seeded) {
  1436. srand( (unsigned)GetTickCount());
  1437. Seeded = TRUE;
  1438. }
  1439. while (Offset < FORMATSIZE) {
  1440. _itoa(rand(), ((*lppPhone)+Offset), 10);
  1441. Offset = strlen(*lppPhone);
  1442. }
  1443. // Overwrite some numbers with formatting characters
  1444. (*lppPhone)[0] = '(';
  1445. (*lppPhone)[4] = ')';
  1446. (*lppPhone)[5] = '-';
  1447. (*lppPhone)[9] = '-';
  1448. (*lppPhone)[FORMATSIZE-1] = '\0'; //Cutoff the end in case it's > FORMATSIZE
  1449. }
  1450. void GenerateRandomText(char **lppText, UINT unSize) {
  1451. unsigned int Offset = 0;
  1452. extern BOOL Seeded;
  1453. extern ULONG glblTest, glblCount, glblDN;
  1454. *lppText = (char*)LocalAlloc(LMEM_FIXED, (unSize+1)*sizeof(char));
  1455. // seed the random number generator with the current time
  1456. if (!Seeded) {
  1457. srand( (unsigned)GetTickCount());
  1458. Seeded = TRUE;
  1459. }
  1460. #ifdef TESTPASS
  1461. for (Offset = 0; Offset < unSize; Offset++) {
  1462. (*lppText)[Offset] = (char)glblTest;
  1463. if ((*lppText)[Offset] == '\0') (*lppText)[Offset] = (char)'?'; //don't want a terminator mid string
  1464. }
  1465. (*lppText)[unSize] = '\0'; //Cutoff the end
  1466. if (glblDN) {
  1467. glblDN = 0;
  1468. if (++glblCount == 15) {
  1469. glblTest++;
  1470. glblCount=0;
  1471. LUIOut(L4, "Testing value %i [%c].", glblTest, glblTest);
  1472. }
  1473. }
  1474. #else
  1475. for (Offset = 0; Offset < unSize; Offset++) {
  1476. (*lppText)[Offset] = rand();
  1477. if ((*lppText)[Offset] == '\0') (*lppText)[Offset] = (char)'?'; //don't want a terminator mid string
  1478. }
  1479. (*lppText)[unSize] = '\0'; //Cutoff the end
  1480. #endif
  1481. }
  1482. void GenerateRandomBoolean(unsigned short *lpBool) {
  1483. extern BOOL Seeded;
  1484. // seed the random number generator with the current time
  1485. if (!Seeded) {
  1486. srand( (unsigned)GetTickCount());
  1487. Seeded = TRUE;
  1488. }
  1489. *lpBool = (unsigned short)(GetTickCount() & 0x01); //If bit 0 is set then true otherwise false
  1490. }
  1491. void GenerateRandomLong(long *lpLong) {
  1492. extern BOOL Seeded;
  1493. // seed the random number generator with the current time
  1494. if (!Seeded) {
  1495. srand( (unsigned)GetTickCount());
  1496. Seeded = TRUE;
  1497. }
  1498. *lpLong = (long)rand();
  1499. }
  1500. void GenerateRandomBinary(SBinary *lpBinary, UINT unSize) {
  1501. unsigned int Offset = 0;
  1502. extern BOOL Seeded;
  1503. lpBinary->lpb = (LPBYTE)LocalAlloc(LMEM_FIXED, unSize);
  1504. lpBinary->cb = unSize;
  1505. // seed the random number generator with the current time
  1506. if (!Seeded) {
  1507. srand( (unsigned)GetTickCount());
  1508. Seeded = TRUE;
  1509. }
  1510. for (Offset = 0; Offset < unSize; Offset++) {
  1511. lpBinary->lpb[Offset] = (BYTE)(rand() * 255)/RAND_MAX;
  1512. }
  1513. }
  1514. //***
  1515. //*** set unCount to AUTONUM_OFF to disable autonumbering display names
  1516. //*** if lppDisplayName is not NULL then the *lppDisplayName string is used for the prefix of
  1517. //*** the DN and the ptr to the completed DisplayName is returned to the callee if lppReturnName is not NULL
  1518. //***
  1519. void CreateProps(LPTSTR lpszFileName, LPTSTR lpszSection, SPropValue** lppProperties, ULONG* lpcValues, UINT unCount, char** lppDisplayName, char ** lppReturnName) {
  1520. UINT StrLen1, PropIndex = 0, Properties = 0; //How many props does the user want to set
  1521. char *lpszLocalDisplayName, DNText[] = {"Test Entry #"};
  1522. extern ULONG glblDN;
  1523. PropTableEntry* lpEntry = PropTable;
  1524. while (lpEntry->ulPropTag) {
  1525. lpEntry->unSize = GetPrivateProfileInt(lpszSection,lpEntry->lpszPropTag,0,lpszFileName);
  1526. if ((lpEntry->ulPropTag == PR_DISPLAY_NAME) && (unCount != AUTONUM_OFF))
  1527. lpEntry->unSize = TRUE; //If we're autonumbering the display name, then make sure unsize is not zero
  1528. if (lpEntry->unSize) Properties++;
  1529. lpEntry++;
  1530. }
  1531. //At this point, any table entry with nonzero size we need to create
  1532. //LUIOut(L3, "Setting %i properties.", Properties);
  1533. *lpcValues = Properties;
  1534. *lppProperties = (SPropValue*)LocalAlloc(LMEM_FIXED, (Properties * sizeof(SPropValue)));
  1535. lpEntry = PropTable;
  1536. while (lpEntry->ulPropTag) {
  1537. if (lpEntry->unSize) {
  1538. //special case phone numbers
  1539. if ((strstr(lpEntry->lpszPropTag, "PHONE")) || (strstr(lpEntry->lpszPropTag, "FAX"))) {
  1540. //LUIOut(L3, "Found a prop I think is a phone number, called %s.", lpEntry->lpszPropTag);
  1541. (*lppProperties)[PropIndex].ulPropTag = lpEntry->ulPropTag;
  1542. GenerateRandomPhoneNumber(&((*lppProperties)[PropIndex].Value.LPSZ));
  1543. }
  1544. //special case for autonumbering display names if requested
  1545. else if ((lpEntry->ulPropTag == PR_DISPLAY_NAME) && (unCount != AUTONUM_OFF)) {
  1546. if ((lppDisplayName)&&(*lppDisplayName)) {
  1547. //Caller passed in a string to use as the prefix
  1548. StrLen1 = strlen(*lppDisplayName);
  1549. lpszLocalDisplayName = (char*)LocalAlloc(LMEM_FIXED, (StrLen1+5)*sizeof(char)); //5 for terminator plus # up to 9999
  1550. strcpy(lpszLocalDisplayName, *lppDisplayName);
  1551. }
  1552. else {
  1553. StrLen1 = strlen(DNText);
  1554. lpszLocalDisplayName = (char*)LocalAlloc(LMEM_FIXED, (StrLen1+5)*sizeof(char)); //5 for terminator plus # up to 9999
  1555. strcpy(lpszLocalDisplayName, DNText);
  1556. }
  1557. // Add the Entry # to the display name
  1558. _itoa(unCount,(char*)&(lpszLocalDisplayName[StrLen1]),10);
  1559. (*lppProperties)[PropIndex].ulPropTag = lpEntry->ulPropTag;
  1560. (*lppProperties)[PropIndex].Value.LPSZ = lpszLocalDisplayName;
  1561. if (lppReturnName) *lppReturnName = lpszLocalDisplayName;
  1562. }
  1563. else {
  1564. switch(PROP_TYPE(lpEntry->ulPropTag)) {
  1565. case PT_STRING8:
  1566. (*lppProperties)[PropIndex].ulPropTag = lpEntry->ulPropTag;
  1567. #ifdef TESTPASS
  1568. if (lpEntry->ulPropTag == PR_DISPLAY_NAME) glblDN = 1;
  1569. #endif
  1570. GenerateRandomText(&((*lppProperties)[PropIndex].Value.LPSZ),lpEntry->unSize);
  1571. if ((lpEntry->ulPropTag == PR_DISPLAY_NAME) && lppReturnName)
  1572. *lppReturnName = (*lppProperties)[PropIndex].Value.LPSZ;
  1573. break;
  1574. case PT_BOOLEAN:
  1575. (*lppProperties)[PropIndex].ulPropTag = lpEntry->ulPropTag;
  1576. GenerateRandomBoolean(&((*lppProperties)[PropIndex].Value.b));
  1577. break;
  1578. case PT_LONG:
  1579. (*lppProperties)[PropIndex].ulPropTag = lpEntry->ulPropTag;
  1580. GenerateRandomLong(&((*lppProperties)[PropIndex].Value.l));
  1581. break;
  1582. case PT_BINARY:
  1583. (*lppProperties)[PropIndex].ulPropTag = lpEntry->ulPropTag;
  1584. GenerateRandomBinary(&((*lppProperties)[PropIndex].Value.bin),lpEntry->unSize);
  1585. break;
  1586. default:
  1587. LUIOut(L1, "Unrecognized prop type 0x%x for property %s", PROP_TYPE(lpEntry->ulPropTag), lpEntry->lpszPropTag);
  1588. }
  1589. }
  1590. PropIndex++;
  1591. }
  1592. lpEntry++;
  1593. }
  1594. }
  1595. //***
  1596. //*** Walks through the expected props and searches the found props for the same prop/value combo
  1597. //***
  1598. BOOL CompareProps(SPropValue* lpExpectedProps, ULONG cValuesExpected, SPropValue* lpCompareProps, ULONG cValuesCompare) {
  1599. ULONG TargetProp, CompareIndex;
  1600. BOOL Result = TRUE, Found;
  1601. for (ULONG PropertyIndex = 0; PropertyIndex < cValuesExpected; PropertyIndex++) {
  1602. TargetProp = lpExpectedProps[PropertyIndex].ulPropTag;
  1603. for (CompareIndex = 0, Found = FALSE; CompareIndex < cValuesCompare; CompareIndex++) {
  1604. if (lpCompareProps[CompareIndex].ulPropTag == TargetProp) {
  1605. //if (TargetProp == PR_DISPLAY_NAME) _asm{int 3};
  1606. Found = TRUE;
  1607. switch(PROP_TYPE(TargetProp)) {
  1608. case PT_STRING8:
  1609. if (strcmp(lpExpectedProps[PropertyIndex].Value.LPSZ, lpCompareProps[CompareIndex].Value.LPSZ)) {
  1610. //Strings did not match so fail compare
  1611. LUIOut(L3, "Comparison failed for prop 0x%x. Expected %s but found %s", TargetProp, lpExpectedProps[PropertyIndex].Value.LPSZ, lpCompareProps[CompareIndex].Value.LPSZ);
  1612. Result = FALSE;
  1613. //_asm{int 3};
  1614. }
  1615. break;
  1616. case PT_BOOLEAN:
  1617. if (lpExpectedProps[PropertyIndex].Value.b != lpCompareProps[CompareIndex].Value.b) {
  1618. //bools did not match so fail compare
  1619. LUIOut(L3, "Comparison failed for prop 0x%x. Expected %u but found %u", TargetProp, lpExpectedProps[PropertyIndex].Value.b, lpCompareProps[CompareIndex].Value.b);
  1620. Result = FALSE;
  1621. }
  1622. break;
  1623. case PT_LONG:
  1624. if (lpExpectedProps[PropertyIndex].Value.l != lpCompareProps[CompareIndex].Value.l) {
  1625. //bools did not match so fail compare
  1626. LUIOut(L3, "Comparison failed for prop 0x%x. Expected %u but found %u", TargetProp, lpExpectedProps[PropertyIndex].Value.l, lpCompareProps[CompareIndex].Value.l);
  1627. Result = FALSE;
  1628. }
  1629. break;
  1630. case PT_BINARY:
  1631. if (memcmp(lpExpectedProps[PropertyIndex].Value.bin.lpb, lpCompareProps[CompareIndex].Value.bin.lpb, lpExpectedProps[PropertyIndex].Value.bin.cb)) {
  1632. //bools did not match so fail compare
  1633. LUIOut(L3, "Comparison failed for prop 0x%x. %u bytes expected, %u found and they are not equal", TargetProp, lpExpectedProps[PropertyIndex].Value.bin.cb, lpCompareProps[CompareIndex].Value.bin.cb);
  1634. Result = FALSE;
  1635. }
  1636. break;
  1637. default:
  1638. LUIOut(L3, "Unrecognized prop type 0x%x", PROP_TYPE(lpExpectedProps[PropertyIndex].ulPropTag));
  1639. } //switch
  1640. } //if propr match
  1641. } //for loop (CompareIndex)
  1642. if (!Found) {
  1643. LUIOut(L3, "Did not find property 0x%x. Compare FAILS", TargetProp);
  1644. Result = FALSE;
  1645. }
  1646. } //for loop (PropertyIndex)
  1647. //LUIOut(L3, "%u propertes compared %s", PropertyIndex, Result ? "Successfully" : "With Errors");
  1648. return(Result);
  1649. } //CompareProps()
  1650. //***
  1651. //*** Walks through the expected props until it finds the target prop and displays its value
  1652. //***
  1653. BOOL DisplayProp(SPropValue *lpSearchProps, ULONG ulTargetProp, ULONG cValues) {
  1654. BOOL Result = TRUE, Found = FALSE;
  1655. for (ULONG PropertyIndex = 0; PropertyIndex < cValues; PropertyIndex++) {
  1656. if (lpSearchProps[PropertyIndex].ulPropTag == ulTargetProp) {
  1657. //if (TargetProp == PR_DISPLAY_NAME) _asm{int 3};
  1658. Found = TRUE;
  1659. switch(PROP_TYPE(ulTargetProp)) {
  1660. case PT_STRING8:
  1661. LUIOut(L4, "Property 0x%x has value:%s", ulTargetProp, lpSearchProps[PropertyIndex].Value.LPSZ);
  1662. break;
  1663. case PT_BOOLEAN:
  1664. LUIOut(L4, "Property 0x%x has value:%i", ulTargetProp, lpSearchProps[PropertyIndex].Value.b);
  1665. break;
  1666. case PT_LONG:
  1667. LUIOut(L4, "Property 0x%x has value:0x%x", ulTargetProp, lpSearchProps[PropertyIndex].Value.l);
  1668. break;
  1669. case PT_BINARY:
  1670. LUIOut(L4, "Binary prop found but not displayed.");
  1671. break;
  1672. default:
  1673. LUIOut(L3, "Unrecognized prop type 0x%x", PROP_TYPE(ulTargetProp));
  1674. } //switch
  1675. } //if propr match
  1676. } //for loop (PropertyIndex)
  1677. if (!Found) {
  1678. LUIOut(L4, "Did not find property 0x%x.", ulTargetProp);
  1679. Result = FALSE;
  1680. }
  1681. return(Result);
  1682. } //DisplayProp()