Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

556 lines
14 KiB

//****************************************************************************
//
// Module: ULS.DLL
// File: cserver.cpp
// Content: This file contains the ULS server object.
// History:
// Wed 17-Apr-1996 11:13:54 -by- Viroon Touranachun [viroont]
//
// Copyright (c) Microsoft Corporation 1996-1997
//
//****************************************************************************
#include "ulsp.h"
#include "culs.h"
#include "localusr.h"
#include "attribs.h"
#include "localprt.h"
#include "callback.h"
//****************************************************************************
// ILS_STATE
// CIlsUser::GetULSState(VOID)
//
// History:
// Wed 17-Apr-1996 11:14:08 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
ILS_STATE CIlsUser::
GetULSState ( VOID )
{
ILS_STATE uULSState;
switch(m_uState)
{
case ULSSVR_INVALID:
case ULSSVR_INIT:
uULSState = ILS_UNREGISTERED;
break;
case ULSSVR_REG_USER:
case ULSSVR_REG_PROT:
uULSState = ILS_REGISTERING;
break;
case ULSSVR_CONNECT:
uULSState = ILS_REGISTERED;
break;
case ULSSVR_UNREG_PROT:
case ULSSVR_UNREG_USER:
uULSState = ILS_UNREGISTERING;
break;
case ULSSVR_RELOGON:
uULSState = ILS_REGISTERED_BUT_INVALID;
break;
case ULSSVR_NETWORK_DOWN:
uULSState = ILS_NETWORK_DOWN;
break;
default:
ASSERT(0);
uULSState = ILS_UNREGISTERED;
break;
};
return uULSState;
}
//****************************************************************************
// void
// CIlsUser::NotifyULSRegister(HRESULT hr)
//
// History:
// Wed 17-Apr-1996 11:14:08 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
void
CIlsUser::NotifyULSRegister(HRESULT hr)
{
g_pCIls->LocalAsyncRespond(WM_ILS_LOCAL_REGISTER, m_uReqID, hr);
m_uReqID = 0;
return;
}
//****************************************************************************
// void
// CIlsUser::NotifyULSUnregister(HRESULT hr)
//
// History:
// Wed 17-Apr-1996 11:14:08 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
void
CIlsUser::NotifyULSUnregister(HRESULT hr)
{
g_pCIls->LocalAsyncRespond(WM_ILS_LOCAL_UNREGISTER, m_uReqID, hr);
m_uReqID = 0;
return;
}
//****************************************************************************
// STDMETHODIMP
// CIlsUser::AddPendingRequest(ULONG uReqType, ULONG uMsgID)
//
// History:
// Wed 17-Apr-1996 11:14:08 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
HRESULT CIlsUser::
AddPendingRequest(ULONG uReqType, ULONG uMsgID)
{
// Add the request to the queue
//
COM_REQ_INFO ri;
ReqInfo_Init (&ri);
ri.uReqType = uReqType;
ri.uMsgID = uMsgID;
ReqInfo_SetUser (&ri, this);
HRESULT hr = g_pReqMgr->NewRequest(&ri);
if (SUCCEEDED(hr))
{
// Make sure the objects do not disappear before we get the response
//
this->AddRef();
// Remember the last request
//
m_uLastMsgID = uMsgID;
}
return hr;
}
//****************************************************************************
// STDMETHODIMP
// CIlsUser::Register (CIlsUser *pUser, CLocalApp *pApp, ULONG uReqID)
//
// History:
// Wed 17-Apr-1996 11:14:08 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
HRESULT CIlsUser::
InternalRegister ( ULONG uReqID )
{
LDAP_ASYNCINFO lai;
PLDAP_CLIENTINFO pui;
HANDLE hUser;
HRESULT hr;
ASSERT(uReqID != 0);
// Validate the proper state
//
if (m_uState != ULSSVR_INIT)
return ILS_E_FAIL;
// Get the protocol enumerator
//
hr = EnumLocalProtocols(&m_pep);
if (SUCCEEDED(hr))
{
// Remember the request ID
//
m_uReqID = uReqID;
// Start the registration state machine
//
hr = InternalRegisterNext (NOERROR);
};
return hr;
}
//****************************************************************************
// STDMETHODIMP
// CIlsUser::InternalRegisterNext (HRESULT hr)
//
// History:
// Wed 17-Apr-1996 11:14:08 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
HRESULT CIlsUser::
InternalRegisterNext (HRESULT hr)
{
// lonchanc:
// I need to change Viroon's logic here.
// We should simply send out a bunch of requests and
// wait for all of them to come back, rather than
// doing a state machine stuff!!!
LDAP_ASYNCINFO lai;
ULONG uReqType;
// Clean up last request
//
m_uLastMsgID = 0;
if (SUCCEEDED(hr))
{
switch (m_uState)
{
case ULSSVR_INIT:
{
PLDAP_CLIENTINFO pui;
HANDLE hUser;
// Snap-shot the user information now
//
hr = InternalGetUserInfo (TRUE, &pui, LU_MOD_ALL);
if (SUCCEEDED(hr))
{
// Register the user with the server
//
hr = ::UlsLdap_RegisterClient ( (DWORD_PTR) this,
m_pIlsServer->GetServerInfo (),
pui,
&hUser,
&lai);
if (SUCCEEDED(hr))
{
// We are registering the user
//
m_hLdapUser = hUser;
m_uState = ULSSVR_REG_USER;
uReqType = WM_ILS_REGISTER_CLIENT;
};
::MemFree (pui);
};
break;
}
case ULSSVR_REG_USER:
m_uState = ULSSVR_REG_PROT;
//
// Fall through to start registering the protocol
//
case ULSSVR_REG_PROT:
{
IIlsProtocol *plp;
// Get the next protocol from the application
//
ASSERT (m_pep != NULL);
hr = m_pep->Next(1, &plp, NULL);
switch (hr)
{
case NOERROR:
{
ASSERT (plp != NULL);
hr = RegisterLocalProtocol(FALSE, (CLocalProt *)plp, &lai);
plp->Release (); // AddRef by m_pep->Next()
uReqType = WM_ILS_REGISTER_PROTOCOL;
break;
}
case S_FALSE:
{
// The last protocol is done. Cleanup enumerator
//
m_pep->Release();
m_pep = NULL;
// Change to connect state and notify the ULS object
// We are done. Get out of here.
//
hr = NOERROR;
m_uState = ULSSVR_CONNECT;
NotifyULSRegister(NOERROR);
return NOERROR;
}
default:
{
// Fail the enumeration, bail out
//
break;
}
};
break;
}
default:
ASSERT(0);
break;
};
};
if (SUCCEEDED(hr))
{
// Add a pending request to handle the response
//
hr = AddPendingRequest(uReqType, lai.uMsgID);
};
if (FAILED(hr))
{
// Oops ! the server failed us. Clean up the registration
//
InternalCleanupRegistration (TRUE);
// Notify the ULS object for the failure
//
NotifyULSRegister(hr);
};
return NOERROR;
}
//****************************************************************************
// STDMETHODIMP
// CIlsUser::CleanupRegistration (void)
//
// History:
// Wed 17-Apr-1996 11:14:08 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
HRESULT
CIlsUser::InternalCleanupRegistration ( BOOL fKeepProtList )
{
LDAP_ASYNCINFO lai;
// Note: This is a fast cleanup. The idea is to unregister everything being
// registered so far without waiting for the unregister result.
//
// Unregister each registered protocol
//
CLocalProt *plp = NULL;
HANDLE hEnum = NULL;
m_ProtList.Enumerate(&hEnum);
if (fKeepProtList)
{
while (m_ProtList.Next (&hEnum, (VOID **) &plp) == NOERROR)
{
ASSERT (plp != NULL);
::UlsLdap_VirtualUnRegisterProtocol(plp->GetProviderHandle());
plp->SetProviderHandle (NULL);
}
}
else
{
while(m_ProtList.Next (&hEnum, (VOID **) &plp) == NOERROR)
{
ASSERT (plp != NULL);
::UlsLdap_UnRegisterProtocol (plp->GetProviderHandle (), &lai);
plp->Release();
}
m_ProtList.Flush ();
}
//
// Unregister user
//
if (m_hLdapUser != NULL)
{
::UlsLdap_UnRegisterClient (m_hLdapUser, &lai);
m_hLdapUser = NULL;
};
// Release all the resource
//
if (m_pep != NULL)
{
m_pep->Release();
m_pep = NULL;
};
// Unwind the object to the initialize state
//
m_uState = ULSSVR_INIT;
return NOERROR;
}
//****************************************************************************
// STDMETHODIMP
// CIlsUser::Unregister (ULONG uReqID)
//
// History:
// Wed 17-Apr-1996 11:14:08 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
HRESULT
CIlsUser::InternalUnregister (ULONG uReqID)
{
HRESULT hr;
ASSERT(uReqID != 0);
// Remove the last request, if any
//
if (m_uLastMsgID != 0)
{
COM_REQ_INFO ri;
ReqInfo_Init (&ri);
// Look for the matching request information
//
ri.uReqID = 0;
ri.uMsgID = m_uLastMsgID;
g_pReqMgr->RequestDone(&ri);
};
// If this is to cancel the current registration, we need to cancel the
// registration then start unregistration.
//
if (m_uReqID != 0)
{
NotifyULSRegister(ILS_E_ABORT);
};
// Determine the starting state
//
hr = NOERROR;
switch (m_uState)
{
case ULSSVR_RELOGON:
case ULSSVR_NETWORK_DOWN:
case ULSSVR_CONNECT:
case ULSSVR_REG_PROT:
//
// In the middle of registering a protocol or an app
// Unregistering the protocol then the app
//
m_uState = ULSSVR_UNREG_PROT;
break;
case ULSSVR_REG_USER:
//
// In the middle of registering the user
// Unregistering the user
//
m_uState = ULSSVR_UNREG_USER;
break;
default:
hr = ILS_E_FAIL;
break;
}
// The initial request succeeds, remember the request ID
//
if (SUCCEEDED(hr))
{
// lonchanc: [11/15/96]
// To fix the "OnLocalRegisterResult: No pending request for 0" problem,
// we have to put uReqID because UnregisterNext() will use uReqID when
// it fails to unregister app/user.
//
m_uReqID = uReqID;
hr = InternalUnregisterNext(hr);
#if 0 // lonchanc: [11/15/96]
// See the comment above.
if (SUCCEEDED(hr))
{
m_uReqID = uReqID;
};
#endif
};
return hr;
}
//****************************************************************************
// STDMETHODIMP
// CIlsUser::InternalUnregisterNext (HRESULT hr)
//
// History:
// Wed 17-Apr-1996 11:14:08 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
HRESULT
CIlsUser::InternalUnregisterNext (HRESULT hr)
{
LDAP_ASYNCINFO lai;
ULONG uReqType;
// Clean up last request
//
m_uLastMsgID = 0;
do
{
switch (m_uState)
{
case ULSSVR_UNREG_PROT:
{
// Is there another protocol?
//
CLocalProt *plp = NULL;
HANDLE hEnum = NULL;
m_ProtList.Enumerate(&hEnum);
while (m_ProtList.Next(&hEnum, (VOID **)&plp) == S_OK)
{
// Do not need to unregister protocols because
// UnregisterUser will delete the entire entry.
//
::UlsLdap_VirtualUnRegisterProtocol (plp->GetProviderHandle());
// Another protocol to clean up
//
plp->SetProviderHandle (NULL);
// Do not need to plp->Release() (cf. AddRef by RegisterLocalProtocol)
// because the user object still contain all the protocol objects
//
}
// Unregister the user
//
m_uState = ULSSVR_UNREG_USER;
hr = ::UlsLdap_UnRegisterClient (m_hLdapUser, &lai);
uReqType = WM_ILS_UNREGISTER_CLIENT;
m_hLdapUser = NULL;
break;
}
case ULSSVR_UNREG_USER:
//
// Put the object back into the init state
//
InternalCleanupRegistration(TRUE);
NotifyULSUnregister(NOERROR);
return NOERROR;
default:
ASSERT(0);
return NOERROR;
};
}
while (FAILED(hr)); // Unregistration failed, nohing to wait for
if (SUCCEEDED(hr))
{
AddPendingRequest(uReqType, lai.uMsgID);
};
return hr;
}