RADMRPC.CPP

/////////////////////////////////////////////////////////////////////////////// 
//
// File Name
// RADMRPC.CPP
//
// Description
//
// Author
// Irving De la Cruz
//
// Revision: 1.7
//
// Written for Microsoft Windows Developer Support
// Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved.
//
#include "_WINDS.H"
#include <RPC.H>
#include "WINDS.H" // Header file generated by the MIDL compiler
#include "WDSADM.H" // Header file generated by the MIDL compiler
#include "COMMON.H" // For the transmition of the DL members list

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmGetServerMailboxes()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmGetServerMailboxes (long * pPipeNumber)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}

*pPipeNumber = GetNextPipeID();

SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;

// Initialize the new security descriptor.
InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);

// Add a NULL descriptor ACL to the security descriptor.
SetSecurityDescriptorDacl (&sd, TRUE, (PACL)NULL, FALSE);

sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = TRUE;

// Create a pipe where we will expect the transport to send the data
TCHAR szPipeName[64];
wsprintf (szPipeName, SERVER_PIPE_NAME_FORMAT, *pPipeNumber);
HANDLE hPipe;
hPipe = CreateNamedPipe (szPipeName,
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
1,
IO_BUFFERSIZE,
IO_BUFFERSIZE,
0,
&sa);
if (INVALID_HANDLE_VALUE == hPipe || ERROR_INVALID_PARAMETER == (DWORD)hPipe)
{
lResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("RemoteAdmGetServerMailboxes: Failed to create pipe", lResult);
return lResult;
}

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_ADMIN_GET_SERVER_MAILBOXES;
g_IOInfo.hActionCompleted = NULL;
g_IOInfo.phLastError = NULL;
g_IOInfo.hTmpFile = hPipe;
LeaveCriticalSection (&g_csIOInfo);

return lResult;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmGetServerDistLists()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmGetServerDistLists (long * pPipeNumber)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}

*pPipeNumber = GetNextPipeID();

SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;

// Initialize the new security descriptor.
InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);

// Add a NULL descriptor ACL to the security descriptor.
SetSecurityDescriptorDacl (&sd, TRUE, (PACL)NULL, FALSE);

sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = TRUE;

TCHAR szPipeName[64];
wsprintf (szPipeName, SERVER_PIPE_NAME_FORMAT, *pPipeNumber);
HANDLE hPipe;
hPipe = CreateNamedPipe (szPipeName,
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
1,
IO_BUFFERSIZE,
IO_BUFFERSIZE,
0,
&sa);
if (INVALID_HANDLE_VALUE == hPipe || ERROR_INVALID_PARAMETER == (DWORD)hPipe)
{
lResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("RemoteAdmGetServerDistLists: Failed to create pipe", lResult);
return lResult;
}

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_ADMIN_GET_SERVER_DISTLISTS;
g_IOInfo.hActionCompleted = NULL;
g_IOInfo.phLastError = NULL;
g_IOInfo.hTmpFile = hPipe;
LeaveCriticalSection (&g_csIOInfo);

return lResult;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmIsServerRunning()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmIsServerRunning()
{
return GetServiceState();
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmCreateMailboxA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmCreateMailboxA (ADM_MAILBOX_INFO_A * pMailboxInfo)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}
if (FALSE == GlobalObjectMap.IsAliasNameAvailable ((LPSTR)pMailboxInfo->szMailboxName))
{
return HRESULT_FROM_WIN32(ERROR_USER_EXISTS);
}

HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!hWaitEvent)
{
lResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("RemoteAdmCreateMailboxA: Failed to create event for I/O thread", lResult);
return lResult;
}

MAILBOX_INFO_A MBInfo = { 0 };
CopyMemory (&MBInfo, pMailboxInfo, sizeof(MAILBOX_INFO_A));

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_CREATE_NEW_MAILBOX;
g_IOInfo.hActionCompleted = hWaitEvent;
g_IOInfo.phLastError = &lResult;
g_IOInfo.pMBInfo = &MBInfo;
LeaveCriticalSection (&g_csIOInfo);
WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
CloseHandle (hWaitEvent);
if (lResult)
{
TraceResult ("RemoteAdmCreateMailboxA: Failed to create the mailbox", lResult);
return lResult;
}

GlobalObjectMap.Insert (MBInfo.dwObjID, MBInfo.szMailboxName, SERVER_USER_MAILBOX);

// Notify clients (i.e. address books) that a new mail user has been added
PWINDS_NOTIFICATION pNotif = (PWINDS_NOTIFICATION)HeapAlloc (ghHeap,
HEAP_ZERO_MEMORY,
sizeof(WINDS_NOTIFICATION));
if (pNotif)
{
pNotif->Event = AB_USER_ADDED;
CopyMemory (&(pNotif->Info.MB), &MBInfo, sizeof(MAILBOX_INFO));
NotifyClients (pNotif); // This will take care of freeing the notification structure
}
else
{
// This is non-fatal
TraceResult ("RemoteAdmCreateMailboxA: Failed to allocate notification structure", E_OUTOFMEMORY);
}
return lResult;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmDeleteObject()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmDeleteObject (unsigned long dwObjID)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}

TCHAR szObjAlias[MAX_ALIAS_SIZE+1];
WINDS_AB_OBJTYPE Type = UNDEFINED_OBJECT_TYPE;
if (S_OK != GlobalObjectMap.FindObjFromID (dwObjID, szObjAlias, &Type))
{
return HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND);
}

HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!hWaitEvent)
{
lResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("RemoteAdmDeleteObject: Failed to create event for I/O thread", lResult);
return lResult;
}
MAILBOX_INFO MBInfo = { 0 };
DIST_LIST_INFO DLInfo = { 0 };

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.hActionCompleted = hWaitEvent;
g_IOInfo.phLastError = &lResult;

if (SERVER_USER_MAILBOX == Type)
{
lstrcpy (MBInfo.szMailboxName, szObjAlias);
g_IOInfo.Action = IO_REMOVE_MAILBOX;
g_IOInfo.pMBInfo = &MBInfo; // On return this will have all the mailbox properties
}
else
{
if (SERVER_DISTRIBUTION_LIST == Type)
{
lstrcpy (DLInfo.szDLAlias, szObjAlias);
g_IOInfo.Action = IO_DELETE_DISTRIBUTION_LIST;
g_IOInfo.pDLInfo = &DLInfo;
}
else
{
TraceMessage ("RemoteAdmDeleteObject: Remove GATEWAY recipient NYI");
}
}

LeaveCriticalSection (&g_csIOInfo);

WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
CloseHandle (hWaitEvent);

if (lResult)
{
TraceResult ("RemoteAdmDeleteObject: Failed to delete the mailbox", lResult);
return lResult;
}

GlobalObjectMap.Delete (dwObjID);
// Notify client address books that a mail user has been deleted
PWINDS_NOTIFICATION pNotif = (PWINDS_NOTIFICATION)HeapAlloc (ghHeap,
HEAP_ZERO_MEMORY,
sizeof(WINDS_NOTIFICATION));
if (pNotif)
{
if (SERVER_USER_MAILBOX == Type)
{
pNotif->Event = AB_USER_DELETED;
CopyMemory (&(pNotif->Info.MB), &MBInfo, sizeof(MAILBOX_INFO));
}
else
{
if (SERVER_DISTRIBUTION_LIST == Type)
{
pNotif->Event = AB_DL_DELETED;
CopyMemory (&(pNotif->Info.DL), &DLInfo, sizeof(DIST_LIST_INFO));
}
else
{
// TODO: Implement this for gateways
}
}
NotifyClients (pNotif); // This will take care of freeing the notification structure
}
else
{
// Non-fatal error
TraceResult ("RemoteAdmDeleteObject: Failed to allocate notification structure", E_OUTOFMEMORY);
}
return lResult;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmGetMailboxPropsA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmGetMailboxPropsA (unsigned long dwObjID,
unsigned long * pdwObjType,
ADM_MAILBOX_INFO_A * pMailboxInfo)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}
return GetObjectProp (dwObjID, pdwObjType, (MAILBOX_INFO*)pMailboxInfo);
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmSetMailboxPropsA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmSetMailboxPropsA (ADM_MAILBOX_INFO_A * pMailboxInfo)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}

if (pMailboxInfo->dwObjID == 0)
{
TraceMessage ("RemoteAdmSetMailboxPropsA: Invoked with Object ID = 0, cannot accept");
return HRESULT_FROM_WIN32 (ERROR_NO_SUCH_USER);
}

HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!hWaitEvent)
{
lResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("RemoteAdmSetMailboxPropsA: Failed to create event for I/O thread", lResult);
return lResult;
}

MAILBOX_INFO_A MBInfo = { 0 };
CopyMemory (&MBInfo, pMailboxInfo, sizeof(MAILBOX_INFO_A));

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_SET_MAILBOX_PROPERTIES;
g_IOInfo.hActionCompleted = hWaitEvent;
g_IOInfo.phLastError = &lResult;
g_IOInfo.pMBInfo = &MBInfo;
LeaveCriticalSection (&g_csIOInfo);

WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
CloseHandle (hWaitEvent);
if (!lResult)
{
// Notify client address books that a mail user has been modified
PWINDS_NOTIFICATION pNotif = (PWINDS_NOTIFICATION)HeapAlloc (ghHeap,
HEAP_ZERO_MEMORY,
sizeof(WINDS_NOTIFICATION));
if (pNotif)
{
pNotif->Event = AB_USER_MODIFIED;
CopyMemory (&(pNotif->Info.MB), &MBInfo, sizeof(MAILBOX_INFO));
NotifyClients (pNotif); // This will take care of freeing the notification structure
}
else
{
// This is non-fatal
TraceResult ("RemoteAdmSetMailboxPropsA: Failed to allocate notification structure", E_OUTOFMEMORY);
}
}
return lResult;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmTerminateNotifA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmTerminateNotifA (unsigned char * szComputerName,
unsigned long ulConnectionID)
{
return RemoteTerminateNotifA (szComputerName, ulConnectionID);
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmValidateNotifA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmValidateNotifA (unsigned char * szComputerName,
unsigned long ulNotifMask,
unsigned long * pulConnectionID)
{
return RemoteValidateNotifA (szComputerName,
(unsigned char *)"WINDS ADMIN",
ulNotifMask,
pulConnectionID);
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmGetGALDirectory()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmGetGALDirectory (unsigned long dwFlags, long * pPipeNumber)
{
return RemoteGetContainerRecipients (dwFlags, GAL_CONTAINER_ID, pPipeNumber);
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmEmptyMailbox()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmEmptyMailbox (unsigned long dwMailboxID)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}

TCHAR szObjAlias[MAX_ALIAS_SIZE+1];
WINDS_AB_OBJTYPE Type = UNDEFINED_OBJECT_TYPE;
if (S_OK != GlobalObjectMap.FindObjFromID (dwMailboxID, szObjAlias, &Type))
{
return HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND);
}
if (SERVER_USER_MAILBOX != Type)
{
return HRESULT_FROM_WIN32 (ERROR_NO_SUCH_USER);
}

HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!hWaitEvent)
{
lResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("RemoteAdmEmptyMailbox: Failed to create event for I/O thread", lResult);
return lResult;
}

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
lstrcpy (g_IOInfo.szObject, szObjAlias);
g_IOInfo.Action = IO_EMPTY_MAILBOX;
g_IOInfo.hActionCompleted = hWaitEvent;
g_IOInfo.phLastError = &lResult;
LeaveCriticalSection (&g_csIOInfo);

WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
CloseHandle (hWaitEvent);

TraceResult ("RemoteAdmEmptyMailbox", lResult);
return lResult;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmGetDLPropsA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmGetDLPropsA (unsigned long dwObjID,
unsigned char * szDLAlias,
unsigned char * szDLFullName,
unsigned long * pdwFlags,
unsigned char * szOwnerAlias,
unsigned char * szOwnerName,
unsigned long * pdwOwnerID,
unsigned char * szComments,
DLM_XMIT_LIST_A * pMembers)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}

if (0 == dwObjID)
{
TraceMessage ("RemoteAdmGetDLPropsA: Invoked with Object ID = 0, cannot accept");
return HRESULT_FROM_WIN32 (ERROR_NO_SUCH_GROUP);
}

DIST_LIST_INFO DLInfo = { 0 };
WINDS_AB_OBJTYPE Type = UNDEFINED_OBJECT_TYPE;
if ((S_OK != GlobalObjectMap.FindObjFromID (dwObjID, DLInfo.szDLAlias, &Type)) ||
(SERVER_DISTRIBUTION_LIST != Type))
{
return HRESULT_FROM_WIN32 (ERROR_NO_SUCH_GROUP);
}

HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!hWaitEvent)
{
lResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("RemoteAdmGetDLPropsA: Failed to create event for I/O thread", lResult);
return lResult;
}
DLInfo.pMembers = (LPVOID)pMembers;

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_GET_DL_PROPERTIES;
g_IOInfo.hActionCompleted = hWaitEvent;
g_IOInfo.phLastError = &lResult;
g_IOInfo.pDLInfo = &DLInfo;
LeaveCriticalSection (&g_csIOInfo);

WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
CloseHandle (hWaitEvent);
if (!lResult)
{
lstrcpy ((LPSTR)szDLAlias, DLInfo.szDLAlias);
lstrcpy ((LPSTR)szDLFullName, DLInfo.szDLFullName);
*pdwFlags = DLInfo.dwFlags;
lstrcpy ((LPSTR)szOwnerAlias, DLInfo.szOwnerAlias);
lstrcpy ((LPSTR)szOwnerName, DLInfo.szOwnerName);
*pdwOwnerID = DLInfo.dwOwnerID;
}

TraceResult ("RemoteAdmGetDLPropsA", lResult);
return lResult;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmSetDLPropsA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmSetDLPropsA (unsigned long dwObjID,
unsigned char * szDLAlias,
unsigned char * szDLFullName,
unsigned long dwFlags,
unsigned char * szOwnerAlias,
unsigned char * szOwnerName,
unsigned long dwOwnerID,
unsigned char * szComments,
DLM_XMIT_LIST_A * pMembers)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}
if (dwObjID == 0)
{
TraceMessage ("RemoteAdmSetDLPropsA: Invoked with Object ID = 0, cannot accept");
return HRESULT_FROM_WIN32 (ERROR_NO_SUCH_GROUP);
}

DIST_LIST_INFO DLInfo = { 0 };
lstrcpy (DLInfo.szDLAlias, (LPSTR)szDLAlias);
lstrcpy (DLInfo.szDLFullName, (LPSTR)szDLFullName);
DLInfo.dwObjID= dwObjID;
DLInfo.dwFlags = dwFlags;
lstrcpy (DLInfo.szOwnerAlias, (LPSTR)szOwnerAlias);
lstrcpy (DLInfo.szOwnerName, (LPSTR)szOwnerName);
DLInfo.dwOwnerID = dwOwnerID;
DLInfo.pMembers = (LPVOID)pMembers;

HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!hWaitEvent)
{
lResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("RemoteAdmSetDLPropsA: Failed to create event for I/O thread", lResult);
return lResult;
}

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_SET_DL_PROPERTIES;
g_IOInfo.hActionCompleted = hWaitEvent;
g_IOInfo.phLastError = &lResult;
g_IOInfo.pDLInfo = &DLInfo;
LeaveCriticalSection (&g_csIOInfo);
WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
CloseHandle (hWaitEvent);

if (!lResult)
{
PWINDS_NOTIFICATION pNotif = (PWINDS_NOTIFICATION)HeapAlloc (ghHeap,
HEAP_ZERO_MEMORY,
sizeof(WINDS_NOTIFICATION));
if (pNotif)
{
pNotif->Event = AB_DL_MODIFIED;
CopyMemory (&(pNotif->Info.DL), &DLInfo, sizeof(DIST_LIST_INFO));
NotifyClients (pNotif); // This will take care of freeing the notification structure
}
else
{
// This is non-fatal
TraceResult ("RemoteAdmSetDLPropsA: Failed to allocate the notification structure", E_OUTOFMEMORY);
}
}
TraceResult ("RemoteAdmSetDLPropsA", lResult);
return lResult;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteAdmCreateDistListA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteAdmCreateDistListA (unsigned char * szDLAlias,
unsigned char * szDLFullName,
unsigned long dwFlags,
unsigned char * szOwnerAlias,
unsigned char * szOwnerName,
unsigned long dwOwnerID,
DLM_XMIT_LIST_A * pMembers)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}
if (FALSE == GlobalObjectMap.IsAliasNameAvailable ((LPSTR)szDLAlias))
{
return HRESULT_FROM_WIN32(ERROR_GROUP_EXISTS);
}

HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!hWaitEvent)
{
lResult = HRESULT_FROM_WIN32(GetLastError());
TraceResult ("RemoteAdmCreateDistListA: Failed to create event for I/O thread", lResult);
return lResult;
}

DIST_LIST_INFO DLInfo = { 0 };
lstrcpy (DLInfo.szDLAlias, (LPSTR)szDLAlias);
lstrcpy (DLInfo.szDLFullName, (LPSTR)szDLFullName);
DLInfo.dwFlags = dwFlags;

lstrcpy (DLInfo.szOwnerAlias, (LPSTR)szOwnerAlias);
lstrcpy (DLInfo.szOwnerName, (LPSTR)szOwnerName);
DLInfo.dwOwnerID = dwOwnerID;
if (pMembers->Info.szMemberName[0])
{
DLInfo.pMembers = (LPVOID)pMembers;
}
else
{
DLInfo.pMembers = NULL;
}

EnterCriticalSection (&g_csIOInfo);
SetEvent (g_IOInfo.hResumeEvent);
g_IOInfo.Action = IO_CREATE_DISTRIBUTION_LIST;
g_IOInfo.hActionCompleted = hWaitEvent;
g_IOInfo.phLastError = &lResult;
g_IOInfo.pDLInfo = &DLInfo;
LeaveCriticalSection (&g_csIOInfo);
WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
CloseHandle (hWaitEvent);

if (lResult)
{
TraceResult ("RemoteAdmCreateDistListA", lResult);
return lResult;
}

GlobalObjectMap.Insert (DLInfo.dwObjID, DLInfo.szDLAlias, SERVER_DISTRIBUTION_LIST);

// Notify client address books that a distribution list has been added
PWINDS_NOTIFICATION pNotif = (PWINDS_NOTIFICATION)HeapAlloc (ghHeap,
HEAP_ZERO_MEMORY,
sizeof(WINDS_NOTIFICATION));
if (pNotif)
{
pNotif->Event = AB_DL_ADDED;
CopyMemory (&(pNotif->Info.DL), &DLInfo, sizeof(DIST_LIST_INFO));
NotifyClients (pNotif); // This will take care of freeing the notification structure
}
else
{
// This is non-fatal
TraceResult ("RemoteAdmCreateDistListA: Failed to allocate the notification structure", E_OUTOFMEMORY);
}
return lResult;
}

// The UNICODE version of these function, has not been implemented yet.
long RemoteAdmTerminateNotifW (wchar_t * szComputerName,
unsigned long ulConnectionID)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteAdmValidateNotifW (wchar_t * szComputerName,
unsigned long ulNotifMask,
unsigned long * pulConnectionID)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteAdmCreateMailboxW (ADM_MAILBOX_INFO_W * pMailboxInfo)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteAdmGetMailboxPropsW (unsigned long dwObjID,
unsigned long * pdwUserType,
ADM_MAILBOX_INFO_W * pMailboxInfo)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteAdmSetMailboxPropsW (ADM_MAILBOX_INFO_W * pMailboxInfo)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteAdmCreateDistListW (wchar_t * szDLAlias,
wchar_t * szDLFullName,
unsigned long dwFlags,
wchar_t * szOwnerAlias,
wchar_t * szOwnerName,
unsigned long dwOwnerID,
DLM_XMIT_LIST_W * pMembers)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteAdmGetDLPropsW (unsigned long dwObjID,
wchar_t * szDLAlias,
wchar_t * szDLFullName,
unsigned long * pdwFlags,
wchar_t * szOwnerAlias,
wchar_t * szOwnerName,
unsigned long * pdwOwnerID,
wchar_t * szComments,
DLM_XMIT_LIST_W * pMembers)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteAdmSetDLPropsW (unsigned long dwObjID,
wchar_t * szDLAlias,
wchar_t * szDLFullName,
unsigned long dwFlags,
wchar_t * szOwnerAlias,
wchar_t * szOwnerName,
unsigned long dwOwnerID,
wchar_t * szComments,
DLM_XMIT_LIST_W * pMembers)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
// End of file for RADMRPC.CPP