|
|
/*++
Copyright (c) 1994-95 Microsoft Corporation
Module Name:
appobj.cpp
Abstract:
OLE-createable application object implementation.
Author:
Don Ryan (donryan) 27-Dec-1994
Environment:
User Mode - Win32
Revision History:
Jeff Parham (jeffparh) 16-Jan-1996 Added Get/SetLastTargetServer() to help isolate server connection problems. (Bug #2993.)
--*/
#include "stdafx.h"
#include "llsmgr.h"
#include "lmerr.h"
#include "lmcons.h"
#include "lmwksta.h"
#include "lmapibuf.h"
#include "lmserver.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__; #endif
IMPLEMENT_DYNCREATE(CApplication, CCmdTarget) // IMPLEMENT_OLECREATE(CApplication, "Llsmgr.Application.1", 0x2c5dffb3, 0x472f, 0x11ce, 0xa0, 0x30, 0x0, 0xaa, 0x0, 0x33, 0x9a, 0x98)
BEGIN_MESSAGE_MAP(CApplication, CCmdTarget) //{{AFX_MSG_MAP(CApplication)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_DISPATCH_MAP(CApplication, CCmdTarget) //{{AFX_DISPATCH_MAP(CApplication)
DISP_PROPERTY_EX(CApplication, "Application", GetApplication, SetNotSupported, VT_DISPATCH) DISP_PROPERTY_EX(CApplication, "FullName", GetFullName, SetNotSupported, VT_BSTR) DISP_PROPERTY_EX(CApplication, "Name", GetName, SetNotSupported, VT_BSTR) DISP_PROPERTY_EX(CApplication, "Parent", GetParent, SetNotSupported, VT_DISPATCH) DISP_PROPERTY_EX(CApplication, "Visible", GetVisible, SetNotSupported, VT_BOOL) DISP_PROPERTY_EX(CApplication, "ActiveController", GetActiveController, SetNotSupported, VT_DISPATCH) DISP_PROPERTY_EX(CApplication, "ActiveDomain", GetActiveDomain, SetNotSupported, VT_DISPATCH) DISP_PROPERTY_EX(CApplication, "LocalDomain", GetLocalDomain, SetNotSupported, VT_DISPATCH) DISP_PROPERTY_EX(CApplication, "IsFocusDomain", IsFocusDomain, SetNotSupported, VT_BOOL) DISP_PROPERTY_EX(CApplication, "LastErrorString", GetLastErrorString, SetNotSupported, VT_BSTR) DISP_FUNCTION(CApplication, "Quit", Quit, VT_EMPTY, VTS_NONE) DISP_FUNCTION(CApplication, "SelectDomain", SelectDomain, VT_BOOL, VTS_VARIANT) DISP_FUNCTION(CApplication, "SelectEnterprise", SelectEnterprise, VT_BOOL, VTS_NONE) DISP_PROPERTY_PARAM(CApplication, "Domains", GetDomains, SetNotSupported, VT_DISPATCH, VTS_VARIANT) DISP_DEFVALUE(CApplication, "Name") //}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
CApplication::CApplication()
/*++
Routine Description:
Constructor for OLE-createable application object.
To keep the application running as long as an OLE automation object is active, we must call AfxOleLockApp.
Arguments:
None.
Return Values:
None.
--*/
{ EnableAutomation();
ASSERT(theApp.m_pApplication == NULL);
if (theApp.m_pApplication == NULL) theApp.m_pApplication = this;
if (theApp.m_bIsAutomated) AfxOleLockApp();
m_pDomains = NULL; m_pLocalDomain = NULL; m_pActiveDomain = NULL; m_bIsFocusDomain = FALSE; m_bDomainsRefreshed = FALSE;
m_strLastTargetServer = TEXT("");
m_domainArray.RemoveAll();
m_pActiveController = new CController; m_idStatus = m_pActiveController ? STATUS_SUCCESS : STATUS_NO_MEMORY; }
CApplication::~CApplication()
/*++
Routine Description:
Destructor for OLE-createable application object.
Arguments:
None.
Return Values:
None.
--*/
{ ASSERT(theApp.m_pApplication == this);
if (theApp.m_pApplication == this) theApp.m_pApplication = NULL;
if (theApp.m_bIsAutomated) AfxOleUnlockApp();
if (m_pDomains) m_pDomains->InternalRelease();
if (m_pLocalDomain) m_pLocalDomain->InternalRelease();
if (m_pActiveDomain) m_pActiveDomain->InternalRelease();
if (m_pActiveController) m_pActiveController->InternalRelease(); }
void CApplication::OnFinalRelease()
/*++
Routine Description:
When the last reference for an automation object is released OnFinalRelease is called. This implementation deletes object.
Arguments:
None.
Return Values:
None.
--*/
{ ResetDomains(); delete this; }
LPDISPATCH CApplication::GetActiveController()
/*++
Routine Description:
Returns the active license controller object.
Arguments:
None.
Return Values:
VT_DISPATCH or VT_EMPTY.
--*/
{ ASSERT_VALID(m_pActiveController); return m_pActiveController->GetIDispatch(TRUE); }
LPDISPATCH CApplication::GetActiveDomain()
/*++
Routine Description:
Returns the active domain object.
Arguments:
None.
Return Values:
VT_DISPATCH or VT_EMPTY.
--*/
{ return m_pActiveDomain ? m_pActiveDomain->GetIDispatch(TRUE) : NULL; }
LPDISPATCH CApplication::GetApplication()
/*++
Routine Description:
Returns the application object.
Arguments:
None.
Return Values:
VT_DISPATCH.
--*/
{ return GetIDispatch(TRUE); }
LPDISPATCH CApplication::GetDomains(const VARIANT FAR& index)
/*++
Routine Description:
Returns a collection object containing all of the domains visible to the local machine or returns an individual domain described by an index into the collection.
Arguments:
index - optional argument that may be a string (VT_BSTR) indicating a domain name or a number (VT_I4) indicating the position within collection.
Return Values:
VT_DISPATCH or VT_EMPTY.
--*/
{ LPDISPATCH lpdispatch = NULL;
if (!m_pDomains) { m_pDomains = new CDomains(this, &m_domainArray); }
if (m_pDomains) { if (V_ISVOID((VARIANT FAR*)&index)) { if (RefreshDomains()) { lpdispatch = m_pDomains->GetIDispatch(TRUE); } } else { if (m_bDomainsRefreshed) { lpdispatch = m_pDomains->GetItem(index); } else if (RefreshDomains()) { lpdispatch = m_pDomains->GetItem(index); } } } else { SetLastStatus(STATUS_NO_MEMORY); }
return lpdispatch; }
BSTR CApplication::GetFullName()
/*++
Routine Description:
Returns the file specification for the application, including path.
Arguments:
None.
Return Values:
VT_BSTR.
--*/
{ TCHAR szModuleFileName[MAX_PATH+1] = {0}; DWORD cch; BSTR bstrFullName = NULL;
cch = GetModuleFileName(AfxGetApp()->m_hInstance, szModuleFileName, MAX_PATH); if (0 != cch && MAX_PATH != cch) { bstrFullName = SysAllocStringLen(szModuleFileName, lstrlen(szModuleFileName)); }
return bstrFullName; }
BSTR CApplication::GetLastErrorString()
/*++
Routine Description:
Retrieves string for last error.
(Routine stolen from winsadmn...).
Arguments:
None.
Return Values:
VT_BSTR.
--*/
{ CString strLastError; DWORD nId = m_idStatus;
if (((long)nId == RPC_S_CALL_FAILED) || ((long)nId == RPC_NT_SS_CONTEXT_MISMATCH)) { strLastError.LoadString(IDP_ERROR_DROPPED_LINK); } else if (((long)nId == RPC_S_SERVER_UNAVAILABLE) || ((long)nId == RPC_NT_SERVER_UNAVAILABLE)) { strLastError.LoadString(IDP_ERROR_NO_RPC_SERVER); } else if ((long)nId == STATUS_MEMBER_IN_GROUP) { strLastError.LoadString(IDP_ERROR_MEMBER_IN_GROUP); } else { HINSTANCE hinstDll = NULL;
if ((nId >= NERR_BASE) && (nId <= MAX_NERR)) { hinstDll = ::LoadLibrary(_T("netmsg.dll")); } else if (nId >= 0x4000000) { hinstDll = ::LoadLibrary(_T("ntdll.dll")); }
TCHAR szLastError[1024]; DWORD cchLastError = sizeof(szLastError) / sizeof(TCHAR);
DWORD dwFlags = FORMAT_MESSAGE_IGNORE_INSERTS| FORMAT_MESSAGE_MAX_WIDTH_MASK| (hinstDll ? FORMAT_MESSAGE_FROM_HMODULE : FORMAT_MESSAGE_FROM_SYSTEM);
cchLastError = ::FormatMessage( dwFlags, hinstDll, nId, 0, szLastError, cchLastError, NULL );
if (hinstDll) { ::FreeLibrary(hinstDll); }
if (cchLastError) { strLastError = szLastError; } else { strLastError.LoadString(IDP_ERROR_UNSUCCESSFUL); } }
return strLastError.AllocSysString(); }
LPDISPATCH CApplication::GetLocalDomain()
/*++
Routine Description:
Returns the local domain object.
Arguments:
None.
Return Values:
VT_DISPATCH or VT_EMPTY.
--*/
{ if (!m_pLocalDomain) { NET_API_STATUS NetStatus; PWKSTA_INFO_100 pWkstaInfo100 = NULL;
NetStatus = NetWkstaGetInfo( NULL, 100, (LPBYTE*)&pWkstaInfo100 );
if (NetStatus == ERROR_SUCCESS) { m_pLocalDomain = new CDomain(this, pWkstaInfo100->wki100_langroup);
if (!m_pLocalDomain) { NetStatus = ERROR_NOT_ENOUGH_MEMORY; }
NetApiBufferFree(pWkstaInfo100); }
SetLastStatus(NetStatus); // called api
}
return m_pLocalDomain ? m_pLocalDomain->GetIDispatch(TRUE) : NULL; }
BSTR CApplication::GetName()
/*++
Routine Description:
Returns the name of the application.
Arguments:
None.
Return Values:
VT_BSTR.
--*/
{ CString AppName = AfxGetAppName(); return AppName.AllocSysString(); }
LPDISPATCH CApplication::GetParent()
/*++
Routine Description:
Returns the parent of the object.
Arguments:
None.
Return Values:
VT_DISPATCH.
--*/
{ return GetApplication(); }
BOOL CApplication::GetVisible()
/*++
Routine Description:
Returns whether or not the application is visible to the user.
Arguments:
None.
Return Values:
VT_BOOL.
--*/
{ return FALSE; }
BOOL CApplication::IsFocusDomain()
/*++
Routine Description:
Returns true if application focused on domain.
Arguments:
None.
Return Values:
VT_BOOL.
--*/
{ return m_bIsFocusDomain; }
BOOL CApplication::RefreshDomains()
/*++
Routine Description:
Refreshs domain object list.
Arguments:
None.
Return Values:
None.
--*/
{ ResetDomains();
NET_API_STATUS NetStatus; DWORD ResumeHandle = 0L;
int iDomain = 0;
do { DWORD EntriesRead; DWORD TotalEntries; LPBYTE ReturnBuffer = NULL;
NetStatus = NetServerEnum( NULL, // servername
100, // level
&ReturnBuffer, LLS_PREFERRED_LENGTH, &EntriesRead, &TotalEntries, SV_TYPE_DOMAIN_ENUM, NULL, // domain
&ResumeHandle );
if (NetStatus == ERROR_SUCCESS || NetStatus == ERROR_MORE_DATA) { CDomain* pDomain; PSERVER_INFO_100 pServerInfo100;
pServerInfo100 = (PSERVER_INFO_100)ReturnBuffer;
ASSERT(iDomain == m_domainArray.GetSize()); m_domainArray.SetSize(m_domainArray.GetSize() + EntriesRead);
while (EntriesRead--) { pDomain = new CDomain(this, pServerInfo100->sv100_name);
m_domainArray.SetAt(iDomain++, pDomain); // validate later
pServerInfo100++; }
NetApiBufferFree(ReturnBuffer); }
} while (NetStatus == ERROR_MORE_DATA);
SetLastStatus(NetStatus); // called api
if (NetStatus == ERROR_SUCCESS) { m_bDomainsRefreshed = TRUE; } else { ResetDomains(); }
return m_bDomainsRefreshed; }
void CApplication::ResetDomains()
/*++
Routine Description:
Resets domain object list.
Arguments:
None.
Return Values:
None.
--*/
{ CDomain* pDomain; INT_PTR iDomain = m_domainArray.GetSize();
while (iDomain--) { pDomain = (CDomain*)m_domainArray[iDomain]; if (NULL != pDomain) { ASSERT(pDomain->IsKindOf(RUNTIME_CLASS(CDomain))); pDomain->InternalRelease(); } }
m_domainArray.RemoveAll(); m_bDomainsRefreshed = FALSE; }
BOOL CApplication::SelectDomain(const VARIANT FAR& domain)
/*++
Routine Description:
Connects to license controller of specified domain.
Arguments:
domain - name of domain.
Return Values:
VT_BOOL.
--*/
{ BOOL bIsSelected = FALSE;
ASSERT_VALID(m_pActiveController);
bIsSelected = m_pActiveController->Connect(domain); if (FALSE != bIsSelected) { LPTSTR pszActiveDomain = MKSTR(m_pActiveController->m_strActiveDomainName);
if (m_pActiveDomain) { m_pActiveDomain->InternalRelease(); m_pActiveDomain = NULL; }
if (pszActiveDomain && *pszActiveDomain) { m_pActiveDomain = new CDomain(this, pszActiveDomain);
if (m_pActiveDomain) { m_bIsFocusDomain = TRUE; } else { m_bIsFocusDomain = FALSE; // invalidate m_pActiveDomain
SetLastStatus(STATUS_NO_MEMORY); } } else { m_bIsFocusDomain = FALSE; // invalidate m_pActiveDomain
} }
return bIsSelected; }
BOOL CApplication::SelectEnterprise()
/*++
Routine Description:
Connects to license controller of enterprise.
Arguments:
None.
Return Values:
VT_BOOL.
--*/
{ BOOL bIsSelected = FALSE;
VARIANT va; VariantInit(&va); // connect to default controller
bIsSelected = m_pActiveController->Connect(va); if (FALSE != bIsSelected) { if (m_pActiveDomain) { m_pActiveDomain->InternalRelease(); m_pActiveDomain = NULL; }
m_bIsFocusDomain = FALSE; }
return bIsSelected; }
void CApplication::Quit()
/*++
Routine Description:
Closes all documents and exits the application.
Arguments:
None.
Return Values:
None.
--*/
{ AfxPostQuitMessage(0); // no main window...
}
BSTR CApplication::GetLastTargetServer()
/*++
Routine Description:
Retrieves string for last server to which we tried to connect.
Arguments:
None.
Return Values:
VT_BSTR.
--*/
{ if ( m_strLastTargetServer.IsEmpty() ) return NULL; else return m_strLastTargetServer.AllocSysString(); }
void CApplication::SetLastTargetServer( LPCTSTR pszServerName )
/*++
Routine Description:
Sets string for last server to which we tried to connect.
Arguments:
pszServerName - last server name to which we tried to connect.
Return Values:
None.
--*/
{ m_strLastTargetServer = pszServerName; }
|