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.

2083 lines
68 KiB

  1. /*
  2. * WABAPI.C - Main entry to WAB API
  3. *
  4. */
  5. #include <_apipch.h>
  6. const LPTSTR lpszOldKeyName = TEXT("Software\\Microsoft\\WAB\\Wab File Name");
  7. const LPTSTR lpszKeyName = TEXT("Software\\Microsoft\\WAB\\WAB4\\Wab File Name");
  8. #if 0
  9. CRITICAL_SECTION csOMIUnload;
  10. // @todo [PaulHi] DLL Leak. Remove this or implement
  11. static s_bIsReallyOnlyWABOpenExSession = FALSE; // [PaulHi] TRUE if any thread in process creates a
  12. // WAB object through the WABOpenEx() function
  13. #endif
  14. //
  15. // IWABObject jump table is defined here...
  16. //
  17. IWOINT_Vtbl vtblIWOINT = {
  18. VTABLE_FILL
  19. (IWOINT_QueryInterface_METHOD FAR *) UNKOBJ_QueryInterface,
  20. (IWOINT_AddRef_METHOD FAR *) UNKOBJ_AddRef,
  21. IWOINT_Release,
  22. (IWOINT_GetLastError_METHOD FAR *) UNKOBJ_GetLastError,
  23. IWOINT_AllocateBuffer,
  24. IWOINT_AllocateMore,
  25. IWOINT_FreeBuffer,
  26. IWOINT_Backup,
  27. IWOINT_Import,
  28. IWOINT_Find,
  29. IWOINT_VCardDisplay,
  30. IWOINT_LDAPUrl,
  31. IWOINT_VCardCreate,
  32. IWOINT_VCardRetrieve,
  33. IWOINT_GetMe,
  34. IWOINT_SetMe
  35. };
  36. /* Interface which can be queried from lpWABOBJECT.
  37. *
  38. * It is important that the order of the interfaces supported be preserved
  39. * and that IID_IUnknown be the last in the list.
  40. */
  41. IID const FAR * argpiidIWABOBJECT[] =
  42. {
  43. &IID_IUnknown
  44. };
  45. #define WAB_USE_OUTLOOK_ALLOCATORS 0x20000000// Note: This internal flag needs to be
  46. // harmonious with external flags defined
  47. // in wabapi.h for WAB_PARAM structs
  48. /****************************************************************
  49. *
  50. - CreateWABObject
  51. -
  52. * Purpose
  53. * Used for creating a WABObject interface in memory.
  54. *
  55. * Arguments
  56. * lppWABObject Pointer to memory location which will receive a
  57. * pointer to the new WABObject.
  58. * lpPropertyStore Property store structure
  59. *
  60. * Returns
  61. * SCODE
  62. *
  63. */
  64. STDAPI_(SCODE)
  65. CreateWABObject(LPWAB_PARAM lpWP, LPPROPERTY_STORE lpPropertyStore, LPWABOBJECT FAR * lppWABObject)
  66. {
  67. SCODE sc;
  68. LPIWOINT lpIWOINT = NULL;
  69. // validate paremeters
  70. AssertSz(lppWABObject &&
  71. !IsBadWritePtr(lppWABObject, sizeof(LPWABOBJECT)) &&
  72. !IsBadWritePtr(lpPropertyStore, sizeof(LPPROPERTY_STORE)),
  73. TEXT("lppWABObject fails address check"));
  74. //
  75. // Create a IPDAT per object for lpMAPIPropInternal so that it gets
  76. // called first.
  77. if (FAILED(sc = MAPIAllocateBuffer(sizeof(*lpIWOINT), &lpIWOINT))) {
  78. goto error;
  79. }
  80. // Init the object to 0, NULL
  81. memset((BYTE *)lpIWOINT, 0, sizeof(*lpIWOINT));
  82. MAPISetBufferName(lpIWOINT, TEXT("WABAPI: lpIWOINT in CreateWABObject"));
  83. // Tag each object that it is created using the OLK MAPI allocators.
  84. if ( lpWP && (lpWP->ulFlags & WAB_USE_OUTLOOK_ALLOCATORS) )
  85. lpIWOINT->bSetOLKAllocators = TRUE;
  86. // Fill in the object specific instance data.
  87. lpIWOINT->inst.hinst = hinstMapiX;//HinstMapi();
  88. #ifdef DEBUG
  89. if (lpIWOINT->inst.hinst == NULL)
  90. TraceSz1( TEXT("WABObject: GetModuleHandle failed with error %08lX"),
  91. GetLastError());
  92. #endif /* DEBUG */
  93. //
  94. // Open the property store
  95. //
  96. if (FAILED(sc = OpenAddRefPropertyStore(lpWP, lpPropertyStore))) {
  97. goto error;
  98. }
  99. lpIWOINT->lpPropertyStore = lpPropertyStore;
  100. // Initialize the TEXT("standard") object. This must be the last operation that can fail.
  101. // If not, explicitly call UNKOBJ_Deinit() for failures after a successful UNKOBJ_Init.
  102. if (FAILED(sc = UNKOBJ_Init((LPUNKOBJ)lpIWOINT,
  103. (UNKOBJ_Vtbl FAR *)&vtblIWOINT,
  104. sizeof(vtblIWOINT),
  105. (LPIID FAR *) argpiidIWABOBJECT,
  106. dimensionof(argpiidIWABOBJECT),
  107. &(lpIWOINT->inst)))) {
  108. DebugTrace( TEXT("CreateWABObject() - Error initializing IWOINT object (SCODE = 0x%08lX)\n"), sc);
  109. ReleasePropertyStore(lpPropertyStore); // undo the above operation
  110. goto error;
  111. }
  112. // Initialize the defaults in WABObject specific part of the object.
  113. lpIWOINT->ulObjAccess = IPROP_READWRITE;
  114. *lppWABObject = (LPWABOBJECT)lpIWOINT;
  115. return(S_OK);
  116. error:
  117. FreeBufferAndNull(&lpIWOINT);
  118. return(sc);
  119. }
  120. // --------
  121. // IUnknown
  122. /*
  123. - IWOINT_Release
  124. -
  125. * Purpose:
  126. * Decrements reference count on the WABObject and
  127. * removes instance data if reference count becomes zero.
  128. *
  129. * Arguments:
  130. * lpWABObject The object to be released.
  131. *
  132. * Returns:
  133. * Decremented reference count
  134. *
  135. * Side effects:
  136. *
  137. * Errors:
  138. */
  139. STDMETHODIMP_(ULONG)
  140. IWOINT_Release(LPIWOINT lpWABObject)
  141. {
  142. ULONG ulcRef;
  143. BOOL bSetOLKAllocators;
  144. #if !defined(NO_VALIDATION)
  145. // Make sure the object is valid.
  146. //
  147. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, Release, lpVtbl)) {
  148. DebugTrace( TEXT("IWOINT::Release() - Bad object passed\n"));
  149. return(1);
  150. }
  151. #endif
  152. UNKOBJ_EnterCriticalSection((LPUNKOBJ)lpWABObject);
  153. ulcRef = --lpWABObject->ulcRef;
  154. UNKOBJ_LeaveCriticalSection((LPUNKOBJ)lpWABObject);
  155. // Free the object.
  156. //
  157. // No critical section lock is required since we are guaranteed to be
  158. // the only thread accessing the object (ie ulcRef == 0).
  159. //
  160. if (!ulcRef) {
  161. // Free the object.
  162. //
  163. UNKOBJ_Deinit((LPUNKOBJ)lpWABObject);
  164. lpWABObject->lpVtbl = NULL;
  165. ReleaseOutlookStore(lpWABObject->lpPropertyStore->hPropertyStore, lpWABObject->lpOutlookStore);
  166. ReleasePropertyStore(lpWABObject->lpPropertyStore);
  167. bSetOLKAllocators = lpWABObject->bSetOLKAllocators;
  168. FreeBufferAndNull(&lpWABObject);
  169. // [PaulHi] 5/5/99 Raid 77138 Null out Outlook allocator function
  170. // pointers if our global count goes to zero.
  171. if (bSetOLKAllocators)
  172. {
  173. Assert(g_nExtMemAllocCount > 0);
  174. InterlockedDecrement((LPLONG)&g_nExtMemAllocCount);
  175. if (g_nExtMemAllocCount == 0)
  176. {
  177. lpfnAllocateBufferExternal = NULL;
  178. lpfnAllocateMoreExternal = NULL;
  179. lpfnFreeBufferExternal = NULL;
  180. }
  181. }
  182. }
  183. return(ulcRef);
  184. }
  185. /*
  186. - IWOINT_AllocateBuffer
  187. -
  188. * Purpose:
  189. * Allocation routine
  190. *
  191. * Arguments:
  192. * lpWABOBJECT this = the open wab object
  193. * cbSize number of bytes to allocate
  194. * lppBuffer -> Returned buffer
  195. *
  196. * Returns:
  197. * SCODE
  198. *
  199. */
  200. STDMETHODIMP_(SCODE)
  201. IWOINT_AllocateBuffer(LPIWOINT lpWABObject, ULONG cbSize, LPVOID FAR * lppBuffer) {
  202. SCODE sc = S_OK;
  203. #if !defined(NO_VALIDATION)
  204. // Make sure the object is valid.
  205. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, AllocateBuffer, lpVtbl)) {
  206. DebugTrace( TEXT("IWABOBJECT::AllocateBuffer() - Bad object passed\n"));
  207. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  208. }
  209. Validate_IWABObject_AllocateBuffer(
  210. lpWABObject,
  211. cbSize,
  212. lppBuffer);
  213. #endif // not NO_VALIDATION
  214. if(!lpWABObject || !lppBuffer)
  215. return MAPI_E_INVALID_PARAMETER;
  216. sc = MAPIAllocateBuffer(cbSize, lppBuffer);
  217. // error:
  218. UNKOBJ_SetLastError((LPUNKOBJ)lpWABObject, sc, 0);
  219. return(sc);
  220. }
  221. /*
  222. - IWOINT_AllocateMore
  223. -
  224. * Purpose:
  225. * Allocation routine
  226. *
  227. * Arguments:
  228. * lpWABOBJECT this = the open wab object
  229. * cbSize number of bytes to allocate
  230. * lpObject original allocation
  231. * lppBuffer -> Returned buffer
  232. *
  233. * Returns:
  234. * SCODE
  235. *
  236. */
  237. STDMETHODIMP_(SCODE)
  238. IWOINT_AllocateMore(LPIWOINT lpWABObject, ULONG cbSize, LPVOID lpObject, LPVOID FAR * lppBuffer) {
  239. SCODE sc = S_OK;
  240. #if !defined(NO_VALIDATION)
  241. // Make sure the object is valid.
  242. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, AllocateMore, lpVtbl)) {
  243. DebugTrace( TEXT("IWABOBJECT::AllocateMore() - Bad object passed\n"));
  244. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  245. }
  246. Validate_IWABObject_AllocateMore(
  247. lpWABObject,
  248. cbSize,
  249. lpObject,
  250. lppBuffer);
  251. #endif // not NO_VALIDATION
  252. if(!lpWABObject || !lppBuffer || !lpObject)
  253. return MAPI_E_INVALID_PARAMETER;
  254. sc = MAPIAllocateMore(cbSize, lpObject, lppBuffer);
  255. // error:
  256. UNKOBJ_SetLastError((LPUNKOBJ)lpWABObject, sc, 0);
  257. return(sc);
  258. }
  259. /*
  260. - IWOINT_FreeBuffer
  261. -
  262. * Purpose:
  263. * Allocation routine
  264. *
  265. * Arguments:
  266. * lpWABOBJECT this = the open wab object
  267. * lpBuffer Buffer to free
  268. *
  269. * Returns:
  270. * SCODE
  271. *
  272. */
  273. STDMETHODIMP_(SCODE)
  274. IWOINT_FreeBuffer(LPIWOINT lpWABObject, LPVOID lpBuffer) {
  275. SCODE sc = S_OK;
  276. #if !defined(NO_VALIDATION)
  277. // Make sure the object is valid.
  278. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, FreeBuffer, lpVtbl)) {
  279. DebugTrace( TEXT("IWABOBJECT::FreeBuffer() - Bad object passed\n"));
  280. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  281. }
  282. Validate_IWABObject_FreeBuffer(
  283. lpWABObject,
  284. lpBuffer);
  285. #endif // not NO_VALIDATION
  286. if(!lpWABObject || !lpBuffer)
  287. return MAPI_E_INVALID_PARAMETER;
  288. sc = MAPIFreeBuffer(lpBuffer);
  289. // error:
  290. UNKOBJ_SetLastError((LPUNKOBJ)lpWABObject, sc, 0);
  291. return(sc);
  292. }
  293. /*
  294. - IWOINT_Backup
  295. -
  296. * Purpose:
  297. * Backup the current database to a file.
  298. *
  299. * Arguments:
  300. * lpWABOBJECT this = the open wab object
  301. * lpFileName Filename to backup to
  302. *
  303. * Returns:
  304. * HRESULT
  305. *
  306. */
  307. STDMETHODIMP
  308. IWOINT_Backup(LPIWOINT lpWABObject, LPSTR lpFileName) {
  309. SCODE sc = S_OK;
  310. #if !defined(NO_VALIDATION)
  311. // Make sure the object is valid.
  312. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, Backup, lpVtbl)) {
  313. DebugTrace( TEXT("IWABOBJECT::Backup() - Bad object passed\n"));
  314. return ResultFromScode(MAPI_E_INVALID_PARAMETER);
  315. }
  316. Validate_IWABObject_Backup(
  317. lpWABObject,
  318. lpFileName);
  319. #endif // not NO_VALIDATION
  320. // Not yet implemented.
  321. DebugTrace( TEXT("IWABOBJECT::Backup() - Not yet implemented!\n"));
  322. sc = MAPI_E_NO_SUPPORT;
  323. // error:
  324. UNKOBJ_SetLastError((LPUNKOBJ)lpWABObject, sc, 0);
  325. return(MakeResult(sc));
  326. }
  327. /*
  328. - IWOINT_Import
  329. -
  330. * Purpose:
  331. * Imports an address book into the current WAB database.
  332. *
  333. * Arguments:
  334. * lpWABOBJECT this = the open wab object
  335. * lpwip - WABIMPORTPARAM struct
  336. *
  337. * Returns:
  338. * HRESULT - MAPI_W_ERRORS_RETURNED if some errors occured during import
  339. * Failure code if something really failed, S_OK otherwise ..
  340. *
  341. */
  342. STDMETHODIMP
  343. IWOINT_Import(LPIWOINT lpWABObject, LPSTR lpWIP)
  344. {
  345. LPWABIMPORTPARAM lpwip = (LPWABIMPORTPARAM) lpWIP;
  346. LPTSTR lpFile = NULL;
  347. HRESULT hr = S_OK;
  348. #if !defined(NO_VALIDATION)
  349. // Make sure the object is valid.
  350. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, Import, lpVtbl)) {
  351. DebugTrace( TEXT("IWABOBJECT::Import() - Bad object passed\n"));
  352. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  353. }
  354. Validate_IWABObject_Import(
  355. lpWABObject,
  356. lpWIP);
  357. #endif // not NO_VALIDATION
  358. if(!lpwip || !lpwip->lpAdrBook || !lpWABObject)
  359. return MAPI_E_INVALID_PARAMETER;
  360. lpFile =
  361. ConvertAtoW(lpwip->lpszFileName);
  362. hr = HrImportWABFile(lpwip->hWnd, lpwip->lpAdrBook, lpwip->ulFlags, lpFile);
  363. LocalFreeAndNull(&lpFile);
  364. return hr;
  365. }
  366. /*
  367. - IWOINT_Find
  368. -
  369. * Purpose:
  370. * Displays the Find dialog so we can do Start | Find | People
  371. *
  372. * Arguments:
  373. * lpWABOBJECT this = the open wab object
  374. * hWnd hWnd of parent for the find dialog
  375. *
  376. * Returns:
  377. * HRESULT
  378. *
  379. */
  380. STDMETHODIMP
  381. IWOINT_Find(LPIWOINT lpWABObject,
  382. LPADRBOOK lpAdrBook,
  383. HWND hWnd)
  384. {
  385. HRESULT hr = S_OK;
  386. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  387. #if !defined(NO_VALIDATION)
  388. // Make sure the object is valid.
  389. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, Find, lpVtbl)) {
  390. DebugTrace( TEXT("IWABOBJECT::Find() - Bad object passed\n"));
  391. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  392. }
  393. #endif // not NO_VALIDATION
  394. if(!lpWABObject || !lpAdrBook)
  395. return MAPI_E_INVALID_PARAMETER;
  396. hr = HrShowSearchDialog(lpAdrBook,
  397. hWnd,
  398. (LPADRPARM_FINDINFO) NULL,
  399. (LPLDAPURL) NULL,
  400. NULL);
  401. return(hr);
  402. }
  403. /*
  404. - IWOINT_VCardDisplay
  405. -
  406. * Purpose:
  407. * Displays One off props on a vCard File
  408. *
  409. * Arguments:
  410. * lpWABOBJECT this = the open wab object
  411. * lpAdrBook lpAdrBook object
  412. * hWnd hWnd of parent for the find dialog
  413. * lpszFileName Null terminated file name to display
  414. *
  415. * Returns:
  416. * HRESULT
  417. *
  418. */
  419. STDMETHODIMP
  420. IWOINT_VCardDisplay(LPIWOINT lpWABObject,
  421. LPADRBOOK lpAdrBook,
  422. HWND hWnd,
  423. LPSTR szvCardFile)
  424. {
  425. HRESULT hr = S_OK;
  426. LPTSTR lpVCard = NULL;
  427. #if !defined(NO_VALIDATION)
  428. // Make sure the object is valid.
  429. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, VCardDisplay, lpVtbl)) {
  430. DebugTrace( TEXT("IWABOBJECT::VCardDisplay() - Bad object passed\n"));
  431. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  432. }
  433. #endif // not NO_VALIDATION
  434. if(!lpWABObject || !lpAdrBook)
  435. return MAPI_E_INVALID_PARAMETER;
  436. lpVCard =
  437. ConvertAtoW(szvCardFile);
  438. hr = HrShowOneOffDetailsOnVCard( lpAdrBook,
  439. hWnd,
  440. lpVCard);
  441. LocalFreeAndNull(&lpVCard);
  442. return(hr);
  443. }
  444. /*
  445. - IWOINT_VCardCreate
  446. -
  447. * Purpose:
  448. * Takes input mailuser object, and converts its properties
  449. * into a vCard file
  450. *
  451. * Arguments:
  452. * lpWABOBJECT this = the open wab object
  453. * lpAdrBook lpAdrBook object
  454. * hWnd hWnd of parent for the find dialog
  455. * lpszFileName Null terminated file name to create
  456. * lpMailUser MailUser object to convert to vCard
  457. *
  458. * Returns:
  459. * HRESULT
  460. *
  461. */
  462. STDMETHODIMP
  463. IWOINT_VCardCreate(LPIWOINT lpWABObject,
  464. LPADRBOOK lpAdrBook,
  465. ULONG ulFlags,
  466. LPSTR szvCardFile,
  467. LPMAILUSER lpMailUser)
  468. {
  469. HRESULT hr = S_OK;
  470. LPTSTR lpVCardFile = NULL;
  471. #if !defined(NO_VALIDATION)
  472. // Make sure the object is valid.
  473. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, VCardDisplay, lpVtbl)) {
  474. DebugTrace( TEXT("IWABOBJECT::VCardDisplay() - Bad object passed\n"));
  475. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  476. }
  477. #endif // not NO_VALIDATION
  478. if(!lpWABObject || !lpAdrBook || !lpMailUser)
  479. return MAPI_E_INVALID_PARAMETER;
  480. lpVCardFile =
  481. ConvertAtoW(szvCardFile);
  482. hr = VCardCreate(lpAdrBook,
  483. NULL,
  484. 0,
  485. lpVCardFile,
  486. lpMailUser);
  487. LocalFreeAndNull(&lpVCardFile);
  488. return(hr);
  489. }
  490. /*
  491. - IWOINT_VCardRetrieve
  492. -
  493. * Purpose:
  494. * Opens a vCard file and creates a corresponding MailUser out of it
  495. *
  496. * Arguments:
  497. * lpWABOBJECT this = the open wab object
  498. * lpAdrBook lpAdrBook object
  499. * ulFlags STREAM or FILE
  500. * lpszFileName Null terminated file name to display
  501. * lppMailUser returned MailUser object
  502. *
  503. * Returns:
  504. * HRESULT
  505. *
  506. */
  507. STDMETHODIMP
  508. IWOINT_VCardRetrieve(LPIWOINT lpWABObject,
  509. LPADRBOOK lpAdrBook,
  510. ULONG ulFlags,
  511. LPSTR szvCard,
  512. LPMAILUSER * lppMailUser)
  513. {
  514. HRESULT hr = S_OK;
  515. LPSTR lpStream = NULL;
  516. LPTSTR lpFileName = NULL;
  517. #if !defined(NO_VALIDATION)
  518. // Make sure the object is valid.
  519. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, VCardDisplay, lpVtbl)) {
  520. DebugTrace( TEXT("IWABOBJECT::VCardDisplay() - Bad object passed\n"));
  521. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  522. }
  523. #endif // not NO_VALIDATION
  524. if( !lpWABObject || !lpAdrBook || !lppMailUser ||
  525. !szvCard || (!(ulFlags&WAB_VCARD_STREAM) && !lstrlenA(szvCard)) )
  526. return MAPI_E_INVALID_PARAMETER;
  527. if(ulFlags & WAB_VCARD_STREAM)
  528. {
  529. DWORD cchSizeStream = (lstrlenA(szvCard)+1);
  530. if (!(lpStream = LocalAlloc(LMEM_ZEROINIT, (sizeof(lpStream[0]) * cchSizeStream))))
  531. return MAPI_E_NOT_ENOUGH_MEMORY;
  532. StrCpyNA(lpStream, szvCard, cchSizeStream);
  533. }
  534. else
  535. {
  536. lpFileName = ConvertAtoW(szvCard);
  537. }
  538. hr = VCardRetrieve(lpAdrBook,
  539. NULL,
  540. 0,
  541. lpFileName,
  542. lpStream,
  543. lppMailUser);
  544. LocalFreeAndNull(&lpFileName);
  545. LocalFreeAndNull(&lpStream);
  546. return(hr);
  547. }
  548. /*
  549. - IWOINT_LDAPUrl
  550. -
  551. * Purpose:
  552. * Handles an LDAP URL
  553. *
  554. * Arguments:
  555. * lpWABOBJECT this = the open wab object
  556. * lpAdrBook lpAdrBook object
  557. * hWnd hWnd of parent for the find dialog
  558. * ulFlags flags saying how we want the results returned
  559. * lpszUrl Null terminated file name to display
  560. * lppMailUser Possible Mailuser to return based on flag
  561. *
  562. * With this API, users can pass in a Wide string URL by casting it to a
  563. * LPSTR and setting ulFlags to MAPI_UNICODE .. if we detect MAPI_UNICODE,
  564. * we cast the string back to a WideChar
  565. * Returns:
  566. * HRESULT
  567. *
  568. */
  569. STDMETHODIMP
  570. IWOINT_LDAPUrl( LPIWOINT lpWABObject,
  571. LPADRBOOK lpAdrBook,
  572. HWND hWnd,
  573. ULONG ulFlags,
  574. LPSTR szLDAPUrl,
  575. LPMAILUSER * lppMailUser)
  576. {
  577. HRESULT hr = S_OK;
  578. LPTSTR lpUrl = NULL;
  579. #if !defined(NO_VALIDATION)
  580. // Make sure the object is valid.
  581. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, LDAPUrl, lpVtbl)) {
  582. DebugTrace( TEXT("IWABOBJECT::LDAPUrl() - Bad object passed\n"));
  583. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  584. }
  585. #endif // not NO_VALIDATION
  586. if(!lpWABObject || !lpAdrBook || !szLDAPUrl)// || !lstrlen(szLDAPUrl))
  587. return MAPI_E_INVALID_PARAMETER;
  588. if(ulFlags & MAPI_UNICODE)
  589. {
  590. lpUrl = (LPWSTR)szLDAPUrl;
  591. }
  592. else
  593. {
  594. lpUrl = ConvertAtoW(szLDAPUrl);
  595. }
  596. if(!lstrlen(lpUrl))
  597. {
  598. hr = MAPI_E_INVALID_PARAMETER;
  599. goto out;
  600. }
  601. hr = HrProcessLDAPUrl( lpAdrBook,
  602. hWnd,
  603. ulFlags | ((!ulFlags && hWnd) ? MAPI_DIALOG : 0),
  604. lpUrl,
  605. lppMailUser);
  606. out:
  607. if(lpUrl && lpUrl != (LPTSTR)szLDAPUrl)
  608. LocalFreeAndNull(&lpUrl);
  609. return hr;
  610. }
  611. /*
  612. - IWOINT_GetMe
  613. -
  614. * Purpose:
  615. * Retrieves the 'Me' entry from the WAB .. if the entry doesnt exist,
  616. * prompts the user to create one or select someone from his address book.
  617. * Unless the caller surpresses the dialog by passing in AB_NO_DIALOG, in
  618. * which case, the entry is created behind-the-scenes. Caller can also
  619. * call this function to check existence of a ME entry without causing a new
  620. * one created as a side effect - to do that they specify the WABOBJECT_ME_NOCREATE flag
  621. * which causes failure with MAPI_E_NOT_FOUND if nothing found
  622. *
  623. * Arguments:
  624. * lpWABOBJECT this = the open wab object
  625. * lpAdrBook lpAdrBook object
  626. * ulFlags 0 or AB_NO_DIALOG
  627. * or WABOBJECT_ME_NOCREATE
  628. * lpdwAction if supplied, returns WABOBJECT_ME_NEW if a new ME was created
  629. * SBinary * returns the entry id of the ME,
  630. * ulParam HWND of parent cast as a (ULONG)
  631. *
  632. * Returns:
  633. * HRESULT
  634. *
  635. */
  636. STDMETHODIMP
  637. IWOINT_GetMe( LPIWOINT lpWABObject,
  638. LPADRBOOK lpAdrBook,
  639. ULONG ulFlags,
  640. DWORD * lpdwAction,
  641. SBinary * lpsbEID,
  642. ULONG ulParam)
  643. {
  644. HRESULT hr = S_OK;
  645. #if !defined(NO_VALIDATION)
  646. // Make sure the object is valid.
  647. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, GetMe, lpVtbl)) {
  648. DebugTrace( TEXT("IWABOBJECT::GetMe() - Bad object passed\n"));
  649. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  650. }
  651. #endif // not NO_VALIDATION
  652. if(!lpWABObject || !lpAdrBook)
  653. return MAPI_E_INVALID_PARAMETER;
  654. hr = HrGetMeObject(lpAdrBook, ulFlags, lpdwAction, lpsbEID, ulParam);
  655. return hr;
  656. }
  657. /*
  658. - IWOINT_SetMe
  659. -
  660. * Purpose:
  661. * Sets the specified object as the Me object .. only 1 Me object will exist in a WAB
  662. * Hence it strips the previous Me object, if different, of its Me status.
  663. * If no entryid is passed in, and MAPI_DIALOG is specified, a dialog pops up
  664. * asking the user to create a ME or to select a ME object .. the selection in the SetMe
  665. * dialog is set to the current ME object, if any
  666. * If no entryid is passed in, and MAPI_DIALOG is not specified, the function fails
  667. * If an entryid is passed in, and MAPI_DIALOG is specified, the SetME dialog is displayed
  668. * with the corresponding entryid-object selected in it
  669. * If an entryid is passed in, and MAPI_DIALOG is not specified, the entryid, if exists, is
  670. * set as the ME object and the old ME object stripped
  671. *
  672. * Arguments:
  673. * lpWABOBJECT this = the open wab object
  674. * lpAdrBook lpAdrBook object
  675. * ulFlags 0 or MAPI_DIALOG
  676. * sbEID entry id of the object to set as ME,
  677. * ulParam HWND of parent for DIalogs cast as a ULONG
  678. *
  679. * Returns:
  680. * HRESULT
  681. *
  682. */
  683. STDMETHODIMP
  684. IWOINT_SetMe( LPIWOINT lpWABObject,
  685. LPADRBOOK lpAdrBook,
  686. ULONG ulFlags,
  687. SBinary sbEID,
  688. ULONG ulParam)
  689. {
  690. HRESULT hr = S_OK;
  691. #if !defined(NO_VALIDATION)
  692. // Make sure the object is valid.
  693. if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, SetMe, lpVtbl)) {
  694. DebugTrace( TEXT("IWABOBJECT::GetMe() - Bad object passed\n"));
  695. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  696. }
  697. #endif // not NO_VALIDATION
  698. if( !lpAdrBook ||
  699. ((!sbEID.cb||!sbEID.lpb) && !ulFlags) )
  700. {
  701. hr = MAPI_E_INVALID_PARAMETER;
  702. goto exit;
  703. }
  704. hr = HrSetMeObject(lpAdrBook, ulFlags, sbEID, ulParam);
  705. exit:
  706. return hr;
  707. }
  708. /*
  709. - ReleasePropertyStore
  710. -
  711. * Purpose:
  712. * Keep track of property store refcount
  713. *
  714. * Arguments:
  715. * lpPropertyStore PROPERTY_STORE structure
  716. *
  717. * Returns:
  718. * Current reference count. When 0, property store is
  719. * no longer open.
  720. *
  721. */
  722. ULONG ReleasePropertyStore(LPPROPERTY_STORE lpPropertyStore) {
  723. if (lpPropertyStore->ulRefCount) {
  724. IF_WIN32(Assert(lpPropertyStore->hPropertyStore);)
  725. if (0 == (--(lpPropertyStore->ulRefCount))) {
  726. // Reference goes to zero, release the property store
  727. ClosePropertyStore(lpPropertyStore->hPropertyStore,0);
  728. lpPropertyStore->hPropertyStore = NULL;
  729. // Free the container list
  730. FreeBufferAndNull(&(lpPropertyStore->rgolkci));
  731. lpPropertyStore->colkci = 0;
  732. // [PaulHi] Raid #61556
  733. // Must reset this global variable or OUT32WAB.DLL will crash
  734. // the next time it is loaded and the store opened.
  735. pmsessOutlookWabSPI = NULL;
  736. }
  737. }
  738. return(lpPropertyStore->ulRefCount);
  739. }
  740. #ifdef WIN16
  741. BOOL WINAPI WABInitThread()
  742. {
  743. // allocate a TLS index
  744. if ((dwTlsIndex = TlsAlloc()) == 0xfffffff)
  745. return FALSE;
  746. return TRUE;
  747. }
  748. #endif
  749. #define WAB_USE_OUTLOOK_CONTACT_STORE 0x10000000// Note: This internal flag needs to be
  750. // harmonious with external flags defined
  751. // in wabapi.h for WAB_PARAM structs
  752. //
  753. // Input information to pass to WABOpen from IE4 WAB
  754. //
  755. typedef struct _tagWAB_PARAM_V4
  756. {
  757. ULONG cbSize; // sizeof(WAB_PARAM).
  758. HWND hwnd; // hWnd of calling client Application. Can be NULL
  759. LPTSTR szFileName; // WAB File name to open. if NULL, opens default.
  760. ULONG ulFlags; // Currently no flags.
  761. } WAB_PARAM_V4, * LPWAB_PARAM_V4;
  762. /*
  763. - WABOpen
  764. -
  765. * Purpose:
  766. * Entry point into the WAB API
  767. *
  768. * Arguments:
  769. * lppAdrBook Returned IAdrBook object
  770. * lppWABOBJECT Returned WABObject
  771. * Reserved1 Reserved for future filename?
  772. * Reserved2 Reserved for future flags
  773. *
  774. * Returns:
  775. * HRESULT
  776. * S_OK
  777. * E_FAIL // some generic error
  778. * MAPI_E_NOT_ENOUGH_MEMORY: // ran out of memory
  779. * MAPI_E_NO_ACCESS: // file is locked by someone
  780. * MAPI_E_CORRUPT_DATA: // file corrupt
  781. * MAPI_E_DISK_ERROR: // some disk related error opening file
  782. * MAPI_E_INVALID_OBJECT: // secified file exists but its GUID doesnt match
  783. *
  784. */
  785. STDMETHODIMP WABOpen(LPADRBOOK FAR * lppAdrBook, LPWABOBJECT FAR * lppWABObject,
  786. LPWAB_PARAM lpWP, DWORD Reserved2) {
  787. SCODE sc = SUCCESS_SUCCESS;
  788. HRESULT hResult = hrSuccess;
  789. static PROPERTY_STORE PropertyStore = {NULL, 0, 0, 0, NULL, 0};
  790. static OUTLOOK_STORE OutlookStore = {NULL, 0};
  791. BOOL bUseOutlook = FALSE;
  792. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  793. LPTSTR lpFile = NULL;
  794. AssertSz(lppAdrBook && !IsBadWritePtr(lppAdrBook, sizeof(LPADRBOOK)),
  795. TEXT("lppAdrBook fails address check"));
  796. AssertSz(lppWABObject && !IsBadWritePtr(lppWABObject, sizeof(LPWABOBJECT)),
  797. TEXT("lppWABObject fails address check"));
  798. if(!lppAdrBook || !lppWABObject)
  799. return MAPI_E_INVALID_PARAMETER;
  800. IF_WIN16(ScInitMapiUtil(0);)
  801. // First check if this is supposed to be an Outlook session
  802. // If we are explicitly told to use the contact store ...
  803. if((lpWP && (lpWP->ulFlags & WAB_USE_OUTLOOK_CONTACT_STORE)) &&
  804. PropertyStore.ulRefCount == 0) // Bad bug where wabopen process calls outlook which
  805. // calls wabopenex and we flunk everywhere since this PropertyStore
  806. // information is a static in the original process..
  807. // force the wabopenex to be a wabopen if this rare case happens
  808. bUseOutlook = TRUE;
  809. else
  810. {
  811. // if a file name is specified and this is not wabopenex, then override any
  812. // outlook use .. this way we can explicitly call the wab to open a .wab file
  813. // from anywhere
  814. if(lpWP && lpWP->szFileName && lstrlenA(lpWP->szFileName))
  815. bUseOutlook = FALSE;
  816. else
  817. bUseOutlook = bUseOutlookStore();
  818. }
  819. #if 0
  820. // @todo [PaulHi] DLL Leak. Remove this or implement
  821. // [PaulHi] Set this process global boolean ONLY if the WAB is opened through the WABOpenEx()
  822. // function ,i.e., by the Outlook process
  823. if (lpWP && (lpWP->ulFlags & WAB_USE_OUTLOOK_CONTACT_STORE))
  824. {
  825. EnterCriticalSection(&csOMIUnload);
  826. s_bIsReallyOnlyWABOpenExSession = TRUE;
  827. LeaveCriticalSection(&csOMIUnload);
  828. }
  829. #endif
  830. //
  831. // if a .wab file is already initialized in this process space, just inherit that file
  832. // [PaulHi] 12/5/98 Raid #56437
  833. // We still need to allow the Outlook refcount to increment if this store has been created.
  834. // So we need to check both the WAB PropertyStore and OutlookStore ref counts to determine
  835. // if we should prevent the Outlook store from being opened.
  836. // Note that these two lines fixes the following problem:
  837. // 1) User opens OE5 (which opens WAB in non-outlook store mode)
  838. // 2) User has the Outlook set as their default mail client.
  839. // 3) User uses the WAB to initiate a send email.
  840. // 4) Since Outlook is the default client it is launched, and in turn opens WAB
  841. // in outlook store mode. At this point the WAB is already open in non-outlook store
  842. // mode so we want to prevent the Outlook store from being initialized.
  843. //
  844. if (PropertyStore.ulRefCount && !OutlookStore.ulRefCount)
  845. bUseOutlook = FALSE;
  846. if(bUseOutlook)
  847. {
  848. // If this call fails, we will just end up defaulting to the WAB store...
  849. // so we can ignore any errors here
  850. OpenAddRefOutlookStore(&OutlookStore);
  851. }
  852. //
  853. // Create the WAB Object
  854. //
  855. if (FAILED(sc = CreateWABObject(lpWP, &PropertyStore, lppWABObject))) {
  856. hResult = ResultFromScode(sc);
  857. if(bUseOutlook) // IE6 bug 15174
  858. pt_bIsWABOpenExSession = FALSE;
  859. goto exit;
  860. }
  861. //
  862. // Create the IAdrBook Object
  863. //
  864. if (HR_FAILED(hResult = HrNewIAB(&PropertyStore, *lppWABObject, lppAdrBook))) {
  865. // IAdrBook creation failed, fail WABOpen and clean up.
  866. UlRelease(*lppWABObject);
  867. goto exit;
  868. }
  869. DebugTrace( TEXT("WABOpen succeeds\n"));
  870. if(bUseOutlook)
  871. {
  872. if( lppWABObject && *lppWABObject &&
  873. OutlookStore.hOutlookStore)
  874. {
  875. ((LPIWOINT)(*lppWABObject))->lpOutlookStore = &OutlookStore;
  876. }
  877. // Bug - Outlook needs a way for its secondary threads to know this is a WABOpenEx session
  878. // without their calling WABOpenEx (They pass the iAdrBook pointer around it seems). Hence
  879. // tag this IADRbook pointer
  880. if(!HR_FAILED(hResult) && lppAdrBook && *lppAdrBook && pt_bIsWABOpenExSession)
  881. ((LPIAB)(*lppAdrBook))->lpPropertyStore->bIsWABOpenExSession = TRUE;
  882. }
  883. if(lppAdrBook && *lppAdrBook)
  884. {
  885. // Load the WABs private named properties
  886. HrLoadPrivateWABProps((LPIAB) *lppAdrBook);
  887. if(lpWP && (lpWP->cbSize > sizeof(WAB_PARAM_V4)) )
  888. ((LPIAB)*lppAdrBook)->guidPSExt = lpWP->guidPSExt;
  889. // As long as this is not an Outlook session, profiles are always
  890. // enabled in the UI
  891. if( !pt_bIsWABOpenExSession &&
  892. !((LPIAB)(*lppAdrBook))->lpPropertyStore->bIsWABOpenExSession )
  893. {
  894. ((LPIAB)(*lppAdrBook))->bProfilesEnabled = TRUE;
  895. }
  896. if( ((LPIAB)(*lppAdrBook))->bProfilesEnabled )
  897. {
  898. if(lpWP && (lpWP->ulFlags & WAB_ENABLE_PROFILES)) // only check for profiles the first time we enter for this process
  899. {
  900. if(PropertyStore.ulRefCount >= 2)
  901. {
  902. ((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled = ((LPIAB)(*lppAdrBook))->bProfilesIdent = TRUE;
  903. }
  904. else
  905. {
  906. ((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled = PropertyStore.bProfileAPIs;
  907. }
  908. if(((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled )
  909. hResult = HrLogonAndGetCurrentUserProfile(lpWP->hwnd, ((LPIAB)(*lppAdrBook)), FALSE, FALSE);
  910. // if there is some identity related error we should then revert to
  911. // non-identity mode
  912. if(HR_FAILED(hResult))
  913. {
  914. PropertyStore.bProfileAPIs = ((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled = FALSE;
  915. hResult = S_OK;
  916. }
  917. else
  918. PropertyStore.bProfileAPIs = ((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled = TRUE;
  919. }
  920. }
  921. if( ((LPIAB)(*lppAdrBook))->bProfilesEnabled )
  922. {
  923. if(HR_FAILED(hResult = HrGetWABProfiles((LPIAB) *lppAdrBook)))
  924. {
  925. // UGH! If this failed then we are quite in trouble and won't be able to support a profile-enabled
  926. // session without crashing badly .. hence above failure is critical enough to stop
  927. // loading the WAB
  928. (*lppAdrBook)->lpVtbl->Release(*lppAdrBook);
  929. (*lppWABObject)->lpVtbl->Release(*lppWABObject);
  930. }
  931. }
  932. ReadWABCustomColumnProps((LPIAB) *lppAdrBook);
  933. // need to be aware of Identity Notifications if this is a profile aware WAB independent
  934. // of whether the store is switched to using Outlook or not
  935. //
  936. // If the caller specifically asked for profiles
  937. // (then assume it is identity aware and register for Identity Notifications
  938. // because if the caller is using Identites, WAB launched as a child window
  939. // needs to be able to shut down when it gets a switch_identites message
  940. if( lpWP && (lpWP->ulFlags & WAB_ENABLE_PROFILES))
  941. HrRegisterUnregisterForIDNotifications( (LPIAB) *lppAdrBook, TRUE);
  942. if( lpWP && (lpWP->ulFlags & WAB_USE_OE_SENDMAIL))
  943. ((LPIAB) *lppAdrBook)->bUseOEForSendMail = TRUE;
  944. }
  945. exit:
  946. return(hResult);
  947. }
  948. /*
  949. - WABOpenEx
  950. -
  951. * Purpose:
  952. * Extended Entry point into the WAB API
  953. *
  954. * Arguments:
  955. * lppAdrBook Returned IAdrBook object
  956. * lppWABOBJECT Returned WABObject
  957. * lpMP WAB Parameter structure (NULL by default)
  958. * Reserved Optional IMAPISession parameter
  959. * fnAllocateBuffer AllocateBuffer function (may be NULL)
  960. * fnAllocateMore AllocateMore function (may be NULL)
  961. * fnFreeBuffer FreeBuffer function (may be NULL)
  962. *
  963. * Returns:
  964. * HRESULT
  965. * S_OK
  966. * E_FAIL // some generic error
  967. * MAPI_E_NOT_ENOUGH_MEMORY: // ran out of memory
  968. * MAPI_E_NO_ACCESS: // file is locked by someone
  969. * MAPI_E_CORRUPT_DATA: // file corrupt
  970. * MAPI_E_DISK_ERROR: // some disk related error opening file
  971. * MAPI_E_INVALID_OBJECT: // secified file exists but its GUID doesnt match
  972. *
  973. */
  974. STDMETHODIMP WABOpenEx(LPADRBOOK FAR * lppAdrBook,
  975. LPWABOBJECT FAR * lppWABObject,
  976. LPWAB_PARAM lpWP,
  977. DWORD Reserved,
  978. ALLOCATEBUFFER * lpfnAllocateBuffer,
  979. ALLOCATEMORE * lpfnAllocateMore,
  980. FREEBUFFER * lpfnFreeBuffer) {
  981. HRESULT hResult = hrSuccess;
  982. SCODE sc = SUCCESS_SUCCESS;
  983. WAB_PARAM wp = {0};
  984. if (Reserved) {
  985. // This is an IMAPISession that needs to be passed to the
  986. // Outlook storage provider interface ..
  987. pmsessOutlookWabSPI = (LPUNKNOWN)IntToPtr(Reserved);
  988. }
  989. if(!lppWABObject || !lppAdrBook)
  990. return MAPI_E_INVALID_PARAMETER;
  991. wp.cbSize = sizeof(WAB_PARAM);
  992. if(!lpWP)
  993. lpWP = &wp;
  994. lpWP->ulFlags |= WAB_USE_OUTLOOK_CONTACT_STORE;
  995. // Did we get allocators? Set up the globals
  996. if (lpfnAllocateBuffer || lpfnAllocateMore || lpfnFreeBuffer)
  997. {
  998. if (lpfnAllocateBuffer && lpfnAllocateMore && lpfnFreeBuffer)
  999. {
  1000. DebugTrace( TEXT("WABOpenEx found external allocators\n"));
  1001. lpfnAllocateBufferExternal = lpfnAllocateBuffer;
  1002. lpfnAllocateMoreExternal = lpfnAllocateMore;
  1003. lpfnFreeBufferExternal = lpfnFreeBuffer;
  1004. lpWP->ulFlags |= WAB_USE_OUTLOOK_ALLOCATORS;
  1005. InterlockedIncrement((LPLONG)&g_nExtMemAllocCount); // Incremented twice for each object created; IAB and IWO
  1006. InterlockedIncrement((LPLONG)&g_nExtMemAllocCount);
  1007. }
  1008. else
  1009. {
  1010. DebugTrace( TEXT("WABOpenEx got one or two allocator functions, but not all three\n"));
  1011. hResult = ResultFromScode(MAPI_E_INVALID_PARAMETER);
  1012. goto exit;
  1013. }
  1014. }
  1015. hResult = WABOpen( lppAdrBook, lppWABObject, lpWP, 0);
  1016. if(lpWP == &wp)
  1017. lpWP = NULL;
  1018. if(HR_FAILED(hResult))
  1019. goto exit;
  1020. exit:
  1021. return(hResult);
  1022. }
  1023. /*
  1024. -
  1025. - GetNewDataDirName
  1026. *
  1027. * Purpose:
  1028. * Gets the path of the new data directory in which the WAB file should be placed
  1029. *
  1030. * We look for:
  1031. * Roaming User App Data Dir; else
  1032. * Program Files\IE\OE\Current User\Address Book; else
  1033. * Common Files\Microsoft Shared\Address Book; else
  1034. * Create c:\Address book\ else
  1035. * Create c:\wab\
  1036. *
  1037. * Returns a valid, existing directory name terminated by a \
  1038. *
  1039. */
  1040. HRESULT GetNewDataDirName(LPTSTR szDir, DWORD cchSizeDir)
  1041. {
  1042. HRESULT hr = E_FAIL;
  1043. const LPTSTR lpszShellFolders = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
  1044. const LPTSTR lpszAppData = TEXT("AppData");
  1045. const LPTSTR lpszCurrentVer = TEXT("Software\\Microsoft\\Windows\\CurrentVersion");
  1046. const LPTSTR lpszCommonFiles = TEXT("CommonFilesDir");
  1047. const LPTSTR lpszMicrosoftShared = TEXT("\\Microsoft Shared");
  1048. const LPTSTR lpszAddressBook = TEXT("\\Address Book");
  1049. const LPTSTR lpszOEKey = TEXT("Software\\Microsoft\\Outlook Express\\5.0");
  1050. const LPTSTR lpszOERoot = TEXT("Store Root");
  1051. const LPTSTR lpszMicrosoft = TEXT("\\Microsoft");
  1052. const LPTSTR lpszCAddressBook = TEXT("c:\\Address book");
  1053. const LPTSTR lpszCWAB = TEXT("c:\\WAB");
  1054. HKEY hKey = NULL;
  1055. DWORD dwSize = 0;
  1056. DWORD dwType = 0;
  1057. TCHAR szPath[MAX_PATH];
  1058. TCHAR szUser[MAX_PATH];
  1059. *szPath='\0';
  1060. if(!szDir)
  1061. goto out;
  1062. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,lpszShellFolders,0,KEY_READ,&hKey))
  1063. {
  1064. // Look for the App Data directory
  1065. dwSize = ARRAYSIZE(szPath);
  1066. if(ERROR_SUCCESS == RegQueryValueEx(hKey, lpszAppData, NULL, &dwType, (LPBYTE) szPath, &dwSize))
  1067. {
  1068. if(lstrlen(szPath))
  1069. {
  1070. StrCpyN(szDir, szPath, cchSizeDir);
  1071. if(GetFileAttributes(szDir) != 0xFFFFFFFF)
  1072. {
  1073. StrCatBuff(szDir, lpszMicrosoft, cchSizeDir);
  1074. if(GetFileAttributes(szDir) == 0xFFFFFFFF)
  1075. CreateDirectory(szDir, NULL);
  1076. StrCatBuff(szDir, lpszAddressBook, cchSizeDir);
  1077. if(GetFileAttributes(szDir) == 0xFFFFFFFF)
  1078. CreateDirectory(szDir, NULL);
  1079. }
  1080. hr = S_OK;
  1081. goto out;
  1082. }
  1083. }
  1084. }
  1085. if(hKey)
  1086. RegCloseKey(hKey);
  1087. hKey = NULL;
  1088. // Didnt find this directory
  1089. // Look for MyDocuments folder - it will only be installed with Office so no gaurantee it will be found
  1090. // <TBD> - there doesnt seem to be a definite location for this except under
  1091. // CurrentVersion\Explorer\Shell Folders\Personal
  1092. // Didnt find a My Documents directory
  1093. // See if OE is installed for the current user ..
  1094. /** commented out until OE has stable dir structure
  1095. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, lpszOEKey, 0, KEY_READ, &hKey))
  1096. {
  1097. dwSize = CharSizeOf(szPath);
  1098. if(ERROR_SUCCESS == RegQueryValueEx(hKey, lpszOERoot, NULL, &dwType, (LPBYTE) szPath, &dwSize))
  1099. {
  1100. if(lstrlen(szPath))
  1101. {
  1102. StrCatBuff(szPath,lpszAddressBook, ARRAYSIZE(szPath));
  1103. //if directory doesnt exist, create it
  1104. CreateDirectory(szPath, NULL); //ignore error if it already exists
  1105. if(GetFileAttributes(szPath) != 0xFFFFFFFF)
  1106. {
  1107. StrCpyN(szDir, szPath, cchSizeDir);
  1108. hr = S_OK;
  1109. goto out;
  1110. }
  1111. }
  1112. }
  1113. }
  1114. if(hKey)
  1115. RegCloseKey(hKey);
  1116. */
  1117. hKey = NULL;
  1118. // No user name .. just get the common files directory and put TEXT("Microsoft Shared\Address Book") under it
  1119. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszCurrentVer, 0, KEY_READ, &hKey))
  1120. {
  1121. dwSize = ARRAYSIZE(szPath);
  1122. if(ERROR_SUCCESS == RegQueryValueEx(hKey, lpszCommonFiles, NULL, &dwType, (LPBYTE) szPath, &dwSize))
  1123. {
  1124. if(lstrlen(szPath))
  1125. {
  1126. StrCatBuff(szPath, lpszMicrosoftShared, ARRAYSIZE(szPath));
  1127. CreateDirectory(szPath, NULL);
  1128. if(GetFileAttributes(szPath) != 0xFFFFFFFF)
  1129. {
  1130. StrCatBuff(szPath, lpszAddressBook, ARRAYSIZE(szPath));
  1131. CreateDirectory(szPath, NULL);
  1132. if(GetFileAttributes(szPath) != 0xFFFFFFFF)
  1133. {
  1134. StrCpyN(szDir, szPath, cchSizeDir);
  1135. hr = S_OK;
  1136. goto out;
  1137. }
  1138. }
  1139. }
  1140. }
  1141. }
  1142. // if all of the above failed then we'll have problems since this function must NEVER fail when
  1143. // it is called,
  1144. // Hence go ahead and try to create c:\address book (which might fail on an 8.3 machine) in which case
  1145. // create c:\wab
  1146. if(CreateDirectory(lpszCAddressBook, NULL))
  1147. {
  1148. StrCpyN(szDir, lpszCAddressBook, cchSizeDir);
  1149. StrCatBuff(szDir, TEXT("\\"), cchSizeDir);
  1150. hr = S_OK;
  1151. goto out;
  1152. }
  1153. // failed - try c:\wab
  1154. if(CreateDirectory(lpszCWAB, NULL))
  1155. {
  1156. StrCpyN(szDir, lpszCWAB, cchSizeDir);
  1157. hr = S_OK;
  1158. goto out;
  1159. }
  1160. // still failed !!!!!???!!? !@#!@#!!!
  1161. // just return the windows directory if we can
  1162. if (GetWindowsDirectory(szPath, ARRAYSIZE(szPath)))
  1163. {
  1164. StrCpyN(szDir, szPath, cchSizeDir);
  1165. hr = S_OK;
  1166. goto out;
  1167. }
  1168. // still failed !!!!!???!!? !@#!@#!!!
  1169. // just return 'c:'
  1170. StrCpyN(szDir, TEXT("c:\\"), cchSizeDir);
  1171. hr = S_OK;
  1172. out:
  1173. if(hKey)
  1174. RegCloseKey(hKey);
  1175. if(szDir && lstrlen(szDir))
  1176. {
  1177. // Add a terminating slash to the directory name if one doesnt exist
  1178. if( *(szDir+lstrlen(szDir)-1) != '\\' )
  1179. StrCatBuff(szDir, szBackSlash, cchSizeDir);
  1180. }
  1181. return hr;
  1182. }
  1183. /*
  1184. -
  1185. - DoFirstRunMigrationAndProcessing
  1186. *
  1187. * Purpose:
  1188. * If this is an IE4 or later first run, move the old WAB file from
  1189. * windows to a new location and/or create a new WAB file so that the
  1190. * old WAB file is not mucked around with
  1191. *
  1192. */
  1193. HRESULT DoFirstRunMigrationAndProcessing()
  1194. {
  1195. HRESULT hr = S_OK;
  1196. const LPTSTR lpszFirstRunValue = TEXT("FirstRun");
  1197. const LPTSTR lpszIE3Ext = TEXT(".ie3");
  1198. DWORD dwType = 0;
  1199. DWORD dwValue = 0;
  1200. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1201. TCHAR szDir[MAX_PATH];
  1202. TCHAR szFileName[MAX_PATH];
  1203. HKEY hKey = NULL;
  1204. DWORD dwSize = sizeof(DWORD);
  1205. // First check if this is a first run - if its not a first run then we can just skip out
  1206. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, lpNewWABRegKey, 0, KEY_READ, &hKey))
  1207. {
  1208. if(ERROR_SUCCESS == RegQueryValueEx( hKey, lpszFirstRunValue, NULL, &dwType, (LPBYTE) &dwValue, &dwSize))
  1209. {
  1210. goto out;
  1211. }
  1212. }
  1213. if(hKey)
  1214. RegCloseKey(hKey);
  1215. hKey = NULL;
  1216. // So this is the first run ..
  1217. // First thing to do is to Migrate the LDAP accounts in this session only ...
  1218. // Set the first run flag
  1219. pt_bFirstRun = TRUE;
  1220. // Get the directory name of the new directory in which the WAB file will be created/copied
  1221. *szDir = '\0';
  1222. if (hr = GetNewDataDirName(szDir, ARRAYSIZE(szDir)))
  1223. goto out;
  1224. *szFileName = '\0';
  1225. // Do we have a pre-existing wab data file ? Check by looking in the registry for the appropriate reg key
  1226. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, lpszOldKeyName, 0, KEY_ALL_ACCESS, &hKey))
  1227. {
  1228. TCHAR szOldPath[MAX_PATH];
  1229. TCHAR szWinPath[MAX_PATH];
  1230. TCHAR szNewName[MAX_PATH];
  1231. // Get the file path ..
  1232. dwSize = ARRAYSIZE(szOldPath);
  1233. *szOldPath = '\0';
  1234. if(ERROR_SUCCESS == RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)szOldPath, &dwSize))
  1235. {
  1236. if(lstrlen(szOldPath) && GetFileAttributes(szOldPath)!= 0xFFFFFFFF)
  1237. {
  1238. LPTSTR lp1= NULL, lp2 = NULL;
  1239. // isolate the wab file name here
  1240. lp1 = szOldPath;
  1241. while(lp1 && *lp1)
  1242. {
  1243. if(*lp1 == '\\')
  1244. lp2 = lp1;
  1245. lp1 = CharNext(lp1);
  1246. }
  1247. if(!lp2)
  1248. lp2 = szOldPath;
  1249. else
  1250. {
  1251. lp1 = lp2;
  1252. lp2 = CharNext(lp1);
  1253. }
  1254. StrCpyN(szFileName, lp2, ARRAYSIZE(szFileName));
  1255. // rename the old file as an ie3 file by appending .ie3 to the end of the file name
  1256. StrCpyN(szNewName, szOldPath, ARRAYSIZE(szNewName));
  1257. StrCatBuff(szNewName, lpszIE3Ext, ARRAYSIZE(szNewName));
  1258. if(MoveFile(szOldPath, szNewName))
  1259. {
  1260. // Update the new name and path in the old registry setting
  1261. RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)szNewName, (lstrlen(szNewName)+1) * sizeof(TCHAR) );
  1262. }
  1263. StrCpyN(szOldPath, szNewName, ARRAYSIZE(szOldPath));
  1264. *szNewName = '\0';
  1265. // Is this in the Windows Directory ??
  1266. *szWinPath = '\0';
  1267. GetWindowsDirectory(szWinPath, ARRAYSIZE(szWinPath));
  1268. if(lstrlen(szWinPath) &&
  1269. lstrlen(szWinPath) < lstrlen(szOldPath))
  1270. {
  1271. // Terminate the old file path just before the filename
  1272. // If the file is in the Windows directory, the remaining filename
  1273. // will be the same as the windows path
  1274. if(*lp1 == '\\') //lp1 was set above
  1275. {
  1276. // First check that the windows directory is not the root directory (e.g. C:\)
  1277. if(lstrlen(szWinPath) == 3 && szWinPath[1]==':' && szWinPath[2]=='\\')
  1278. lp1 = CharNext(lp1); // Move lp1 past the '\'
  1279. *lp1 = '\0';
  1280. }
  1281. if(!lstrcmpi(szOldPath, szWinPath))
  1282. {
  1283. dwSize = ARRAYSIZE(szOldPath);
  1284. RegQueryValueEx(hKey, NULL, 0, &dwType, (LPBYTE) szOldPath, &dwSize);
  1285. StrCpyN(szNewName, szDir, ARRAYSIZE(szNewName));
  1286. StrCatBuff(szNewName, szFileName, ARRAYSIZE(szNewName));
  1287. StrCatBuff(szNewName, lpszIE3Ext, ARRAYSIZE(szNewName));
  1288. // move this file to the new directory
  1289. if(MoveFile(szOldPath, szNewName))
  1290. {
  1291. // Update the newname in the registry
  1292. RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)szNewName, (lstrlen(szNewName)+1) * sizeof(TCHAR) );
  1293. }
  1294. StrCpyN(szOldPath, szNewName, ARRAYSIZE(szOldPath));
  1295. }
  1296. }
  1297. // Since the old WAB file exists, we will make a copy and put it in the newdir
  1298. StrCpyN(szNewName, szDir, ARRAYSIZE(szNewName));
  1299. StrCatBuff(szNewName, szFileName, ARRAYSIZE(szNewName));
  1300. CopyFile(szOldPath, szNewName, TRUE);
  1301. {
  1302. // if the CopyFile fails because something already exists in the new dir, still update
  1303. // the path to the new dir (prevent using the old file no matter what)
  1304. HKEY hKeyNew = NULL;
  1305. DWORD dwDisposition = 0;
  1306. if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, lpszKeyName, 0, NULL, 0, KEY_ALL_ACCESS,
  1307. NULL, &hKeyNew, &dwDisposition))
  1308. {
  1309. RegSetValueEx(hKeyNew, NULL, 0, REG_SZ, (LPBYTE)szNewName, (lstrlen(szNewName)+1) * sizeof(TCHAR) );
  1310. }
  1311. if(hKeyNew)
  1312. RegCloseKey(hKeyNew);
  1313. }
  1314. }
  1315. }
  1316. }
  1317. // update the first run flag
  1318. if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, lpNewWABRegKey, 0, KEY_ALL_ACCESS, &hKey))
  1319. {
  1320. dwValue = 1;
  1321. dwSize = sizeof(dwValue);
  1322. if(ERROR_SUCCESS != RegSetValueEx( hKey, lpszFirstRunValue, 0, REG_DWORD, (LPBYTE) &dwValue, dwSize))
  1323. {
  1324. goto out;
  1325. }
  1326. }
  1327. if(hKey)
  1328. RegCloseKey(hKey);
  1329. hKey = NULL;
  1330. hr = S_OK;
  1331. out:
  1332. if(hKey)
  1333. RegCloseKey(hKey);
  1334. return hr;
  1335. }
  1336. // Random test data .. ignore
  1337. // static OlkContInfo rgOlk[2];
  1338. // LPTSTR lp1 = "Contact Folder 1";
  1339. // LPTSTR lp2 = "Second Contact Folder";
  1340. extern void ConvertOlkConttoWABCont( ULONG * lpcolk, OutlookContInfo ** lprgolk,
  1341. ULONG * lpcolkci, OlkContInfo ** lprgolkci);
  1342. /*
  1343. - OpenAddRefPropertyStore
  1344. -
  1345. * Purpose:
  1346. * Get the property store name from the registry and open it.
  1347. * Addref it
  1348. *
  1349. * Arguments:
  1350. * lpPropertyStore PROPERTY_STORE structure
  1351. *
  1352. * Returns:
  1353. * SCODE
  1354. *
  1355. * Notes:
  1356. * This routine is kind of a mess with all these gotos and special cases
  1357. * for failed registry functions. I'm not sure why, but the registry
  1358. * functions operate differently on NT and Win95, but in both cases,
  1359. * they sometimes act as though the key already exists even when it doesn't.
  1360. *
  1361. */
  1362. SCODE OpenAddRefPropertyStore(LPWAB_PARAM lpWP, LPPROPERTY_STORE lpPropertyStore) {
  1363. HRESULT hResult = hrSuccess;
  1364. SCODE sc = SUCCESS_SUCCESS;
  1365. TCHAR szFileName[MAX_PATH];
  1366. LPTSTR lpCurrent;
  1367. HKEY hKey = NULL;
  1368. DWORD cchLenName = ARRAYSIZE(szFileName);
  1369. DWORD cchCurrent = 0;
  1370. DWORD dwDisposition = 0;
  1371. DWORD dwType = 0;
  1372. HWND hWnd = NULL;
  1373. ULONG ulFlags = AB_OPEN_ALWAYS;
  1374. LPTSTR lpszWABExt = TEXT(".wab");
  1375. BOOL fNewKey = FALSE;
  1376. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1377. szFileName[0]='\0';
  1378. if (lpWP)
  1379. {
  1380. // The cbSize parameter will, in the future, tell us what version
  1381. // of the WAB_PARAM is being called so we can upgrade the WAB_PARAM
  1382. // structure in future releases. For this version the cbSize
  1383. // doesnt really matter.
  1384. hWnd = lpWP->hwnd;
  1385. if(!lpWP->ulFlags && lpWP->szFileName )
  1386. {
  1387. LPWSTR lpW = ConvertAtoW(lpWP->szFileName);
  1388. if (lpW != NULL)
  1389. {
  1390. lstrcpy(szFileName, lpW);
  1391. LocalFreeAndNull(&lpW);
  1392. }
  1393. }
  1394. }
  1395. if (! lpPropertyStore->ulRefCount) {
  1396. if (pt_bIsWABOpenExSession) {
  1397. hResult = OpenPropertyStore(NULL, 0, hWnd,
  1398. &(lpPropertyStore->hPropertyStore));
  1399. if (SUCCEEDED(hResult))
  1400. {
  1401. LPWABSTORAGEPROVIDER lpWSP;
  1402. ULONG colk = 0;
  1403. OutlookContInfo * rgolk = NULL;
  1404. Assert(lpPropertyStore->hPropertyStore);
  1405. Assert(!lpPropertyStore->rgolkci);
  1406. Assert(!lpPropertyStore->colkci);
  1407. lpWSP = (LPWABSTORAGEPROVIDER)(lpPropertyStore->hPropertyStore);
  1408. hResult = lpWSP->lpVtbl->GetContainerList(lpWSP, &colk, &rgolk);
  1409. if(!HR_FAILED(hResult))
  1410. {
  1411. DebugTrace(TEXT("WABStorageProvider::GetContainerList returns:%x\n"),hResult);
  1412. ConvertOlkConttoWABCont(&colk, &rgolk, &lpPropertyStore->colkci, &lpPropertyStore->rgolkci);
  1413. FreeBufferAndNull(&rgolk);
  1414. }
  1415. else
  1416. {
  1417. lpWSP->lpVtbl->Release(lpWSP);
  1418. lpPropertyStore->hPropertyStore = NULL;
  1419. }
  1420. }
  1421. if (FAILED(hResult)) {
  1422. sc = ResultFromScode(hResult);
  1423. goto error;
  1424. }
  1425. //lpPropertyStore->colkci = 2;
  1426. //rgOlk[0].lpEntryID = rgOlk[1].lpEntryID = lpPropertyStore->rgolkci[0].lpEntryID;
  1427. //rgOlk[0].lpszName = lp1;
  1428. //rgOlk[1].lpszName = lp2;
  1429. //lpPropertyStore->rgolkci = rgOlk;
  1430. goto out;
  1431. }
  1432. //
  1433. // Get the default WAB file name from the registry
  1434. // if we don't have a name supplied in lpWP
  1435. //
  1436. try_again:
  1437. if(!lstrlen(szFileName))
  1438. {
  1439. DoFirstRunMigrationAndProcessing();
  1440. // First, try to open an existing key
  1441. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
  1442. lpszKeyName,
  1443. 0, // options, MBZ
  1444. KEY_ALL_ACCESS,
  1445. &hKey))
  1446. {
  1447. dwDisposition = REG_OPENED_EXISTING_KEY;
  1448. }
  1449. else
  1450. {
  1451. // Create the key
  1452. if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER,
  1453. lpszKeyName,
  1454. 0, //reserved
  1455. NULL,
  1456. REG_OPTION_NON_VOLATILE,
  1457. KEY_ALL_ACCESS,
  1458. NULL,
  1459. &hKey,
  1460. &dwDisposition))
  1461. {
  1462. DebugTrace( TEXT("RegCreateKeyEx failed\n"));
  1463. sc = MAPI_E_NOT_FOUND; // ??
  1464. goto error;
  1465. }
  1466. }
  1467. if (dwDisposition == REG_CREATED_NEW_KEY)
  1468. {
  1469. new_key:
  1470. // prevent more than one retry
  1471. if (fNewKey)
  1472. {
  1473. hResult = ResultFromScode(MAPI_E_NOT_INITIALIZED);
  1474. goto error;
  1475. }
  1476. fNewKey = TRUE;
  1477. //
  1478. // New key ... need to give it a value ..
  1479. //
  1480. // BUG - dont use windows directory for new wab files ..
  1481. // use one of the application data directories ...
  1482. if (GetNewDataDirName(szFileName, ARRAYSIZE(szFileName)))
  1483. {
  1484. DebugTrace( TEXT("GetNewDataDirName failed\n"));
  1485. sc = MAPI_E_NOT_FOUND; // ??
  1486. goto error;
  1487. }
  1488. cchCurrent = lstrlen(szFileName);
  1489. //Tag on a trailing slash if 1 doesnt exist ..
  1490. if (szFileName[cchCurrent-1] != '\\')
  1491. {
  1492. StrCatBuff(szFileName, szBackSlash, ARRAYSIZE(szFileName));
  1493. }
  1494. // Get a user name ...
  1495. cchCurrent = lstrlen(szFileName);
  1496. lpCurrent = szFileName + cchCurrent;
  1497. cchLenName = (ARRAYSIZE(szFileName) - cchCurrent);
  1498. if (!GetUserName(lpCurrent, &cchLenName))
  1499. {
  1500. cchLenName = (ARRAYSIZE(szFileName) - cchCurrent);
  1501. // On failure just create some dummy file name
  1502. StrCpyN(lpCurrent, TEXT("AddrBook"), cchLenName);
  1503. }
  1504. // Fix any invalid characters in the filename
  1505. while (*lpCurrent) {
  1506. switch (*lpCurrent) {
  1507. case '\\':
  1508. case '/':
  1509. case '<':
  1510. case '>':
  1511. case ':':
  1512. case '"':
  1513. case '|':
  1514. case '?':
  1515. case '*':
  1516. case '.':
  1517. *lpCurrent = '_'; // replace with underscore
  1518. break;
  1519. default:
  1520. break;
  1521. }
  1522. lpCurrent++;
  1523. }
  1524. StrCatBuff(szFileName, lpszWABExt, ARRAYSIZE(szFileName));
  1525. cchLenName = sizeof(TCHAR)*lstrlen(szFileName);
  1526. //save this as the value of the Wab file in the registry
  1527. if (ERROR_SUCCESS != RegSetValueEx(hKey,
  1528. NULL,
  1529. 0,
  1530. REG_SZ,
  1531. (LPBYTE)szFileName,
  1532. cchLenName))
  1533. {
  1534. DebugTrace( TEXT("RegSetValue failed\n"));
  1535. sc = MAPI_E_NOT_FOUND; // ??
  1536. goto error;
  1537. }
  1538. }
  1539. else
  1540. {
  1541. // Didn't create a new key, so get the key value
  1542. if (ERROR_SUCCESS != RegQueryValueEx(hKey,
  1543. NULL,
  1544. NULL,
  1545. &dwType, //reserved
  1546. (LPBYTE)szFileName,
  1547. &cchLenName))
  1548. {
  1549. DebugTrace( TEXT("RegSetValue failed\n"));
  1550. goto new_key;
  1551. }
  1552. else if (! lstrlen(szFileName))
  1553. {
  1554. DebugTrace( TEXT("Warning: Found empty name key!\n"));
  1555. goto new_key;
  1556. }
  1557. //Check that the name in the existing key is a valid filename
  1558. // If it is not a valid file name then we should remove it
  1559. // from the registry and create a new default file name
  1560. if(0xFFFFFFFF == GetFileAttributes(szFileName))
  1561. {
  1562. // There is some problem with this file ...
  1563. // Remove it from the registry and recreate a new file name
  1564. // only if the path doesnt exist. Its possible that the file
  1565. // doesnt exist, in which case we create a new file in open
  1566. // property store
  1567. DWORD dwErr = GetLastError();
  1568. //NT5 bug 180007 - upgrading from Win95 to WinNT 5, if the
  1569. // old file name had quotes around it, CreateFile will fail and
  1570. // so will GetFileAttributes.
  1571. // Strip out the quotes and try again
  1572. if( (dwErr == ERROR_PATH_NOT_FOUND || dwErr == ERROR_INVALID_NAME) &&
  1573. lstrlen(szFileName) && szFileName[0] == '"' && szFileName[lstrlen(szFileName)-1] == '"')
  1574. {
  1575. // remove the quotes
  1576. szFileName[lstrlen(szFileName)-1] = '\0';
  1577. StrCpyN(szFileName, szFileName+1, ARRAYSIZE(szFileName));
  1578. if(0xFFFFFFFF != GetFileAttributes(szFileName))
  1579. goto open_file;
  1580. }
  1581. // otherwise some unknown error with the file name - just discard the
  1582. // file name and try again
  1583. RegCloseKey(hKey);
  1584. RegDeleteKey(HKEY_CURRENT_USER, lpszKeyName);
  1585. szFileName[0]='\0';
  1586. fNewKey = FALSE;
  1587. goto try_again;
  1588. }
  1589. }
  1590. }
  1591. open_file:
  1592. //
  1593. // now we have the file name, open the property store
  1594. //
  1595. if (HR_FAILED(hResult = OpenPropertyStore(szFileName,
  1596. AB_OPEN_ALWAYS,
  1597. hWnd, // HWND for potential Message Boxes
  1598. &(lpPropertyStore->hPropertyStore))))
  1599. {
  1600. // The above call should always pass unless we ran out of disk space or
  1601. // some such thing ..
  1602. DebugTrace( TEXT("OpenPropertyStore failed\n"));
  1603. if(hResult == MAPI_E_NO_ACCESS)
  1604. {
  1605. sc = GetScode(hResult);
  1606. goto error;
  1607. }
  1608. // There is a chance that this may have failed due to a long file name
  1609. // which the machine could not accept.
  1610. if(lstrlen(szFileName) > 8 + 1 + lstrlen(lpszWABExt)) // 8+.+3
  1611. {
  1612. LPTSTR lpLast = szFileName;
  1613. LPTSTR lpTemp = szFileName;
  1614. while(*lpTemp)
  1615. {
  1616. if((*lpTemp) == '\\')
  1617. lpLast = lpTemp;
  1618. lpTemp = CharNext(lpTemp);
  1619. }
  1620. // lpLast points to the last \ .. everything after this will be the file name
  1621. if(lstrlen(lpLast+1) > 12)
  1622. {
  1623. // we need to truncate this name
  1624. *(lpLast+8) = '\0';
  1625. StrCatBuff(szFileName, lpszWABExt, ARRAYSIZE(szFileName));
  1626. hResult = OpenPropertyStore(szFileName,
  1627. AB_OPEN_ALWAYS,
  1628. hWnd, // HWND for potential Message Boxes
  1629. &(lpPropertyStore->hPropertyStore));
  1630. }
  1631. }
  1632. if(HR_FAILED(hResult))
  1633. {
  1634. sc = GetScode(hResult);
  1635. goto error;
  1636. }
  1637. }
  1638. }
  1639. out:
  1640. lpPropertyStore->ulRefCount++;
  1641. error:
  1642. if (hKey) {
  1643. RegCloseKey(hKey);
  1644. }
  1645. return(sc);
  1646. }
  1647. /*
  1648. - ReleaseOutlookStore
  1649. -
  1650. * Purpose:
  1651. * Keep track of outlook store dll refcount
  1652. *
  1653. * Arguments:
  1654. * lpOutlookStore OUTLOOK_STORE structure
  1655. *
  1656. * Returns:
  1657. * Current reference count. When 0, unload outlook-wab dll
  1658. * no longer open.
  1659. *
  1660. */
  1661. ULONG ReleaseOutlookStore(HANDLE hPropertyStore, LPOUTLOOK_STORE lpOutlookStore)
  1662. {
  1663. if(lpOutlookStore)
  1664. {
  1665. lpOutlookStore->ulRefCount--;
  1666. if(0==lpOutlookStore->ulRefCount)
  1667. {
  1668. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1669. if(pt_bIsWABOpenExSession && hPropertyStore)
  1670. {
  1671. // This is a WABOpenEx session using outlooks storage provider
  1672. LPWABSTORAGEPROVIDER lpWSP = (LPWABSTORAGEPROVIDER) hPropertyStore;
  1673. lpWSP->lpVtbl->Release(lpWSP);
  1674. }
  1675. if(lpOutlookStore->hOutlookStore)
  1676. {
  1677. FreeLibrary(lpOutlookStore->hOutlookStore);
  1678. lpOutlookStore->hOutlookStore = NULL;
  1679. #if 0
  1680. // @todo [PaulHi] DLL Leak. Remove this or implement
  1681. // [PaulHi] 3/12/99 @hack Serious HACK warning
  1682. // The Outlook outlwab.dll store module is not unloading some Outlook
  1683. // dlls. This causes Outlook to get confused about who loaded these dlls
  1684. // and whether Outlook or OE should service MAPI calls.
  1685. // HACK Forcibly remove these dlls HACK
  1686. // But only if the WAB WASN'T opened by OL process.
  1687. EnterCriticalSection(&csOMIUnload);
  1688. if (!s_bIsReallyOnlyWABOpenExSession)
  1689. {
  1690. LPCSTR c_lpszOMI9DLL = "omi9.dll";
  1691. LPCSTR c_lpszOMI9PSTDLL = "omipst9.dll";
  1692. LPCSTR c_lpszOMINTDLL = "omint.dll";
  1693. LPCSTR c_lpszOMINTPSTDLL = "omipstnt.dll";
  1694. HINSTANCE hinst;
  1695. // It is essential to unload the omipst9.dll and omipstnt.dll
  1696. // modules first because they load the omi9.dll and omint.dll
  1697. // modules. The FreeLibary() on the omi9/omint modules should
  1698. // not be necessary.
  1699. if ( hinst = GetModuleHandleA(c_lpszOMI9PSTDLL) )
  1700. FreeLibrary(hinst);
  1701. if ( hinst = GetModuleHandleA(c_lpszOMINTPSTDLL) )
  1702. FreeLibrary(hinst);
  1703. if ( hinst = GetModuleHandleA(c_lpszOMI9DLL) )
  1704. FreeLibrary(hinst);
  1705. if ( hinst = GetModuleHandleA(c_lpszOMINTDLL) )
  1706. FreeLibrary(hinst);
  1707. }
  1708. LeaveCriticalSection(&csOMIUnload);
  1709. #endif
  1710. }
  1711. }
  1712. return lpOutlookStore->ulRefCount;
  1713. }
  1714. return 0;
  1715. }
  1716. /*
  1717. - OpenAddRefOutlookStore
  1718. -
  1719. * Purpose:
  1720. * Open or ref count outlook-wab dll
  1721. *
  1722. * Arguments:
  1723. * lpOutlookStore OUTLOOK_STORE structure
  1724. *
  1725. * Returns:
  1726. *
  1727. */
  1728. SCODE OpenAddRefOutlookStore(LPOUTLOOK_STORE lpOutlookStore)
  1729. {
  1730. LPPTGDATA lpPTGData=GetThreadStoragePointer();
  1731. if(!lpOutlookStore)
  1732. return(MAPI_E_INVALID_PARAMETER);
  1733. if(!lpOutlookStore->ulRefCount)
  1734. {
  1735. TCHAR szOutlWABPath[MAX_PATH];
  1736. *szOutlWABPath = '\0';
  1737. if (!bCheckForOutlookWABDll(szOutlWABPath, ARRAYSIZE(szOutlWABPath)) ||
  1738. !lstrlen(szOutlWABPath) ||
  1739. !(lpOutlookStore->hOutlookStore = LoadLibrary(szOutlWABPath)) )
  1740. return MAPI_E_NOT_INITIALIZED;
  1741. // Load the Outlook WABStorageProvider Dll Entry Point here
  1742. // First try to load the Unicode version (doesn't exist but we're thinking forward here)
  1743. lpfnWABOpenStorageProvider = (LPWABOPENSTORAGEPROVIDER) GetProcAddress(lpOutlookStore->hOutlookStore, WAB_SPI_ENTRY_POINT_W);
  1744. if(lpfnWABOpenStorageProvider)
  1745. pt_bIsUnicodeOutlook = TRUE;
  1746. else
  1747. {
  1748. pt_bIsUnicodeOutlook = FALSE;
  1749. lpfnWABOpenStorageProvider = (LPWABOPENSTORAGEPROVIDER) GetProcAddress(lpOutlookStore->hOutlookStore, WAB_SPI_ENTRY_POINT);
  1750. }
  1751. }
  1752. if(lpfnWABOpenStorageProvider && lpOutlookStore->hOutlookStore)
  1753. {
  1754. // Tag this thread as a valid Outlook store session
  1755. // If this flag below is false, we willd default to
  1756. // using the WAB store
  1757. pt_bIsWABOpenExSession = TRUE;
  1758. }
  1759. lpOutlookStore->ulRefCount++;
  1760. return S_OK;
  1761. }