home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////////
- //
- // File Name
- // XPSRVCE.CPP
- //
- // Description
- // This file implements the entry points, XPProviderInit and
- // ServiceEntry for this provider's DLL.
- //
- // Author
- // Irving De la Cruz
- //
- // Revision: 1.7
- //
- // Written for Microsoft Windows Developer Support
- // Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved.
- //
- #include "XPWDSR.H"
-
- // Remark this line to turn verbose tracing OFF
- #define DO_INFO_TRACES
- #ifdef DO_INFO_TRACES
- #define InfoTrace(a) TraceInfoMessage(a)
- #else
- #define InfoTrace(a)
- #endif // DO_INFO_TRACES
-
- DTBLEDIT DtUploadTime = { sizeof(DTBLEDIT), fMapiUnicode, 5, PR_TMP_UPLOAD_TIME };
- DTBLCHECKBOX DtGetHeaders = { sizeof(DTBLCHECKBOX), fMapiUnicode, PR_SMP_GET_HEADERS };
-
- DTCTL XPConfigPage[] =
- {
- { DTCT_PAGE, 0, NULL, 0, NULL, 0, &DtPage },
- { DTCT_EDIT, DT_REQUIRED, NULL, 0, szFilter, IDC_UPLOAD_TIME, &DtUploadTime },
- { DTCT_CHECKBOX, 0, NULL, 0, NULL, IDC_UPDATE_HEADERS, &DtGetHeaders },
- { DTCT_LABEL, 0, NULL, 0, NULL, IDC_STATIC1, &DtLabel },
- { DTCT_GROUPBOX, 0, NULL, 0, NULL, IDC_STATIC2, &DtGroupBox },
- { DTCT_GROUPBOX, 0, NULL, 0, NULL, IDC_STATIC3, &DtGroupBox }
- };
-
- TCHAR szDefaultTime[] = TEXT("23:59");
-
- // Global pointer to the MAPI memory allocation functions
- LPALLOCATEBUFFER gpfnAllocateBuffer; // MAPIAllocateBuffer function
- LPALLOCATEMORE gpfnAllocateMore; // MAPIAllocateMore function
- LPFREEBUFFER gpfnFreeBuffer; // MAPIFreeBuffer function
-
- ///////////////////////////////////////////////////////////////////////////////
- // ServiceEntry()
- //
- // Parameters
- // { Refer to MAPI Documentation on this method }
- //
- // Purpose
- // Called by the profile setup API to display the provider
- // configuration properties for this transport provider
- //
- // Return Value
- // An HRESULT
- //
- HRESULT STDAPICALLTYPE ServiceEntry (HINSTANCE hInstance,
- LPMALLOC pMallocObj,
- LPMAPISUP pSupObj,
- ULONG ulUIParam,
- ULONG ulFlags,
- ULONG ulContext,
- ULONG ulCfgPropCount,
- LPSPropValue pCfgProps,
- LPPROVIDERADMIN pAdminProvObj,
- LPMAPIERROR * ppMAPIError)
- {
- // Look at TRACES.H and TRACES.CPP for more options to the InitTraces() function
- //InitTraces (0); // Send output only to the COM1 port
- InitTraces (TRACES_CONSOLE | TRACES_NO_COM_OUTPUT); // Send output to a console window BUT NOT to the COM1
- //InitTraces (TRACES_CONSOLE | TRACES_LOG_FILE); // Send output to COM1 port AND a console window AND to a log file in C:\MAPILOG.TXT
-
- InfoTrace ("ServiceEntry function called");
- HRESULT hResult = S_OK;
- LPPROFSECT pProfileObj = NULL;
- ULONG ulPropCount;
- LPSPropValue pProps = NULL;
- HANDLE hUIMutex = NULL;
-
- // What context where were we called in?
- if (MSG_SERVICE_INSTALL == ulContext ||
- MSG_SERVICE_UNINSTALL == ulContext ||
- MSG_SERVICE_PROVIDER_CREATE == ulContext ||
- MSG_SERVICE_PROVIDER_DELETE == ulContext)
- {
- // We don't handle any of these contexts
- TraceString1 ("ServiceEntry: Immediate return. Context: %d", ulContext);
- goto ErrorExit;
- }
- TraceString1 ("ServiceEntry: Context for call: %d", ulContext);
- ghInstance = hInstance;
-
- // Get the MAPI memory allocation routines we'll be needing
- hResult = pSupObj->GetMemAllocRoutines (&gpfnAllocateBuffer, &gpfnAllocateMore, &gpfnFreeBuffer);
- if (hResult)
- {
- TraceResult ("ServiceEntry: Failed to get the memory allocation functions", hResult);
- goto ErrorExit;
- }
-
- // Open the Profile Section for this service
- hResult = pAdminProvObj->OpenProfileSection (NULL,
- NULL,
- MAPI_MODIFY,
- &pProfileObj);
- if (hResult)
- {
- goto ErrorExit;
- }
- if (MSG_SERVICE_CREATE == ulContext)
- {
- // If ServiceEntry is called because it the service is being created, we create a temporary
- // file where we save the headers text file when the user updates them from
- // the remote host. The headers should be persistent from session to
- // session (using the same profile, of course) but unique per session.
- TCHAR szTmpDir[_MAX_PATH], szFile[_MAX_PATH];
- GetTempPath (_MAX_PATH, szTmpDir);
- lstrcat (szTmpDir, WINDS_DATA_DIRECTORY);
- CreateDirectory (szTmpDir, NULL);
- GetTempFileName (szTmpDir, // Create the file in the system temp directory
- TEXT("XRH"), // Our transport fixed prefix for temp files
- 0, // Use the time to create a pseudo-random number
- szFile); // Destination buffer
- SPropValue spvProps[4] = { 0 };
- spvProps[0].ulPropTag = PR_SMP_HEADERS_FILENAME;
- spvProps[0].Value.LPSZ = szFile;
- SYSTEMTIME st;
- GetLocalTime (&st);
- st.wHour = 23; st.wMinute = 59; st.wSecond = 0;
- spvProps[1].ulPropTag = PR_SMP_UPLOAD_TIME;
- SystemTimeToFileTime (&st, &spvProps[1].Value.ft);
- spvProps[2].ulPropTag = PR_SMP_CONNECTION_TYPE;
- spvProps[2].Value.l = OFFLINE_CONNECT;
- spvProps[3].ulPropTag = PR_SMP_GET_HEADERS;
- spvProps[3].Value.b = TRUE;
- hResult = pProfileObj->SetProps (sizeof(spvProps)/sizeof(SPropValue), spvProps, NULL);
- TraceResult ("ServiceEntry: Failed to save the headers file name back into the profile", hResult);
- }
- // The profile section is open, get the properties out of it
- hResult = pProfileObj->GetProps ((LPSPropTagArray)&sptLogonProps,
- fMapiUnicode,
- &ulPropCount,
- &pProps);
- if (FAILED(hResult))
- {
- TraceResult ("ServiceEntry: Failed to get profile section properties", hResult);
- goto ErrorExit;
- }
- ASSERT (NUM_LOGON_PROPERTIES == ulPropCount);
-
- if (MSG_SERVICE_DELETE == ulContext)
- {
- // If the service is being removed from a profile, we must cleanup
- // any temporary file (i.e. the headers text file)
- if (PR_SMP_HEADERS_FILENAME == pProps[HEADER_FILE].ulPropTag)
- {
- DeleteFile (pProps[HEADER_FILE].Value.LPSZ);
- }
- TCHAR szTmpDir[_MAX_PATH], szDownloadDir[_MAX_PATH];
- GetTempPath (_MAX_PATH, szTmpDir);
- lstrcat (szTmpDir, WINDS_DATA_DIRECTORY);
- if (PR_SMP_MAILBOX_NAME == pProps[MAILBOX_NAME].ulPropTag)
- {
- wsprintf (szDownloadDir, WINDS_DOWNLOAD_DIR_NAME_FORMAT, szTmpDir, pProps[MAILBOX_NAME].Value.LPSZ);
- RemoveDirectory (szDownloadDir);
- }
- RemoveDirectory (szTmpDir);
- // We are done
- hResult = S_OK;
- goto ErrorExit;
- }
- // After the setup wizard has been called the ServiceEntry functions gets called
- // with a set of properties obtained from the user for configuring this provider.
- // Merge or replace those properties onto the one we obtained from the profile section.
- if (pCfgProps && ulCfgPropCount)
- {
- hResult = MergeConfigProps (ulCfgPropCount, pCfgProps, pProps);
- if (hResult)
- {
- goto ErrorExit;
- }
- }
- // If we can, display the UI...
- if (SERVICE_UI_ALWAYS & ulFlags || SERVICE_UI_ALLOWED & ulFlags)
- {
- CFGDLG CfgDialog = { 0 };
- hUIMutex = CreateMutex (NULL, FALSE, CONFIG_UI_MUTEX);
- if (NULL == hUIMutex)
- {
- TraceResult ("ServiceEntry: Failed to create UI mutext", GetLastError());
- }
- PrivInitialize3DCtl (hInstance);
- if (WAIT_TIMEOUT == WaitForSingleObject (hUIMutex, 250)) // Wait for the MUTEX for 1/4 second
- {
- PrivateMessageBox (IDS_MSG_CONFIG_UI_IN_USE, (HWND)ulUIParam);
- hResult = MAPI_E_BUSY;
- goto ErrorExit;
- }
-
- // Fill in the logon UI structure
- CfgDialog.hInst = hInstance;
- CfgDialog.hWnd = (HWND)ulUIParam;
- CfgDialog.ppProps = &pProps;
- CfgDialog.pSupObj = pSupObj;
- CfgDialog.ulFlags = MSG_SERVICE_UI_READ_ONLY & ulFlags ? UI_READONLY : 0;
- CfgDialog.hUIMutex = NULL; // So that the DoLogonDlg() won't have to wait.
- ShowPropsAgain:
- hResult = DoLogonDlg (&CfgDialog);
- if (hResult)
- {
- goto ErrorExit;
- }
- if (!PingRemoteServer ((HWND)ulUIParam, pProps))
- {
- goto ShowPropsAgain;
- }
- }
- if (PR_SMP_MAILBOX_NAME == pProps[MAILBOX_NAME].ulPropTag)
- {
- TCHAR szTmpDir[_MAX_PATH], szDownloadDir[_MAX_PATH];
- GetTempPath (_MAX_PATH, szTmpDir);
- lstrcat (szTmpDir, WINDS_DATA_DIRECTORY);
- wsprintf (szDownloadDir, WINDS_DOWNLOAD_DIR_NAME_FORMAT, szTmpDir, pProps[MAILBOX_NAME].Value.LPSZ);
- CreateDirectory (szDownloadDir, NULL);
- }
-
- hResult = pProfileObj->SetProps (NUM_LOGON_PROPERTIES, pProps, NULL);
- TraceResult ("ServiceEntry: Failed to save the properties back into the profile", hResult);
-
- ErrorExit:
- // Clean up
- if (pProfileObj)
- {
- pProfileObj->Release();
- }
- if (gpfnFreeBuffer)
- {
- gpfnFreeBuffer (pProps);
- }
- if (hUIMutex)
- {
- ReleaseMutex (hUIMutex);
- CloseHandle (hUIMutex);
- }
- // In case the DLL was loaded, unload it.
- // This DLL gets loaded and initialized in the call to DoLogonDlg()
- PrivUninitialize3DCtl (hInstance);
-
- // If we have remote connections going on, close them now
- TerminateRemoteConnections();
-
- // Close down the traces
- UnInitTraces();
- return hResult;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // DoLogonDlg()
- //
- // Parameters
- // pCfgDialog Pointer to an CFGDLG structure.
- //
- // Purpose
- // This functions gets called to display the configuration properties for
- // this transport. When invoked, it will parse the transport logon
- // property array and initialize the fields in the property sheet with it.
- // The function could also get invoked to display the settings in
- // READ-ONLY mode in which case we disable writing to the editable fields.
- //
- // Return Value
- // An HRESULT
- //
- HRESULT WINAPI DoLogonDlg (PCFGDLG pCfgDialog)
- {
- DWORD dwWait = WaitForSingleObject (pCfgDialog->hUIMutex, 1000); // Wait for the MUTEX for 1 second
- PrivInitialize3DCtl (pCfgDialog->hInst);
- if (WAIT_TIMEOUT == dwWait)
- {
- PrivateMessageBox (IDS_MSG_CONFIG_UI_IN_USE, pCfgDialog->hWnd);
- return MAPI_E_BUSY;
- }
-
- LPMAPITABLE pTableObj= NULL;
- ULONG ulPropCount;
- SizedSPropTagArray(NUM_LOGON_PROPERTIES, sptCfgProps);
- CopyMemory (&sptCfgProps, &sptLogonProps, sizeof(sptLogonProps));
- sptCfgProps.aulPropTag[UPLOAD_TIME] = PR_TMP_UPLOAD_TIME;
-
- // Take ownership of the property value array, so calling code
- // will not leak memory
- LPSPropValue pProps = *pCfgDialog->ppProps;
- *pCfgDialog->ppProps = NULL;
-
- // Retrieve the dialog title string
- TCHAR szDialogTitle[64], szTimeString[32];
- LoadString (pCfgDialog->hInst, IDS_SERVICE_PROPERTY_SHEETS_TITLE, szDialogTitle, 64);
- CUIMAPIProp * pPropObj = NULL;
- HRESULT hResult = S_OK;
- try
- {
- pPropObj = new CUIMAPIProp (pCfgDialog->hInst,
- gpfnAllocateBuffer,
- gpfnAllocateMore,
- gpfnFreeBuffer,
- pCfgDialog->ulFlags & UI_READONLY);
- if (!pPropObj)
- {
- hResult = E_OUTOFMEMORY;
- }
- }
- catch (CException & Exception)
- {
- hResult = Exception.GetError();
- }
- if (hResult)
- {
- goto ErrorExit;
- }
-
- ASSERT (PR_SMP_UPLOAD_TIME == pProps[UPLOAD_TIME].ulPropTag);
- GetTimeString (szTimeString, pProps[UPLOAD_TIME].Value.ft);
- pProps[UPLOAD_TIME].ulPropTag = PR_TMP_UPLOAD_TIME;
- pProps[UPLOAD_TIME].Value.LPSZ = szTimeString;
-
- hResult = pPropObj->SetProps (NUM_LOGON_PROPERTIES, pProps, NULL);
- if (hResult)
- {
- TraceResult ("DoLogonDlg: Failed to set the properties", hResult);
- goto ErrorExit;
- }
- DTPAGE DtPropPages[2];
- DtPropPages[0].cctl = NUM_CFG_USERINFO_PAGE_CTLS; // Count of controls in the ConfigPage array
- DtPropPages[0].lpszComponent = szBlank;
- DtPropPages[0].lpszResourceName = MAKEINTRESOURCE (IDD_CFG_USERINFO);
- DtPropPages[0].lpctl = UserConfigPage;
-
- DtPropPages[1].cctl = sizeof(XPConfigPage)/sizeof(DTCTL); // Count of controls in the ConfigPage array
- DtPropPages[1].lpszComponent = szBlank;
- DtPropPages[1].lpszResourceName = MAKEINTRESOURCE (IDD_CFG_XPCONNECT);
- DtPropPages[1].lpctl = XPConfigPage;
-
- // If the UI_READONLY flag is set, then we are being called from the
- // SettingDialog method in Read Only mode. Disable all of the controls
- // on the property sheets, else Enable them
- if (pCfgDialog->ulFlags & UI_READONLY)
- {
- // Disable the controls (make them read-only)
- DtPropPages[0].lpctl[1].ulCtlFlags &= ~(DT_EDITABLE | DT_SET_IMMEDIATE);
- DtPropPages[0].lpctl[7].ulCtlFlags &= ~(DT_EDITABLE | DT_SET_IMMEDIATE);
- DtPropPages[1].lpctl[1].ulCtlFlags &= ~DT_EDITABLE;
- DtPropPages[1].lpctl[2].ulCtlFlags &= ~DT_EDITABLE;
- }
- else
- {
- // Enable the controls (make them read/write)
- DtPropPages[0].lpctl[1].ulCtlFlags |= (DT_EDITABLE | DT_SET_IMMEDIATE);
- DtPropPages[0].lpctl[7].ulCtlFlags |= (DT_EDITABLE | DT_SET_IMMEDIATE);
- DtPropPages[1].lpctl[1].ulCtlFlags |= DT_EDITABLE;
- DtPropPages[1].lpctl[2].ulCtlFlags |= DT_EDITABLE;
- }
-
- // Create the display table for the logon dialog. It is based on dialog
- // resources plus the static information at the head of this module.
- LPTABLEDATA pTableData;
- hResult = BuildDisplayTable (gpfnAllocateBuffer,
- gpfnAllocateMore,
- gpfnFreeBuffer,
- NULL,
- pCfgDialog->hInst,
- sizeof(DtPropPages)/sizeof(DTPAGE),
- DtPropPages,
- fMapiUnicode,
- &pTableObj,
- &pTableData);
- if (!hResult)
- {
- pPropObj->SetTableData (pTableData);
- pTableData->Release();
-
- // Display the dialog/property sheets
- DisplayPropsAgain:
- hResult = pCfgDialog->pSupObj->DoConfigPropsheet ((ULONG)pCfgDialog->hWnd,
- 0,
- szDialogTitle,
- pTableObj,
- pPropObj,
- 0); // Default index for the top property sheet
- if (!hResult)
- {
- // Retrieve the altered data
- gpfnFreeBuffer (pProps);
- pProps = NULL;
- hResult = pPropObj->GetProps ((LPSPropTagArray)&sptCfgProps, fMapiUnicode, &ulPropCount, &pProps);
- if (hResult)
- {
- if (MAPI_W_ERRORS_RETURNED == hResult)
- {
- if (PR_TMP_UPLOAD_TIME != pProps[UPLOAD_TIME].ulPropTag)
- {
- pProps[UPLOAD_TIME].ulPropTag = PR_TMP_UPLOAD_TIME;
- pProps[UPLOAD_TIME].Value.LPSZ = szDefaultTime;
- }
- hResult = S_OK;
- }
- else
- {
- TraceResult ("DoLogonDlg: GetProps failed", hResult);
- goto ErrorExit;
- }
- }
- // Check the Server name
- if (!IsValidServerName (pProps[SERVER_NAME].Value.LPSZ))
- {
- gpfnFreeBuffer (pProps);
- pProps = NULL;
- PrivateMessageBox (IDS_MSG_INVALID_SERVER_NAME, pCfgDialog->hWnd);
- goto DisplayPropsAgain;
- }
-
- ASSERT (PR_TMP_UPLOAD_TIME == pProps[UPLOAD_TIME].ulPropTag);
- SYSTEMTIME st;
- GetLocalTime (&st);
- if (ParseTime (pProps[UPLOAD_TIME].Value.LPSZ, &st.wHour, &st.wMinute))
- {
- pProps[UPLOAD_TIME].ulPropTag = PR_SMP_UPLOAD_TIME;
- SystemTimeToFileTime (&st, &pProps[UPLOAD_TIME].Value.ft);
- }
- else
- {
- gpfnFreeBuffer (pProps);
- pProps = NULL;
- PrivateMessageBox (IDS_MSG_BAD_TIME_FORMAT, pCfgDialog->hWnd);
- goto DisplayPropsAgain;
- }
-
- // Return the new property array
- *pCfgDialog->ppProps = pProps;
- pProps = NULL; // do not free this in cleanup code below
- }
- }
-
- ErrorExit:
- // Release objects
- if (pTableObj)
- {
- pTableObj->Release();
- }
- if (pPropObj)
- {
- pPropObj->Release();
- }
- gpfnFreeBuffer (pProps);
- PrivUninitialize3DCtl (pCfgDialog->hInst);
- ReleaseMutex (pCfgDialog->hUIMutex);
- return hResult;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // ParseTime()
- //
- // Parameters
- // [IN] pszTime String in the form HH:MM.
- // [OUT] pwHour Hour of day, 0-23
- // [OUT] pwMinute Minute of hour, 0-59
- //
- // Purpose
- // This function parses the string in pszTime and returns the numbers
- // for the hour and minute of day in a 24 hour clock format.
- //
- // Return Value
- // TRUE on success, FALSE if we failed or the string passed
- // in is invalid.
- //
- BOOL WINAPI ParseTime (LPTSTR pszTime, WORD * pwHour, WORD * pwMinute)
- {
- TCHAR szTemp[6];
- lstrcpy (szTemp, pszTime);
- LPTSTR pszSubStr = strtok(szTemp, TEXT(":"));
- if (!pszSubStr)
- {
- return FALSE;
- }
- *pwHour = atoi (pszSubStr);
- if (*pwHour < 0 || *pwHour > 23)
- {
- return FALSE;
- }
- pszSubStr = strtok (NULL, TEXT(" "));
- if (!pszSubStr)
- {
- return FALSE;
- }
- *pwMinute = atoi(pszSubStr);
- if (*pwMinute < 0 || *pwMinute > 59)
- {
- return FALSE;
- }
- return TRUE;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // GetTimeString()
- //
- // Parameters
- // [OUT] pszTime Pointer to a buffer where the function copies the
- // formatted time string. The buffer must have been
- // allocated by the caller.
- // [IN] FileTime FILETIME structure with the time for the string.
- //
- // Purpose
- // This function returns a string formatted as "HH:MM"
- // The formatted string is returned in a buffer supplied by the caller
- // of the function.
- //
- // Return Value
- // None.
- //
- void WINAPI GetTimeString (LPTSTR pszTime, FILETIME FileTime)
- {
- // Convert the FILETIME structure to a more readable form
- SYSTEMTIME sysTime;
- FileTimeToSystemTime (&FileTime, &sysTime);
- wsprintf (pszTime, TEXT("%d:%02d"), sysTime.wHour, sysTime.wMinute);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // GetMAPIError()
- //
- // Parameters
- // ppMAPIError Pointer to a location where the newly
- // allocated MAPIERROR structure is returened.
- // ulFlags Flags for the allocation of the structure
- // hError Handle to the error for which a string will
- // be returned
- // hInstance Handle to instance of DLL where the resource
- // strings are located
- //
- // Purpose
- // This provider implements a shared function for the two different
- // GetLastError methods in the IMAPIFolder and IMAPIStatus interfaces.
- // These interfaces do not maintain (cached) the last error result, so
- // we trust the client that the hError passed in is indeed the last error.
- // This simplifies implementation of GetLastError, but it will give up
- // giving error strings on the exact context of the actual last error
- // in the case a client passes the wrong hResult.
- // ISV's should weight the benefits and trade-off of this implementation.
- //
- // Return Value
- // An HRESULT
- //
- HRESULT WINAPI GetMAPIError (LPMAPIERROR * ppMAPIError,
- ULONG ulFlags,
- HRESULT hError,
- HINSTANCE hInstance)
- {
- // The following array maps a string identifier (IDS) to an hResult
- // The order of HRESULTs in the array has an external dependency:
- // the order of elements in the array is dictated by the IDS definitions
- // in RESOURCE.H. This implicit association must be maintained for the
- // strings associated with string identifiers to make sense. Thus, if
- // either this structure or the RESOURCE.H defines changes, the other
- // must change to match it
- static const HRESULT MapOfhResults[] =
- {
- S_OK,
-
- E_FAIL,
- E_OUTOFMEMORY,
- E_INVALIDARG,
- E_NOINTERFACE,
- E_ACCESSDENIED,
-
- MAPI_E_BUSY,
- MAPI_E_NO_SUPPORT,
- MAPI_E_NOT_FOUND,
- MAPI_E_UNKNOWN_FLAGS,
- MAPI_E_VERSION,
- MAPI_E_INVALID_ENTRYID,
- MAPI_E_USER_CANCEL,
- MAPI_E_DISK_ERROR,
- MAPI_E_CORRUPT_DATA,
- MAPI_E_BAD_CHARWIDTH,
- MAPI_E_UNCONFIGURED,
-
-
- CO_E_NOTINITIALIZED, // This error could only be comming from the server
-
- MAPI_W_ERRORS_RETURNED
- };
-
- // Default the a return value in case we don't have the specified error
- // Allocate the memory for the MAPIERROR structure. The caller is
- // responsible for free this
- HRESULT hResult = gpfnAllocateBuffer (sizeof(MAPIERROR), (LPVOID *)ppMAPIError);
- if (hResult)
- {
- TraceResult ("GetMAPIError: Failed to allocate memory for the MAPIERROR structure", hResult);
- return hResult;
- }
-
- // Zero-out all the members in the structure
- ZeroMemory (*ppMAPIError, sizeof(MAPIERROR));
- (*ppMAPIError)->ulVersion = MAPI_ERROR_VERSION;
- // See if we have the string for the error. If so, make a copy
- // and pass it back. The memory for the string will be linked to
- // the memory of the structure so that the caller can make a
- // single release on the structure
-
- // Search for the hResult in the HRESULT map
- UINT i, uMaxNum, uStringID;
- uStringID = 0;
- uMaxNum = sizeof (MapOfhResults) / sizeof (HRESULT);
- for (i=0; i<uMaxNum; i++ )
- {
- if (MapOfhResults[i] == hError)
- {
- break;
- }
- }
-
- if (i == uMaxNum)
- {
- (*ppMAPIError)->ulLowLevelError = LOWORD(hError);
- if (HRESULT_FACILITY(hError) == FACILITY_RPC)
- {
- uStringID = IDS_RPC_ERROR;
- }
- else
- {
- if (HRESULT_FACILITY(hError) == FACILITY_WIN32 ||
- HRESULT_FACILITY(hError) == FACILITY_NULL)
- {
- uStringID = IDS_SYSTEM_ERROR;
- }
- else
- {
- uStringID = IDS_E_UNKNOWN_ERROR;
- }
- }
- }
- else
- {
- uStringID = i + IDS_SUCCESS;
- }
-
- TCHAR szBuffer[512];
- int nCharsRead = LoadString (hInstance, uStringID, szBuffer, sizeof(szBuffer) -1);
- if (!nCharsRead)
- {
- TraceString1 ("GetMAPIError: Could not find error string for ID %d", uStringID);
- hResult = MAPI_E_NOT_FOUND;
- }
- else
- {
- // Allocate memory for return variable and set it.
- // The memory for this string is linked to the memory in the pMemBlock parameter
- hResult = gpfnAllocateMore (Cbtszsize (szBuffer),
- *ppMAPIError,
- (LPVOID *)&(*ppMAPIError)->lpszError);
- if (!hResult)
- {
- lstrcpy ((*ppMAPIError)->lpszError, szBuffer);
- hResult = gpfnAllocateMore (Cbtszsize (TRANSPORT_DISPLAY_NAME_STRING),
- *ppMAPIError,
- (LPVOID *)&(*ppMAPIError)->lpszComponent);
- if (!hResult)
- {
- lstrcpy ((*ppMAPIError)->lpszComponent, TRANSPORT_DISPLAY_NAME_STRING);
- }
- else
- {
- TraceResult ("GetMAPIError: Failed to allocate the memory for the component string", hResult);
- }
- }
- else
- {
- TraceResult ("GetMAPIError: Failed to allocate the memory for the error string", hResult);
- }
- }
-
- if (hResult)
- {
- gpfnFreeBuffer (*ppMAPIError);
- *ppMAPIError = NULL;
- }
- return hResult;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // XPProviderInit()
- //
- // Parameters
- // { Refer to MAPI Documentation on this method }
- //
- // Purpose
- // Entry point called by the MAPI spooler when a profile uses this
- // transport. The spooler calls this method and expects a pointer to an
- // implementation of the IXPProvider interface. MAPI uses the returned
- // IXPProvider interface pointer to logon on the transport provider
- //
- // Return Value
- // An HRESULT
- //
- STDINITMETHODIMP XPProviderInit (HINSTANCE hInstance,
- LPMALLOC pMallocObj,
- LPALLOCATEBUFFER pfnAllocateBuffer,
- LPALLOCATEMORE pfnAllocateMore,
- LPFREEBUFFER pfnFreeBuffer,
- ULONG ulFlags,
- ULONG ulMAPIVer,
- ULONG * pulProviderVer,
- LPXPPROVIDER * ppXPProviderObj)
- {
- // Look at TRACES.H and TRACES.CPP for more options to the InitTraces() function
- //InitTraces (0); // Send output only to the COM1 port
- InitTraces (TRACES_CONSOLE | TRACES_NO_COM_OUTPUT); // Send output to a console window BUT NOT to the COM1
- //InitTraces (TRACES_CONSOLE | TRACES_LOG_FILE); // Send output to COM1 port AND a console window AND to a log file in C:\MAPILOG.TXT
- InfoTrace ("XPProviderInit function called");
- *pulProviderVer = CURRENT_SPI_VERSION;
- if (ulMAPIVer < CURRENT_SPI_VERSION)
- {
- TraceMessage ("XPProviderInit: The version of the subsystem cannot handle this version of the provider");
- return MAPI_E_VERSION;
- }
- // Save the pointer to the allocation routines in global variables
- gpfnAllocateBuffer = pfnAllocateBuffer;
- gpfnAllocateMore = pfnAllocateMore;
- gpfnFreeBuffer = pfnFreeBuffer;
- ghInstance = hInstance;
- // Allocate a new XPProvider object, the constructor will initialize the data member
- CXPProvider * pXPProvider = new CXPProvider (hInstance);
- if (!pXPProvider)
- {
- TraceMessage ("XPProviderInit: Failed to allocate a new CXPProvider object");
- return E_OUTOFMEMORY;
- }
- // Copy pointer to the allocated object back into the return IXPProvider object pointer
- *ppXPProviderObj = (LPXPPROVIDER)pXPProvider;
- return S_OK;
- }
-
- // End of file for XPSRVCE.CPP
-