NOTIFY.CPP

/////////////////////////////////////////////////////////////////////////////// 
//
// File Name
// NOTIFY.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

typedef struct _WINDS_NOTIF_CLIENT
{
struct _WINDS_NOTIF_CLIENT * pNext;
TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
TCHAR szObjectName[MAX_ALIAS_SIZE+1];
DWORD dwFlags;
DWORD dwNotifMask;
} WINDS_NOTIF_CLIENT, *PWINDS_NOTIF_CLIENT;

PWINDS_NOTIF_CLIENT gpNotifLinks = NULL;

///////////////////////////////////////////////////////////////////////////////
// RemoteLogonMailBoxAndSetNotifA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteLogonMailBoxAndSetNotifA (unsigned char * szMailbox,
unsigned char * szPassword,
unsigned char * szFullName,
unsigned long * pdwMailboxID,
unsigned char * szComputerName,
unsigned long ulNotifMask,
unsigned long * pulConnectionID)
{
long lResult = RemoteLogonMailBoxA (szMailbox, szPassword, szFullName, pdwMailboxID);
if (lResult)
{
return lResult;
}
RemoteValidateNotifA (szComputerName, szMailbox, ulNotifMask, pulConnectionID);
return S_OK;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteValidateNotifA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteValidateNotifA (unsigned char * szComputerName,
unsigned char * szMailbox,
unsigned long ulNotifMask,
unsigned long * pulConnectionID)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}
PWINDS_NOTIF_CLIENT pNode, pNewNode = (PWINDS_NOTIF_CLIENT)HeapAlloc (ghHeap,
HEAP_ZERO_MEMORY,
sizeof(WINDS_NOTIF_CLIENT));
if (pNewNode)
{
pNewNode->dwNotifMask = ulNotifMask;
lstrcpy (pNewNode->szComputerName, (LPSTR)szComputerName);
lstrcpy (pNewNode->szObjectName, (LPSTR)szMailbox);

EnterCriticalSection (&g_csNotifLinks);
if (gpNotifLinks)
{
pNode = gpNotifLinks;
while (pNode)
{
if (NULL == pNode->pNext)
{
pNode->pNext = pNewNode;
break; // Out of the WHILE() loop
}
pNode = pNode->pNext;
}
}
else
{
gpNotifLinks = pNewNode;
}
LeaveCriticalSection (&g_csNotifLinks);

*pulConnectionID = (unsigned long)pNewNode;
}
TraceMessageIf ("RemoteValidateNotifA: Failed to allocated new node", 0 == *pulConnectionID);
return S_OK;
}

///////////////////////////////////////////////////////////////////////////////
// RemoteTerminateNotifA()
//
// Parameters
//
// Purpose
//
// Return Value
//
long RemoteTerminateNotifA (unsigned char * szComputerName,
unsigned long ulConnectionID)
{
long lResult = GetServiceState();
if (lResult)
{
return lResult;
}

long cbSize = lstrlen ((LPSTR)szComputerName);
EnterCriticalSection (&g_csNotifLinks);
PWINDS_NOTIF_CLIENT pNext, pPrev = NULL, pNode = gpNotifLinks;
while (pNode)
{
if (ulConnectionID == (unsigned long)pNode && (0 == memcmp (pNode->szComputerName, szComputerName, cbSize)))
{
// If the node is the head of the list, make the head point to the next node
if (gpNotifLinks == pNode)
{
gpNotifLinks = gpNotifLinks->pNext;
}
// Save the next pointer so that we may delete the current node
pNext = pNode->pNext;
HeapFree (ghHeap, 0, pNode);
// If we have a previous node, we are doing a delete in the middle of a single link list
if (pPrev)
{
pPrev->pNext = pNext;
}
break; // Out of the WHILE() loop
}
else
{
// Don't delete this node, save is as the "previous" node in the linear list
pPrev = pNode;
pNode = pNode->pNext;
}
}
LeaveCriticalSection (&g_csNotifLinks);
return S_OK;
}

///////////////////////////////////////////////////////////////////////////////
// RemoveAllNotifLinks()
//
// Parameters
//
// Purpose
//
// Return Value
// None.
//
void WINAPI RemoveAllNotifLinks()
{
EnterCriticalSection (&g_csNotifLinks);
PWINDS_NOTIF_CLIENT pNode = gpNotifLinks;
while (gpNotifLinks)
{
pNode = gpNotifLinks->pNext;
HeapFree (ghHeap, 0, gpNotifLinks);
gpNotifLinks = pNode;
}
gpNotifLinks = NULL;
LeaveCriticalSection (&g_csNotifLinks);
}

///////////////////////////////////////////////////////////////////////////////
// NotifyClients()
//
// Parameters
//
// Purpose
//
// Return Value
// None.
//
void WINAPI NotifyClients (PWINDS_NOTIFICATION pNotif)
{
DWORD dwThreadID;
HANDLE hThread = CreateThread (NULL,
0,
(LPTHREAD_START_ROUTINE)ClientNotifThreadProc,
(LPVOID)pNotif,
CREATE_SUSPENDED,
&dwThreadID);
if (hThread)
{
TraceDebugger ("NotifyClients: Notif dispatcher thread spawned. ID: %X", dwThreadID);
ResumeThread (hThread);
CloseHandle (hThread);
}
else
{
TraceResult ("NotifyClients: Failed to create notification dispatching thread", HRESULT_FROM_WIN32(GetLastError()));
HeapFree (ghHeap, 0, pNotif);
}
}

///////////////////////////////////////////////////////////////////////////////
// ClientNotifThreadProc()
//
// Parameters
//
// Purpose
//
// Return Value
// None.
//
DWORD WINAPI ClientNotifThreadProc (PWINDS_NOTIFICATION pNotif)
{
TCHAR szTargetMailslot[MAX_PATH] = { 0 };
DWORD dwWritten, dwNotifEvent = 0;
HANDLE hClientMailSlot;
LPTSTR szMailSlotSink = NULL;

SYSTEMTIME st;
GetSystemTime (&st);
SystemTimeToFileTime (&st, &(pNotif->ftEventTime));

if (pNotif->Event >= AB_NOTIF_MIN && pNotif->Event <= AB_NOTIF_MAX)
{
dwNotifEvent = WINDS_NOTIF_ON_AB | WINDS_NOTIF_ON_USER;
szMailSlotSink = AB_WINDS_NOTIFICATION_MAILSLOT;
}
else
{
if (pNotif->Event >= XP_NOTIF_MIN && pNotif->Event <= XP_NOTIF_MAX)
{
dwNotifEvent = WINDS_NOTIF_ON_XP;
szMailSlotSink = XP_WINDS_NOTIFICATION_MAILSLOT;
}
else
{
if (pNotif->Event >= MS_NOTIF_MIN && pNotif->Event <= MS_NOTIF_MAX)
{
dwNotifEvent = WINDS_NOTIF_ON_MS;
szMailSlotSink = MS_WINDS_NOTIFICATION_MAILSLOT;
}
else
{
if (pNotif->Event >= GENERAL_NOTIF_MIN && pNotif->Event <= GENERAL_NOTIF_MAX)
{
dwNotifEvent = WINDS_NOTIF_ON_USER;
}
}
}
}

EnterCriticalSection (&g_csNotifLinks);
PWINDS_NOTIF_CLIENT pNode = gpNotifLinks;
while (pNode)
{
if (dwNotifEvent & pNode->dwNotifMask)
{
if (WINDS_NOTIF_ON_USER & dwNotifEvent)
{
if (WINDS_NOTIF_ON_AB & pNode->dwNotifMask)
{
szMailSlotSink = AB_WINDS_NOTIFICATION_MAILSLOT;
}
else
{
if (WINDS_NOTIF_ON_XP & pNode->dwNotifMask)
{
szMailSlotSink = XP_WINDS_NOTIFICATION_MAILSLOT;
}
else
{
szMailSlotSink = MS_WINDS_NOTIFICATION_MAILSLOT;
}
}
}
if (WINDS_NOTIF_ON_XP == dwNotifEvent && XP_NEW_MAIL_ARRIVED == pNotif->Event)
{
if (lstrcmpi (pNode->szObjectName, pNotif->Info.MB.szMailboxName))
{
goto NextNode;
}
}
if (WINDS_ADMINISTRATOR & pNode->dwNotifMask)
{
szMailSlotSink = ADMIN_WINDS_NOTIFICATION_MAILSLOT;
}
wsprintf (szTargetMailslot,
SERVER_MAILSLOT_SINK_NAME_FORMAT,
pNode->szComputerName,
szMailSlotSink,
pNode); // the connection number is the pointer address in the server side (this is unique within a given process)

hClientMailSlot = CreateFile (szTargetMailslot,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hClientMailSlot)
{
TraceResult ("ClientNotifThreadProc: Failed to open client mailslot", HRESULT_FROM_WIN32(GetLastError()));
}
else
{
if (!WriteFile (hClientMailSlot, pNotif, sizeof(WINDS_NOTIFICATION), &dwWritten, NULL))
{
TraceResult ("ClientNotifThreadProc: Failed to write to the client mailslot", HRESULT_FROM_WIN32(GetLastError()));
}
CloseHandle (hClientMailSlot);
}
}
NextNode:
pNode = pNode->pNext;
}

#define CLIENTS_NOTIF_CACHE_FILE TEXT("WINDS Service - Last Session Clients.WINDS")
if (SERVER_IS_SHUTTING_DOWN == pNotif->Event && gpNotifLinks)
{
DWORD dwBytesWritten;
WINDS_NOTIF_CLIENT tmpNode;
HANDLE hFile = CreateFile (CLIENTS_NOTIF_CACHE_FILE,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
TraceResult ("ClientNotifThreadProc: Failed to create clients cache file", HRESULT_FROM_WIN32(GetLastError()));
}
else
{
pNode = gpNotifLinks;
while (pNode)
{
tmpNode = *pNode;
tmpNode.pNext = pNode;
// This is so that the node address gets written to the disk. This is the
// connection number and the name of the mailslot in the client side.
WriteFile (hFile, &tmpNode, sizeof(WINDS_NOTIF_CLIENT), &dwBytesWritten, NULL);
pNode = pNode->pNext;
}
}
}
if (SERVER_HAS_RESTARTED == pNotif->Event)
{
DWORD dwBytesRead;
WINDS_NOTIF_CLIENT tmpNode = { 0 };
HANDLE hFile = CreateFile (CLIENTS_NOTIF_CACHE_FILE,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
do
{
if (TRUE == ReadFile (hFile, &tmpNode, sizeof(WINDS_NOTIF_CLIENT), &dwBytesRead, NULL))
{
if (WINDS_NOTIF_ON_AB & tmpNode.dwNotifMask)
{
szMailSlotSink = AB_WINDS_NOTIFICATION_MAILSLOT;
}
else
{
if (WINDS_NOTIF_ON_XP & tmpNode.dwNotifMask)
{
szMailSlotSink = XP_WINDS_NOTIFICATION_MAILSLOT;
}
else
{
szMailSlotSink = MS_WINDS_NOTIFICATION_MAILSLOT;
}
}
if (WINDS_ADMINISTRATOR & tmpNode.dwNotifMask)
{
szMailSlotSink = ADMIN_WINDS_NOTIFICATION_MAILSLOT;
}
wsprintf (szTargetMailslot,
SERVER_MAILSLOT_SINK_NAME_FORMAT,
tmpNode.szComputerName,
szMailSlotSink,
tmpNode.pNext); // The connection number is the pointer address in the server side (this is unique within a process address space)
hClientMailSlot = CreateFile (szTargetMailslot,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hClientMailSlot)
{
pNotif->Event = SERVER_HAS_RESTARTED;
pNotif->ftEventTime.dwLowDateTime++;
pNotif->ftEventTime.dwHighDateTime++;
WriteFile (hClientMailSlot, pNotif, sizeof(WINDS_NOTIFICATION), &dwWritten, NULL);
pNotif->Event = RESET_LINKS_WITH_SERVER;
pNotif->ftEventTime.dwLowDateTime++;
pNotif->ftEventTime.dwHighDateTime++;
WriteFile (hClientMailSlot, pNotif, sizeof(WINDS_NOTIFICATION), &dwWritten, NULL);
CloseHandle (hClientMailSlot);
}
}
} while (dwBytesRead);
CloseHandle (hFile);
}
}

LeaveCriticalSection (&g_csNotifLinks);
HeapFree (ghHeap, 0, pNotif);
return S_OK;
}

// End of file for NOTIFY.CPP