ADMIN.C

// Admin.C --------------------------------------------------------------------- 
// Functions to support Exchange Admin Configuration Extension Dialogs for C
// programs. This does the majority of the handshaking necessary.
// (See ExAdmin.CPP for C++ support)
//
// This module is intended to be a generic MAIN source file for creating an
// Exchange Administration DLL. You could take this file and include it in your
// project as starting place for your DLL.
//
// Copyright (C) Microsoft Corp. 1986-1996. All Rights Reserved.
// -----------------------------------------------------------------------------

#include "edk.h"
#include "retcode.h"
#include "admin.h"
#include "admin.chk"

HINSTANCE hDLLInst = NULL;
BOOL bReadOnly = FALSE; // The mode is read only if TRUE.

ADMIN_AdministratorFunction* pAdminFunctions; // Admin functions available to you.
ADMIN_ObjectInfo* pAdminObjectInfo; // Admin server name and other useful DNs.

extern BOOL __stdcall _CRT_INIT( HINSTANCE, DWORD, LPVOID);

//$--LibMain--------------------------------------------------------------------
// Eported Function. Called when DLL is first loaded.
// -----------------------------------------------------------------------------

BOOL APIENTRY LibMain( // Returns TRUE if DLL has been initialized.
IN HINSTANCE hinstDLL, // Handle to this DLL instance
IN DWORD dwReason, // Reason DLL is being initialized.
IN LPVOID lpContext) // Context (not used)
{
// Set global instance variable.
hDLLInst = hinstDLL;

// Initialize the C Run Time DLL.
if( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH )
{
if( _CRT_INIT( hinstDLL, dwReason, lpContext) == FALSE)
{
HR_LOG( E_FAIL);
return( FALSE);
}
}

return( TRUE);
}

//$--bInitSheet()---------------------------------------------------------------
// This function initializes the property sheet info and returns it to admin.
//
// Since this piece of code is written to be a generic MAIN source file for
// creating an Exchange Administration DLL we use global data defined outside
// of this module to contain the information about the property sheet dialogs.
// You will need to make sure your code contains the following two globals:
//
// 1) ADMIN_SheetInfo rgSheetInfo[] Array of info about your
// property sheets.
//
// 2) int cSheetInfo = ARRAY_CNT( rgSheetInfo); The count of property sheets
// in the array.
// -----------------------------------------------------------------------------

BOOL PASCAL bInitSheet( // RETURNS: TRUE if initialization OK
IN ADMIN_ObjectInfo* poi, // Computer name & DN.
IN ULONG fFlags, // Tells us if it is read only or not.
OUT ADMIN_SheetInfo** ppSheetInfo, // Property sheet description array
OUT UINT* pcsi, // Number of property sheets
OUT VOID** ppNotUsed) // Local data
{
int iSheet = 0;

DEBUGPUBLIC( "bInitSheet()\n");
if( FAILED( CHK_bInitSheet( poi, fFlags, ppSheetInfo, pcsi, ppNotUsed)))
return( FALSE);

// Remember these for later usage.
pAdminObjectInfo = poi;
bReadOnly = (fFlags & fxfReadOnly) > 0;

// Initialize Admin property sheet info array.
for( iSheet = 0; iSheet < cSheetInfo; iSheet++)
{ // Update each array item with info we know about.
rgSheetInfo[ iSheet].hInstance = hDLLInst;
rgSheetInfo[ iSheet].langid = MAKELANGID(LANG_ENGLISH,SUBLANG_NEUTRAL);
}

// Set return values.
*pcsi = cSheetInfo;
*ppSheetInfo = rgSheetInfo;
*ppNotUsed = NULL;

return( TRUE);
}

//$--DeinitSheet()--------------------------------------------------------------
// Admin calls this when the property sheet dialog box is about to be removed.
// -----------------------------------------------------------------------------

void PASCAL DeinitSheet(
IN VOID* pNotUsed) // Extension data.
{
DeinitSheet1();
}

//$--bInstallExtension()--------------------------------------------------------
// -----------------------------------------------------------------------------

BOOL PASCAL bInstallExtension(ADMIN_ObjectInfo * poi)
{
return(TRUE);
}

//$--bDeinstallExtension()------------------------------------------------------
// -----------------------------------------------------------------------------

BOOL PASCAL bDeinstallExtension(ADMIN_ObjectInfo * poi)
{
return(TRUE);
}


//$--bShowPage()----------------------------------------------------------------
// This is called once per standard property sheet. Not at all for our property
// sheets. If you want to disable some or all of the standard property sheets
// then return FALSE for those default property sheets.
// -----------------------------------------------------------------------------

BOOL PASCAL bShowPage( UINT iddAdminPage)
{
BOOL bRet = TRUE; // Show the standard property sheet.
return( bRet);
}

//$--iStartPage()---------------------------------------------------------------
// This function is called once durring initialization. Return -1 to cause the
// first standard property sheet to be displayed. Or return the index of one of
// our property sheets to have it come up first.
// -----------------------------------------------------------------------------

INT PASCAL iStartPage( void)
{
int i = -1; // Default to the first standard property sheet.
return( i);
}

//$--ADMIN_Initialize()---------------------------------------------------------
// Exported function. This is the first function called by admin after the DLL
// has been initialized.
// -----------------------------------------------------------------------------

VOID PASCAL ADMIN_Initialize(
IN ADMIN_AdministratorConnections* pAdminConnections, // Global Administrator Connections
IN ADMIN_AdministratorFunction* pAdminFuncs, // Global admin function
OUT ADMIN_ExtensionFunction** ppExtensionFunction)// Global Extension function
{
DEBUGPUBLIC( "ADMIN_Initialize()\n");
if( FAILED( CHK_ADMIN_Initialize( pAdminConnections, pAdminFuncs, ppExtensionFunction)))
return;

// We need to keep a global copy of admin's function pointers.
pAdminFunctions = pAdminFuncs;

// Tell admin where it can find the rest of our functions that it needs.
*ppExtensionFunction = &extensionFunctions;
}

// -----------------------------------------------------------------------------


// =============================================================================
// Miscelaneous support functions. The above functions are required by admin.,
// the functions listed below are not.
// =============================================================================


//$--HrLoadExtData()------------------------------------------------------------
// Loads the extension data from Exchange Admin into an array of property values.
// -----------------------------------------------------------------------------

HRESULT HrLoadExtData(
IN HWND hDlg, // Handle of property sheet dialog.
IN LPTSTR lpszExtDataName, // Name of extension data to retrieve.
OUT ULONG* lpcExtProps, // Ptr to receive count of ext data properties.
OUT LPSPropValue* lppExtProps) // Ptr to ptr to extension data properties.
{
HRESULT hr = NOERROR;
RC rc = RC_SUCCESS;
UINT cTemp = 0;
ULONG cRawExtData = 0; // Count of raw extension data blob.
LPBYTE lpbRawExtData = NULL; // Ptr to raw extension data blob.
LPWSTR lpwszExtDataName = NULL; // Ptr to mapi allocated WIDE extension data name.

//hr = CHK_HrLoadExtData( lpszExtDataName, lpcExtProps, lppExtProps);
//if( FAILED( hr))
//RETURN( hr);

// Make sure the property count starts at zero.
*lpcExtProps = 0;

// Convert extension data name string to a wide string
// which is required by Exchange Admin.
hr = HrStrToStrW( lpszExtDataName, &lpwszExtDataName);
if( FAILED( hr))
goto cleanup;

// Ask Exchange Admin the size of the buffer needed to hold the data.
rc = pAdminFunctions->pfnGetObjectDataSize( hDlg, lpwszExtDataName, &cTemp);
if( RC_FAILED( rc))
{
hr = HR_LOG( E_FAIL);
goto cleanup;
}

// Convert UINT to a ULONG.
cRawExtData = cTemp;

// Allocate a buffer to hold the extension data returned from Exchange Admin.
hr = MAPIAllocateBuffer( cRawExtData, (LPVOID*) &lpbRawExtData);
if( FAILED( hr))
{
hr = HR_LOG( E_FAIL);
goto cleanup;
}

// Get the extension data from Exchange Admin.
rc = pAdminFunctions->pfnGetObjectData( hDlg, lpwszExtDataName, lpbRawExtData, cRawExtData);
if( RC_FAILED(rc))
{
hr = HR_LOG( E_FAIL);
goto cleanup;
}

// Unpack the Exchange Admin data into a MAPI style property value array.
hr = HrCfgUnpackData( cRawExtData, lpbRawExtData, NULL, lpcExtProps, lppExtProps);
if( FAILED( hr))
goto cleanup;

cleanup:
MAPIFREEBUFFER( lpwszExtDataName);
MAPIFREEBUFFER( lpbRawExtData);

RETURN( hr);
}

// -----------------------------------------------------------------------------
// Saves the extension data into an Exchange Admin buffer. Admin will not
// commit this data until the user presses the Apply or OK button. However the
// changed data is then available to other property sheets.
// -----------------------------------------------------------------------------

HRESULT HrSaveExtData(
IN HWND hDlg, // Handle of property sheet dialog.
IN LPTSTR lpszExtDataName, // Name of extension data to save.
IN ULONG cExtProps, // Count of ext data properties.
IN LPSPropValue lpExtProps, // Ptr to extension data properties.
IN BOOL bNew) // Indicates the blob is new.
{
HRESULT hr = NOERROR;
RC rc = RC_SUCCESS;
ULONG cExtData = 0;
LPBYTE lpbExtData = NULL;

// Validate the data to save.
if( cExtProps != 0 && !TEST_READ_PTR( lpExtProps, sizeof( SPropValue) * cExtProps))
{
hr = HR_LOG( E_FAIL);
goto cleanup;
}

// Pack the configuration data from a MAPI style property value array
// into a format that Exchange Admin will be able to save.
hr = HrCfgPackData( lpszExtDataName, cExtProps, lpExtProps, &cExtData, &lpbExtData);
if( FAILED( hr))
goto cleanup;

// Set the extension data using Exchange Admin.
rc = pAdminFunctions->pfnSetObjectData( hDlg, lpbExtData, cExtData, bNew);
if( RC_FAILED(rc))
{
hr = HR_LOG( E_FAIL);
goto cleanup;
}

cleanup:
MAPIFREEBUFFER( lpbExtData);
RETURN( hr);
}

//$--HrLoadDialogTemplate()-----------------------------------------------------
// Use this function to create child dialog box templates. It will ensure that
// the correct language and fonts are used.
//
// To display the dialog use DialogBoxIndirect() which is a Windows SDK
// function.
// -----------------------------------------------------------------------------

HRESULT HrLoadDialogTemplate(
IN UINT iddDialog, // Resource ID of dialog.
OUT HGLOBAL* phDlgTemplate) // Ptr to var to store handle in.
{
HRESULT hr = NOERROR;

if( !pAdminFunctions->pfnLoadDialogResource( hDLLInst, iddDialog,
LANGIDFROMLCID(pAdminObjectInfo->lcid), (LPBYTE*) phDlgTemplate))
hr = HR_LOG( E_FAIL);

RETURN( hr);
}

// -----------------------------------------------------------------------------