|
|
/*
* WABAPI.C - Main entry to WAB API * */
#include <_apipch.h>
const LPTSTR lpszOldKeyName = TEXT("Software\\Microsoft\\WAB\\Wab File Name"); const LPTSTR lpszKeyName = TEXT("Software\\Microsoft\\WAB\\WAB4\\Wab File Name");
#if 0
CRITICAL_SECTION csOMIUnload; // @todo [PaulHi] DLL Leak. Remove this or implement
static s_bIsReallyOnlyWABOpenExSession = FALSE; // [PaulHi] TRUE if any thread in process creates a
// WAB object through the WABOpenEx() function
#endif
//
// IWABObject jump table is defined here...
//
IWOINT_Vtbl vtblIWOINT = { VTABLE_FILL (IWOINT_QueryInterface_METHOD FAR *) UNKOBJ_QueryInterface, (IWOINT_AddRef_METHOD FAR *) UNKOBJ_AddRef, IWOINT_Release, (IWOINT_GetLastError_METHOD FAR *) UNKOBJ_GetLastError, IWOINT_AllocateBuffer, IWOINT_AllocateMore, IWOINT_FreeBuffer, IWOINT_Backup, IWOINT_Import, IWOINT_Find, IWOINT_VCardDisplay, IWOINT_LDAPUrl, IWOINT_VCardCreate, IWOINT_VCardRetrieve, IWOINT_GetMe, IWOINT_SetMe };
/* Interface which can be queried from lpWABOBJECT.
* * It is important that the order of the interfaces supported be preserved * and that IID_IUnknown be the last in the list. */ IID const FAR * argpiidIWABOBJECT[] = { &IID_IUnknown };
#define WAB_USE_OUTLOOK_ALLOCATORS 0x20000000// Note: This internal flag needs to be
// harmonious with external flags defined
// in wabapi.h for WAB_PARAM structs
/****************************************************************
* - CreateWABObject - * Purpose * Used for creating a WABObject interface in memory. * * Arguments * lppWABObject Pointer to memory location which will receive a * pointer to the new WABObject. * lpPropertyStore Property store structure * * Returns * SCODE * */
STDAPI_(SCODE) CreateWABObject(LPWAB_PARAM lpWP, LPPROPERTY_STORE lpPropertyStore, LPWABOBJECT FAR * lppWABObject) { SCODE sc; LPIWOINT lpIWOINT = NULL;
// validate paremeters
AssertSz(lppWABObject && !IsBadWritePtr(lppWABObject, sizeof(LPWABOBJECT)) && !IsBadWritePtr(lpPropertyStore, sizeof(LPPROPERTY_STORE)), TEXT("lppWABObject fails address check"));
//
// Create a IPDAT per object for lpMAPIPropInternal so that it gets
// called first.
if (FAILED(sc = MAPIAllocateBuffer(sizeof(*lpIWOINT), &lpIWOINT))) { goto error; }
// Init the object to 0, NULL
memset((BYTE *)lpIWOINT, 0, sizeof(*lpIWOINT));
MAPISetBufferName(lpIWOINT, TEXT("WABAPI: lpIWOINT in CreateWABObject"));
// Tag each object that it is created using the OLK MAPI allocators.
if ( lpWP && (lpWP->ulFlags & WAB_USE_OUTLOOK_ALLOCATORS) ) lpIWOINT->bSetOLKAllocators = TRUE;
// Fill in the object specific instance data.
lpIWOINT->inst.hinst = hinstMapiX;//HinstMapi();
#ifdef DEBUG
if (lpIWOINT->inst.hinst == NULL) TraceSz1( TEXT("WABObject: GetModuleHandle failed with error %08lX"), GetLastError()); #endif /* DEBUG */
//
// Open the property store
//
if (FAILED(sc = OpenAddRefPropertyStore(lpWP, lpPropertyStore))) { goto error; }
lpIWOINT->lpPropertyStore = lpPropertyStore;
// Initialize the TEXT("standard") object. This must be the last operation that can fail.
// If not, explicitly call UNKOBJ_Deinit() for failures after a successful UNKOBJ_Init.
if (FAILED(sc = UNKOBJ_Init((LPUNKOBJ)lpIWOINT, (UNKOBJ_Vtbl FAR *)&vtblIWOINT, sizeof(vtblIWOINT), (LPIID FAR *) argpiidIWABOBJECT, dimensionof(argpiidIWABOBJECT), &(lpIWOINT->inst)))) { DebugTrace( TEXT("CreateWABObject() - Error initializing IWOINT object (SCODE = 0x%08lX)\n"), sc); ReleasePropertyStore(lpPropertyStore); // undo the above operation
goto error; }
// Initialize the defaults in WABObject specific part of the object.
lpIWOINT->ulObjAccess = IPROP_READWRITE;
*lppWABObject = (LPWABOBJECT)lpIWOINT;
return(S_OK);
error: FreeBufferAndNull(&lpIWOINT);
return(sc); }
// --------
// IUnknown
/*
- IWOINT_Release - * Purpose: * Decrements reference count on the WABObject and * removes instance data if reference count becomes zero. * * Arguments: * lpWABObject The object to be released. * * Returns: * Decremented reference count * * Side effects: * * Errors: */ STDMETHODIMP_(ULONG) IWOINT_Release(LPIWOINT lpWABObject) { ULONG ulcRef; BOOL bSetOLKAllocators;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
//
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, Release, lpVtbl)) { DebugTrace( TEXT("IWOINT::Release() - Bad object passed\n")); return(1); } #endif
UNKOBJ_EnterCriticalSection((LPUNKOBJ)lpWABObject); ulcRef = --lpWABObject->ulcRef; UNKOBJ_LeaveCriticalSection((LPUNKOBJ)lpWABObject);
// Free the object.
//
// No critical section lock is required since we are guaranteed to be
// the only thread accessing the object (ie ulcRef == 0).
//
if (!ulcRef) { // Free the object.
//
UNKOBJ_Deinit((LPUNKOBJ)lpWABObject);
lpWABObject->lpVtbl = NULL;
ReleaseOutlookStore(lpWABObject->lpPropertyStore->hPropertyStore, lpWABObject->lpOutlookStore);
ReleasePropertyStore(lpWABObject->lpPropertyStore);
bSetOLKAllocators = lpWABObject->bSetOLKAllocators; FreeBufferAndNull(&lpWABObject);
// [PaulHi] 5/5/99 Raid 77138 Null out Outlook allocator function
// pointers if our global count goes to zero.
if (bSetOLKAllocators) { Assert(g_nExtMemAllocCount > 0); InterlockedDecrement((LPLONG)&g_nExtMemAllocCount); if (g_nExtMemAllocCount == 0) { lpfnAllocateBufferExternal = NULL; lpfnAllocateMoreExternal = NULL; lpfnFreeBufferExternal = NULL; } } }
return(ulcRef); }
/*
- IWOINT_AllocateBuffer - * Purpose: * Allocation routine * * Arguments: * lpWABOBJECT this = the open wab object * cbSize number of bytes to allocate * lppBuffer -> Returned buffer * * Returns: * SCODE * */ STDMETHODIMP_(SCODE) IWOINT_AllocateBuffer(LPIWOINT lpWABObject, ULONG cbSize, LPVOID FAR * lppBuffer) { SCODE sc = S_OK;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, AllocateBuffer, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::AllocateBuffer() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
Validate_IWABObject_AllocateBuffer( lpWABObject, cbSize, lppBuffer);
#endif // not NO_VALIDATION
if(!lpWABObject || !lppBuffer) return MAPI_E_INVALID_PARAMETER;
sc = MAPIAllocateBuffer(cbSize, lppBuffer);
// error:
UNKOBJ_SetLastError((LPUNKOBJ)lpWABObject, sc, 0);
return(sc); }
/*
- IWOINT_AllocateMore - * Purpose: * Allocation routine * * Arguments: * lpWABOBJECT this = the open wab object * cbSize number of bytes to allocate * lpObject original allocation * lppBuffer -> Returned buffer * * Returns: * SCODE * */ STDMETHODIMP_(SCODE) IWOINT_AllocateMore(LPIWOINT lpWABObject, ULONG cbSize, LPVOID lpObject, LPVOID FAR * lppBuffer) { SCODE sc = S_OK;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, AllocateMore, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::AllocateMore() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
Validate_IWABObject_AllocateMore( lpWABObject, cbSize, lpObject, lppBuffer);
#endif // not NO_VALIDATION
if(!lpWABObject || !lppBuffer || !lpObject) return MAPI_E_INVALID_PARAMETER;
sc = MAPIAllocateMore(cbSize, lpObject, lppBuffer);
// error:
UNKOBJ_SetLastError((LPUNKOBJ)lpWABObject, sc, 0);
return(sc); }
/*
- IWOINT_FreeBuffer - * Purpose: * Allocation routine * * Arguments: * lpWABOBJECT this = the open wab object * lpBuffer Buffer to free * * Returns: * SCODE * */ STDMETHODIMP_(SCODE) IWOINT_FreeBuffer(LPIWOINT lpWABObject, LPVOID lpBuffer) { SCODE sc = S_OK;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, FreeBuffer, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::FreeBuffer() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
Validate_IWABObject_FreeBuffer( lpWABObject, lpBuffer);
#endif // not NO_VALIDATION
if(!lpWABObject || !lpBuffer) return MAPI_E_INVALID_PARAMETER;
sc = MAPIFreeBuffer(lpBuffer);
// error:
UNKOBJ_SetLastError((LPUNKOBJ)lpWABObject, sc, 0);
return(sc); }
/*
- IWOINT_Backup - * Purpose: * Backup the current database to a file. * * Arguments: * lpWABOBJECT this = the open wab object * lpFileName Filename to backup to * * Returns: * HRESULT * */ STDMETHODIMP IWOINT_Backup(LPIWOINT lpWABObject, LPSTR lpFileName) { SCODE sc = S_OK;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, Backup, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::Backup() - Bad object passed\n")); return ResultFromScode(MAPI_E_INVALID_PARAMETER); }
Validate_IWABObject_Backup( lpWABObject, lpFileName);
#endif // not NO_VALIDATION
// Not yet implemented.
DebugTrace( TEXT("IWABOBJECT::Backup() - Not yet implemented!\n")); sc = MAPI_E_NO_SUPPORT;
// error:
UNKOBJ_SetLastError((LPUNKOBJ)lpWABObject, sc, 0);
return(MakeResult(sc)); }
/*
- IWOINT_Import - * Purpose: * Imports an address book into the current WAB database. * * Arguments: * lpWABOBJECT this = the open wab object * lpwip - WABIMPORTPARAM struct * * Returns: * HRESULT - MAPI_W_ERRORS_RETURNED if some errors occured during import * Failure code if something really failed, S_OK otherwise .. * */ STDMETHODIMP IWOINT_Import(LPIWOINT lpWABObject, LPSTR lpWIP) { LPWABIMPORTPARAM lpwip = (LPWABIMPORTPARAM) lpWIP; LPTSTR lpFile = NULL; HRESULT hr = S_OK;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, Import, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::Import() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
Validate_IWABObject_Import( lpWABObject, lpWIP);
#endif // not NO_VALIDATION
if(!lpwip || !lpwip->lpAdrBook || !lpWABObject) return MAPI_E_INVALID_PARAMETER;
lpFile = ConvertAtoW(lpwip->lpszFileName);
hr = HrImportWABFile(lpwip->hWnd, lpwip->lpAdrBook, lpwip->ulFlags, lpFile);
LocalFreeAndNull(&lpFile);
return hr; }
/*
- IWOINT_Find - * Purpose: * Displays the Find dialog so we can do Start | Find | People * * Arguments: * lpWABOBJECT this = the open wab object * hWnd hWnd of parent for the find dialog * * Returns: * HRESULT * */ STDMETHODIMP IWOINT_Find(LPIWOINT lpWABObject, LPADRBOOK lpAdrBook, HWND hWnd) { HRESULT hr = S_OK; LPPTGDATA lpPTGData=GetThreadStoragePointer();
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, Find, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::Find() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
#endif // not NO_VALIDATION
if(!lpWABObject || !lpAdrBook) return MAPI_E_INVALID_PARAMETER;
hr = HrShowSearchDialog(lpAdrBook, hWnd, (LPADRPARM_FINDINFO) NULL, (LPLDAPURL) NULL, NULL);
return(hr); }
/*
- IWOINT_VCardDisplay - * Purpose: * Displays One off props on a vCard File * * Arguments: * lpWABOBJECT this = the open wab object * lpAdrBook lpAdrBook object * hWnd hWnd of parent for the find dialog * lpszFileName Null terminated file name to display * * Returns: * HRESULT * */ STDMETHODIMP IWOINT_VCardDisplay(LPIWOINT lpWABObject, LPADRBOOK lpAdrBook, HWND hWnd, LPSTR szvCardFile) { HRESULT hr = S_OK; LPTSTR lpVCard = NULL;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, VCardDisplay, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::VCardDisplay() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
#endif // not NO_VALIDATION
if(!lpWABObject || !lpAdrBook) return MAPI_E_INVALID_PARAMETER;
lpVCard = ConvertAtoW(szvCardFile);
hr = HrShowOneOffDetailsOnVCard( lpAdrBook, hWnd, lpVCard); LocalFreeAndNull(&lpVCard); return(hr); }
/*
- IWOINT_VCardCreate - * Purpose: * Takes input mailuser object, and converts its properties * into a vCard file * * Arguments: * lpWABOBJECT this = the open wab object * lpAdrBook lpAdrBook object * hWnd hWnd of parent for the find dialog * lpszFileName Null terminated file name to create * lpMailUser MailUser object to convert to vCard * * Returns: * HRESULT * */ STDMETHODIMP IWOINT_VCardCreate(LPIWOINT lpWABObject, LPADRBOOK lpAdrBook, ULONG ulFlags, LPSTR szvCardFile, LPMAILUSER lpMailUser) { HRESULT hr = S_OK; LPTSTR lpVCardFile = NULL;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, VCardDisplay, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::VCardDisplay() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
#endif // not NO_VALIDATION
if(!lpWABObject || !lpAdrBook || !lpMailUser) return MAPI_E_INVALID_PARAMETER;
lpVCardFile = ConvertAtoW(szvCardFile);
hr = VCardCreate(lpAdrBook, NULL, 0, lpVCardFile, lpMailUser); LocalFreeAndNull(&lpVCardFile); return(hr); }
/*
- IWOINT_VCardRetrieve - * Purpose: * Opens a vCard file and creates a corresponding MailUser out of it * * Arguments: * lpWABOBJECT this = the open wab object * lpAdrBook lpAdrBook object * ulFlags STREAM or FILE * lpszFileName Null terminated file name to display * lppMailUser returned MailUser object * * Returns: * HRESULT * */ STDMETHODIMP IWOINT_VCardRetrieve(LPIWOINT lpWABObject, LPADRBOOK lpAdrBook, ULONG ulFlags, LPSTR szvCard, LPMAILUSER * lppMailUser) { HRESULT hr = S_OK; LPSTR lpStream = NULL; LPTSTR lpFileName = NULL;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, VCardDisplay, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::VCardDisplay() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
#endif // not NO_VALIDATION
if( !lpWABObject || !lpAdrBook || !lppMailUser || !szvCard || (!(ulFlags&WAB_VCARD_STREAM) && !lstrlenA(szvCard)) ) return MAPI_E_INVALID_PARAMETER;
if(ulFlags & WAB_VCARD_STREAM) { DWORD cchSizeStream = (lstrlenA(szvCard)+1); if (!(lpStream = LocalAlloc(LMEM_ZEROINIT, (sizeof(lpStream[0]) * cchSizeStream)))) return MAPI_E_NOT_ENOUGH_MEMORY; StrCpyNA(lpStream, szvCard, cchSizeStream); } else { lpFileName = ConvertAtoW(szvCard); }
hr = VCardRetrieve(lpAdrBook, NULL, 0, lpFileName, lpStream, lppMailUser); LocalFreeAndNull(&lpFileName); LocalFreeAndNull(&lpStream);
return(hr); }
/*
- IWOINT_LDAPUrl - * Purpose: * Handles an LDAP URL * * Arguments: * lpWABOBJECT this = the open wab object * lpAdrBook lpAdrBook object * hWnd hWnd of parent for the find dialog * ulFlags flags saying how we want the results returned * lpszUrl Null terminated file name to display * lppMailUser Possible Mailuser to return based on flag * * With this API, users can pass in a Wide string URL by casting it to a * LPSTR and setting ulFlags to MAPI_UNICODE .. if we detect MAPI_UNICODE, * we cast the string back to a WideChar * Returns: * HRESULT * */ STDMETHODIMP IWOINT_LDAPUrl( LPIWOINT lpWABObject, LPADRBOOK lpAdrBook, HWND hWnd, ULONG ulFlags, LPSTR szLDAPUrl, LPMAILUSER * lppMailUser) { HRESULT hr = S_OK; LPTSTR lpUrl = NULL;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, LDAPUrl, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::LDAPUrl() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
#endif // not NO_VALIDATION
if(!lpWABObject || !lpAdrBook || !szLDAPUrl)// || !lstrlen(szLDAPUrl))
return MAPI_E_INVALID_PARAMETER;
if(ulFlags & MAPI_UNICODE) { lpUrl = (LPWSTR)szLDAPUrl; } else { lpUrl = ConvertAtoW(szLDAPUrl); }
if(!lstrlen(lpUrl)) { hr = MAPI_E_INVALID_PARAMETER; goto out; }
hr = HrProcessLDAPUrl( lpAdrBook, hWnd, ulFlags | ((!ulFlags && hWnd) ? MAPI_DIALOG : 0), lpUrl, lppMailUser); out: if(lpUrl && lpUrl != (LPTSTR)szLDAPUrl) LocalFreeAndNull(&lpUrl);
return hr; }
/*
- IWOINT_GetMe - * Purpose: * Retrieves the 'Me' entry from the WAB .. if the entry doesnt exist, * prompts the user to create one or select someone from his address book. * Unless the caller surpresses the dialog by passing in AB_NO_DIALOG, in * which case, the entry is created behind-the-scenes. Caller can also * call this function to check existence of a ME entry without causing a new * one created as a side effect - to do that they specify the WABOBJECT_ME_NOCREATE flag * which causes failure with MAPI_E_NOT_FOUND if nothing found * * Arguments: * lpWABOBJECT this = the open wab object * lpAdrBook lpAdrBook object * ulFlags 0 or AB_NO_DIALOG * or WABOBJECT_ME_NOCREATE * lpdwAction if supplied, returns WABOBJECT_ME_NEW if a new ME was created * SBinary * returns the entry id of the ME, * ulParam HWND of parent cast as a (ULONG) * * Returns: * HRESULT * */ STDMETHODIMP IWOINT_GetMe( LPIWOINT lpWABObject, LPADRBOOK lpAdrBook, ULONG ulFlags, DWORD * lpdwAction, SBinary * lpsbEID, ULONG ulParam) { HRESULT hr = S_OK;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, GetMe, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::GetMe() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
#endif // not NO_VALIDATION
if(!lpWABObject || !lpAdrBook) return MAPI_E_INVALID_PARAMETER;
hr = HrGetMeObject(lpAdrBook, ulFlags, lpdwAction, lpsbEID, ulParam);
return hr;
}
/*
- IWOINT_SetMe - * Purpose: * Sets the specified object as the Me object .. only 1 Me object will exist in a WAB * Hence it strips the previous Me object, if different, of its Me status. * If no entryid is passed in, and MAPI_DIALOG is specified, a dialog pops up * asking the user to create a ME or to select a ME object .. the selection in the SetMe * dialog is set to the current ME object, if any * If no entryid is passed in, and MAPI_DIALOG is not specified, the function fails * If an entryid is passed in, and MAPI_DIALOG is specified, the SetME dialog is displayed * with the corresponding entryid-object selected in it * If an entryid is passed in, and MAPI_DIALOG is not specified, the entryid, if exists, is * set as the ME object and the old ME object stripped * * Arguments: * lpWABOBJECT this = the open wab object * lpAdrBook lpAdrBook object * ulFlags 0 or MAPI_DIALOG * sbEID entry id of the object to set as ME, * ulParam HWND of parent for DIalogs cast as a ULONG * * Returns: * HRESULT * */ STDMETHODIMP IWOINT_SetMe( LPIWOINT lpWABObject, LPADRBOOK lpAdrBook, ULONG ulFlags, SBinary sbEID, ULONG ulParam) { HRESULT hr = S_OK;
#if !defined(NO_VALIDATION)
// Make sure the object is valid.
if (BAD_STANDARD_OBJ(lpWABObject, IWOINT_, SetMe, lpVtbl)) { DebugTrace( TEXT("IWABOBJECT::GetMe() - Bad object passed\n")); return(ResultFromScode(MAPI_E_INVALID_PARAMETER)); }
#endif // not NO_VALIDATION
if( !lpAdrBook || ((!sbEID.cb||!sbEID.lpb) && !ulFlags) ) { hr = MAPI_E_INVALID_PARAMETER; goto exit; }
hr = HrSetMeObject(lpAdrBook, ulFlags, sbEID, ulParam);
exit: return hr;
}
/*
- ReleasePropertyStore - * Purpose: * Keep track of property store refcount * * Arguments: * lpPropertyStore PROPERTY_STORE structure * * Returns: * Current reference count. When 0, property store is * no longer open. * */ ULONG ReleasePropertyStore(LPPROPERTY_STORE lpPropertyStore) { if (lpPropertyStore->ulRefCount) { IF_WIN32(Assert(lpPropertyStore->hPropertyStore);) if (0 == (--(lpPropertyStore->ulRefCount))) { // Reference goes to zero, release the property store
ClosePropertyStore(lpPropertyStore->hPropertyStore,0); lpPropertyStore->hPropertyStore = NULL;
// Free the container list
FreeBufferAndNull(&(lpPropertyStore->rgolkci)); lpPropertyStore->colkci = 0;
// [PaulHi] Raid #61556
// Must reset this global variable or OUT32WAB.DLL will crash
// the next time it is loaded and the store opened.
pmsessOutlookWabSPI = NULL; } } return(lpPropertyStore->ulRefCount); }
#ifdef WIN16
BOOL WINAPI WABInitThread() { // allocate a TLS index
if ((dwTlsIndex = TlsAlloc()) == 0xfffffff) return FALSE;
return TRUE; } #endif
#define WAB_USE_OUTLOOK_CONTACT_STORE 0x10000000// Note: This internal flag needs to be
// harmonious with external flags defined
// in wabapi.h for WAB_PARAM structs
//
// Input information to pass to WABOpen from IE4 WAB
//
typedef struct _tagWAB_PARAM_V4 { ULONG cbSize; // sizeof(WAB_PARAM).
HWND hwnd; // hWnd of calling client Application. Can be NULL
LPTSTR szFileName; // WAB File name to open. if NULL, opens default.
ULONG ulFlags; // Currently no flags.
} WAB_PARAM_V4, * LPWAB_PARAM_V4;
/*
- WABOpen - * Purpose: * Entry point into the WAB API * * Arguments: * lppAdrBook Returned IAdrBook object * lppWABOBJECT Returned WABObject * Reserved1 Reserved for future filename? * Reserved2 Reserved for future flags * * Returns: * HRESULT * S_OK * E_FAIL // some generic error
* MAPI_E_NOT_ENOUGH_MEMORY: // ran out of memory
* MAPI_E_NO_ACCESS: // file is locked by someone
* MAPI_E_CORRUPT_DATA: // file corrupt
* MAPI_E_DISK_ERROR: // some disk related error opening file
* MAPI_E_INVALID_OBJECT: // secified file exists but its GUID doesnt match
* */ STDMETHODIMP WABOpen(LPADRBOOK FAR * lppAdrBook, LPWABOBJECT FAR * lppWABObject, LPWAB_PARAM lpWP, DWORD Reserved2) { SCODE sc = SUCCESS_SUCCESS; HRESULT hResult = hrSuccess; static PROPERTY_STORE PropertyStore = {NULL, 0, 0, 0, NULL, 0}; static OUTLOOK_STORE OutlookStore = {NULL, 0}; BOOL bUseOutlook = FALSE; LPPTGDATA lpPTGData=GetThreadStoragePointer(); LPTSTR lpFile = NULL;
AssertSz(lppAdrBook && !IsBadWritePtr(lppAdrBook, sizeof(LPADRBOOK)), TEXT("lppAdrBook fails address check"));
AssertSz(lppWABObject && !IsBadWritePtr(lppWABObject, sizeof(LPWABOBJECT)), TEXT("lppWABObject fails address check"));
if(!lppAdrBook || !lppWABObject) return MAPI_E_INVALID_PARAMETER;
IF_WIN16(ScInitMapiUtil(0);)
// First check if this is supposed to be an Outlook session
// If we are explicitly told to use the contact store ...
if((lpWP && (lpWP->ulFlags & WAB_USE_OUTLOOK_CONTACT_STORE)) && PropertyStore.ulRefCount == 0) // Bad bug where wabopen process calls outlook which
// calls wabopenex and we flunk everywhere since this PropertyStore
// information is a static in the original process..
// force the wabopenex to be a wabopen if this rare case happens
bUseOutlook = TRUE; else { // if a file name is specified and this is not wabopenex, then override any
// outlook use .. this way we can explicitly call the wab to open a .wab file
// from anywhere
if(lpWP && lpWP->szFileName && lstrlenA(lpWP->szFileName)) bUseOutlook = FALSE; else bUseOutlook = bUseOutlookStore(); }
#if 0
// @todo [PaulHi] DLL Leak. Remove this or implement
// [PaulHi] Set this process global boolean ONLY if the WAB is opened through the WABOpenEx()
// function ,i.e., by the Outlook process
if (lpWP && (lpWP->ulFlags & WAB_USE_OUTLOOK_CONTACT_STORE)) { EnterCriticalSection(&csOMIUnload); s_bIsReallyOnlyWABOpenExSession = TRUE; LeaveCriticalSection(&csOMIUnload); } #endif
//
// if a .wab file is already initialized in this process space, just inherit that file
// [PaulHi] 12/5/98 Raid #56437
// We still need to allow the Outlook refcount to increment if this store has been created.
// So we need to check both the WAB PropertyStore and OutlookStore ref counts to determine
// if we should prevent the Outlook store from being opened.
// Note that these two lines fixes the following problem:
// 1) User opens OE5 (which opens WAB in non-outlook store mode)
// 2) User has the Outlook set as their default mail client.
// 3) User uses the WAB to initiate a send email.
// 4) Since Outlook is the default client it is launched, and in turn opens WAB
// in outlook store mode. At this point the WAB is already open in non-outlook store
// mode so we want to prevent the Outlook store from being initialized.
//
if (PropertyStore.ulRefCount && !OutlookStore.ulRefCount) bUseOutlook = FALSE;
if(bUseOutlook) { // If this call fails, we will just end up defaulting to the WAB store...
// so we can ignore any errors here
OpenAddRefOutlookStore(&OutlookStore); }
//
// Create the WAB Object
//
if (FAILED(sc = CreateWABObject(lpWP, &PropertyStore, lppWABObject))) { hResult = ResultFromScode(sc); if(bUseOutlook) // IE6 bug 15174
pt_bIsWABOpenExSession = FALSE; goto exit; }
//
// Create the IAdrBook Object
//
if (HR_FAILED(hResult = HrNewIAB(&PropertyStore, *lppWABObject, lppAdrBook))) { // IAdrBook creation failed, fail WABOpen and clean up.
UlRelease(*lppWABObject); goto exit; } DebugTrace( TEXT("WABOpen succeeds\n"));
if(bUseOutlook) { if( lppWABObject && *lppWABObject && OutlookStore.hOutlookStore) { ((LPIWOINT)(*lppWABObject))->lpOutlookStore = &OutlookStore; }
// Bug - Outlook needs a way for its secondary threads to know this is a WABOpenEx session
// without their calling WABOpenEx (They pass the iAdrBook pointer around it seems). Hence
// tag this IADRbook pointer
if(!HR_FAILED(hResult) && lppAdrBook && *lppAdrBook && pt_bIsWABOpenExSession) ((LPIAB)(*lppAdrBook))->lpPropertyStore->bIsWABOpenExSession = TRUE; }
if(lppAdrBook && *lppAdrBook) { // Load the WABs private named properties
HrLoadPrivateWABProps((LPIAB) *lppAdrBook);
if(lpWP && (lpWP->cbSize > sizeof(WAB_PARAM_V4)) ) ((LPIAB)*lppAdrBook)->guidPSExt = lpWP->guidPSExt;
// As long as this is not an Outlook session, profiles are always
// enabled in the UI
if( !pt_bIsWABOpenExSession && !((LPIAB)(*lppAdrBook))->lpPropertyStore->bIsWABOpenExSession ) { ((LPIAB)(*lppAdrBook))->bProfilesEnabled = TRUE; }
if( ((LPIAB)(*lppAdrBook))->bProfilesEnabled ) { if(lpWP && (lpWP->ulFlags & WAB_ENABLE_PROFILES)) // only check for profiles the first time we enter for this process
{ if(PropertyStore.ulRefCount >= 2) { ((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled = ((LPIAB)(*lppAdrBook))->bProfilesIdent = TRUE; } else { ((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled = PropertyStore.bProfileAPIs; }
if(((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled ) hResult = HrLogonAndGetCurrentUserProfile(lpWP->hwnd, ((LPIAB)(*lppAdrBook)), FALSE, FALSE); // if there is some identity related error we should then revert to
// non-identity mode
if(HR_FAILED(hResult)) { PropertyStore.bProfileAPIs = ((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled = FALSE; hResult = S_OK; } else PropertyStore.bProfileAPIs = ((LPIAB)(*lppAdrBook))->bProfilesAPIEnabled = TRUE; } }
if( ((LPIAB)(*lppAdrBook))->bProfilesEnabled ) { if(HR_FAILED(hResult = HrGetWABProfiles((LPIAB) *lppAdrBook))) { // UGH! If this failed then we are quite in trouble and won't be able to support a profile-enabled
// session without crashing badly .. hence above failure is critical enough to stop
// loading the WAB
(*lppAdrBook)->lpVtbl->Release(*lppAdrBook); (*lppWABObject)->lpVtbl->Release(*lppWABObject); } } ReadWABCustomColumnProps((LPIAB) *lppAdrBook);
// need to be aware of Identity Notifications if this is a profile aware WAB independent
// of whether the store is switched to using Outlook or not
//
// If the caller specifically asked for profiles
// (then assume it is identity aware and register for Identity Notifications
// because if the caller is using Identites, WAB launched as a child window
// needs to be able to shut down when it gets a switch_identites message
if( lpWP && (lpWP->ulFlags & WAB_ENABLE_PROFILES)) HrRegisterUnregisterForIDNotifications( (LPIAB) *lppAdrBook, TRUE);
if( lpWP && (lpWP->ulFlags & WAB_USE_OE_SENDMAIL)) ((LPIAB) *lppAdrBook)->bUseOEForSendMail = TRUE; }
exit: return(hResult); }
/*
- WABOpenEx - * Purpose: * Extended Entry point into the WAB API * * Arguments: * lppAdrBook Returned IAdrBook object * lppWABOBJECT Returned WABObject * lpMP WAB Parameter structure (NULL by default) * Reserved Optional IMAPISession parameter * fnAllocateBuffer AllocateBuffer function (may be NULL) * fnAllocateMore AllocateMore function (may be NULL) * fnFreeBuffer FreeBuffer function (may be NULL) * * Returns: * HRESULT * S_OK * E_FAIL // some generic error
* MAPI_E_NOT_ENOUGH_MEMORY: // ran out of memory
* MAPI_E_NO_ACCESS: // file is locked by someone
* MAPI_E_CORRUPT_DATA: // file corrupt
* MAPI_E_DISK_ERROR: // some disk related error opening file
* MAPI_E_INVALID_OBJECT: // secified file exists but its GUID doesnt match
* */ STDMETHODIMP WABOpenEx(LPADRBOOK FAR * lppAdrBook, LPWABOBJECT FAR * lppWABObject, LPWAB_PARAM lpWP, DWORD Reserved, ALLOCATEBUFFER * lpfnAllocateBuffer, ALLOCATEMORE * lpfnAllocateMore, FREEBUFFER * lpfnFreeBuffer) {
HRESULT hResult = hrSuccess; SCODE sc = SUCCESS_SUCCESS; WAB_PARAM wp = {0}; if (Reserved) { // This is an IMAPISession that needs to be passed to the
// Outlook storage provider interface ..
pmsessOutlookWabSPI = (LPUNKNOWN)IntToPtr(Reserved); }
if(!lppWABObject || !lppAdrBook) return MAPI_E_INVALID_PARAMETER;
wp.cbSize = sizeof(WAB_PARAM); if(!lpWP) lpWP = ℘ lpWP->ulFlags |= WAB_USE_OUTLOOK_CONTACT_STORE; // Did we get allocators? Set up the globals
if (lpfnAllocateBuffer || lpfnAllocateMore || lpfnFreeBuffer) { if (lpfnAllocateBuffer && lpfnAllocateMore && lpfnFreeBuffer) { DebugTrace( TEXT("WABOpenEx found external allocators\n")); lpfnAllocateBufferExternal = lpfnAllocateBuffer; lpfnAllocateMoreExternal = lpfnAllocateMore; lpfnFreeBufferExternal = lpfnFreeBuffer; lpWP->ulFlags |= WAB_USE_OUTLOOK_ALLOCATORS; InterlockedIncrement((LPLONG)&g_nExtMemAllocCount); // Incremented twice for each object created; IAB and IWO
InterlockedIncrement((LPLONG)&g_nExtMemAllocCount); } else { DebugTrace( TEXT("WABOpenEx got one or two allocator functions, but not all three\n")); hResult = ResultFromScode(MAPI_E_INVALID_PARAMETER); goto exit; } }
hResult = WABOpen( lppAdrBook, lppWABObject, lpWP, 0);
if(lpWP == &wp) lpWP = NULL;
if(HR_FAILED(hResult)) goto exit;
exit: return(hResult); }
/*
- - GetNewDataDirName * * Purpose: * Gets the path of the new data directory in which the WAB file should be placed * * We look for: * Roaming User App Data Dir; else * Program Files\IE\OE\Current User\Address Book; else * Common Files\Microsoft Shared\Address Book; else * Create c:\Address book\ else * Create c:\wab\ * * Returns a valid, existing directory name terminated by a \ * */ HRESULT GetNewDataDirName(LPTSTR szDir, DWORD cchSizeDir) { HRESULT hr = E_FAIL; const LPTSTR lpszShellFolders = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"); const LPTSTR lpszAppData = TEXT("AppData"); const LPTSTR lpszCurrentVer = TEXT("Software\\Microsoft\\Windows\\CurrentVersion"); const LPTSTR lpszCommonFiles = TEXT("CommonFilesDir"); const LPTSTR lpszMicrosoftShared = TEXT("\\Microsoft Shared"); const LPTSTR lpszAddressBook = TEXT("\\Address Book"); const LPTSTR lpszOEKey = TEXT("Software\\Microsoft\\Outlook Express\\5.0"); const LPTSTR lpszOERoot = TEXT("Store Root"); const LPTSTR lpszMicrosoft = TEXT("\\Microsoft"); const LPTSTR lpszCAddressBook = TEXT("c:\\Address book"); const LPTSTR lpszCWAB = TEXT("c:\\WAB");
HKEY hKey = NULL; DWORD dwSize = 0;
DWORD dwType = 0; TCHAR szPath[MAX_PATH]; TCHAR szUser[MAX_PATH];
*szPath='\0';
if(!szDir) goto out;
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,lpszShellFolders,0,KEY_READ,&hKey)) { // Look for the App Data directory
dwSize = ARRAYSIZE(szPath); if(ERROR_SUCCESS == RegQueryValueEx(hKey, lpszAppData, NULL, &dwType, (LPBYTE) szPath, &dwSize)) { if(lstrlen(szPath)) { StrCpyN(szDir, szPath, cchSizeDir); if(GetFileAttributes(szDir) != 0xFFFFFFFF) { StrCatBuff(szDir, lpszMicrosoft, cchSizeDir); if(GetFileAttributes(szDir) == 0xFFFFFFFF) CreateDirectory(szDir, NULL); StrCatBuff(szDir, lpszAddressBook, cchSizeDir); if(GetFileAttributes(szDir) == 0xFFFFFFFF) CreateDirectory(szDir, NULL); } hr = S_OK; goto out; } } }
if(hKey) RegCloseKey(hKey); hKey = NULL;
// Didnt find this directory
// Look for MyDocuments folder - it will only be installed with Office so no gaurantee it will be found
// <TBD> - there doesnt seem to be a definite location for this except under
// CurrentVersion\Explorer\Shell Folders\Personal
// Didnt find a My Documents directory
// See if OE is installed for the current user ..
/** commented out until OE has stable dir structure
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, lpszOEKey, 0, KEY_READ, &hKey)) { dwSize = CharSizeOf(szPath); if(ERROR_SUCCESS == RegQueryValueEx(hKey, lpszOERoot, NULL, &dwType, (LPBYTE) szPath, &dwSize)) { if(lstrlen(szPath)) { StrCatBuff(szPath,lpszAddressBook, ARRAYSIZE(szPath));
//if directory doesnt exist, create it
CreateDirectory(szPath, NULL); //ignore error if it already exists
if(GetFileAttributes(szPath) != 0xFFFFFFFF) { StrCpyN(szDir, szPath, cchSizeDir); hr = S_OK; goto out; } } } }
if(hKey) RegCloseKey(hKey); */ hKey = NULL;
// No user name .. just get the common files directory and put TEXT("Microsoft Shared\Address Book") under it
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszCurrentVer, 0, KEY_READ, &hKey)) { dwSize = ARRAYSIZE(szPath); if(ERROR_SUCCESS == RegQueryValueEx(hKey, lpszCommonFiles, NULL, &dwType, (LPBYTE) szPath, &dwSize)) { if(lstrlen(szPath)) { StrCatBuff(szPath, lpszMicrosoftShared, ARRAYSIZE(szPath)); CreateDirectory(szPath, NULL); if(GetFileAttributes(szPath) != 0xFFFFFFFF) { StrCatBuff(szPath, lpszAddressBook, ARRAYSIZE(szPath)); CreateDirectory(szPath, NULL); if(GetFileAttributes(szPath) != 0xFFFFFFFF) { StrCpyN(szDir, szPath, cchSizeDir); hr = S_OK; goto out; } } } } }
// if all of the above failed then we'll have problems since this function must NEVER fail when
// it is called,
// Hence go ahead and try to create c:\address book (which might fail on an 8.3 machine) in which case
// create c:\wab
if(CreateDirectory(lpszCAddressBook, NULL)) { StrCpyN(szDir, lpszCAddressBook, cchSizeDir); StrCatBuff(szDir, TEXT("\\"), cchSizeDir); hr = S_OK; goto out; }
// failed - try c:\wab
if(CreateDirectory(lpszCWAB, NULL)) { StrCpyN(szDir, lpszCWAB, cchSizeDir); hr = S_OK; goto out; }
// still failed !!!!!???!!? !@#!@#!!!
// just return the windows directory if we can
if (GetWindowsDirectory(szPath, ARRAYSIZE(szPath))) { StrCpyN(szDir, szPath, cchSizeDir); hr = S_OK; goto out; } // still failed !!!!!???!!? !@#!@#!!!
// just return 'c:'
StrCpyN(szDir, TEXT("c:\\"), cchSizeDir); hr = S_OK;
out: if(hKey) RegCloseKey(hKey);
if(szDir && lstrlen(szDir)) { // Add a terminating slash to the directory name if one doesnt exist
if( *(szDir+lstrlen(szDir)-1) != '\\' ) StrCatBuff(szDir, szBackSlash, cchSizeDir); }
return hr; }
/*
- - DoFirstRunMigrationAndProcessing * * Purpose: * If this is an IE4 or later first run, move the old WAB file from * windows to a new location and/or create a new WAB file so that the * old WAB file is not mucked around with * */ HRESULT DoFirstRunMigrationAndProcessing() { HRESULT hr = S_OK; const LPTSTR lpszFirstRunValue = TEXT("FirstRun"); const LPTSTR lpszIE3Ext = TEXT(".ie3"); DWORD dwType = 0; DWORD dwValue = 0; LPPTGDATA lpPTGData=GetThreadStoragePointer(); TCHAR szDir[MAX_PATH]; TCHAR szFileName[MAX_PATH]; HKEY hKey = NULL; DWORD dwSize = sizeof(DWORD);
// First check if this is a first run - if its not a first run then we can just skip out
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, lpNewWABRegKey, 0, KEY_READ, &hKey)) { if(ERROR_SUCCESS == RegQueryValueEx( hKey, lpszFirstRunValue, NULL, &dwType, (LPBYTE) &dwValue, &dwSize)) { goto out; } }
if(hKey) RegCloseKey(hKey); hKey = NULL;
// So this is the first run ..
// First thing to do is to Migrate the LDAP accounts in this session only ...
// Set the first run flag
pt_bFirstRun = TRUE;
// Get the directory name of the new directory in which the WAB file will be created/copied
*szDir = '\0';
if (hr = GetNewDataDirName(szDir, ARRAYSIZE(szDir))) goto out;
*szFileName = '\0';
// Do we have a pre-existing wab data file ? Check by looking in the registry for the appropriate reg key
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, lpszOldKeyName, 0, KEY_ALL_ACCESS, &hKey)) { TCHAR szOldPath[MAX_PATH]; TCHAR szWinPath[MAX_PATH]; TCHAR szNewName[MAX_PATH];
// Get the file path ..
dwSize = ARRAYSIZE(szOldPath); *szOldPath = '\0'; if(ERROR_SUCCESS == RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)szOldPath, &dwSize)) { if(lstrlen(szOldPath) && GetFileAttributes(szOldPath)!= 0xFFFFFFFF) { LPTSTR lp1= NULL, lp2 = NULL;
// isolate the wab file name here
lp1 = szOldPath; while(lp1 && *lp1) { if(*lp1 == '\\') lp2 = lp1; lp1 = CharNext(lp1); }
if(!lp2) lp2 = szOldPath; else { lp1 = lp2; lp2 = CharNext(lp1); }
StrCpyN(szFileName, lp2, ARRAYSIZE(szFileName));
// rename the old file as an ie3 file by appending .ie3 to the end of the file name
StrCpyN(szNewName, szOldPath, ARRAYSIZE(szNewName)); StrCatBuff(szNewName, lpszIE3Ext, ARRAYSIZE(szNewName));
if(MoveFile(szOldPath, szNewName)) { // Update the new name and path in the old registry setting
RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)szNewName, (lstrlen(szNewName)+1) * sizeof(TCHAR) ); } StrCpyN(szOldPath, szNewName, ARRAYSIZE(szOldPath)); *szNewName = '\0';
// Is this in the Windows Directory ??
*szWinPath = '\0'; GetWindowsDirectory(szWinPath, ARRAYSIZE(szWinPath)); if(lstrlen(szWinPath) && lstrlen(szWinPath) < lstrlen(szOldPath)) { // Terminate the old file path just before the filename
// If the file is in the Windows directory, the remaining filename
// will be the same as the windows path
if(*lp1 == '\\') //lp1 was set above
{ // First check that the windows directory is not the root directory (e.g. C:\)
if(lstrlen(szWinPath) == 3 && szWinPath[1]==':' && szWinPath[2]=='\\') lp1 = CharNext(lp1); // Move lp1 past the '\'
*lp1 = '\0'; }
if(!lstrcmpi(szOldPath, szWinPath)) { dwSize = ARRAYSIZE(szOldPath); RegQueryValueEx(hKey, NULL, 0, &dwType, (LPBYTE) szOldPath, &dwSize);
StrCpyN(szNewName, szDir, ARRAYSIZE(szNewName)); StrCatBuff(szNewName, szFileName, ARRAYSIZE(szNewName)); StrCatBuff(szNewName, lpszIE3Ext, ARRAYSIZE(szNewName));
// move this file to the new directory
if(MoveFile(szOldPath, szNewName)) { // Update the newname in the registry
RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)szNewName, (lstrlen(szNewName)+1) * sizeof(TCHAR) ); }
StrCpyN(szOldPath, szNewName, ARRAYSIZE(szOldPath)); } }
// Since the old WAB file exists, we will make a copy and put it in the newdir
StrCpyN(szNewName, szDir, ARRAYSIZE(szNewName)); StrCatBuff(szNewName, szFileName, ARRAYSIZE(szNewName));
CopyFile(szOldPath, szNewName, TRUE); { // if the CopyFile fails because something already exists in the new dir, still update
// the path to the new dir (prevent using the old file no matter what)
HKEY hKeyNew = NULL; DWORD dwDisposition = 0; if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, lpszKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKeyNew, &dwDisposition)) { RegSetValueEx(hKeyNew, NULL, 0, REG_SZ, (LPBYTE)szNewName, (lstrlen(szNewName)+1) * sizeof(TCHAR) ); } if(hKeyNew) RegCloseKey(hKeyNew); } } } }
// update the first run flag
if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, lpNewWABRegKey, 0, KEY_ALL_ACCESS, &hKey)) { dwValue = 1; dwSize = sizeof(dwValue); if(ERROR_SUCCESS != RegSetValueEx( hKey, lpszFirstRunValue, 0, REG_DWORD, (LPBYTE) &dwValue, dwSize)) { goto out; } }
if(hKey) RegCloseKey(hKey);
hKey = NULL;
hr = S_OK;
out:
if(hKey) RegCloseKey(hKey);
return hr; }
// Random test data .. ignore
// static OlkContInfo rgOlk[2];
// LPTSTR lp1 = "Contact Folder 1";
// LPTSTR lp2 = "Second Contact Folder";
extern void ConvertOlkConttoWABCont( ULONG * lpcolk, OutlookContInfo ** lprgolk, ULONG * lpcolkci, OlkContInfo ** lprgolkci);
/*
- OpenAddRefPropertyStore - * Purpose: * Get the property store name from the registry and open it. * Addref it * * Arguments: * lpPropertyStore PROPERTY_STORE structure * * Returns: * SCODE * * Notes: * This routine is kind of a mess with all these gotos and special cases * for failed registry functions. I'm not sure why, but the registry * functions operate differently on NT and Win95, but in both cases, * they sometimes act as though the key already exists even when it doesn't. * */ SCODE OpenAddRefPropertyStore(LPWAB_PARAM lpWP, LPPROPERTY_STORE lpPropertyStore) { HRESULT hResult = hrSuccess; SCODE sc = SUCCESS_SUCCESS; TCHAR szFileName[MAX_PATH]; LPTSTR lpCurrent; HKEY hKey = NULL; DWORD cchLenName = ARRAYSIZE(szFileName); DWORD cchCurrent = 0; DWORD dwDisposition = 0; DWORD dwType = 0; HWND hWnd = NULL; ULONG ulFlags = AB_OPEN_ALWAYS; LPTSTR lpszWABExt = TEXT(".wab"); BOOL fNewKey = FALSE; LPPTGDATA lpPTGData=GetThreadStoragePointer();
szFileName[0]='\0';
if (lpWP) { // The cbSize parameter will, in the future, tell us what version
// of the WAB_PARAM is being called so we can upgrade the WAB_PARAM
// structure in future releases. For this version the cbSize
// doesnt really matter.
hWnd = lpWP->hwnd;
if(!lpWP->ulFlags && lpWP->szFileName ) { LPWSTR lpW = ConvertAtoW(lpWP->szFileName); if (lpW != NULL) { lstrcpy(szFileName, lpW); LocalFreeAndNull(&lpW); } }
}
if (! lpPropertyStore->ulRefCount) { if (pt_bIsWABOpenExSession) { hResult = OpenPropertyStore(NULL, 0, hWnd, &(lpPropertyStore->hPropertyStore)); if (SUCCEEDED(hResult)) { LPWABSTORAGEPROVIDER lpWSP; ULONG colk = 0; OutlookContInfo * rgolk = NULL; Assert(lpPropertyStore->hPropertyStore); Assert(!lpPropertyStore->rgolkci); Assert(!lpPropertyStore->colkci); lpWSP = (LPWABSTORAGEPROVIDER)(lpPropertyStore->hPropertyStore); hResult = lpWSP->lpVtbl->GetContainerList(lpWSP, &colk, &rgolk); if(!HR_FAILED(hResult)) { DebugTrace(TEXT("WABStorageProvider::GetContainerList returns:%x\n"),hResult); ConvertOlkConttoWABCont(&colk, &rgolk, &lpPropertyStore->colkci, &lpPropertyStore->rgolkci); FreeBufferAndNull(&rgolk); } else { lpWSP->lpVtbl->Release(lpWSP); lpPropertyStore->hPropertyStore = NULL; } } if (FAILED(hResult)) { sc = ResultFromScode(hResult); goto error; } //lpPropertyStore->colkci = 2;
//rgOlk[0].lpEntryID = rgOlk[1].lpEntryID = lpPropertyStore->rgolkci[0].lpEntryID;
//rgOlk[0].lpszName = lp1;
//rgOlk[1].lpszName = lp2;
//lpPropertyStore->rgolkci = rgOlk;
goto out; }
//
// Get the default WAB file name from the registry
// if we don't have a name supplied in lpWP
//
try_again: if(!lstrlen(szFileName)) { DoFirstRunMigrationAndProcessing();
// First, try to open an existing key
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, lpszKeyName, 0, // options, MBZ
KEY_ALL_ACCESS, &hKey)) { dwDisposition = REG_OPENED_EXISTING_KEY; } else { // Create the key
if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, lpszKeyName, 0, //reserved
NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition)) { DebugTrace( TEXT("RegCreateKeyEx failed\n")); sc = MAPI_E_NOT_FOUND; // ??
goto error; } }
if (dwDisposition == REG_CREATED_NEW_KEY) { new_key: // prevent more than one retry
if (fNewKey) { hResult = ResultFromScode(MAPI_E_NOT_INITIALIZED); goto error; } fNewKey = TRUE; //
// New key ... need to give it a value ..
//
// BUG - dont use windows directory for new wab files ..
// use one of the application data directories ...
if (GetNewDataDirName(szFileName, ARRAYSIZE(szFileName))) { DebugTrace( TEXT("GetNewDataDirName failed\n")); sc = MAPI_E_NOT_FOUND; // ??
goto error; }
cchCurrent = lstrlen(szFileName);
//Tag on a trailing slash if 1 doesnt exist ..
if (szFileName[cchCurrent-1] != '\\') { StrCatBuff(szFileName, szBackSlash, ARRAYSIZE(szFileName)); }
// Get a user name ...
cchCurrent = lstrlen(szFileName); lpCurrent = szFileName + cchCurrent; cchLenName = (ARRAYSIZE(szFileName) - cchCurrent); if (!GetUserName(lpCurrent, &cchLenName)) { cchLenName = (ARRAYSIZE(szFileName) - cchCurrent);
// On failure just create some dummy file name
StrCpyN(lpCurrent, TEXT("AddrBook"), cchLenName); }
// Fix any invalid characters in the filename
while (*lpCurrent) { switch (*lpCurrent) { case '\\': case '/': case '<': case '>': case ':': case '"': case '|': case '?': case '*': case '.': *lpCurrent = '_'; // replace with underscore
break;
default: break; }
lpCurrent++; }
StrCatBuff(szFileName, lpszWABExt, ARRAYSIZE(szFileName));
cchLenName = sizeof(TCHAR)*lstrlen(szFileName);
//save this as the value of the Wab file in the registry
if (ERROR_SUCCESS != RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)szFileName, cchLenName)) { DebugTrace( TEXT("RegSetValue failed\n")); sc = MAPI_E_NOT_FOUND; // ??
goto error; } } else { // Didn't create a new key, so get the key value
if (ERROR_SUCCESS != RegQueryValueEx(hKey, NULL, NULL, &dwType, //reserved
(LPBYTE)szFileName, &cchLenName)) { DebugTrace( TEXT("RegSetValue failed\n")); goto new_key; } else if (! lstrlen(szFileName)) { DebugTrace( TEXT("Warning: Found empty name key!\n")); goto new_key; }
//Check that the name in the existing key is a valid filename
// If it is not a valid file name then we should remove it
// from the registry and create a new default file name
if(0xFFFFFFFF == GetFileAttributes(szFileName)) { // There is some problem with this file ...
// Remove it from the registry and recreate a new file name
// only if the path doesnt exist. Its possible that the file
// doesnt exist, in which case we create a new file in open
// property store
DWORD dwErr = GetLastError(); //NT5 bug 180007 - upgrading from Win95 to WinNT 5, if the
// old file name had quotes around it, CreateFile will fail and
// so will GetFileAttributes.
// Strip out the quotes and try again
if( (dwErr == ERROR_PATH_NOT_FOUND || dwErr == ERROR_INVALID_NAME) && lstrlen(szFileName) && szFileName[0] == '"' && szFileName[lstrlen(szFileName)-1] == '"') { // remove the quotes
szFileName[lstrlen(szFileName)-1] = '\0'; StrCpyN(szFileName, szFileName+1, ARRAYSIZE(szFileName)); if(0xFFFFFFFF != GetFileAttributes(szFileName)) goto open_file; } // otherwise some unknown error with the file name - just discard the
// file name and try again
RegCloseKey(hKey); RegDeleteKey(HKEY_CURRENT_USER, lpszKeyName); szFileName[0]='\0'; fNewKey = FALSE; goto try_again; } } } open_file: //
// now we have the file name, open the property store
//
if (HR_FAILED(hResult = OpenPropertyStore(szFileName, AB_OPEN_ALWAYS, hWnd, // HWND for potential Message Boxes
&(lpPropertyStore->hPropertyStore)))) { // The above call should always pass unless we ran out of disk space or
// some such thing ..
DebugTrace( TEXT("OpenPropertyStore failed\n"));
if(hResult == MAPI_E_NO_ACCESS) { sc = GetScode(hResult); goto error; }
// There is a chance that this may have failed due to a long file name
// which the machine could not accept.
if(lstrlen(szFileName) > 8 + 1 + lstrlen(lpszWABExt)) // 8+.+3
{ LPTSTR lpLast = szFileName; LPTSTR lpTemp = szFileName;
while(*lpTemp) { if((*lpTemp) == '\\') lpLast = lpTemp; lpTemp = CharNext(lpTemp); }
// lpLast points to the last \ .. everything after this will be the file name
if(lstrlen(lpLast+1) > 12) { // we need to truncate this name
*(lpLast+8) = '\0'; StrCatBuff(szFileName, lpszWABExt, ARRAYSIZE(szFileName)); hResult = OpenPropertyStore(szFileName, AB_OPEN_ALWAYS, hWnd, // HWND for potential Message Boxes
&(lpPropertyStore->hPropertyStore)); } }
if(HR_FAILED(hResult)) { sc = GetScode(hResult); goto error; } } }
out: lpPropertyStore->ulRefCount++;
error: if (hKey) { RegCloseKey(hKey); }
return(sc); }
/*
- ReleaseOutlookStore - * Purpose: * Keep track of outlook store dll refcount * * Arguments: * lpOutlookStore OUTLOOK_STORE structure * * Returns: * Current reference count. When 0, unload outlook-wab dll * no longer open. * */ ULONG ReleaseOutlookStore(HANDLE hPropertyStore, LPOUTLOOK_STORE lpOutlookStore) { if(lpOutlookStore) { lpOutlookStore->ulRefCount--;
if(0==lpOutlookStore->ulRefCount) { LPPTGDATA lpPTGData=GetThreadStoragePointer(); if(pt_bIsWABOpenExSession && hPropertyStore) { // This is a WABOpenEx session using outlooks storage provider
LPWABSTORAGEPROVIDER lpWSP = (LPWABSTORAGEPROVIDER) hPropertyStore; lpWSP->lpVtbl->Release(lpWSP); }
if(lpOutlookStore->hOutlookStore) { FreeLibrary(lpOutlookStore->hOutlookStore); lpOutlookStore->hOutlookStore = NULL;
#if 0
// @todo [PaulHi] DLL Leak. Remove this or implement
// [PaulHi] 3/12/99 @hack Serious HACK warning
// The Outlook outlwab.dll store module is not unloading some Outlook
// dlls. This causes Outlook to get confused about who loaded these dlls
// and whether Outlook or OE should service MAPI calls.
// HACK Forcibly remove these dlls HACK
// But only if the WAB WASN'T opened by OL process.
EnterCriticalSection(&csOMIUnload); if (!s_bIsReallyOnlyWABOpenExSession) { LPCSTR c_lpszOMI9DLL = "omi9.dll"; LPCSTR c_lpszOMI9PSTDLL = "omipst9.dll"; LPCSTR c_lpszOMINTDLL = "omint.dll"; LPCSTR c_lpszOMINTPSTDLL = "omipstnt.dll"; HINSTANCE hinst;
// It is essential to unload the omipst9.dll and omipstnt.dll
// modules first because they load the omi9.dll and omint.dll
// modules. The FreeLibary() on the omi9/omint modules should
// not be necessary.
if ( hinst = GetModuleHandleA(c_lpszOMI9PSTDLL) ) FreeLibrary(hinst);
if ( hinst = GetModuleHandleA(c_lpszOMINTPSTDLL) ) FreeLibrary(hinst);
if ( hinst = GetModuleHandleA(c_lpszOMI9DLL) ) FreeLibrary(hinst);
if ( hinst = GetModuleHandleA(c_lpszOMINTDLL) ) FreeLibrary(hinst); } LeaveCriticalSection(&csOMIUnload); #endif
} }
return lpOutlookStore->ulRefCount; }
return 0; }
/*
- OpenAddRefOutlookStore - * Purpose: * Open or ref count outlook-wab dll * * Arguments: * lpOutlookStore OUTLOOK_STORE structure * * Returns: * */ SCODE OpenAddRefOutlookStore(LPOUTLOOK_STORE lpOutlookStore) { LPPTGDATA lpPTGData=GetThreadStoragePointer();
if(!lpOutlookStore) return(MAPI_E_INVALID_PARAMETER);
if(!lpOutlookStore->ulRefCount) { TCHAR szOutlWABPath[MAX_PATH]; *szOutlWABPath = '\0'; if (!bCheckForOutlookWABDll(szOutlWABPath, ARRAYSIZE(szOutlWABPath)) || !lstrlen(szOutlWABPath) || !(lpOutlookStore->hOutlookStore = LoadLibrary(szOutlWABPath)) ) return MAPI_E_NOT_INITIALIZED;
// Load the Outlook WABStorageProvider Dll Entry Point here
// First try to load the Unicode version (doesn't exist but we're thinking forward here)
lpfnWABOpenStorageProvider = (LPWABOPENSTORAGEPROVIDER) GetProcAddress(lpOutlookStore->hOutlookStore, WAB_SPI_ENTRY_POINT_W); if(lpfnWABOpenStorageProvider) pt_bIsUnicodeOutlook = TRUE; else { pt_bIsUnicodeOutlook = FALSE; lpfnWABOpenStorageProvider = (LPWABOPENSTORAGEPROVIDER) GetProcAddress(lpOutlookStore->hOutlookStore, WAB_SPI_ENTRY_POINT); } }
if(lpfnWABOpenStorageProvider && lpOutlookStore->hOutlookStore) { // Tag this thread as a valid Outlook store session
// If this flag below is false, we willd default to
// using the WAB store
pt_bIsWABOpenExSession = TRUE; }
lpOutlookStore->ulRefCount++;
return S_OK; }
|