Source code of Windows XP (NT5)
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.

1680 lines
42 KiB

  1. /***********************************************************************
  2. *
  3. * ABCONT.C
  4. *
  5. * Microsoft At Work Fax AB directory container object
  6. *
  7. * This file contains the code for implementing the Microsoft At Work Fax AB
  8. * directory container object.
  9. *
  10. * This directory container was retrieved by OpenEntry on the entryid
  11. * retrieved from the single row of the hierarchy table (IVTROOT in root.c).
  12. *
  13. * Many things are not yet implemented in this object. For example, no
  14. * advanced search dialog, or details dialog are available. Also the
  15. * ICON to PR_DISPLAY_TYPE table isn't available.
  16. *
  17. *
  18. * The following routines are implemented in this file:
  19. *
  20. * HrNewFaxDirectory
  21. * ABC_Release
  22. * ABC_SaveChanges
  23. * ABC_OpenProperty
  24. * ABC_GetContentsTable
  25. * ABC_GetHierarchyTable
  26. *
  27. * HrGetDetailsDialog
  28. *
  29. * HrNewABCButton
  30. * ABCBUTT_QueryInterface
  31. * ABCBUTT_Release
  32. * ABCBUTT_Activate
  33. * ABCBUTT_GetState
  34. *
  35. * Copyright 1992, 1993 Microsoft Corporation. All Rights Reserved.
  36. *
  37. * Revision History:
  38. *
  39. * When Who What
  40. * -------- ------------------ ---------------------------------------
  41. * 1.1.94 MAPI Original source from MAPI sample AB Provider
  42. * 1.27.94 Yoram Yaacovi Modifications to make it an At Work Fax ABP
  43. * 3.6.94 Yoram Yaacovi Update to MAPI build 154
  44. * 4.1.94 Yoram Yaacovi Update to MAPI and Sample AB build 157
  45. * 8.1.94 Yoram Yaacovi Update to MAPI and Sample AB build 304
  46. * 10.6.94 Yoram Yaacovi Update to MAPI and Sample AB build 313
  47. * Mainly adding a ResolveName method to ABContainer
  48. * 11.3.94 Yoram Yaacovi Update to MAPI 318.
  49. *
  50. ***********************************************************************/
  51. #include "faxab.h"
  52. #define PR_BUTTON_PRESS PROP_TAG(PT_OBJECT, 0x6603)
  53. #define PR_FAB_FILE_TEMP_A PROP_TAG(PT_STRING8,0x6605)
  54. #define PR_IMPORT_FROM_FILE_A PROP_TAG(PT_STRING8,0x6606)
  55. #define PR_IMPORT_TO_FILE_A PROP_TAG(PT_STRING8,0x6607)
  56. #define PR_BUTTON_IMPORT_A PROP_TAG(PT_STRING8,0x6608)
  57. #define PR_IMPORT_FORMAT_A PROP_TAG(PT_STRING8,0x6609)
  58. #define PR_DDLBX_IMPORT_FORMATS_A PROP_TAG(PT_STRING8,0x660a)
  59. #define FAB_FILE_NAME_NOTIF_ID 99L
  60. /*****************************
  61. **** Notification **********
  62. *****************************/
  63. typedef struct
  64. {
  65. MAPIUID muid;
  66. ULONG ulIdc;
  67. } NOTIFDATA;
  68. NOTIFDATA notifdata = { MUIDABMAWF, IDC_DIR_FAB_FILE_NAME };
  69. /*****************************
  70. ** Display Table structures *
  71. *****************************/
  72. DTBLEDIT editDirFileName =
  73. {
  74. SIZEOF(DTBLEDIT),
  75. 0,
  76. MAX_PATH,
  77. PR_FAB_FILE_TEMP_A
  78. };
  79. DTBLEDIT editImportFromFile =
  80. {
  81. SIZEOF(DTBLEDIT),
  82. 0,
  83. MAX_PATH,
  84. PR_IMPORT_FROM_FILE_A
  85. };
  86. DTBLEDIT editImportToFile =
  87. {
  88. SIZEOF(DTBLEDIT),
  89. 0,
  90. MAX_PATH,
  91. PR_IMPORT_TO_FILE_A
  92. };
  93. DTBLBUTTON buttonImport =
  94. {
  95. SIZEOF(DTBLBUTTON),
  96. 0,
  97. PR_BUTTON_IMPORT_A
  98. };
  99. DTBLBUTTON buttonDirChange =
  100. {
  101. SIZEOF(DTBLBUTTON),
  102. 0,
  103. PR_BUTTON_PRESS
  104. };
  105. DTBLDDLBX ddlbxImportFormats =
  106. {
  107. SIZEOF(DTBLDDLBX),
  108. PR_DISPLAY_NAME_A,
  109. PR_IMPORT_FORMAT_A,
  110. PR_DDLBX_IMPORT_FORMATS_A
  111. };
  112. /* General page layout */
  113. DTCTL rgdtctlDirGeneral[] =
  114. {
  115. /* directory general propery page */
  116. { DTCT_PAGE, 0, NULL, 0, NULL, 0, &dtblpage },
  117. /* static controls and edit control containing fab file name */
  118. { DTCT_LABEL, 0, NULL, 0, NULL, IDC_STATIC_CONTROL, &dtbllabel },
  119. { DTCT_LABEL, 0, NULL, 0, NULL, IDC_STATIC_CONTROL, &dtbllabel },
  120. { DTCT_EDIT, 0, (LPBYTE)&notifdata, SIZEOF(NOTIFDATA), (LPTSTR)szFileNameFilter, IDC_DIR_FAB_FILE_NAME, &editDirFileName },
  121. /* push button for changing fab file */
  122. { DTCT_BUTTON, 0, NULL, 0, NULL, IDC_DIR_CHANGE, &buttonDirChange },
  123. /* Import GroupBox */
  124. { DTCT_GROUPBOX, 0, NULL, 0, NULL, IDC_STATIC_CONTROL, &dtblgroupbox },
  125. // Import from file
  126. { DTCT_LABEL, 0, NULL, 0, NULL, IDC_STATIC_CONTROL, &dtbllabel },
  127. { DTCT_EDIT, 0, NULL, 0, (LPTSTR)szFileNameFilter, IDC_IMPORT_FROM_FILE, &editImportFromFile },
  128. // Import format
  129. { DTCT_LABEL, 0, NULL, 0, NULL, IDC_STATIC_CONTROL, &dtbllabel },
  130. { DTCT_DDLBX, 0, NULL, 0, NULL, IDC_IMPORT_FORMAT, &ddlbxImportFormats },
  131. // Import into file
  132. { DTCT_LABEL, 0, NULL, 0, NULL, IDC_STATIC_CONTROL, &dtbllabel },
  133. { DTCT_EDIT, 0, NULL, 0, (LPTSTR)szFileNameFilter, IDC_IMPORT_TO_FILE, &editImportToFile },
  134. // Import Button
  135. { DTCT_BUTTON, 0, NULL, 0, NULL, IDC_IMPORT, &buttonImport },
  136. };
  137. /* Display table pages for Directory */
  138. DTPAGE rgdtpageDir[] =
  139. {
  140. {
  141. SIZEOF(rgdtctlDirGeneral) / SIZEOF(DTCTL),
  142. (LPTSTR)MAKEINTRESOURCE(DirGeneralPage),
  143. TEXT(""),
  144. rgdtctlDirGeneral
  145. }
  146. };
  147. /*
  148. * ABCont jump table is defined here...
  149. */
  150. ABC_Vtbl vtblABC =
  151. {
  152. (ABC_QueryInterface_METHOD *) ROOT_QueryInterface,
  153. (ABC_AddRef_METHOD *) ROOT_AddRef,
  154. (ABC_AddRef_METHOD *) ABC_Release,
  155. (ABC_GetLastError_METHOD *) ROOT_GetLastError,
  156. ABC_SaveChanges,
  157. (ABC_GetProps_METHOD *) WRAP_GetProps,
  158. (ABC_GetPropList_METHOD *) WRAP_GetPropList,
  159. ABC_OpenProperty,
  160. (ABC_SetProps_METHOD *) WRAP_SetProps,
  161. (ABC_DeleteProps_METHOD *) WRAP_DeleteProps,
  162. (ABC_CopyTo_METHOD *) WRAP_CopyTo,
  163. (ABC_CopyProps_METHOD *) WRAP_CopyProps,
  164. (ABC_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs,
  165. (ABC_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames,
  166. ABC_GetContentsTable,
  167. ABC_GetHierarchyTable,
  168. (ABC_OpenEntry_METHOD *) ROOT_OpenEntry,
  169. (ABC_SetSearchCriteria_METHOD *) ROOT_SetSearchCriteria,
  170. (ABC_GetSearchCriteria_METHOD *) ROOT_GetSearchCriteria,
  171. (ABC_CreateEntry_METHOD *) ROOT_CreateEntry,
  172. (ABC_CopyEntries_METHOD *) ROOT_CopyEntries,
  173. (ABC_DeleteEntries_METHOD *) ROOT_DeleteEntries,
  174. (ABC_ResolveNames_METHOD *) ROOT_ResolveNames
  175. };
  176. static const SizedSPropTagArray(1, ABC_SPT_TMP_FAB) = {1, {PR_FAB_FILE_TEMP_A}};
  177. /*
  178. * Private functions
  179. */
  180. HRESULT HrNewABCButton( LPABCNT lpABC,
  181. ULONG ulInterfaceOptions,
  182. ULONG ulFlags,
  183. LPMAPICONTROL FAR * lppMAPICont);
  184. HRESULT HrGetSearchDialog(LPABCNT lpABC, LPMAPITABLE * lppSearchTable);
  185. HRESULT HrGetDetailsDialog(LPABCNT lpABC, LPMAPITABLE * lppDetailsTable);
  186. /*************************************************************************
  187. *
  188. - HrNewFaxDirectory
  189. -
  190. * Creates a Directory container object.
  191. *
  192. *
  193. */
  194. /*
  195. * Properties that are initially set on this object
  196. */
  197. enum { ivalabcPR_DISPLAY_TYPE = 0,
  198. ivalabcPR_OBJECT_TYPE,
  199. ivalabcPR_ENTRYID,
  200. ivalabcPR_RECORD_KEY,
  201. ivalabcPR_SEARCH_KEY,
  202. ivalabcPR_DISPLAY_NAME,
  203. ivalabcPR_CONTAINER_FLAGS,
  204. ivalabcPR_FAB_FILE,
  205. ivalabcPR_FAB_FILE_TEMP,
  206. ivalabcPR_IMPORT_FROM_FILE,
  207. ivalabcPR_IMPORT_TO_FILE,
  208. ivalabcPR_IMPORT_FORMAT,
  209. cvalabcMax };
  210. HRESULT
  211. HrNewFaxDirectory( LPABCONT * lppABC,
  212. ULONG * lpulObjType,
  213. LPABLOGON lpABLogon,
  214. LPCIID lpInterface,
  215. HINSTANCE hLibrary,
  216. LPALLOCATEBUFFER lpAllocBuff,
  217. LPALLOCATEMORE lpAllocMore,
  218. LPFREEBUFFER lpFreeBuff,
  219. LPMALLOC lpMalloc )
  220. {
  221. HINSTANCE hInst;
  222. HRESULT hResult = hrSuccess;
  223. LPABCNT lpABC = NULL;
  224. SCODE sc;
  225. LPPROPDATA lpPropData = NULL;
  226. SPropValue spv[cvalabcMax];
  227. MAPIUID * lpMuidLogon;
  228. LPTSTR lpszFileName;
  229. #ifdef UNICODE
  230. CHAR szAnsiFileName[ MAX_PATH ];
  231. #endif
  232. ULONG ulPropAccess = IPROP_CLEAN|IPROP_READWRITE; /* READWRITE is redundant */
  233. DIR_ENTRYID eidRoot = { {0, 0, 0, 0},
  234. MUIDABMAWF,
  235. MAWF_VERSION,
  236. MAWF_DIRECTORY
  237. };
  238. /* Do I support this interface?? */
  239. if (lpInterface)
  240. {
  241. if (memcmp(lpInterface, &IID_IABContainer, SIZEOF(IID)) &&
  242. memcmp(lpInterface, &IID_IMAPIContainer, SIZEOF(IID)) &&
  243. memcmp(lpInterface, &IID_IMAPIProp, SIZEOF(IID)) &&
  244. memcmp(lpInterface, &IID_IUnknown, SIZEOF(IID)))
  245. {
  246. DebugTraceSc(HrNewSampDirectory, MAPI_E_INTERFACE_NOT_SUPPORTED);
  247. return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  248. }
  249. }
  250. /*
  251. * Allocate space for the directory container structure
  252. */
  253. sc = lpAllocBuff( SIZEOF(ABCNT), (LPVOID *) & lpABC);
  254. if (sc != SUCCESS_SUCCESS)
  255. {
  256. DebugTraceSc( HrNewFaxDirectory, sc );
  257. hResult = ResultFromScode( sc );
  258. goto err;
  259. }
  260. lpABC->lpVtbl = &vtblABC;
  261. lpABC->lcInit = 1;
  262. lpABC->hResult = hrSuccess;
  263. lpABC->idsLastError = 0;
  264. lpABC->hLibrary = hLibrary;
  265. lpABC->lpAllocBuff = lpAllocBuff;
  266. lpABC->lpAllocMore = lpAllocMore;
  267. lpABC->lpFreeBuff = lpFreeBuff;
  268. lpABC->lpMalloc = lpMalloc;
  269. lpABC->lpABLogon = lpABLogon;
  270. lpABC->lpTDatDetails = NULL;
  271. // Get the instance handle, so that I can get the display strings off the resource file
  272. hInst = lpABC->hLibrary;
  273. /*
  274. * Create lpPropData
  275. */
  276. sc = CreateIProp( (LPIID) &IID_IMAPIPropData,
  277. lpAllocBuff,
  278. lpAllocMore,
  279. lpFreeBuff,
  280. lpMalloc,
  281. &lpPropData
  282. );
  283. if (FAILED(sc))
  284. {
  285. DebugTraceSc(HrNewFaxDirectory, sc);
  286. hResult=ResultFromScode (sc);
  287. goto err;
  288. }
  289. /*
  290. * initialize the muid in the entry id
  291. */
  292. lpMuidLogon = LpMuidFromLogon(lpABLogon);
  293. eidRoot.muidID = *lpMuidLogon;
  294. /*
  295. * Set up initial set of properties associated with this
  296. * container.
  297. */
  298. spv[ivalabcPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
  299. spv[ivalabcPR_DISPLAY_TYPE].Value.l = DT_NOT_SPECIFIC;
  300. spv[ivalabcPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
  301. spv[ivalabcPR_OBJECT_TYPE].Value.l = MAPI_ABCONT;
  302. spv[ivalabcPR_ENTRYID].ulPropTag = PR_ENTRYID;
  303. spv[ivalabcPR_ENTRYID].Value.bin.cb = SIZEOF(DIR_ENTRYID);
  304. spv[ivalabcPR_ENTRYID].Value.bin.lpb = (LPBYTE) &eidRoot;
  305. spv[ivalabcPR_RECORD_KEY].ulPropTag = PR_RECORD_KEY;
  306. spv[ivalabcPR_RECORD_KEY].Value.bin.cb = SIZEOF(DIR_ENTRYID);
  307. spv[ivalabcPR_RECORD_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
  308. spv[ivalabcPR_SEARCH_KEY].ulPropTag = PR_SEARCH_KEY;
  309. spv[ivalabcPR_SEARCH_KEY].Value.bin.cb = SIZEOF(DIR_ENTRYID);
  310. spv[ivalabcPR_SEARCH_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
  311. // MAPI is not UNICODE for this one...
  312. spv[ivalabcPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
  313. // MAPI 304 sample AB
  314. // GenerateContainerDN(lpABLogon, szBuf);
  315. // spv[ivalabcPR_DISPLAY_NAME].Value.LPSZ = szBuf;
  316. if ( (sc = lpAllocMore( MAX_DISPLAY_NAME,
  317. (LPVOID) lpABC,
  318. (LPVOID *) & spv[ivalabcPR_DISPLAY_NAME].Value.lpszA)) != SUCCESS_SUCCESS)
  319. {
  320. hResult = ResultFromScode( sc );
  321. goto err;
  322. }
  323. else
  324. {
  325. // Load the strings
  326. // A display name longer than MAX_DISPLAY_NAME will be truncated
  327. // MAPI is not UNICODE for this attribute
  328. LoadStringA( hInst,
  329. IDS_APP_NAME,
  330. spv[ivalabcPR_DISPLAY_NAME].Value.lpszA,
  331. MAX_DISPLAY_NAME
  332. );
  333. }
  334. spv[ivalabcPR_CONTAINER_FLAGS].ulPropTag = PR_CONTAINER_FLAGS;
  335. spv[ivalabcPR_CONTAINER_FLAGS].Value.l = AB_RECIPIENTS;
  336. /*
  337. * Get the current .FAB file name from our logon object
  338. */
  339. hResult = HrLpszGetCurrentFileName(lpABLogon, &lpszFileName);
  340. if (HR_FAILED(hResult))
  341. {
  342. goto err;
  343. }
  344. // MAPI ==> NO UNICODE FOR YOU! <MAPI Doesn't like UNICODE>
  345. #ifdef UNICODE
  346. spv[ivalabcPR_FAB_FILE].ulPropTag = PR_FAB_FILE_A;
  347. szAnsiFileName[0] = 0;
  348. WideCharToMultiByte( CP_ACP, 0, lpszFileName, -1, szAnsiFileName, ARRAYSIZE(szAnsiFileName), NULL, NULL );
  349. spv[ivalabcPR_FAB_FILE].Value.lpszA = szAnsiFileName;
  350. spv[ivalabcPR_FAB_FILE_TEMP].ulPropTag = PR_FAB_FILE_TEMP_A;
  351. spv[ivalabcPR_FAB_FILE_TEMP].Value.lpszA = szAnsiFileName;
  352. spv[ivalabcPR_IMPORT_FROM_FILE].ulPropTag = PR_IMPORT_FROM_FILE_A;
  353. spv[ivalabcPR_IMPORT_FROM_FILE].Value.lpszA = "";
  354. spv[ivalabcPR_IMPORT_TO_FILE].ulPropTag = PR_IMPORT_TO_FILE_A;
  355. spv[ivalabcPR_IMPORT_TO_FILE].Value.lpszA = szAnsiFileName;
  356. #else
  357. spv[ivalabcPR_FAB_FILE].ulPropTag = PR_FAB_FILE_A;
  358. spv[ivalabcPR_FAB_FILE].Value.lpszA = (LPSTR)lpszFileName;
  359. spv[ivalabcPR_FAB_FILE_TEMP].ulPropTag = PR_FAB_FILE_TEMP_A;
  360. spv[ivalabcPR_FAB_FILE_TEMP].Value.lpszA = (LPSTR)lpszFileName;
  361. spv[ivalabcPR_IMPORT_FROM_FILE].ulPropTag = PR_IMPORT_FROM_FILE_A;
  362. spv[ivalabcPR_IMPORT_FROM_FILE].Value.lpszA = "";
  363. spv[ivalabcPR_IMPORT_TO_FILE].ulPropTag = PR_IMPORT_TO_FILE_A;
  364. spv[ivalabcPR_IMPORT_TO_FILE].Value.lpszA = (LPSTR)lpszFileName;
  365. #endif
  366. spv[ivalabcPR_IMPORT_FORMAT].ulPropTag = PR_IMPORT_FORMAT_A;
  367. spv[ivalabcPR_IMPORT_FORMAT].Value.lpszA = "Your Favorite PIM";
  368. /*
  369. * Set the default properties
  370. */
  371. hResult = lpPropData->lpVtbl->SetProps( lpPropData,
  372. cvalabcMax,
  373. spv,
  374. NULL
  375. );
  376. /*
  377. * No longer need this buffer
  378. */
  379. lpFreeBuff(lpszFileName);
  380. if (HR_FAILED(hResult))
  381. {
  382. DebugTraceSc( HrNewFaxDirectory, sc );
  383. goto err;
  384. }
  385. lpPropData->lpVtbl->HrSetPropAccess( lpPropData,
  386. (LPSPropTagArray) &ABC_SPT_TMP_FAB,
  387. &ulPropAccess
  388. );
  389. InitializeCriticalSection( &lpABC->cs );
  390. lpABC->lpPropData = (LPMAPIPROP)lpPropData;
  391. *lppABC = (LPABCONT)lpABC;
  392. *lpulObjType = MAPI_ABCONT;
  393. out:
  394. DebugTraceResult(HrNewFaxDirectory, hResult);
  395. return hResult;
  396. err:
  397. /*
  398. * free the ABContainer object
  399. */
  400. lpFreeBuff( lpABC );
  401. /*
  402. * free the property storage object
  403. */
  404. if (lpPropData)
  405. lpPropData->lpVtbl->Release(lpPropData);
  406. goto out;
  407. }
  408. /***************************************************
  409. *
  410. * The actual ABContainer methods
  411. */
  412. /* --------
  413. * IUnknown
  414. */
  415. /*************************************************************************
  416. *
  417. *
  418. - ABC_QueryInterface
  419. -
  420. *
  421. * Uses the ROOT method
  422. *
  423. */
  424. /*************************************************************************
  425. *
  426. - ABC_AddRef
  427. -
  428. *
  429. * Uses the ROOT method
  430. *
  431. */
  432. /**************************************************
  433. *
  434. - ABC_Release
  435. -
  436. * Decrement lpInit.
  437. * When lcInit == 0, free up the lpABC structure
  438. *
  439. */
  440. STDMETHODIMP_(ULONG)
  441. ABC_Release(LPABCNT lpABC)
  442. {
  443. long lcInit;
  444. /*
  445. * Check to see if it has a jump table
  446. */
  447. if (IsBadReadPtr(lpABC, SIZEOF(ABCNT)))
  448. {
  449. /*
  450. * No jump table found
  451. */
  452. return 1;
  453. }
  454. /*
  455. * Check to see that it's the correct jump table
  456. */
  457. if (lpABC->lpVtbl != &vtblABC)
  458. {
  459. /*
  460. * Not my jump table
  461. */
  462. return 1;
  463. }
  464. EnterCriticalSection(&lpABC->cs);
  465. lcInit = --lpABC->lcInit;
  466. LeaveCriticalSection(&lpABC->cs);
  467. if (lcInit == 0)
  468. {
  469. /*
  470. * Get rid of the lpPropData
  471. */
  472. if (lpABC->lpPropData)
  473. lpABC->lpPropData->lpVtbl->Release(lpABC->lpPropData);
  474. /*
  475. * Get rid of the details table
  476. */
  477. if (lpABC->lpTDatDetails)
  478. lpABC->lpTDatDetails->lpVtbl->Release(lpABC->lpTDatDetails);
  479. /*
  480. * Destroy the critical section for this object
  481. */
  482. DeleteCriticalSection(&lpABC->cs);
  483. /*
  484. * Set the Jump table to NULL. This way the client will find out
  485. * real fast if it's calling a method on a released object. That is,
  486. * the client will crash. Hopefully, this will happen during the
  487. * development stage of the client.
  488. */
  489. lpABC->lpVtbl = NULL;
  490. /*
  491. * Need to free the object
  492. */
  493. lpABC->lpFreeBuff(lpABC);
  494. return 0;
  495. }
  496. return lpABC->lcInit;
  497. }
  498. /* ---------
  499. * IMAPIProp
  500. */
  501. /*
  502. * GetLastError - use ROOT's
  503. *
  504. *
  505. */
  506. /*************************************************************************
  507. *
  508. - ABC_SaveChanges
  509. -
  510. * This is used to save changes associated with the search dialog
  511. * in order to get the advanced search restriction and to save changes
  512. * associated with the container details dialog.
  513. *
  514. */
  515. SPropTagArray SPT_FAB_FILE =
  516. {
  517. 1,
  518. {
  519. PR_FAB_FILE_TEMP_A
  520. }
  521. };
  522. STDMETHODIMP
  523. ABC_SaveChanges (LPABCNT lpABC, ULONG ulFlags)
  524. {
  525. HRESULT hResult = hrSuccess;
  526. ULONG ulCount;
  527. LPSPropValue lpspv = NULL;
  528. ULONG FAR * rgulAccess = NULL;
  529. ULONG ulAccess = IPROP_CLEAN|IPROP_READWRITE; /* READWRITE is redundant */
  530. LPSPropTagArray lpspt = (LPSPropTagArray) &ABC_SPT_TMP_FAB;
  531. LPPROPDATA lpPropData = (LPPROPDATA) lpABC->lpPropData;
  532. #ifdef UNICODE
  533. WCHAR szFileName[ MAX_PATH ];
  534. #endif
  535. /*
  536. * Check to see if it has a jump table
  537. */
  538. if (IsBadReadPtr(lpABC, sizeof(ABCNT)))
  539. {
  540. /*
  541. * No jump table found
  542. */
  543. hResult = ResultFromScode(E_INVALIDARG);
  544. return hResult;
  545. }
  546. /*
  547. * Check to see that it's the correct jump table
  548. */
  549. if (lpABC->lpVtbl != &vtblABC)
  550. {
  551. /*
  552. * Not my jump table
  553. */
  554. hResult = ResultFromScode(E_INVALIDARG);
  555. return hResult;
  556. }
  557. EnterCriticalSection(&lpABC->cs);
  558. /*
  559. * Check to see if anyone has dirtied the PR_FAB_FILE_TEMP
  560. */
  561. lpPropData->lpVtbl->HrGetPropAccess( lpPropData, (LPSPropTagArray *) &lpspt, &rgulAccess);
  562. if (!rgulAccess || !((*rgulAccess) & IPROP_DIRTY))
  563. {
  564. /*
  565. * No, nothing to update then head on out
  566. */
  567. goto ret;
  568. }
  569. /*
  570. * Go ahead and set back to being clean
  571. */
  572. (void )lpPropData->lpVtbl->HrSetPropAccess( lpPropData, (LPSPropTagArray) lpspt, &ulAccess);
  573. /*
  574. * Get the temporary fab file name
  575. */
  576. hResult = lpPropData->lpVtbl->GetProps(
  577. lpPropData,
  578. &SPT_FAB_FILE,
  579. 0, // ansi
  580. &ulCount,
  581. &lpspv);
  582. if (HR_FAILED(hResult))
  583. {
  584. goto ret;
  585. }
  586. if (lpspv->ulPropTag != PR_FAB_FILE_TEMP_A)
  587. {
  588. /*
  589. * There's no reason this property shouldn't be there.
  590. */
  591. hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
  592. goto ret;
  593. }
  594. /*
  595. * Save the new name back into the object as PR_FAB_FILE
  596. */
  597. lpspv->ulPropTag = PR_FAB_FILE_A;
  598. hResult = lpPropData->lpVtbl->SetProps(
  599. lpPropData,
  600. 1, // ANSI
  601. lpspv, NULL);
  602. if (HR_FAILED(hResult))
  603. {
  604. /*
  605. * Do nothing... So I couldn't save it away this time...
  606. */
  607. hResult = hrSuccess;
  608. goto ret;
  609. }
  610. /*
  611. * Update every other object that needs this new information
  612. */
  613. #ifdef UNICODE
  614. szFileName[0] = 0;
  615. MultiByteToWideChar( CP_ACP, 0, lpspv->Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
  616. hResult = HrReplaceCurrentFileName(lpABC->lpABLogon, szFileName);
  617. #else
  618. hResult = HrReplaceCurrentFileName(lpABC->lpABLogon, lpspv->Value.LPSZ);
  619. #endif
  620. ret:
  621. LeaveCriticalSection(&lpABC->cs);
  622. lpABC->lpFreeBuff(lpspv);
  623. lpABC->lpFreeBuff(rgulAccess);
  624. DebugTraceResult(ABC_SaveChanges, hResult);
  625. return hResult;
  626. }
  627. /*************************************************************************
  628. *
  629. - ABC_OpenProperty
  630. -
  631. * This method allows the opening of the following object:
  632. *
  633. * PR_BUTTON_PRESS :- Gets the MAPIControl object associated
  634. * with the button on this container's details.
  635. * PR_DETAILS_TABLE :- Gets the display table associated with
  636. * the details for this container.
  637. * PR_SEARCH :- Gets the advanced search object associated with
  638. * this container.
  639. * PR_CONTAINER_CONTENTS :- Same as GetContentsTable()
  640. * PR_CONTAINER_HIERARCHY :- Same as GetHierarchyTable()
  641. *
  642. */
  643. STDMETHODIMP
  644. ABC_OpenProperty( LPABCNT lpABC,
  645. ULONG ulPropTag,
  646. LPCIID lpiid,
  647. ULONG ulInterfaceOptions,
  648. ULONG ulFlags,
  649. LPUNKNOWN * lppUnk
  650. )
  651. {
  652. HRESULT hResult;
  653. /*
  654. * Check to see if it has a jump table
  655. */
  656. if (IsBadReadPtr(lpABC, SIZEOF(ABCNT)))
  657. {
  658. /*
  659. * No jump table found
  660. */
  661. hResult = ResultFromScode( E_INVALIDARG );
  662. DebugTraceResult( ABC_OpenProperty, hResult );
  663. goto out;
  664. }
  665. /*
  666. * Check to see that it's the correct jump table
  667. */
  668. if (lpABC->lpVtbl != &vtblABC)
  669. {
  670. /*
  671. * Not my jump table
  672. */
  673. hResult = ResultFromScode( E_INVALIDARG );
  674. DebugTraceResult(ABC_OpenProperty, hResult);
  675. goto out;
  676. }
  677. if (IsBadWritePtr(lppUnk, sizeof(LPUNKNOWN)))
  678. {
  679. /*
  680. * Got to be able to return an object
  681. */
  682. hResult = ResultFromScode(E_INVALIDARG);
  683. goto out;
  684. }
  685. if (IsBadReadPtr(lpiid, (UINT) SIZEOF(IID)))
  686. {
  687. /*
  688. * An interface ID is required for this call.
  689. */
  690. hResult = ResultFromScode(E_INVALIDARG);
  691. goto out;
  692. }
  693. /*
  694. * check for unknown flags
  695. */
  696. if (ulFlags & ~(MAPI_DEFERRED_ERRORS | MAPI_CREATE | MAPI_MODIFY))
  697. {
  698. hResult = ResultFromScode (MAPI_E_UNKNOWN_FLAGS);
  699. DebugTraceResult(ABC_OpenProperty, hResult);
  700. goto out;
  701. }
  702. /*
  703. * Check for flags we can't support
  704. */
  705. if (ulFlags & (MAPI_CREATE|MAPI_MODIFY))
  706. {
  707. hResult = ResultFromScode (E_ACCESSDENIED);
  708. DebugTraceResult(ABC_OpenProperty, hResult);
  709. goto out;
  710. }
  711. if (ulInterfaceOptions & ~MAPI_UNICODE)
  712. {
  713. /*
  714. * Only UNICODE flag should be set for any of the objects that might
  715. * be returned from this object.
  716. */
  717. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  718. goto out;
  719. }
  720. if ( ulInterfaceOptions & MAPI_UNICODE )
  721. {
  722. hResult = ResultFromScode(MAPI_E_BAD_CHARWIDTH);
  723. DebugTraceArg( ABC_OpenProperty, "bad character width" );
  724. goto out;
  725. }
  726. /*
  727. * Details for this directory entry
  728. */
  729. if ( (ulPropTag == PR_DETAILS_TABLE) ||
  730. (ulPropTag == PR_BUTTON_PRESS) ||
  731. (ulPropTag == PR_CONTAINER_CONTENTS) ||
  732. (ulPropTag == PR_CONTAINER_HIERARCHY)||
  733. (ulPropTag == PR_SEARCH)
  734. )
  735. {
  736. /*
  737. * Check to see if they're expecting a table interface
  738. */
  739. if ( (ulPropTag != PR_BUTTON_PRESS) &&
  740. (ulPropTag != PR_SEARCH) &&
  741. memcmp(lpiid, &IID_IMAPITable, sizeof(IID))
  742. )
  743. {
  744. hResult = ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  745. goto out;
  746. }
  747. switch (ulPropTag)
  748. {
  749. case PR_BUTTON_PRESS:
  750. {
  751. /*
  752. * Check to see if they're expecting a generic control interface
  753. */
  754. if (memcmp( lpiid, &IID_IMAPIControl, SIZEOF(IID) ))
  755. {
  756. hResult = ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  757. goto out;
  758. }
  759. hResult = HrNewABCButton( lpABC,
  760. ulInterfaceOptions,
  761. ulFlags,
  762. (LPMAPICONTROL FAR *) lppUnk
  763. );
  764. break;
  765. }
  766. case PR_DETAILS_TABLE:
  767. {
  768. hResult = HrGetDetailsDialog(lpABC, (LPMAPITABLE *) lppUnk);
  769. break;
  770. }
  771. case PR_SEARCH:
  772. {
  773. /*
  774. * Check to see if they're expecting a generic control interface
  775. */
  776. if (memcmp(lpiid, &IID_IMAPIContainer, SIZEOF(IID)))
  777. {
  778. hResult = ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  779. goto out;
  780. }
  781. hResult = HrNewSearch( (LPMAPICONTAINER *) lppUnk,
  782. lpABC->lpABLogon,
  783. lpiid,
  784. lpABC->hLibrary,
  785. lpABC->lpAllocBuff,
  786. lpABC->lpAllocMore,
  787. lpABC->lpFreeBuff,
  788. lpABC->lpMalloc
  789. );
  790. break;
  791. }
  792. case PR_CONTAINER_CONTENTS:
  793. {
  794. hResult = ABC_GetContentsTable( lpABC, 0, (LPMAPITABLE *) lppUnk);
  795. break;
  796. }
  797. case PR_CONTAINER_HIERARCHY:
  798. {
  799. hResult = ABC_GetHierarchyTable( lpABC, 0, (LPMAPITABLE *) lppUnk);
  800. break;
  801. }
  802. default:
  803. break;
  804. }
  805. }
  806. else
  807. {
  808. hResult = ResultFromScode (MAPI_E_NO_SUPPORT);
  809. }
  810. out:
  811. DebugTraceResult(ABC_OpenProperty, hResult);
  812. return hResult;
  813. }
  814. /*************************************************************************
  815. *
  816. - ABC_GetContentsTable
  817. -
  818. *
  819. * Retrieves the IMAPITable that has the contents of this container.
  820. * The big one!
  821. */
  822. STDMETHODIMP
  823. ABC_GetContentsTable( LPABCNT lpABC,
  824. ULONG ulFlags,
  825. LPMAPITABLE * lppTable
  826. )
  827. {
  828. HRESULT hResult;
  829. /*
  830. * Validate parameters
  831. */
  832. /*
  833. * Check to see if it's large enough to be this object
  834. */
  835. if (IsBadReadPtr(lpABC, SIZEOF(ABCNT)))
  836. {
  837. /*
  838. * Not large enough to be this object
  839. */
  840. hResult = ResultFromScode(E_INVALIDARG);
  841. goto out;
  842. }
  843. /*
  844. * Check to see that it's the correct jump table
  845. */
  846. if (lpABC->lpVtbl != &vtblABC)
  847. {
  848. /*
  849. * Not my jump table
  850. */
  851. hResult = ResultFromScode (E_INVALIDARG);
  852. goto out;
  853. }
  854. /*
  855. * Check lppTable to validate its writability
  856. */
  857. if (IsBadWritePtr (lppTable, SIZEOF(LPMAPITABLE)))
  858. {
  859. hResult = ResultFromScode (E_INVALIDARG);
  860. goto out;
  861. }
  862. /*
  863. * Check flags
  864. */
  865. if (ulFlags & ~(MAPI_UNICODE|MAPI_DEFERRED_ERRORS|MAPI_ASSOCIATED))
  866. {
  867. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  868. goto out;
  869. }
  870. /*
  871. * Certain flags are not supported
  872. */
  873. if (ulFlags & (MAPI_ASSOCIATED))
  874. {
  875. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  876. goto out;
  877. }
  878. if ( ulFlags & MAPI_UNICODE )
  879. {
  880. DebugTraceArg( ABC_GetContentsTable, "Bad character width" );
  881. hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  882. goto out;
  883. }
  884. /*
  885. * Create the new Contents table
  886. */
  887. hResult = HrNewIVTAbc( lppTable,
  888. lpABC->lpABLogon,
  889. (LPABCONT) lpABC,
  890. lpABC->hLibrary,
  891. lpABC->lpAllocBuff,
  892. lpABC->lpAllocMore,
  893. lpABC->lpFreeBuff,
  894. lpABC->lpMalloc
  895. );
  896. out:
  897. DebugTraceResult(ABC_GetContentsTable, hResult);
  898. return hResult;
  899. }
  900. /*************************************************************************
  901. *
  902. - ABC_GetHierarchyTable
  903. -
  904. *
  905. * There is no hierarchy table associated with this object.
  906. *
  907. */
  908. STDMETHODIMP
  909. ABC_GetHierarchyTable( LPABCNT lpABC,
  910. ULONG ulFlags,
  911. LPMAPITABLE * lppTable
  912. )
  913. {
  914. HRESULT hResult;
  915. /*
  916. * Check to see if it has a lpVtbl object member
  917. */
  918. if (IsBadReadPtr(lpABC, offsetof(ABCNT, lpVtbl)+SIZEOF(ABC_Vtbl *)))
  919. {
  920. /*
  921. * Not large enough
  922. */
  923. hResult = MakeResult(E_INVALIDARG);
  924. DebugTraceResult(ABC_HierarchyTable, hResult);
  925. return hResult;
  926. }
  927. /*
  928. * Check to see that the Vtbl is large enough to include this method
  929. */
  930. if (IsBadReadPtr(lpABC->lpVtbl,
  931. offsetof(ABC_Vtbl, GetHierarchyTable)+SIZEOF(ABC_GetHierarchyTable_METHOD *)))
  932. {
  933. /*
  934. * Jump table not derived from IUnknown
  935. */
  936. hResult = MakeResult(E_INVALIDARG);
  937. DebugTraceResult(ABC_HierarchyTable, hResult);
  938. return hResult;
  939. }
  940. /*
  941. * Check to see if the method is the same
  942. */
  943. if (ABC_GetHierarchyTable != lpABC->lpVtbl->GetHierarchyTable)
  944. {
  945. /*
  946. * Wrong object - the object passed doesn't have this
  947. * method.
  948. */
  949. hResult = ResultFromScode(E_INVALIDARG);
  950. DebugTraceResult(ABC_HierarchyTable, hResult);
  951. return hResult;
  952. }
  953. /*
  954. * See if I can set the return variable
  955. */
  956. if (IsBadWritePtr(lppTable, SIZEOF(LPMAPITABLE)))
  957. {
  958. hResult = ResultFromScode(E_INVALIDARG);
  959. goto out;
  960. }
  961. /*
  962. * Check flags:
  963. * The only valid flags are CONVENIENT_DEPTH and MAPI_DEFERRED_ERRORS
  964. */
  965. if (ulFlags & ~(CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS))
  966. {
  967. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  968. goto out;
  969. }
  970. /*
  971. * We don't support this method on this object
  972. */
  973. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  974. out:
  975. DebugTraceResult(ABC_GetHierarchyTable, hResult);
  976. return hResult;
  977. }
  978. /*
  979. * OpenEntry() <- uses ROOT's
  980. */
  981. /*
  982. * SetSearchCriteria() <- uses ROOT's
  983. */
  984. /*
  985. * GetSearchCriteria() <- uses ROOT's
  986. */
  987. /*
  988. * ABC_CreateEntry() <- uses ROOT's
  989. */
  990. /*
  991. * ABC_CopyEntries() <- uses ROOT's
  992. */
  993. /*
  994. * ABC_DeleteEntries() <- uses ROOT's
  995. */
  996. /**********************************************************************
  997. *
  998. * Private functions
  999. */
  1000. /*
  1001. - HrGetDetailsDialog
  1002. -
  1003. * Builds a display table for this directory.
  1004. */
  1005. HRESULT
  1006. HrGetDetailsDialog(LPABCNT lpABC, LPMAPITABLE * lppDetailsTable)
  1007. {
  1008. HRESULT hResult;
  1009. /* Create a display table */
  1010. if (!lpABC->lpTDatDetails)
  1011. {
  1012. /* Create a display table */
  1013. hResult = BuildDisplayTable(
  1014. lpABC->lpAllocBuff,
  1015. lpABC->lpAllocMore,
  1016. lpABC->lpFreeBuff,
  1017. lpABC->lpMalloc,
  1018. lpABC->hLibrary,
  1019. SIZEOF(rgdtpageDir) / SIZEOF(DTPAGE),
  1020. rgdtpageDir,
  1021. 0,
  1022. lppDetailsTable,
  1023. &lpABC->lpTDatDetails);
  1024. }
  1025. else
  1026. {
  1027. hResult = lpABC->lpTDatDetails->lpVtbl->HrGetView(
  1028. lpABC->lpTDatDetails,
  1029. NULL,
  1030. NULL,
  1031. 0,
  1032. lppDetailsTable);
  1033. }
  1034. DebugTraceResult(HrGetDetailsDialog, hResult);
  1035. return hResult;
  1036. }
  1037. /*
  1038. * Button object for this directory's details dialog
  1039. */
  1040. ABCBUTT_Vtbl vtblABCBUTT =
  1041. {
  1042. ABCBUTT_QueryInterface,
  1043. (ABCBUTT_AddRef_METHOD *) ROOT_AddRef,
  1044. ABCBUTT_Release,
  1045. (ABCBUTT_GetLastError_METHOD *) ROOT_GetLastError,
  1046. ABCBUTT_Activate,
  1047. ABCBUTT_GetState
  1048. };
  1049. HRESULT
  1050. HrNewABCButton( LPABCNT lpABC,
  1051. ULONG ulInterfaceOptions,
  1052. ULONG ulFlags,
  1053. LPMAPICONTROL FAR * lppMAPICont
  1054. )
  1055. {
  1056. LPABCBUTT lpABCButt = NULL;
  1057. SCODE scode;
  1058. /*
  1059. * Creates a the object behind the button control in the directory
  1060. * details dialog...
  1061. */
  1062. scode = lpABC->lpAllocBuff(SIZEOF(ABCBUTT),(LPVOID *) &lpABCButt);
  1063. if (FAILED(scode))
  1064. {
  1065. DebugTraceSc(HrNewABCButton, scode);
  1066. return ResultFromScode(scode);
  1067. }
  1068. lpABCButt->lpVtbl = &vtblABCBUTT;
  1069. lpABCButt->lcInit = 1;
  1070. lpABCButt->hResult = hrSuccess;
  1071. lpABCButt->idsLastError = 0;
  1072. lpABCButt->hLibrary = lpABC->hLibrary;
  1073. lpABCButt->lpAllocBuff = lpABC->lpAllocBuff;
  1074. lpABCButt->lpAllocMore = lpABC->lpAllocMore;
  1075. lpABCButt->lpFreeBuff = lpABC->lpFreeBuff;
  1076. lpABCButt->lpMalloc = lpABC->lpMalloc;
  1077. lpABCButt->lpABC = lpABC;
  1078. lpABC->lpVtbl->AddRef(lpABC);
  1079. InitializeCriticalSection(&lpABCButt->cs);
  1080. *lppMAPICont = (LPMAPICONTROL) lpABCButt;
  1081. return hrSuccess;
  1082. }
  1083. /*************************************************************************
  1084. *
  1085. *
  1086. - ABCBUTT_QueryInterface
  1087. -
  1088. *
  1089. * Allows QI'ing to IUnknown and IMAPIControl.
  1090. *
  1091. *
  1092. */
  1093. STDMETHODIMP
  1094. ABCBUTT_QueryInterface( LPABCBUTT lpABCButt,
  1095. REFIID lpiid,
  1096. LPVOID FAR * lppNewObj
  1097. )
  1098. {
  1099. HRESULT hResult = hrSuccess;
  1100. /* Minimally validate the lpABCButt parameter */
  1101. if (IsBadReadPtr(lpABCButt, SIZEOF(ABCBUTT)))
  1102. {
  1103. hResult = ResultFromScode(E_INVALIDARG);
  1104. goto out;
  1105. }
  1106. if (lpABCButt->lpVtbl != &vtblABCBUTT)
  1107. {
  1108. hResult = ResultFromScode(E_INVALIDARG);
  1109. goto out;
  1110. }
  1111. /* Check the other parameters */
  1112. if (!lpiid || IsBadReadPtr(lpiid, (UINT) SIZEOF(IID)))
  1113. {
  1114. hResult = ResultFromScode(E_INVALIDARG);
  1115. goto out;
  1116. }
  1117. if (IsBadWritePtr(lppNewObj, (UINT) SIZEOF(LPVOID)))
  1118. {
  1119. hResult = ResultFromScode(E_INVALIDARG);
  1120. goto out;
  1121. }
  1122. /* See if the requested interface is one of ours */
  1123. if ( memcmp (lpiid, &IID_IUnknown, SIZEOF(IID)) &&
  1124. memcmp (lpiid, &IID_IMAPIControl, SIZEOF(IID))
  1125. )
  1126. {
  1127. *lppNewObj = NULL; /* OLE requires zeroing [out] parameter */
  1128. hResult = ResultFromScode(E_NOINTERFACE);
  1129. goto out;
  1130. }
  1131. /* We'll do this one. Bump the usage count and return a new pointer. */
  1132. EnterCriticalSection(&lpABCButt->cs);
  1133. ++lpABCButt->lcInit;
  1134. LeaveCriticalSection(&lpABCButt->cs);
  1135. *lppNewObj = lpABCButt;
  1136. out:
  1137. DebugTraceResult(ABCBUTT_QueryInterface, hResult);
  1138. return hResult;
  1139. }
  1140. /*
  1141. - ABCBUTT_Release
  1142. -
  1143. * Releases and cleans up this object
  1144. */
  1145. STDMETHODIMP_(ULONG)
  1146. ABCBUTT_Release(LPABCBUTT lpABCButt)
  1147. {
  1148. long lcInit;
  1149. /* Minimally validate the lpABCButt parameter */
  1150. if (IsBadReadPtr(lpABCButt, SIZEOF(ABCBUTT)))
  1151. {
  1152. return 1;
  1153. }
  1154. if (lpABCButt->lpVtbl != &vtblABCBUTT)
  1155. {
  1156. return 1;
  1157. }
  1158. EnterCriticalSection(&lpABCButt->cs);
  1159. lcInit = --lpABCButt->lcInit;
  1160. LeaveCriticalSection(&lpABCButt->cs);
  1161. if (lcInit == 0)
  1162. {
  1163. /*
  1164. * Release my parent
  1165. */
  1166. lpABCButt->lpABC->lpVtbl->Release(lpABCButt->lpABC);
  1167. /*
  1168. * Destroy the critical section for this object
  1169. */
  1170. DeleteCriticalSection(&lpABCButt->cs);
  1171. /*
  1172. * Set the Jump table to NULL. This way the client will find out
  1173. * real fast if it's calling a method on a released object. That is,
  1174. * the client will crash. Hopefully, this will happen during the
  1175. * development stage of the client.
  1176. */
  1177. lpABCButt->lpVtbl = NULL;
  1178. /*
  1179. * Free the object
  1180. */
  1181. lpABCButt->lpFreeBuff(lpABCButt);
  1182. return 0;
  1183. }
  1184. return lcInit;
  1185. }
  1186. /*
  1187. - ABCBUTT_Activate
  1188. -
  1189. *
  1190. * Activates this control. In this case, it brings up the common file browsing
  1191. * dialog and allows the user to pick a different .SAB file.
  1192. *
  1193. * Note that if all is successful it sends a display table notification. The UI
  1194. * will respond to this by updating the particular control that was said to have
  1195. * changed in the notification.
  1196. */
  1197. STDMETHODIMP
  1198. ABCBUTT_Activate( LPABCBUTT lpABCButt,
  1199. ULONG ulFlags,
  1200. ULONG ulUIParam
  1201. )
  1202. {
  1203. HRESULT hResult = hrSuccess;
  1204. OPENFILENAME openfilename;
  1205. TCHAR szFileName[MAX_PATH];
  1206. TCHAR szDirName[MAX_PATH];
  1207. SPropValue sProp;
  1208. LPSPropValue lpspv = NULL;
  1209. ULONG ulCount,ich;
  1210. #ifdef UNICODE
  1211. CHAR szAnsiFileName[ MAX_PATH ];
  1212. #endif
  1213. /* Minimally validate the lpABCButt parameter */
  1214. if (IsBadReadPtr(lpABCButt, SIZEOF(ABCBUTT)))
  1215. {
  1216. hResult = ResultFromScode(E_INVALIDARG);
  1217. goto out;
  1218. }
  1219. if (lpABCButt->lpVtbl != &vtblABCBUTT)
  1220. {
  1221. hResult = ResultFromScode(E_INVALIDARG);
  1222. goto out;
  1223. }
  1224. if (ulFlags)
  1225. {
  1226. /*
  1227. * No flags defined for this method
  1228. */
  1229. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  1230. goto out;
  1231. }
  1232. /*
  1233. * First, get the old FAB file name so that it shows up in the
  1234. * choose file dialog
  1235. */
  1236. hResult = lpABCButt->lpABC->lpPropData->lpVtbl->GetProps(
  1237. lpABCButt->lpABC->lpPropData,
  1238. &SPT_FAB_FILE,
  1239. 0, /* ansi */
  1240. &ulCount,
  1241. &lpspv);
  1242. if (HR_FAILED(hResult))
  1243. {
  1244. goto out;
  1245. }
  1246. if (lpspv->ulPropTag != PR_FAB_FILE_TEMP_A)
  1247. {
  1248. /*
  1249. * Property wasn't there...
  1250. */
  1251. hResult = ResultFromScode(MAPI_E_CORRUPT_DATA);
  1252. goto out;
  1253. }
  1254. #ifdef UNICODE
  1255. szFileName[0] = 0;
  1256. MultiByteToWideChar( CP_ACP, 0, lpspv->Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
  1257. #else
  1258. lstrcpy(szFileName, lpspv->Value.lpszA);
  1259. #endif
  1260. szDirName[0] = TEXT('\0');
  1261. /* get the path name */
  1262. // MAPI --> NO UNICODE FOR YOU! (These must be ANSI)
  1263. for (ich = lstrlenA(lpspv->Value.lpszA) - 1; ich >= 0; ich--)
  1264. {
  1265. if (lpspv->Value.lpszA[ich] == '\\')
  1266. {
  1267. lpspv->Value.lpszA[ich] = '\0';
  1268. break;
  1269. }
  1270. else if (lpspv->Value.lpszA[ich] == ':')
  1271. {
  1272. lpspv->Value.lpszA[ich + 1] = '\0';
  1273. break;
  1274. }
  1275. }
  1276. #ifdef UNICODE
  1277. szDirName[0] = 0;
  1278. MultiByteToWideChar( CP_ACP, 0, lpspv->Value.lpszA, -1, szDirName, ARRAYSIZE(szDirName) );
  1279. #else
  1280. lstrcpy(szDirName, lpspv->Value.lpszA);
  1281. #endif
  1282. /*
  1283. * Get the user to select one
  1284. */
  1285. openfilename.lStructSize = SIZEOF(OPENFILENAME);
  1286. openfilename.hwndOwner = (HWND) ulUIParam;
  1287. openfilename.hInstance = 0; /* Ignored */
  1288. openfilename.lpstrFilter = TEXT("Microsoft Fax Address Book files\0*.fab\0\0");
  1289. openfilename.lpstrCustomFilter = NULL;
  1290. openfilename.nMaxCustFilter = 0;
  1291. openfilename.nFilterIndex = 0;
  1292. openfilename.lpstrFile = szFileName;
  1293. openfilename.nMaxFile = MAX_PATH;
  1294. openfilename.lpstrFileTitle = NULL;
  1295. openfilename.nMaxFileTitle = 0;
  1296. openfilename.lpstrInitialDir = szDirName;
  1297. openfilename.lpstrTitle = TEXT("Microsoft Fax Address Book");
  1298. openfilename.Flags = OFN_FILEMUSTEXIST |
  1299. OFN_HIDEREADONLY |
  1300. OFN_NOCHANGEDIR;
  1301. openfilename.nFileOffset = 0;
  1302. openfilename.nFileExtension = 0;
  1303. openfilename.lpstrDefExt = TEXT("fab");
  1304. openfilename.lCustData = 0;
  1305. openfilename.lpfnHook = NULL;
  1306. openfilename.lpTemplateName = NULL;
  1307. /*
  1308. * Call up the common dialog
  1309. */
  1310. if (!GetOpenFileName( &openfilename ))
  1311. {
  1312. hResult = hrSuccess;
  1313. goto out;
  1314. }
  1315. /*
  1316. * Save FAB FileName into the container object
  1317. */
  1318. sProp.ulPropTag = PR_FAB_FILE_TEMP_A;
  1319. #ifdef UNICODE
  1320. szAnsiFileName[0] = 0;
  1321. WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szAnsiFileName, ARRAYSIZE(szAnsiFileName), NULL, NULL );
  1322. sProp.Value.lpszA = szAnsiFileName;
  1323. #else
  1324. sProp.Value.lpszA = szFileName;
  1325. #endif
  1326. hResult = lpABCButt->lpABC->lpPropData->lpVtbl->SetProps(
  1327. lpABCButt->lpABC->lpPropData,
  1328. 1, // ansi
  1329. &sProp,
  1330. NULL);
  1331. if (HR_FAILED(hResult))
  1332. {
  1333. goto out;
  1334. }
  1335. /*
  1336. * Notify the details table so that everyone with a view open
  1337. * will get notified
  1338. */
  1339. if (lpABCButt->lpABC->lpTDatDetails)
  1340. {
  1341. sProp.ulPropTag = PR_CONTROL_ID;
  1342. sProp.Value.bin.lpb = (LPBYTE)&notifdata;
  1343. sProp.Value.bin.cb = SIZEOF(NOTIFDATA);
  1344. hResult = lpABCButt->lpABC->lpTDatDetails->lpVtbl->HrNotify(
  1345. lpABCButt->lpABC->lpTDatDetails,
  1346. 0,
  1347. 1,
  1348. &sProp);
  1349. }
  1350. out:
  1351. lpABCButt->lpFreeBuff(lpspv);
  1352. DebugTraceResult(ABCBUTT_Activate, hResult);
  1353. return hResult;
  1354. }
  1355. /*
  1356. - ABCBUTT_GetState
  1357. -
  1358. * Says whether this control should appear enabled or not at this time.
  1359. *
  1360. */
  1361. STDMETHODIMP
  1362. ABCBUTT_GetState( LPABCBUTT lpABCButt,
  1363. ULONG ulFlags,
  1364. ULONG * lpulState
  1365. )
  1366. {
  1367. HRESULT hResult = hrSuccess;
  1368. /* Minimally validate the lpABCButt parameter */
  1369. if (IsBadReadPtr(lpABCButt, SIZEOF(ABCBUTT)))
  1370. {
  1371. hResult = ResultFromScode(E_INVALIDARG);
  1372. goto out;
  1373. }
  1374. if (lpABCButt->lpVtbl != &vtblABCBUTT)
  1375. {
  1376. hResult = ResultFromScode(E_INVALIDARG);
  1377. goto out;
  1378. }
  1379. if (IsBadWritePtr(lpulState, SIZEOF(ULONG)))
  1380. {
  1381. hResult = ResultFromScode(E_INVALIDARG);
  1382. goto out;
  1383. }
  1384. if (ulFlags)
  1385. {
  1386. /*
  1387. * No flags defined for this method
  1388. */
  1389. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  1390. goto out;
  1391. }
  1392. /*
  1393. * Means that at this time this button should appear enabled.
  1394. */
  1395. *lpulState = MAPI_ENABLED;
  1396. out:
  1397. DebugTraceResult(ABCBUTT_GetState, hResult);
  1398. return hResult;
  1399. }
  1400. #undef _FAXAB_ABCONT