556 lines
14 KiB
C++
556 lines
14 KiB
C++
//****************************************************************************
|
||
//
|
||
// 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;
|
||
}
|
||
|
||
|