1404 lines
38 KiB
C
1404 lines
38 KiB
C
/***********************************************************************
|
|
*
|
|
* ABP.C
|
|
*
|
|
*
|
|
* The Microsoft At Work Fax Address Book Provider.
|
|
* This file contains the routines that handle the ABPJump table.
|
|
*
|
|
* The following routines are implemented in this file:
|
|
*
|
|
* ABProviderInit
|
|
* ABP_QueryInterface
|
|
* ABP_Release
|
|
* ABP_Shutdown
|
|
* ABP_Logon
|
|
*
|
|
* ServiceEntry
|
|
* HrOpenSingleProvider
|
|
*
|
|
* RemoveLogonObject
|
|
* FindLogonObject
|
|
* ScLoadString
|
|
*
|
|
* Globals defined in this file:
|
|
*
|
|
* Copyright 1992, 1993 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* Revision History:
|
|
*
|
|
* When Who What
|
|
* -------- ------------------ ---------------------------------------
|
|
* 1.1.94 MAPI Original source from MAPI sample AB Provider
|
|
* 1.27.94 Yoram Yaacovi Modifications to make it an At Work Fax ABP
|
|
* 3.5.94 Yoram Yaacovi Update to MAPI build 154
|
|
* 4.1.94 Yoram Yaacovi Update to MAPI and sample AB build 157
|
|
* 8.1.94 Yoram Yaacovi Update to MAPI and sample AB build 306
|
|
*
|
|
***********************************************************************/
|
|
|
|
#define _FAXAB_ABP
|
|
#include "faxab.h"
|
|
|
|
/*
|
|
* Prototypes for the functions in this file, most of which I return
|
|
* in the jump table returned from ABProviderInit().
|
|
*/
|
|
|
|
ABPROVIDERINIT ABProviderInit;
|
|
MSGSERVICEENTRY FABServiceEntry;
|
|
HRESULT HrOpenSingleProvider( LPPROVIDERADMIN lpAdminProviders,
|
|
LPPROFSECT FAR *lppProfSect
|
|
);
|
|
void LoadIniParams(void);
|
|
|
|
/*
|
|
* The jump table returned from ABProviderInit().
|
|
*/
|
|
ABP_Vtbl vtblABP =
|
|
{
|
|
ABP_QueryInterface,
|
|
(ABP_AddRef_METHOD *) ROOT_AddRef,
|
|
ABP_Release,
|
|
ABP_Shutdown,
|
|
ABP_Logon
|
|
};
|
|
|
|
/*************************************************************************
|
|
*
|
|
- ABProviderInit
|
|
-
|
|
* Initializes this provider. Returns a jump table that contains the
|
|
* addresses of the rest of the functions.
|
|
*
|
|
*/
|
|
|
|
HRESULT STDMAPIINITCALLTYPE
|
|
ABProviderInit (
|
|
HINSTANCE hLibrary,
|
|
LPMALLOC lpMalloc,
|
|
LPALLOCATEBUFFER lpAllocBuff,
|
|
LPALLOCATEMORE lpAllocMore,
|
|
LPFREEBUFFER lpFreeBuff,
|
|
ULONG ulFlags,
|
|
ULONG ulMAPIVersion,
|
|
ULONG FAR * lpulABVersion,
|
|
LPABPROVIDER FAR * lppABProvider)
|
|
{
|
|
HRESULT hResult = hrSuccess;
|
|
LPABP lpABP;
|
|
SCODE scode;
|
|
|
|
//DebugBreak();
|
|
|
|
DebugTrace("AWFXAB32(ABProviderInit): entering\n");
|
|
// Get registry settings
|
|
LoadIniParams();
|
|
|
|
#ifdef DEBUG
|
|
if (fDebugTrap)
|
|
DebugBreak();
|
|
#endif
|
|
|
|
/*
|
|
* Check the version
|
|
*/
|
|
if (ulMAPIVersion < CURRENT_SPI_VERSION)
|
|
{
|
|
/*
|
|
* MAPI's version is too old.
|
|
*/
|
|
|
|
/*
|
|
* See if they understand my version
|
|
*/
|
|
|
|
*lpulABVersion = CURRENT_SPI_VERSION;
|
|
|
|
DebugTraceSc(ABProviderInit, MAPI_E_VERSION);
|
|
return ResultFromScode(MAPI_E_VERSION);
|
|
}
|
|
|
|
/*
|
|
* Allocate memory for this Init Object
|
|
*/
|
|
scode = lpAllocBuff (SIZEOF(ABP), &lpABP);
|
|
if (FAILED(scode))
|
|
{
|
|
/*
|
|
* Out of memory
|
|
*/
|
|
DebugTraceSc(ABProviderInit, scode);
|
|
return ResultFromScode(scode);
|
|
}
|
|
|
|
/*
|
|
* Initialize the idle engine that MAPI supplies. This is most useful
|
|
* when browsing the .FAB file. See ABCTBLn.C.
|
|
*/
|
|
|
|
if (MAPIInitIdle( NULL )==-1)
|
|
{
|
|
hResult = ResultFromScode(E_FAIL);
|
|
goto err;
|
|
}
|
|
|
|
/*
|
|
* Hold on to the lpMalloc
|
|
*/
|
|
if (lpMalloc)
|
|
lpMalloc->lpVtbl->AddRef(lpMalloc);
|
|
|
|
lpABP->lpVtbl = &vtblABP;
|
|
lpABP->lcInit = 1;
|
|
lpABP->hLibrary = hLibrary;
|
|
|
|
lpABP->lpMalloc = lpMalloc;
|
|
lpABP->lpAllocBuff = lpAllocBuff;
|
|
lpABP->lpAllocMore = lpAllocMore;
|
|
lpABP->lpFreeBuff = lpFreeBuff;
|
|
lpABP->lpObjectList= NULL;
|
|
|
|
InitializeCriticalSection(&lpABP->cs);
|
|
|
|
*lppABProvider = (LPABPROVIDER)lpABP;
|
|
*lpulABVersion = CURRENT_SPI_VERSION;
|
|
|
|
/*
|
|
* Get our Locale Identifier
|
|
*/
|
|
lcidUser = GetUserDefaultLCID();
|
|
|
|
|
|
out:
|
|
DebugTraceResult(ABProviderInit, hResult);
|
|
return hResult;
|
|
|
|
err:
|
|
lpFreeBuff(lpABP);
|
|
|
|
goto out;
|
|
}
|
|
|
|
|
|
/*
|
|
* The Init Object's methods implementation
|
|
*/
|
|
|
|
|
|
/**********************************************************************
|
|
- ABP_QueryInterface
|
|
-
|
|
* Supports QI'ing to IUnknown and IABProvider
|
|
*
|
|
* Note that for all the methods of IABProvider that parameter validation
|
|
* is unnecessary. This is because MAPI is handling all the parameters
|
|
* being passed in.
|
|
* At best you can assert your parameters.
|
|
*/
|
|
STDMETHODIMP
|
|
ABP_QueryInterface (LPABP lpABP, REFIID lpiid, LPVOID *ppvObj)
|
|
{
|
|
DebugTrace("AWFXAB32(ABP_QueryInterface): entering\n");
|
|
|
|
/* See if the requested interface is one of ours */
|
|
|
|
if ( memcmp (lpiid, &IID_IUnknown, SIZEOF (IID)) &&
|
|
memcmp (lpiid, &IID_IABProvider, SIZEOF (IID))
|
|
)
|
|
{
|
|
*ppvObj = NULL; /* OLE requires zeroing [out] parameter on error */
|
|
DebugTraceSc(ABP_QueryInterface, E_NOINTERFACE);
|
|
return ResultFromScode (E_NOINTERFACE);
|
|
}
|
|
|
|
/* We'll do this one. Bump the usage count and return a new pointer. */
|
|
|
|
EnterCriticalSection(&lpABP->cs);
|
|
++lpABP->lcInit;
|
|
LeaveCriticalSection(&lpABP->cs);
|
|
|
|
*ppvObj = lpABP;
|
|
|
|
return hrSuccess;
|
|
}
|
|
|
|
/*
|
|
* Use ROOTs AddRef
|
|
*/
|
|
|
|
/*************************************************************************
|
|
*
|
|
- ABP_Release
|
|
-
|
|
* Releases and cleans up this object
|
|
*/
|
|
STDMETHODIMP_(ULONG)
|
|
ABP_Release (LPABP lpABP)
|
|
{
|
|
long lcInit;
|
|
|
|
DebugTrace("AWFXAB32(ABP_Release): entering\n");
|
|
|
|
EnterCriticalSection(&lpABP->cs);
|
|
lcInit = --lpABP->lcInit;
|
|
LeaveCriticalSection(&lpABP->cs);
|
|
|
|
if (lcInit == 0)
|
|
{
|
|
DeleteCriticalSection(&lpABP->cs);
|
|
|
|
lpABP->lpVtbl = NULL;
|
|
lpABP->lpFreeBuff(lpABP);
|
|
return (0);
|
|
}
|
|
return lcInit;
|
|
}
|
|
|
|
/**********************************************************************
|
|
- ABP_Shutdown
|
|
-
|
|
* Informs this provider that MAPI is done with it.
|
|
*
|
|
*
|
|
*/
|
|
STDMETHODIMP
|
|
ABP_Shutdown (LPABP lpABP, ULONG FAR *lpulFlags)
|
|
{
|
|
DebugTrace("AWFXAB32(ABP_Shutdown): entering\n");
|
|
|
|
MAPIDeinitIdle();
|
|
|
|
if (lpABP->lpMalloc)
|
|
{
|
|
lpABP->lpMalloc->lpVtbl->Release(lpABP->lpMalloc);
|
|
lpABP->lpMalloc = NULL;
|
|
}
|
|
|
|
return hrSuccess;
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
- ABP_Logon
|
|
-
|
|
* Create a logon object and return it to MAPI.
|
|
*
|
|
*/
|
|
/*
|
|
* The PropTagArray used to retrieve logon properties
|
|
*/
|
|
enum { ivallogonPR_FAB_FILE=0,
|
|
ivallogonPR_FAB_UID,
|
|
cvallogonMax };
|
|
|
|
static const SizedSPropTagArray(cvallogonMax, tagaFABLogonProps) =
|
|
{
|
|
cvallogonMax,
|
|
{
|
|
PR_FAB_FILE_A,
|
|
PR_FAB_UID
|
|
}
|
|
};
|
|
|
|
STDMETHODIMP
|
|
ABP_Logon( LPABP lpABP,
|
|
LPMAPISUP lpMAPISup,
|
|
ULONG ulUIParam,
|
|
LPTSTR lpszProfileName,
|
|
ULONG ulFlags,
|
|
ULONG FAR * lpulpcbSecurity,
|
|
LPBYTE FAR * lppbSecurity,
|
|
LPMAPIERROR FAR * lppMapiError,
|
|
LPABLOGON FAR * lppABPLogon
|
|
)
|
|
{
|
|
LPABLOGON lpABLogon = NULL;
|
|
HRESULT hResult = hrSuccess;
|
|
SCODE scode;
|
|
LPPROFSECT lpProfSect = NULL;
|
|
LPSPropValue lpsPropVal = NULL;
|
|
ULONG cValues = 0;
|
|
TCHAR szFileName[MAX_PATH];
|
|
LPTSTR lpstrT = NULL;
|
|
BOOL fUINeeded;
|
|
BOOL fNeedMAPIUID = FALSE;
|
|
MAPIUID muidID;
|
|
LPOBJECTLIST lpObjectList;
|
|
LPTSTR lpszAppName=NULL;
|
|
#ifdef UNICODE
|
|
CHAR szAnsiFileName[ MAX_PATH ];
|
|
#endif
|
|
|
|
#ifdef EXTENDED_DEBUG
|
|
MessageBox((HWND) ulUIParam, TEXT("ABP_Logon: entering"), TEXT("awfxab debug message"), MB_OK);
|
|
#endif
|
|
|
|
DebugTrace("AWFXAB32(ABP_Logon): entering\n");
|
|
|
|
szFileName[0] = TEXT('\0');
|
|
|
|
*lppMapiError = NULL;
|
|
|
|
if ( ulFlags & MAPI_UNICODE )
|
|
{
|
|
DebugTraceArg( ABP_Logon, "Bad Character width" );
|
|
return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
|
|
}
|
|
|
|
/*
|
|
* Get the name of my browse file from the profile section
|
|
*/
|
|
|
|
/* Open the section for my provider */
|
|
hResult = lpMAPISup->lpVtbl->OpenProfileSection( lpMAPISup,
|
|
NULL,
|
|
MAPI_MODIFY,
|
|
&lpProfSect
|
|
);
|
|
|
|
if (HR_FAILED(hResult))
|
|
goto out;
|
|
|
|
/* Get the property containing the Fax AB file name. */
|
|
hResult = lpProfSect->lpVtbl->GetProps( lpProfSect,
|
|
(LPSPropTagArray)&tagaFABLogonProps,
|
|
0, // ANSI
|
|
&cValues,
|
|
&lpsPropVal
|
|
);
|
|
|
|
if (HR_FAILED(hResult))
|
|
goto out;
|
|
|
|
#ifdef DEBUG
|
|
/* The only expected return code is MAPI_E_NOT_FOUND. */
|
|
if (hResult != hrSuccess)
|
|
{
|
|
if (GetScode (hResult) != MAPI_W_ERRORS_RETURNED)
|
|
{
|
|
DebugTrace("AWFXAB32(ABP_Logon): got unexpected hResult: ");
|
|
DebugTraceResult(ProfileGetProps, hResult);
|
|
}
|
|
else if (lpsPropVal[0].Value.err != MAPI_E_NOT_FOUND)
|
|
{
|
|
DebugTrace("AWFXAB32(ABP_Logon): got unexpected scode: ");
|
|
DebugTraceSc(ProfileGetProps, lpsPropVal[0].Value.err);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Ignore warnings from reading the property. */
|
|
hResult = hrSuccess;
|
|
|
|
/* copy the Fax Address Book file name */
|
|
if (lpsPropVal[0].ulPropTag==PR_FAB_FILE_A)
|
|
{
|
|
UINT cch = lstrlenA(lpsPropVal[0].Value.lpszA);
|
|
|
|
if (cch >= MAX_PATH)
|
|
cch = MAX_PATH-1;
|
|
|
|
if (cch)
|
|
#ifdef UNICODE
|
|
MultiByteToWideChar( CP_ACP, 0, lpsPropVal[0].Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
|
|
#else
|
|
memcpy(szFileName, lpsPropVal[0].Value.lpszA, cch);
|
|
#endif
|
|
|
|
szFileName[cch] = TEXT('\0');
|
|
}
|
|
else
|
|
{
|
|
DebugTrace("AWFXAB32(ABP_Logon): PR_FAB_FILE not found\n");
|
|
}
|
|
|
|
/* copy the fab uid */
|
|
if (lpsPropVal[1].ulPropTag==PR_FAB_UID)
|
|
{
|
|
memcpy(&muidID,lpsPropVal[1].Value.bin.lpb, SIZEOF(MAPIUID));
|
|
}
|
|
else
|
|
{
|
|
DebugTrace("AWFXAB32(ABP_Logon): PR_FAB_UID not found\n");
|
|
fNeedMAPIUID = TRUE;
|
|
}
|
|
|
|
/* Discard GetProps() return data, if any. */
|
|
lpABP->lpFreeBuff (lpsPropVal);
|
|
|
|
/*
|
|
* (UI needed unless the file name is good and file exists.)
|
|
*
|
|
* in Fax, the AB is not exposed, so there is never a UI
|
|
* If you insist on using a fax AB, you can set the name in the registry
|
|
*/
|
|
|
|
fUINeeded = TRUE;
|
|
|
|
if (szFileName[0] != 0)
|
|
{
|
|
/* Verify the file exists. */
|
|
|
|
HANDLE hFile = CreateFile (
|
|
szFileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle (hFile);
|
|
|
|
fUINeeded = FALSE;
|
|
}
|
|
}
|
|
|
|
// Am I allowed to bring up UI ?
|
|
if (ulFlags & AB_NO_DIALOG)
|
|
fUINeeded = FALSE;
|
|
|
|
// If the registry flag does not allow to expose the fax AB UI, don't allow it, no
|
|
// matter what happened earlier
|
|
if (!fExposeFaxAB)
|
|
fUINeeded = FALSE;
|
|
|
|
/*
|
|
* if the sab file name was not found in the profile or the sab file
|
|
* does not exist we have to get the user to pick another one and
|
|
* save back into the profile
|
|
*/
|
|
|
|
if (fUINeeded)
|
|
{
|
|
OPENFILENAME openfilename;
|
|
SPropValue sProp[1];
|
|
|
|
/*
|
|
* Can't bring up UI unless the client allows it
|
|
*/
|
|
if (ulFlags & AB_NO_DIALOG)
|
|
{
|
|
hResult = ResultFromScode (MAPI_E_LOGON_FAILED);
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* Get the user to select a file
|
|
*/
|
|
openfilename.lStructSize = SIZEOF(OPENFILENAME);
|
|
openfilename.hwndOwner = (HWND) ulUIParam;
|
|
openfilename.hInstance = 0; /* Ignored */
|
|
openfilename.lpstrFilter = TEXT("Microsoft Fax Address Book files\0*.fab\0\0");
|
|
openfilename.lpstrCustomFilter = NULL;
|
|
openfilename.nMaxCustFilter = 0;
|
|
openfilename.nFilterIndex = 0;
|
|
openfilename.lpstrFile = szFileName;
|
|
openfilename.nMaxFile = MAX_PATH;
|
|
openfilename.lpstrFileTitle = NULL;
|
|
openfilename.nMaxFileTitle = 0;
|
|
openfilename.lpstrInitialDir = NULL;
|
|
openfilename.lpstrTitle = TEXT("Microsoft Fax Address Book");
|
|
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
|
|
openfilename.nFileOffset = 0;
|
|
openfilename.nFileExtension = 0;
|
|
openfilename.lpstrDefExt = TEXT("fab");
|
|
openfilename.lCustData = 0;
|
|
openfilename.lpfnHook = NULL;
|
|
openfilename.lpTemplateName = NULL;
|
|
|
|
/*
|
|
* Call up the common dialog
|
|
*/
|
|
if (!GetOpenFileName (&openfilename))
|
|
{
|
|
#ifdef DEBUG
|
|
DWORD dwT;
|
|
dwT = CommDlgExtendedError();
|
|
#endif /* DEBUG */
|
|
|
|
// next two lines not needed for fax AB. an empty fax AB is valid.
|
|
// hResult = ResultFromScode (MAPI_E_LOGON_FAILED);
|
|
// goto out;
|
|
}
|
|
|
|
/*
|
|
* Set the fab file name property value
|
|
*/
|
|
sProp[0].ulPropTag = PR_FAB_FILE_A;
|
|
#ifdef UNICODE
|
|
WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szAnsiFileName, ARRAYSIZE(szAnsiFileName), NULL, NULL );
|
|
sProp[0].Value.lpszA = szAnsiFileName;
|
|
#else
|
|
sProp[0].Value.lpszA = szFileName;
|
|
#endif
|
|
|
|
/*
|
|
* Save the fab file into the profile
|
|
*/
|
|
if (hResult = lpProfSect->lpVtbl->SetProps(lpProfSect, 1, sProp, NULL))
|
|
{
|
|
/*
|
|
* Do nothing... So I couldn't save it away this time...
|
|
*/
|
|
DebugTraceResult("ABP_Logon got unexpected result on SetProps\n", hResult);
|
|
hResult = hrSuccess;
|
|
}
|
|
} // if (fUINeeded)
|
|
|
|
/*
|
|
* if the uid was not found we have to generate a new muid for the
|
|
* PR_SAB_ID property and save it back into the profile
|
|
*/
|
|
|
|
if (fNeedMAPIUID)
|
|
{
|
|
SPropValue sProp[1];
|
|
|
|
/*
|
|
* Get a new fab uid
|
|
*/
|
|
hResult=lpMAPISup->lpVtbl->NewUID(lpMAPISup,&muidID);
|
|
if (HR_FAILED(hResult))
|
|
{
|
|
DebugTraceResult(NewUID, hResult);
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* Set the fab uid property value
|
|
*/
|
|
sProp[1].ulPropTag = PR_FAB_UID;
|
|
sProp[1].Value.bin.cb = SIZEOF(MAPIUID);
|
|
sProp[1].Value.bin.lpb = (LPBYTE)&muidID;
|
|
|
|
/*
|
|
* Save the sab uid into the profile
|
|
*/
|
|
if (hResult = lpProfSect->lpVtbl->SetProps(lpProfSect, 1, sProp, NULL))
|
|
{
|
|
/*
|
|
* Do nothing... So I couldn't save it away this time...
|
|
*/
|
|
DebugTraceResult("ABP_Logon got unexpected result on SetProps\n", hResult);
|
|
hResult = hrSuccess;
|
|
}
|
|
} // if (fNeedMAPIUID)
|
|
|
|
/*
|
|
* Allocate space for keeping the file name in the ABLogon object
|
|
*/
|
|
|
|
if (scode = lpABP->lpAllocBuff((lstrlen(szFileName)+1)*SIZEOF(TCHAR), &lpstrT))
|
|
{
|
|
hResult = ResultFromScode (scode);
|
|
goto out;
|
|
}
|
|
lstrcpy (lpstrT, szFileName);
|
|
|
|
hResult = HrNewABLogon( &lpABLogon,
|
|
(LPABPROVIDER) lpABP,
|
|
lpMAPISup,
|
|
lpstrT,
|
|
&muidID,
|
|
lpABP->hLibrary,
|
|
lpABP->lpAllocBuff,
|
|
lpABP->lpAllocMore,
|
|
lpABP->lpFreeBuff,
|
|
lpABP->lpMalloc
|
|
);
|
|
if (HR_FAILED(hResult))
|
|
{
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* Allocate space for another object list item
|
|
*/
|
|
|
|
if (scode = lpABP->lpAllocBuff( sizeof(OBJECTLIST), &lpObjectList))
|
|
{
|
|
hResult = ResultFromScode(scode);
|
|
goto out;
|
|
}
|
|
|
|
/*
|
|
* add logon object to list
|
|
*/
|
|
|
|
/* Get the Critical Section */
|
|
EnterCriticalSection(&lpABP->cs);
|
|
|
|
/* add logon object to begining of providers object list */
|
|
lpObjectList->lpObject = (LPVOID) lpABLogon;
|
|
lpObjectList->lppNext = lpABP->lpObjectList;
|
|
|
|
/* insert new logon object into the head of the providers object list */
|
|
lpABP->lpObjectList = lpObjectList;
|
|
|
|
/* leave critical section */
|
|
LeaveCriticalSection(&lpABP->cs);
|
|
|
|
|
|
/*
|
|
* Register my MAPIUID for this provider,
|
|
* but do not allow an error from setting the
|
|
* MAPIUID to cause failure to Logon.
|
|
*/
|
|
|
|
(void)lpMAPISup->lpVtbl->SetProviderUID(lpMAPISup,
|
|
(LPMAPIUID) &muidABMAWF, 0);
|
|
|
|
#ifdef DO_WE_REALLY_NEED_TAPI
|
|
/*
|
|
* TAPI
|
|
*
|
|
* everything seems OK. get TAPI initialized
|
|
*/
|
|
scode = ScLoadString( IDS_APP_NAME,
|
|
MAX_PATH,
|
|
lpABP->lpAllocBuff,
|
|
lpABP->hLibrary,
|
|
&lpszAppName
|
|
);
|
|
|
|
InitTAPI(lpABP->hLibrary, (HWND) ulUIParam, lpszAppName);
|
|
|
|
// Make sure we have the required location information handy
|
|
// bring up mini-dial helper if not
|
|
InitLocationParams((HWND) ulUIParam);
|
|
#endif
|
|
|
|
lpABP->lpFreeBuff(lpszAppName);
|
|
|
|
// return the object to the caller
|
|
*lppABPLogon = lpABLogon;
|
|
|
|
out:
|
|
if (lpProfSect)
|
|
lpProfSect->lpVtbl->Release(lpProfSect);
|
|
|
|
if (hResult)
|
|
{
|
|
lpABP->lpFreeBuff(lpstrT);
|
|
|
|
Assert(lpABLogon == NULL);
|
|
|
|
/* Verify we don't return warnings at this time. */
|
|
Assert(HR_FAILED(hResult));
|
|
}
|
|
|
|
DebugTraceResult(ABP_Logon, hResult);
|
|
return hResult;
|
|
}
|
|
|
|
/*************************************************************************
|
|
-
|
|
- RemoveLogonObject
|
|
-
|
|
* Removes a particular logon object from the list of logon objects
|
|
* that's kept track of in the IABProvider object
|
|
*/
|
|
void
|
|
RemoveLogonObject( LPABPROVIDER lpABProvider,
|
|
LPVOID lpvABLogon,
|
|
LPFREEBUFFER lpFreeBuff
|
|
)
|
|
{
|
|
|
|
LPOBJECTLIST *lppObjectList;
|
|
LPOBJECTLIST lpObjectListT;
|
|
LPABP lpABP = (LPABP) lpABProvider;
|
|
|
|
#if defined DEBUG
|
|
BOOL fFound = FALSE;
|
|
|
|
#endif
|
|
|
|
/* Get the Critical Section */
|
|
EnterCriticalSection(&lpABP->cs);
|
|
|
|
/*
|
|
* remove this logon object from the provider init objects list
|
|
* of logon objects
|
|
*/
|
|
lppObjectList = &(lpABP->lpObjectList);
|
|
|
|
while (*lppObjectList)
|
|
{
|
|
/* is this the logon object? */
|
|
if ((*lppObjectList)->lpObject == lpvABLogon)
|
|
{
|
|
/* save next list item */
|
|
lpObjectListT = (*lppObjectList)->lppNext;
|
|
|
|
/* free the object list item */
|
|
lpFreeBuff(*lppObjectList);
|
|
|
|
/* delete object from the list */
|
|
*lppObjectList = lpObjectListT;
|
|
|
|
#if defined DEBUG
|
|
fFound = TRUE;
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
lppObjectList = &(*lppObjectList)->lppNext;
|
|
}
|
|
|
|
/* leave critical section */
|
|
LeaveCriticalSection(&lpABP->cs);
|
|
|
|
#if defined DEBUG
|
|
AssertSz(fFound, "Logon object not found on providers object list");
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
-
|
|
- FindLogonObject
|
|
-
|
|
* Finds a particular logon object by its muid.
|
|
*/
|
|
void
|
|
FindLogonObject( LPABPROVIDER lpABProvider,
|
|
LPMAPIUID lpMuidToFind,
|
|
LPABLOGON * lppABLogon
|
|
)
|
|
{
|
|
LPABP lpABP = (LPABP) lpABProvider;
|
|
LPABLOGON lpABLogonT = NULL;
|
|
LPOBJECTLIST lpObjectList = NULL;
|
|
LPMAPIUID lpMuidLogon = NULL;
|
|
|
|
Assert(!IsBadReadPtr(lpABP, SIZEOF(ABP)));
|
|
Assert(!IsBadReadPtr(lpMuidToFind, SIZEOF(MAPIUID)));
|
|
Assert(!IsBadReadPtr(lppABLogon, SIZEOF(LPABLOGON)));
|
|
|
|
/* Get the Critical Section */
|
|
EnterCriticalSection(&lpABP->cs);
|
|
|
|
*lppABLogon = NULL;
|
|
|
|
for (lpObjectList = lpABP->lpObjectList;
|
|
lpObjectList; lpObjectList = lpObjectList->lppNext)
|
|
{
|
|
lpABLogonT = (LPABLOGON) lpObjectList->lpObject;
|
|
|
|
lpMuidLogon = LpMuidFromLogon(lpABLogonT);
|
|
|
|
if (memcmp((LPVOID) lpMuidLogon, (LPVOID) lpMuidToFind, SIZEOF(MAPIUID)) == 0)
|
|
{
|
|
*lppABLogon = lpABLogonT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* leave critical section */
|
|
LeaveCriticalSection(&lpABP->cs);
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
- FABServiceEntry
|
|
-
|
|
* This funtion is used by MAPI to configure the Sample Address Book.
|
|
* It's a lot like ABP_Logon, except that it doesn't return a logon object
|
|
* and it can be passed in its configuration information (as defined in
|
|
* smpab.h) from MAPI so that no UI is required.
|
|
*
|
|
* lppMapiError a pointer to a MAPI error structure which allows
|
|
* the provider to return extended error info to MAPI
|
|
*/
|
|
STDAPI
|
|
FABServiceEntry(
|
|
HINSTANCE hInstance,
|
|
LPMALLOC lpMalloc,
|
|
LPMAPISUP lpMAPISup,
|
|
ULONG ulUIParam,
|
|
ULONG ulFlags,
|
|
ULONG ulContext,
|
|
ULONG cValues,
|
|
LPSPropValue lpProps,
|
|
LPPROVIDERADMIN lpAdminProviders,
|
|
LPMAPIERROR FAR *lppMapiError)
|
|
{
|
|
OPENFILENAME openfilename;
|
|
TCHAR szFileName[MAX_PATH];
|
|
HRESULT hResult=hrSuccess;
|
|
SPropValue sProp[cvallogonMax];
|
|
LPSPropValue lpsPropVal = NULL;
|
|
ULONG ulCount = 0;
|
|
LPALLOCATEBUFFER lpAllocBuff;
|
|
LPALLOCATEMORE lpAllocMore;
|
|
LPFREEBUFFER lpFreeBuff;
|
|
MAPIUID muid;
|
|
LPPROFSECT lpProf = NULL;
|
|
BOOL fFABFound=FALSE; // No fab file name yet
|
|
BOOL fUIDFound=FALSE; // No fab uid yet
|
|
BOOL fNeedMAPIUID = FALSE;
|
|
ULONG uliProp;
|
|
#ifdef UNICODE
|
|
CHAR szAnsiFileName[ MAX_PATH ];
|
|
#endif
|
|
#ifdef EXTENDED_DEBUG
|
|
TCHAR szTempBuf[256];
|
|
#endif
|
|
|
|
//DebugBreak();
|
|
|
|
DebugTrace("AWFXAB32(ServiceEntry): entering\n");
|
|
|
|
// Get registry settings
|
|
LoadIniParams();
|
|
|
|
#ifdef DEBUG
|
|
if (fDebugTrap)
|
|
DebugBreak();
|
|
#endif
|
|
|
|
/*
|
|
* Parameter validation
|
|
*/
|
|
|
|
// check the support object
|
|
if (IsBadReadPtr(lpMAPISup, SIZEOF(LPMAPISUP)))
|
|
{
|
|
DebugTraceSc(ServiceEntry, E_INVALIDARG);
|
|
return ResultFromScode(E_INVALIDARG);
|
|
}
|
|
|
|
if ( ulFlags & MAPI_UNICODE )
|
|
{
|
|
DebugTraceArg( ServiceEntry, "Bad character width" );
|
|
return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
|
|
}
|
|
|
|
#ifdef EXTENDED_DEBUG
|
|
switch (ulContext) {
|
|
|
|
case MSG_SERVICE_DELETE:
|
|
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_DELETE called!"), TEXT("awfxab debug message"), MB_OK);
|
|
break;
|
|
|
|
case MSG_SERVICE_INSTALL:
|
|
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_INSTALL called!"), TEXT("awfxab debug message"), MB_OK);
|
|
break;
|
|
|
|
case MSG_SERVICE_UNINSTALL:
|
|
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_UNINSTALL called!"), TEXT("awfxab debug message"), MB_OK);
|
|
break;
|
|
|
|
case MSG_SERVICE_CREATE:
|
|
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_CREATE called!"), TEXT("awfxab debug message"), MB_OK);
|
|
break;
|
|
|
|
case MSG_SERVICE_CONFIGURE:
|
|
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_CONFIGURE called!"), TEXT("awfxab debug message"), MB_OK);
|
|
break;
|
|
|
|
case MSG_SERVICE_PROVIDER_CREATE:
|
|
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_PROVIDER_CREATE called!"), TEXT("awfxab debug message"), MB_OK);
|
|
break;
|
|
|
|
case MSG_SERVICE_PROVIDER_DELETE:
|
|
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_PROVIDER_DELETE called!"), TEXT("awfxab debug message"), MB_OK);
|
|
break;
|
|
|
|
default:
|
|
MessageBox((HWND) ulUIParam, TEXT("ServiceEntry unknown called!"), TEXT("awfxab debug message"), MB_OK);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Check what to do
|
|
*/
|
|
if ( ulContext==MSG_SERVICE_DELETE ||
|
|
ulContext==MSG_SERVICE_INSTALL ||
|
|
ulContext==MSG_SERVICE_UNINSTALL
|
|
)
|
|
{
|
|
return hrSuccess;
|
|
}
|
|
|
|
// Only supporting MSG_SERVICE_CONFIGURE and MSG_SERVICE_CREATE
|
|
if ( ulContext!=MSG_SERVICE_CONFIGURE &&
|
|
ulContext!=MSG_SERVICE_CREATE
|
|
)
|
|
{
|
|
DebugTrace("ServiceEntry unsupported context\n");
|
|
return ResultFromScode(MAPI_E_NO_SUPPORT);
|
|
}
|
|
|
|
/* Get the memory allocation routines we'll be needing. */
|
|
hResult = lpMAPISup->lpVtbl->GetMemAllocRoutines( lpMAPISup,
|
|
&lpAllocBuff,
|
|
&lpAllocMore,
|
|
&lpFreeBuff
|
|
);
|
|
if (hResult)
|
|
{
|
|
DebugTraceResult (MAPISUP::GetMemAllocRoutines, hResult);
|
|
goto out;
|
|
}
|
|
|
|
/* Open the profile section associated with our provider */
|
|
hResult = HrOpenSingleProvider(lpAdminProviders, &lpProf);
|
|
if (hResult)
|
|
{
|
|
DebugTrace ("AWFXAB32(ServiceEntry): Unable to open the profile.");
|
|
goto out;
|
|
}
|
|
|
|
#ifdef EXTENDED_DEBUG
|
|
wsprintf (szTempBuf, TEXT("ServiceEntry: HrOpenSingleProvider succeeded. hResult=0x%08lx\n"), (ULONG) hResult);
|
|
MessageBox( (HWND)ulUIParam,
|
|
szTempBuf,
|
|
TEXT("awfxab Debug Message"),
|
|
MB_ICONINFORMATION
|
|
);
|
|
#endif
|
|
|
|
// No file name for now
|
|
szFileName[0] = TEXT('\0');
|
|
|
|
/*
|
|
* Now looking for the two properties I need:
|
|
* PR_FAB_FILE
|
|
* PR_FAB_UID
|
|
*
|
|
* they can either be:
|
|
* 1. in the lpProps passed to ServiceEntry
|
|
* 2. in my profile section
|
|
* 3. be requested from the user through a UI
|
|
*/
|
|
|
|
// see if these properties exist on the profile
|
|
hResult = lpProf->lpVtbl->GetProps( lpProf,
|
|
(LPSPropTagArray)&tagaFABLogonProps,
|
|
ulFlags & MAPI_UNICODE,
|
|
&ulCount,
|
|
&lpsPropVal
|
|
);
|
|
|
|
// If the GetProps fail, I'm dump some debug messages, but it's OK to continue.
|
|
// Can still get the props from the ServiceEntry input parameter or from UI
|
|
if (hResult!=hrSuccess)
|
|
{
|
|
#ifdef DEBUG
|
|
/* The only expected return code is MAPI_E_NOT_FOUND. */
|
|
if (GetScode (hResult) != MAPI_W_ERRORS_RETURNED)
|
|
{
|
|
DebugTrace("AWFXAB32(ServiceEntry): got unexpected hResult: ");
|
|
DebugTraceResult(ProfileGetProps, hResult);
|
|
}
|
|
else if (lpsPropVal[0].Value.err != MAPI_E_NOT_FOUND)
|
|
{
|
|
DebugTrace("AWFXAB32(ServiceEntry): got unexpected scode: ");
|
|
DebugTraceSc(ProfileGetProps, lpsPropVal[0].Value.err);
|
|
}
|
|
#endif
|
|
/* Ignore errors/warnings from reading the property. */
|
|
hResult = hrSuccess;
|
|
// These two should be false anyway at this point
|
|
fFABFound = FALSE;
|
|
fUIDFound = FALSE;
|
|
}
|
|
|
|
/************************
|
|
*** PR_FAB_FILE ******
|
|
************************/
|
|
|
|
/*
|
|
* 1. Check the lpProps (cValues) passed to ServiceEntry
|
|
*/
|
|
|
|
// First, look for the fab file property in the config props that were passed to
|
|
// ServiceEntry. So I am not really looking at what I got in the above GetProps yet
|
|
|
|
for (uliProp=0; uliProp < cValues; uliProp++)
|
|
{
|
|
if (PROP_ID(lpProps[uliProp].ulPropTag)==PROP_ID(PR_FAB_FILE_A))
|
|
// This is the fab file property
|
|
break;
|
|
}
|
|
|
|
// If the fab file property was found (must be found, isn't it ?) and it has a
|
|
// non-error value, get the fab filename from it
|
|
if ((uliProp < cValues) && (PROP_TYPE(lpProps[uliProp].ulPropTag)!=PT_ERROR))
|
|
{
|
|
ULONG cch = lstrlenA(lpProps[uliProp].Value.lpszA);
|
|
|
|
if (cch >= MAX_PATH)
|
|
cch = MAX_PATH-1;
|
|
|
|
if (cch)
|
|
#ifdef UNICODE
|
|
MultiByteToWideChar( CP_ACP, 0, lpProps[uliProp].Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
|
|
#else
|
|
memcpy(szFileName, lpProps[uliProp].Value.LPSZ, (size_t)cch*SIZEOF(TCHAR));
|
|
#endif
|
|
|
|
szFileName[cch] = TEXT('\0');
|
|
|
|
// got my FAB file. Might be "". No need for UI for that
|
|
fFABFound = TRUE;
|
|
|
|
}
|
|
|
|
/*
|
|
* 2. Now the properties I got from the profile (if any)
|
|
*/
|
|
|
|
// no fab file name in the input properties. Look in the profile properties
|
|
else if ( (PROP_ID(lpsPropVal[0].ulPropTag) == PROP_ID(PR_FAB_FILE_A)) &&
|
|
(PROP_TYPE(lpsPropVal[0].ulPropTag)!= PT_ERROR)
|
|
)
|
|
{
|
|
ULONG cch = lstrlenA(lpsPropVal[0].Value.lpszA);
|
|
|
|
if (cch >= MAX_PATH)
|
|
cch = MAX_PATH-1;
|
|
|
|
if (cch)
|
|
#ifdef UNICODE
|
|
MultiByteToWideChar( CP_ACP, 0, lpProps[0].Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
|
|
#else
|
|
memcpy(szFileName, lpsPropVal[0].Value.LPSZ, (size_t)cch*SIZEOF(TCHAR));
|
|
#endif
|
|
|
|
szFileName[cch] = TEXT('\0');
|
|
fFABFound = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fFABFound = FALSE;
|
|
}
|
|
|
|
/*
|
|
* 3. Last resort: UI
|
|
*/
|
|
if (fExposeFaxAB)
|
|
{
|
|
if (!fFABFound || (ulFlags & UI_SERVICE))
|
|
{
|
|
openfilename.lStructSize = SIZEOF(OPENFILENAME);
|
|
openfilename.hwndOwner = (HWND) ulUIParam;
|
|
openfilename.hInstance = 0; /* Ignored */
|
|
openfilename.lpstrFilter = TEXT("Microsoft Fax Address Book files\0*.fab\0\0");
|
|
openfilename.lpstrCustomFilter = NULL;
|
|
openfilename.nMaxCustFilter = 0;
|
|
openfilename.nFilterIndex = 0;
|
|
openfilename.lpstrFile = szFileName;
|
|
openfilename.nMaxFile = MAX_PATH;
|
|
openfilename.lpstrFileTitle = NULL;
|
|
openfilename.nMaxFileTitle = 0;
|
|
openfilename.lpstrInitialDir = NULL;
|
|
openfilename.lpstrTitle = TEXT("Pick a Microsoft Fax Address Book file");
|
|
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
|
|
openfilename.nFileOffset = 0;
|
|
openfilename.nFileExtension = 0;
|
|
openfilename.lpstrDefExt = TEXT("fab");
|
|
openfilename.lCustData = 0;
|
|
openfilename.lpfnHook = NULL;
|
|
openfilename.lpTemplateName = NULL;
|
|
|
|
|
|
// This hides the fax address book. define FAXAB_YES to expose it.
|
|
// No Fax address book, unless it's hardcoded into the profile
|
|
/*
|
|
* Call up the common dialog
|
|
*/
|
|
|
|
if (!GetOpenFileName (&openfilename))
|
|
{
|
|
// user pressed cancel
|
|
// CHECK: This means we do not have a fab file. Shouldn't I return
|
|
// some kind of an error ? The SAB doesn't.
|
|
goto out;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the file name property
|
|
*/
|
|
|
|
sProp[ivallogonPR_FAB_FILE].ulPropTag = PR_FAB_FILE_A;
|
|
#ifdef UNICODE
|
|
WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szAnsiFileName, ARRAYSIZE(szAnsiFileName), NULL, NULL );
|
|
sProp[ivallogonPR_FAB_FILE].Value.lpszA = szAnsiFileName;
|
|
#else
|
|
sProp[ivallogonPR_FAB_FILE].Value.lpszA = szFileName;
|
|
#endif
|
|
|
|
/* if no properties were found then we're configuring for the
|
|
* first time and so we have to generate a new muid for the
|
|
* PR_FAB_ID property
|
|
*/
|
|
|
|
/************************
|
|
*** PR_FAB_UID ******
|
|
************************/
|
|
|
|
/*
|
|
* 1. Check the lpProps (cValues) passed to ServiceEntry
|
|
*/
|
|
|
|
for (uliProp=0; uliProp < cValues; uliProp++)
|
|
{
|
|
if (PROP_ID(lpProps[uliProp].ulPropTag)==PROP_ID(PR_FAB_UID))
|
|
break;
|
|
|
|
}
|
|
|
|
if ( (uliProp < cValues) && (PROP_TYPE(lpProps[uliProp].ulPropTag)!=PT_ERROR))
|
|
{
|
|
memcpy(&muid,lpProps[uliProp].Value.bin.lpb,SIZEOF(MAPIUID));
|
|
fUIDFound = TRUE;
|
|
}
|
|
|
|
/*
|
|
* 2. Now the properties I got from the profile (if any)
|
|
*/
|
|
|
|
else if ( (PROP_ID(lpsPropVal[1].ulPropTag) == PROP_ID(PR_FAB_UID)) &&
|
|
(PROP_TYPE(lpsPropVal[1].ulPropTag) != PT_ERROR)
|
|
)
|
|
{
|
|
memcpy(&muid,lpsPropVal[1].Value.bin.lpb,SIZEOF(MAPIUID));
|
|
fUIDFound = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* need to generate a uid */
|
|
fUIDFound = FALSE;
|
|
}
|
|
|
|
/* Discard GetProps() return data, if any. */
|
|
if (lpsPropVal)
|
|
lpFreeBuff (lpsPropVal);
|
|
|
|
|
|
/*
|
|
* 3. Last resort: generate a UID
|
|
*/
|
|
|
|
if (!fUIDFound)
|
|
{
|
|
hResult = lpMAPISup->lpVtbl->NewUID(lpMAPISup,&muid);
|
|
if (HR_FAILED(hResult))
|
|
{
|
|
/*
|
|
* Can't get a uid so just leave
|
|
*/
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the id property
|
|
*/
|
|
|
|
sProp[ivallogonPR_FAB_UID].ulPropTag = PR_FAB_UID;
|
|
sProp[ivallogonPR_FAB_UID].Value.bin.cb = SIZEOF(MAPIUID);
|
|
sProp[ivallogonPR_FAB_UID].Value.bin.lpb = (LPBYTE) &muid;
|
|
|
|
/*
|
|
* Save the file name and the id back into the profile
|
|
*/
|
|
|
|
hResult=lpProf->lpVtbl->SetProps( lpProf,
|
|
cvallogonMax,
|
|
sProp,
|
|
NULL
|
|
);
|
|
|
|
if (HR_FAILED(hResult))
|
|
{
|
|
/*
|
|
* Do nothing... So I couldn't save it away this time...
|
|
*/
|
|
DebugTrace("AWFXAB32(ServiceEntry): could not SetProps in profile\n");
|
|
hResult = hrSuccess;
|
|
}
|
|
|
|
|
|
out:
|
|
|
|
if (lpProf)
|
|
lpProf->lpVtbl->Release(lpProf);
|
|
|
|
DebugTraceResult(ServiceEntry, hResult);
|
|
return hResult;
|
|
}
|
|
|
|
/*************************************************************************
|
|
- HrOpenSingleProvider
|
|
-
|
|
* Opens the profile section associated with this provider.
|
|
*
|
|
* If the ServiceEntry() function exported from a provider had
|
|
* more than 1 section associated with it, this is where you'd get the chance
|
|
* to get all of them.
|
|
*/
|
|
|
|
static SizedSPropTagArray(1, tagaProviderTable) =
|
|
{
|
|
1,
|
|
{
|
|
PR_PROVIDER_UID
|
|
}
|
|
};
|
|
|
|
HRESULT
|
|
HrOpenSingleProvider( LPPROVIDERADMIN lpAdminProviders,
|
|
LPPROFSECT FAR * lppProfSect
|
|
)
|
|
{
|
|
HRESULT hResult;
|
|
LPMAPITABLE lpTable = NULL;
|
|
LPSRowSet lpRows = NULL;
|
|
LPSPropValue lpProp;
|
|
|
|
hResult = lpAdminProviders->lpVtbl->GetProviderTable( lpAdminProviders,
|
|
0,
|
|
&lpTable
|
|
);
|
|
if (HR_FAILED(hResult))
|
|
goto out;
|
|
|
|
hResult = lpTable->lpVtbl->SetColumns(lpTable, (LPSPropTagArray) &tagaProviderTable, 0);
|
|
if (HR_FAILED(hResult))
|
|
goto out;
|
|
|
|
hResult = lpTable->lpVtbl->QueryRows(lpTable, 1, 0, &lpRows);
|
|
if (HR_FAILED(hResult))
|
|
goto out;
|
|
|
|
if (lpRows->cRows == 0)
|
|
{
|
|
hResult = ResultFromScode(MAPI_E_NOT_FOUND);
|
|
goto out;
|
|
}
|
|
|
|
lpProp = lpRows->aRow[0].lpProps;
|
|
|
|
hResult = lpAdminProviders->lpVtbl->OpenProfileSection(
|
|
lpAdminProviders,
|
|
(LPMAPIUID) lpProp->Value.bin.lpb,
|
|
NULL,
|
|
MAPI_MODIFY,
|
|
lppProfSect);
|
|
|
|
out:
|
|
FreeProws(lpRows);
|
|
|
|
if (lpTable)
|
|
lpTable->lpVtbl->Release(lpTable);
|
|
|
|
DebugTraceResult(HrOpenSingleProvider, hResult);
|
|
return hResult;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
- ScLoadString
|
|
-
|
|
* Loads a string from a resource. It will optionally allocate the string if
|
|
* a allocation function is passed in. Otherwise it assumes that the *lppsz
|
|
* is already allocated.
|
|
*/
|
|
|
|
SCODE ScLoadString( UINT ids,
|
|
ULONG ulcch,
|
|
LPALLOCATEBUFFER lpAllocBuff,
|
|
HINSTANCE hLibrary,
|
|
LPTSTR * lppsz
|
|
)
|
|
{
|
|
SCODE sc = S_OK;
|
|
int iRet;
|
|
|
|
/*
|
|
* Assert parameters
|
|
*/
|
|
Assert((lpAllocBuff ? !IsBadCodePtr((FARPROC) lpAllocBuff):TRUE));
|
|
Assert(ids!=0);
|
|
|
|
if (lpAllocBuff)
|
|
{
|
|
sc = lpAllocBuff(ulcch*SIZEOF(TCHAR), lppsz);
|
|
if (FAILED(sc))
|
|
{
|
|
goto out;
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
Assert(!IsBadWritePtr(*lppsz, (UINT) ulcch*SIZEOF(TCHAR)));
|
|
}
|
|
#endif /* DEBUG */
|
|
|
|
iRet = LoadString( hLibrary,
|
|
ids,
|
|
*lppsz,
|
|
(UINT)ulcch
|
|
);
|
|
|
|
if (!iRet)
|
|
{
|
|
DebugTrace("AWFXAB32(ScLoadString): LoadString() failed...\n");
|
|
sc = E_FAIL;
|
|
goto out;
|
|
}
|
|
out:
|
|
|
|
DebugTraceSc(ScLoadString, sc);
|
|
return sc;
|
|
}
|
|
|
|
/*************************************************************************
|
|
*
|
|
- LoadIniParams
|
|
-
|
|
* Loads any paramters I need from the registry
|
|
*
|
|
*/
|
|
void LoadIniParams(void)
|
|
{
|
|
|
|
//fExposeFaxAB = TRUE;
|
|
#if 0
|
|
fExposeFaxAB = GetInitializerInt( HKEY_CURRENT_USER,
|
|
TEXT("Address Book Provider"),
|
|
TEXT("ExposeFaxAB"),
|
|
FALSE,
|
|
TEXT("Software\\Microsoft\\At Work Fax")
|
|
);
|
|
|
|
fDebugTrap = GetInitializerInt( HKEY_CURRENT_USER,
|
|
TEXT("Address Book Provider"),
|
|
TEXT("DebugTrap"),
|
|
FALSE,
|
|
TEXT("Software\\Microsoft\\At Work Fax")
|
|
);
|
|
#endif
|
|
}
|
|
|
|
#undef _FAXAB_ABP
|