Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1190 lines
23 KiB

/*++
Copyright (c) 1994-95 Microsoft Corporation
Module Name:
ctlobj.cpp
Abstract:
License controller object implementation.
Author:
Don Ryan (donryan) 27-Dec-1994
Environment:
User Mode - Win32
Revision History:
Jeff Parham (jeffparh) 16-Jan-1996
Added SetLastTargetServer() to Connect() to help isolate server
connection problems. (Bug #2993.)
--*/
#include "stdafx.h"
#include "llsmgr.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CController, CCmdTarget)
BEGIN_MESSAGE_MAP(CController, CCmdTarget)
//{{AFX_MSG_MAP(CController)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_DISPATCH_MAP(CController, CCmdTarget)
//{{AFX_DISPATCH_MAP(CController)
DISP_PROPERTY_EX(CController, "Name", GetName, SetNotSupported, VT_BSTR)
DISP_PROPERTY_EX(CController, "Application", GetApplication, SetNotSupported, VT_DISPATCH)
DISP_PROPERTY_EX(CController, "Parent", GetParent, SetNotSupported, VT_DISPATCH)
DISP_PROPERTY_EX(CController, "IsConnected", IsConnected, SetNotSupported, VT_BOOL)
DISP_FUNCTION(CController, "Connect", Connect, VT_BOOL, VTS_VARIANT)
DISP_FUNCTION(CController, "Disconnect", Disconnect, VT_EMPTY, VTS_NONE)
DISP_FUNCTION(CController, "Refresh", Refresh, VT_EMPTY, VTS_NONE)
DISP_PROPERTY_PARAM(CController, "Mappings", GetMappings, SetNotSupported, VT_DISPATCH, VTS_VARIANT)
DISP_PROPERTY_PARAM(CController, "Users", GetUsers, SetNotSupported, VT_DISPATCH, VTS_VARIANT)
DISP_PROPERTY_PARAM(CController, "Licenses", GetLicenses, SetNotSupported, VT_DISPATCH, VTS_VARIANT)
DISP_PROPERTY_PARAM(CController, "Products", GetProducts, SetNotSupported, VT_DISPATCH, VTS_VARIANT)
DISP_DEFVALUE(CController, "Name")
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
CController::CController()
/*++
Routine Description:
Constructor for license controller object.
Arguments:
None.
Return Values:
None.
--*/
{
EnableAutomation();
m_strName.Empty();
m_pProducts = NULL;
m_pUsers = NULL;
m_pMappings = NULL;
m_pLicenses = NULL;
m_llsHandle = NULL;
m_productArray.RemoveAll();
m_licenseArray.RemoveAll();
m_mappingArray.RemoveAll();
m_userArray.RemoveAll();
m_bProductsRefreshed = FALSE;
m_bLicensesRefreshed = FALSE;
m_bMappingsRefreshed = FALSE;
m_bUsersRefreshed = FALSE;
m_bIsConnected = FALSE;
}
CController::~CController()
/*++
Routine Description:
Destructor for license controller object.
Arguments:
None.
Return Values:
None.
--*/
{
Disconnect();
if (m_pProducts)
m_pProducts->InternalRelease();
if (m_pLicenses)
m_pLicenses->InternalRelease();
if (m_pMappings)
m_pMappings->InternalRelease();
if (m_pUsers)
m_pUsers->InternalRelease();
}
BOOL CController::Connect(const VARIANT FAR& start)
/*++
Routine Description:
Seek out license controller and establish connection.
Arguments:
start - either a server or domain to start searching for
the license controller from.
Return Values:
VT_BOOL.
--*/
{
VARIANT va;
VariantInit(&va);
LPTSTR pControllerName = NULL;
if (!V_ISVOID((VARIANT FAR*)&start))
{
if (start.vt == VT_BSTR)
{
pControllerName = start.bstrVal;
}
else if (SUCCEEDED(VariantChangeType(&va, (VARIANT FAR*)&start, 0, VT_BSTR)))
{
pControllerName = va.bstrVal;
}
else
{
LlsSetLastStatus(STATUS_INVALID_PARAMETER);
return FALSE;
}
}
NTSTATUS NtStatus;
LPVOID llsHandle = NULL;
PLLS_CONNECT_INFO_0 pConnectInfo0 = NULL;
NtStatus = ::LlsEnterpriseServerFind(
pControllerName,
0,
(LPBYTE*)&pConnectInfo0
);
if (NT_SUCCESS(NtStatus))
{
LlsSetLastTargetServer( pConnectInfo0->EnterpriseServer );
NtStatus = ::LlsConnect(
pConnectInfo0->EnterpriseServer,
&llsHandle
);
if (NT_SUCCESS(NtStatus))
{
Disconnect();
m_bIsConnected = TRUE;
m_llsHandle = llsHandle;
m_strName = pConnectInfo0->EnterpriseServer;
m_strActiveDomainName = pConnectInfo0->Domain;
m_strName.MakeUpper();
m_strActiveDomainName.MakeUpper();
}
::LlsFreeMemory(pConnectInfo0);
}
else
{
LlsSetLastTargetServer( TEXT( "" ) );
}
VariantClear(&va);
LlsSetLastStatus(NtStatus);
return NT_SUCCESS(NtStatus);
}
void CController::Disconnect()
/*++
Routine Description:
Closes connection to license controller.
Arguments:
None.
Return Values:
None.
--*/
{
if (m_bIsConnected)
{
LlsClose(m_llsHandle);
m_llsHandle = NULL;
m_bIsConnected = FALSE;
m_strName.Empty();
m_strActiveDomainName.Empty();
ResetLicenses();
ResetProducts();
ResetUsers();
ResetMappings();
}
}
BSTR CController::GetActiveDomainName()
/*++
Routine Description:
Returns the name of the active domain (internal).
Arguments:
None.
Return Values:
VT_BSTR.
--*/
{
return m_strActiveDomainName.AllocSysString();
}
LPDISPATCH CController::GetApplication()
/*++
Routine Description:
Returns the application object.
Arguments:
None.
Return Values:
VT_DISPATCH.
--*/
{
return theApp.GetAppIDispatch();
}
LPDISPATCH CController::GetLicenses(const VARIANT FAR& index)
/*++
Routine Description:
Returns a collection object containing all of the
license agreements recorded on the license controller
or returns an individual license agreement described by
an index into the collection.
Arguments:
index - optional argument that may be a number (VT_I4)
indicating the position within collection.
Return Values:
VT_DISPATCH or VT_EMPTY.
--*/
{
LPDISPATCH lpdispatch = NULL;
if (!m_pLicenses)
{
m_pLicenses = new CLicenses(this, &m_licenseArray);
}
if (m_pLicenses)
{
if (V_ISVOID((VARIANT FAR*)&index))
{
if (RefreshLicenses())
{
lpdispatch = m_pLicenses->GetIDispatch(TRUE);
}
}
else
{
if (m_bLicensesRefreshed)
{
lpdispatch = m_pLicenses->GetItem(index);
}
else if (RefreshLicenses())
{
lpdispatch = m_pLicenses->GetItem(index);
}
}
}
else
{
LlsSetLastStatus(ERROR_OUTOFMEMORY);
}
return lpdispatch;
}
LPDISPATCH CController::GetMappings(const VARIANT FAR& index)
/*++
Routine Description:
Returns a collection object containing all of the
user/node associations recorded on the license controller
or returns an individual user/node association described by
an index into the collection.
Arguments:
index - optional argument that may be a string (VT_BSTR)
indicating a mapping name or a number (VT_I4) indicating
the position within collection.
Return Values:
VT_DISPATCH or VT_EMPTY.
--*/
{
LPDISPATCH lpdispatch = NULL;
if (!m_pMappings)
{
m_pMappings = new CMappings(this, &m_mappingArray);
}
if (m_pMappings)
{
if (V_ISVOID((VARIANT FAR*)&index))
{
if (RefreshMappings())
{
lpdispatch = m_pMappings->GetIDispatch(TRUE);
}
}
else
{
if (m_bMappingsRefreshed)
{
lpdispatch = m_pMappings->GetItem(index);
}
else if (RefreshMappings())
{
lpdispatch = m_pMappings->GetItem(index);
}
}
}
else
{
LlsSetLastStatus(ERROR_OUTOFMEMORY);
}
return lpdispatch;
}
BSTR CController::GetName()
/*++
Routine Description:
Returns the name of the license controller.
Arguments:
None.
Return Values:
VT_BSTR.
--*/
{
return m_strName.AllocSysString();
}
LPDISPATCH CController::GetParent()
/*++
Routine Description:
Returns the parent of the object.
Arguments:
None.
Return Values:
VT_DISPATCH.
--*/
{
return GetApplication();
}
LPDISPATCH CController::GetProducts(const VARIANT FAR& index)
/*++
Routine Description:
Returns a collection object containing all of the
registered products replicated to the license controller
or returns an individual product described by an index
into the collection.
Arguments:
index - optional argument that may be a string (VT_BSTR)
indicating a product name or a number (VT_I4) indicating
the position within collection.
Return Values:
VT_DISPATCH or VT_EMPTY.
--*/
{
LPDISPATCH lpdispatch = NULL;
if (!m_pProducts)
{
m_pProducts = new CProducts(this, &m_productArray);
}
if (m_pProducts)
{
if (V_ISVOID((VARIANT FAR*)&index))
{
if (RefreshProducts())
{
lpdispatch = m_pProducts->GetIDispatch(TRUE);
}
}
else
{
if (m_bProductsRefreshed)
{
lpdispatch = m_pProducts->GetItem(index);
}
else if (RefreshProducts())
{
lpdispatch = m_pProducts->GetItem(index);
}
}
}
else
{
LlsSetLastStatus(ERROR_OUTOFMEMORY);
}
return lpdispatch;
}
LPDISPATCH CController::GetUsers(const VARIANT FAR& index)
/*++
Routine Description:
Returns a collection object containing all of the
registered users replicated to the license controller
or returns an individual user described by an index
into the collection.
Arguments:
index - optional argument that may be a string (VT_BSTR)
indicating a user name or a number (VT_I4) indicating the
position within collection.
Return Values:
VT_DISPATCH or VT_EMPTY.
--*/
{
LPDISPATCH lpdispatch = NULL;
if (!m_pUsers)
{
m_pUsers = new CUsers(this, &m_userArray);
}
if (m_pUsers)
{
if (V_ISVOID((VARIANT FAR*)&index))
{
if (RefreshUsers())
{
lpdispatch = m_pUsers->GetIDispatch(TRUE);
}
}
else
{
if (m_bUsersRefreshed)
{
lpdispatch = m_pUsers->GetItem(index);
}
else if (RefreshUsers())
{
lpdispatch = m_pUsers->GetItem(index);
}
}
}
else
{
LlsSetLastStatus(ERROR_OUTOFMEMORY);
}
return lpdispatch;
}
BOOL CController::IsConnected()
/*++
Routine Description:
Returns true if a connection has been established.
Arguments:
None.
Return Values:
VT_BOOL.
--*/
{
return m_bIsConnected;
}
void CController::Refresh()
/*++
Routine Description:
Retrieve latest data from license controller.
Arguments:
None.
Return Values:
None.
--*/
{
RefreshProducts();
RefreshUsers();
RefreshMappings();
RefreshLicenses();
}
BOOL CController::RefreshLicenses()
/*++
Routine Description:
Refreshs license object array.
Arguments:
None.
Return Values:
VT_BOOL.
--*/
{
ResetLicenses();
if (!m_bIsConnected)
return TRUE;
NTSTATUS NtStatus;
DWORD ResumeHandle = 0L;
int iLicense = 0;
do
{
DWORD EntriesRead;
DWORD TotalEntries;
LPBYTE ReturnBuffer = NULL;
NtStatus = ::LlsLicenseEnum(
m_llsHandle,
0,
&ReturnBuffer,
LLS_PREFERRED_LENGTH,
&EntriesRead,
&TotalEntries,
&ResumeHandle
);
if (NtStatus == STATUS_SUCCESS ||
NtStatus == STATUS_MORE_ENTRIES)
{
CLicense* pLicense;
PLLS_LICENSE_INFO_0 pLicenseInfo0;
pLicenseInfo0 = (PLLS_LICENSE_INFO_0)ReturnBuffer;
ASSERT(iLicense == m_licenseArray.GetSize());
m_licenseArray.SetSize(m_licenseArray.GetSize() + EntriesRead);
while (EntriesRead--)
{
pLicense = new CLicense(
this,
pLicenseInfo0->Product,
pLicenseInfo0->Admin,
pLicenseInfo0->Date,
pLicenseInfo0->Quantity,
pLicenseInfo0->Comment
);
m_licenseArray.SetAt(iLicense++, pLicense); // validate later...
#ifndef DISABLE_PER_NODE_ALLOCATION
::LlsFreeMemory(pLicenseInfo0->Product);
::LlsFreeMemory(pLicenseInfo0->Admin);
::LlsFreeMemory(pLicenseInfo0->Comment);
#endif // DISABLE_PER_NODE_ALLOCATION
pLicenseInfo0++;
}
::LlsFreeMemory(ReturnBuffer);
}
} while (NtStatus == STATUS_MORE_ENTRIES);
LlsSetLastStatus(NtStatus); // called api
if (NT_SUCCESS(NtStatus))
{
m_bLicensesRefreshed = TRUE;
}
else
{
ResetLicenses();
}
return m_bLicensesRefreshed;
}
BOOL CController::RefreshMappings()
/*++
Routine Description:
Refreshs mapping object array.
Arguments:
None.
Return Values:
None.
--*/
{
ResetMappings();
if (!m_bIsConnected)
return TRUE;
NTSTATUS NtStatus;
DWORD ResumeHandle = 0L;
int iMapping = 0;
do
{
DWORD EntriesRead;
DWORD TotalEntries;
LPBYTE ReturnBuffer = NULL;
NtStatus = ::LlsGroupEnum(
m_llsHandle,
1,
&ReturnBuffer,
LLS_PREFERRED_LENGTH,
&EntriesRead,
&TotalEntries,
&ResumeHandle
);
if (NtStatus == STATUS_SUCCESS ||
NtStatus == STATUS_MORE_ENTRIES)
{
CMapping* pMapping ;
PLLS_GROUP_INFO_1 pMappingInfo1;
pMappingInfo1 = (PLLS_GROUP_INFO_1)ReturnBuffer;
ASSERT(iMapping == m_mappingArray.GetSize());
m_mappingArray.SetSize(m_mappingArray.GetSize() + EntriesRead);
while (EntriesRead--)
{
pMapping = new CMapping(
this,
pMappingInfo1->Name,
pMappingInfo1->Licenses,
pMappingInfo1->Comment
);
m_mappingArray.SetAt(iMapping++, pMapping); // validate later...
#ifndef DISABLE_PER_NODE_ALLOCATION
::LlsFreeMemory(pMappingInfo1->Name);
::LlsFreeMemory(pMappingInfo1->Comment);
#endif // DISABLE_PER_NODE_ALLOCATION
pMappingInfo1++;
}
::LlsFreeMemory(ReturnBuffer);
}
} while (NtStatus == STATUS_MORE_ENTRIES);
LlsSetLastStatus(NtStatus); // called api
if (NT_SUCCESS(NtStatus))
{
m_bMappingsRefreshed = TRUE;
}
else
{
ResetMappings();
}
return m_bMappingsRefreshed;
}
BOOL CController::RefreshProducts()
/*++
Routine Description:
Refreshs product object array.
Arguments:
None.
Return Values:
None.
--*/
{
ResetProducts();
if (!m_bIsConnected)
return TRUE;
NTSTATUS NtStatus;
DWORD ResumeHandle = 0L;
int iProduct = 0;
do
{
DWORD EntriesRead;
DWORD TotalEntries;
LPBYTE ReturnBuffer = NULL;
NtStatus = ::LlsProductEnum(
m_llsHandle,
1,
&ReturnBuffer,
LLS_PREFERRED_LENGTH,
&EntriesRead,
&TotalEntries,
&ResumeHandle
);
if (NtStatus == STATUS_SUCCESS ||
NtStatus == STATUS_MORE_ENTRIES)
{
CProduct* pProduct;
PLLS_PRODUCT_INFO_1 pProductInfo1;
pProductInfo1 = (PLLS_PRODUCT_INFO_1)ReturnBuffer;
ASSERT(iProduct == m_productArray.GetSize());
m_productArray.SetSize(m_productArray.GetSize() + EntriesRead);
while (EntriesRead--)
{
pProduct = new CProduct(
this,
pProductInfo1->Product,
pProductInfo1->Purchased,
pProductInfo1->InUse,
pProductInfo1->ConcurrentTotal,
pProductInfo1->HighMark
);
m_productArray.SetAt(iProduct++, pProduct); // validate later...
#ifndef DISABLE_PER_NODE_ALLOCATION
::LlsFreeMemory(pProductInfo1->Product);
#endif // DISABLE_PER_NODE_ALLOCATION
pProductInfo1++;
}
::LlsFreeMemory(ReturnBuffer);
}
} while (NtStatus == STATUS_MORE_ENTRIES);
LlsSetLastStatus(NtStatus);
if (NT_SUCCESS(NtStatus))
{
m_bProductsRefreshed = TRUE;
}
else
{
ResetProducts();
}
return m_bProductsRefreshed;
}
BOOL CController::RefreshUsers()
/*++
Routine Description:
Refreshs user object array.
Arguments:
None.
Return Values:
None.
--*/
{
ResetUsers();
if (!m_bIsConnected)
return TRUE;
NTSTATUS NtStatus;
DWORD ResumeHandle = 0L;
int iUser = 0;
do
{
DWORD EntriesRead;
DWORD TotalEntries;
LPBYTE ReturnBuffer = NULL;
NtStatus = ::LlsUserEnum(
m_llsHandle,
2,
&ReturnBuffer,
LLS_PREFERRED_LENGTH,
&EntriesRead,
&TotalEntries,
&ResumeHandle
);
if (NtStatus == STATUS_SUCCESS ||
NtStatus == STATUS_MORE_ENTRIES)
{
CUser* pUser;
PLLS_USER_INFO_2 pUserInfo2;
pUserInfo2 = (PLLS_USER_INFO_2)ReturnBuffer;
ASSERT(iUser == m_userArray.GetSize());
m_userArray.SetSize(m_userArray.GetSize() + EntriesRead);
while (EntriesRead--)
{
pUser = new CUser(
this,
pUserInfo2->Name,
pUserInfo2->Flags,
pUserInfo2->Licensed,
pUserInfo2->UnLicensed,
pUserInfo2->Group,
pUserInfo2->Products
);
m_userArray.SetAt(iUser++, pUser); // validate later...
#ifndef DISABLE_PER_NODE_ALLOCATION
::LlsFreeMemory(pUserInfo2->Name);
::LlsFreeMemory(pUserInfo2->Group);
::LlsFreeMemory(pUserInfo2->Products);
#endif // DISABLE_PER_NODE_ALLOCATION
pUserInfo2++;
}
::LlsFreeMemory(ReturnBuffer);
}
} while (NtStatus == STATUS_MORE_ENTRIES);
LlsSetLastStatus(NtStatus); // called api
if (NT_SUCCESS(NtStatus))
{
m_bUsersRefreshed = TRUE;
}
else
{
ResetUsers();
}
return m_bUsersRefreshed;
}
void CController::ResetLicenses()
/*++
Routine Description:
Resets license object array.
Arguments:
None.
Return Values:
None.
--*/
{
CLicense* pLicense;
int iLicense = m_licenseArray.GetSize();
while (iLicense--)
{
if (pLicense = (CLicense*)m_licenseArray[iLicense])
{
ASSERT(pLicense->IsKindOf(RUNTIME_CLASS(CLicense)));
pLicense->InternalRelease();
}
}
m_licenseArray.RemoveAll();
m_bLicensesRefreshed = FALSE;
}
void CController::ResetMappings()
/*++
Routine Description:
Resets mapping object array.
Arguments:
None.
Return Values:
None.
--*/
{
CMapping* pMapping;
int iMapping = m_mappingArray.GetSize();
while (iMapping--)
{
if (pMapping = (CMapping*)m_mappingArray[iMapping])
{
ASSERT(pMapping->IsKindOf(RUNTIME_CLASS(CMapping)));
pMapping->InternalRelease();
}
}
m_mappingArray.RemoveAll();
m_bMappingsRefreshed = FALSE;
}
void CController::ResetProducts()
/*++
Routine Description:
Resets product object array.
Arguments:
None.
Return Values:
None.
--*/
{
CProduct* pProduct;
int iProduct = m_productArray.GetSize();
while (iProduct--)
{
if (pProduct = (CProduct*)m_productArray[iProduct])
{
ASSERT(pProduct->IsKindOf(RUNTIME_CLASS(CProduct)));
pProduct->InternalRelease();
}
}
m_productArray.RemoveAll();
m_bProductsRefreshed = FALSE;
}
void CController::ResetUsers()
/*++
Routine Description:
Resets user object array.
Arguments:
None.
Return Values:
None.
--*/
{
CUser* pUser;
int iUser = m_userArray.GetSize();
while (iUser--)
{
if (pUser = (CUser*)m_userArray[iUser])
{
ASSERT(pUser->IsKindOf(RUNTIME_CLASS(CUser)));
pUser->InternalRelease();
}
}
m_userArray.RemoveAll();
m_bUsersRefreshed = FALSE;
}