Windows2003-3790/termsrv/newclient/uilib/browsesrv.cpp
2020-09-30 16:53:55 +02:00

2195 lines
64 KiB
C++

//
// browsesrv.cpp: browse for servers list box
//
// This file is built for both UNICODE and ANSI
// and is shared between the mstsc replacement (clshell) and
// the mmc client
//
#include "stdafx.h"
#include "browsesrv.h"
//#include "atlconv.h"
#include "winsock.h"
#include "wuiids.h"
CBrowseServersCtl::CBrowseServersCtl(HINSTANCE hResInstance) : _hInst(hResInstance)
{
bIsWin95 = FALSE;
hLibrary = NULL;
#ifndef OS_WINCE
lpfnNetServerEnum = NULL;
lpfnNetApiBufferFree = NULL;
lpfnNetServerEnum2 = NULL;
lpfnNetWkStaGetInfo = NULL;
lpfnNetWkStaGetInfo_NT = NULL;
lpfnDsGetDcName = NULL;
lpfnNetEnumerateTrustedDomains = NULL;
#else
lpfnWNetOpenEnum = NULL;
lpfnWNetEnumResource = NULL;
lpfnWNetCloseEnum = NULL;
#endif
_fbrowseDNSDomain = FALSE;
_hEvent = NULL;
_hwndDialog = NULL;
_refCount = 0;
_nServerImage=0;
_nDomainImage=0;
_nDomainSelectedImage=0;
_hPrev = (HTREEITEM) TVI_FIRST;
_hPrevRootItem = NULL;
_hPrevLev2Item = NULL;
}
CBrowseServersCtl::~CBrowseServersCtl()
{
// ASSERT(0 == _refCount);
#ifdef OS_WINCE
if (hLibrary)
FreeLibrary(hLibrary);
#endif
}
//
// Ref count mechanism is used to control lifetime because up to two threads
// use this class and have different lifetimes..
//
DCINT CBrowseServersCtl::AddRef()
{
#ifdef OS_WIN32
return InterlockedIncrement( ( LPLONG )&_refCount );
#else
return InterlockedIncrement( ++_refCount );
#endif
}
DCINT CBrowseServersCtl::Release()
{
#ifdef OS_WIN32
if( InterlockedDecrement( ( LPLONG )&_refCount ) == 0 )
#else
if(0 == --_refCount)
#endif
{
delete this;
return 0;
}
return _refCount;
}
//
// Initialize the image lists
//
#define NUM_IMGLIST_ICONS 2
BOOL CBrowseServersCtl::Init(HWND hwndDlg)
{
HIMAGELIST himl; // handle to image list
HICON hIcon; // handle to icon
HWND hwndTV = NULL;
UINT uFlags = TRUE;
int cxSmIcon;
int cySmIcon;
cxSmIcon = GetSystemMetrics(SM_CXSMICON);
cySmIcon = GetSystemMetrics(SM_CYSMICON);
hwndTV = GetDlgItem( hwndDlg, UI_IDC_SERVERS_TREE);
if(!hwndTV)
{
return FALSE;
}
// Create the image list.
if ((himl = ImageList_Create(cxSmIcon, cySmIcon,
TRUE, NUM_IMGLIST_ICONS, 1)) == NULL)
{
return FALSE;
}
// Add icons for the tree (computer, domain)
hIcon = (HICON)LoadImage(_hInst, MAKEINTRESOURCE(UI_IDI_SERVER), IMAGE_ICON,
cxSmIcon, cySmIcon, LR_DEFAULTCOLOR);
if (hIcon)
{
_nServerImage = ImageList_AddIcon(himl, hIcon);
DestroyIcon(hIcon);
}
hIcon = (HICON)LoadImage(_hInst, MAKEINTRESOURCE(UI_IDI_DOMAIN), IMAGE_ICON,
cxSmIcon, cySmIcon, LR_DEFAULTCOLOR);
if (hIcon)
{
_nDomainImage = ImageList_AddIcon(himl, hIcon);
DestroyIcon(hIcon);
}
// Fail if not all of the images were added.
if (ImageList_GetImageCount(himl) < NUM_IMGLIST_ICONS)
return FALSE;
// Associate the image list with the tree view control.
TreeView_SetImageList(hwndTV, himl, TVSIL_NORMAL);
return TRUE;
}
//
// Cleanup any image lists that need to be freed
//
BOOL CBrowseServersCtl::Cleanup()
{
return TRUE;
}
#ifdef OS_WIN32
/****************************************************************************/
/* Name: PopulateListBox */
/* */
/* Purpose: Fills in the owner-draw list box with the Hydra servers */
/* */
/* Returns: pointer to a domain list box item array. */
/* */
/* Params: HWND hwndDlg Handle to the dialogwindow containing the list-box */
/****************************************************************************/
ServerListItem*
CBrowseServersCtl::PopulateListBox(
HWND hwndDlg,
DCUINT *pDomainCount
)
{
//
// check to see we are running on win9x and call out appropriate worker
// routine.
//
#ifndef OS_WINCE
if( bIsWin95 == TRUE ) {
return( PopulateListBox95(hwndDlg, pDomainCount) );
}
#endif
return( PopulateListBoxNT(hwndDlg, pDomainCount) );
}
#ifndef OS_WINCE
/****************************************************************************/
/* Name: PopulateListBox95 */
/* */
/* Purpose: Fills in the owner-draw list box with the Hydra servers */
/* */
/* Returns: pointer to a domain list box item array. */
/* */
/* Params: HWND hwndDlg Handle to the dialogwindow containing the list-box */
/****************************************************************************/
ServerListItem*
CBrowseServersCtl::PopulateListBox95(
HWND hwndDlg,
DCUINT *pDomainCount
)
{
DWORD dwError;
ServerListItem *plbi = NULL;
ServerListItem *plbiAllotted = NULL;
ServerListItem *plbiReturned = NULL;
DWORD dwIndex = 0;
struct wksta_info_10 *pwki10 = NULL;
unsigned short cb;
DWORD dwDomains;
int nCount;
HWND hTree = NULL;
hTree = GetDlgItem( hwndDlg, UI_IDC_SERVERS_TREE );
//
// set return parameters to zero first.
//
*pDomainCount = 0;
//
// check to see the load library was done before calling this
// routine, if not, simply return.
//
if( lpfnNetWkStaGetInfo == NULL ) {
dwError = ERROR_INVALID_DATA;
goto Cleanup;
}
if( hwndDlg == NULL ) {
dwError = ERROR_INVALID_HANDLE;
goto Cleanup;
}
//
// get work group domain.
//
dwError = (*lpfnNetWkStaGetInfo)(NULL, 10, NULL, 0, &cb);
if( dwError != NERR_BufTooSmall ) {
goto Cleanup;
}
//
// allocated required buffer size.
//
pwki10 = (struct wksta_info_10 *)LocalAlloc(LMEM_FIXED, cb);
if( pwki10 == NULL ){
dwError = ERROR_OUTOFMEMORY;
goto Cleanup;
}
//
// query again.
//
dwError = (*lpfnNetWkStaGetInfo)(NULL, 10, (char *)pwki10, cb, &cb);
if( dwError != ERROR_SUCCESS ) {
goto Cleanup;
}
//
// check to see we are browsing a dns domain also, if so, allocated 2 list
// entries.
//
dwDomains = _fbrowseDNSDomain ? 2 : 1;
plbiAllotted = plbi =
(ServerListItem*)LocalAlloc( LMEM_FIXED, sizeof(ServerListItem) * dwDomains );
if( plbiAllotted == NULL ) {
dwError = ERROR_OUTOFMEMORY;
goto Cleanup;
}
//
// display and expand DNS domain if we need to.
//
if( _fbrowseDNSDomain ) {
_tcscpy( plbi->ContainerName, (LPTSTR)_browseDNSDomainName );
plbi->Comment[0] = _T('\0');
plbi->bContainsServers = TRUE;
plbi->bServersExpandedOnce = FALSE;
plbi->bDNSDomain = TRUE;
plbi->nServerCount = 0;
plbi->ServerItems = NULL;
AddItemToTree( hTree, plbi->ContainerName, NULL,
plbi, SRV_TREE_DOMAINLEVEL);
//
// Expand DNS Domain
//
ExpandDomain(hwndDlg, plbi->ContainerName, plbi, &dwIndex);
//
// move to the next list box entry.
//
plbi++;
}
//
// fill up the work group domain now.
//
#ifdef UNICODE
//
// convert to UNICODE.
//
nCount =
MultiByteToWideChar(
CP_ACP,
MB_COMPOSITE,
(LPSTR)pwki10->wki10_langroup,
-1,
plbi->ContainerName,
sizeof(plbi->ContainerName)/sizeof(WCHAR));
if( nCount == 0 )
{
dwError = GetLastError();
goto Cleanup;
}
#else
_tcscpy( plbi->ContainerName, pwki10->wki10_langroup );
#endif
plbi->Comment[0] = _T('\0');
plbi->bContainsServers = TRUE;
plbi->bServersExpandedOnce = FALSE;
plbi->bDNSDomain = FALSE;
plbi->nServerCount = 0;
plbi->ServerItems = NULL;
AddItemToTree( hTree, plbi->ContainerName, NULL,
plbi, SRV_TREE_DOMAINLEVEL);
//
// Expand the present Domain
//
ExpandDomain(hwndDlg, NULL, plbi, &dwIndex);
//
// we successfully populated the domain list,
// set return parameters.
//
plbiReturned = plbiAllotted;
*pDomainCount = dwDomains;
plbiAllotted = NULL;
dwError = ERROR_SUCCESS;
Cleanup:
if( plbiAllotted != NULL ) {
LocalFree(plbiAllotted);
}
if( pwki10 != NULL ) {
LocalFree(pwki10);
}
SetLastError( dwError );
return plbiReturned;
}
#endif
/****************************************************************************/
/* Name: PopulateListBoxNT */
/* */
/* Purpose: Fills in the owner-draw list box with the Hydra servers */
/* */
/* Returns: pointer to a domain list box item array. */
/* */
/* Params: HWND hwndDlg Handle to the dialogwindow containing the list-box */
/****************************************************************************/
ServerListItem*
CBrowseServersCtl::PopulateListBoxNT(
HWND hwndDlg,
DCUINT *pdwDomainCount
)
{
DWORD dwError;
PDCTCHAR pchTrustedDomains = NULL;
PDCTCHAR pchTDomain;
DCUINT dwDomainCount = 0;
ServerListItem *plbiAllotted = NULL;
ServerListItem *plbiReturned = NULL;
ServerListItem *plbi;
HWND hTree = NULL;
DWORD dwDlgIndex=0;
DWORD i;
hTree = GetDlgItem( hwndDlg, UI_IDC_SERVERS_TREE );
//
// set the return parameter to zero first.
//
*pdwDomainCount = 0;
if( hwndDlg == NULL ) {
dwError = ERROR_INVALID_HANDLE;
goto Cleanup;
}
//
// enumurate trusted domain names.
//
pchTrustedDomains = UIGetTrustedDomains();
if( pchTrustedDomains == NULL ) {
dwError = ERROR_CANT_ACCESS_DOMAIN_INFO;
goto Cleanup;
}
//
// count number of domains.
//
pchTDomain = pchTrustedDomains;
while( *pchTDomain != _T('\0') ) {
dwDomainCount++;
pchTDomain += (_tcslen(pchTDomain) + 1);
}
//
// check to see we need to browse the DNS domain.
//
if( _fbrowseDNSDomain ) {
dwDomainCount++;
}
//
// allocate the memory for the ServerListItem (based on the no. of domains)
//
plbiAllotted = (ServerListItem *)
LocalAlloc( LMEM_FIXED, (sizeof(ServerListItem) * dwDomainCount) );
if ( plbiAllotted == NULL ) {
dwError = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// set scan variables.
//
plbi = plbiAllotted;
pchTDomain = pchTrustedDomains;
//
// display and expand DNS domain if we need to.
//
if( _fbrowseDNSDomain ) {
_tcscpy(plbi->ContainerName, (LPTSTR)_browseDNSDomainName );
plbi->Comment[0] = _T('\0');
plbi->bContainsServers = TRUE;
plbi->bServersExpandedOnce = FALSE;
plbi->bDNSDomain = TRUE;
plbi->nServerCount = 0;
plbi->ServerItems = NULL;
plbi->hTreeParentItem = NULL;
plbi->hTreeItem = AddItemToTree( hTree, plbi->ContainerName,
NULL, plbi, SRV_TREE_DOMAINLEVEL);
//
// expand the primary domain
//
ExpandDomain(hwndDlg, plbi->ContainerName, plbi, &dwDlgIndex);
//
// move to next list entry.
//
plbi++;
}
//
// first entry in the domain list is the primary domain,
// display it and expand it by default.
//
_tcscpy(plbi->ContainerName, pchTDomain);
plbi->Comment[0] = _T('\0');
plbi->bContainsServers = TRUE;
plbi->bServersExpandedOnce = FALSE;
plbi->bDNSDomain = FALSE;
plbi->nServerCount = 0;
plbi->ServerItems = NULL;
plbi->hTreeParentItem = NULL;
plbi->hTreeItem = AddItemToTree( hTree, pchTDomain, NULL, plbi,
SRV_TREE_DOMAINLEVEL);
//
// expand the primary domain
//
if(ExpandDomain(hwndDlg, NULL, plbi, &dwDlgIndex))
{
if(plbi->hTreeItem)
{
//Expand default domain
TreeView_Expand( hTree, plbi->hTreeItem, TVE_EXPAND);
}
}
//
// display other domains, don't expand them.
//
for((i = (_fbrowseDNSDomain == TRUE) ? 2 : 1); i < dwDomainCount; i++) {
//
// move to the next entry in the domain list.
//
plbi++;
pchTDomain += (_tcslen(pchTDomain) + 1);
_tcscpy(plbi->ContainerName, pchTDomain);
plbi->Comment[0] = _T('\0');
plbi->bContainsServers = TRUE;
plbi->bServersExpandedOnce = FALSE;
plbi->bDNSDomain = FALSE;
plbi->nServerCount = 0;
plbi->ServerItems = NULL;
plbi->hTreeParentItem = NULL;
plbi->hTreeItem = AddItemToTree( hTree, pchTDomain, NULL, plbi,
SRV_TREE_DOMAINLEVEL);
}
//
// we successfully populated the domain list,
// set return parameters.
//
*pdwDomainCount = dwDomainCount;
plbiReturned = plbiAllotted;
plbiAllotted = NULL;
dwError = ERROR_SUCCESS;
Cleanup:
if( pchTrustedDomains != NULL ) {
LocalFree( pchTrustedDomains );
}
if( plbiAllotted != NULL ) {
LocalFree( plbiAllotted );
}
SetLastError( dwError );
return( plbiReturned );
}
#endif //OS_WIN32
#ifdef OS_WIN32
/****************************************************************************/
/* Name: LoadLibraries */
/* */
/* Purpose: Load the appropriate libraries for win95 and winnt. */
/* */
/* Returns: None */
/* */
/* Params: None */
/****************************************************************************/
void CBrowseServersCtl::LoadLibraries(void)
{
#ifndef OS_WINCE
OSVERSIONINFOA osVersionInfo;
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
//A version to avoid wrapping
if(GetVersionExA(&osVersionInfo) == TRUE)
{
if(VER_PLATFORM_WIN32_WINDOWS == osVersionInfo.dwPlatformId )
{
bIsWin95 = TRUE;
if(!hLibrary)
{
hLibrary = LoadLibrary(__T("msnet32.dll"));
}
if(NULL == hLibrary)
return ;
lpfnNetServerEnum2 = (LPFNNETSERVERENUM2)GetProcAddress((HMODULE)hLibrary,
(LPCSTR)0x0029);
lpfnNetWkStaGetInfo = (LPFNNETWKSTAGETINFO)GetProcAddress((HMODULE)hLibrary,
(LPCSTR)0x0039);
}
else if(VER_PLATFORM_WIN32_NT == osVersionInfo.dwPlatformId )
{
if(!hLibrary)
{
hLibrary = LoadLibrary(__T("NetApi32.dll"));
}
if(NULL == hLibrary)
return;
lpfnNetServerEnum = (LPFNNETSERVERENUM)
GetProcAddress((HMODULE)hLibrary,
"NetServerEnum");
lpfnNetApiBufferFree = (LPFNNETAPIBUFFERFREE)
GetProcAddress((HMODULE)hLibrary,
"NetApiBufferFree");
lpfnNetWkStaGetInfo_NT = (LPFNNETWKSTAGETINFO_NT)GetProcAddress(
(HMODULE)hLibrary,
"NetWkstaGetInfo");
lpfnNetEnumerateTrustedDomains = (LPFNNETENUMERATETRUSTEDDOMAINS)
GetProcAddress((HMODULE)hLibrary,
"NetEnumerateTrustedDomains");
#ifdef UNICODE
lpfnDsGetDcName = (LPFNDSGETDCNAME)
GetProcAddress((HMODULE)hLibrary,
"DsGetDcNameW");
#else // UNICODE
lpfnDsGetDcName = (LPFNDSGETDCNAME)
GetProcAddress((HMODULE)hLibrary,
"DsGetDcNameA");
#endif // UNICODE
}
}
return;
#else
hLibrary = LoadLibrary(L"coredll.dll");
lpfnWNetOpenEnum = (LPFNWNETOPENENUM )
GetProcAddress((HMODULE)hLibrary,
L"WNetOpenEnumW");
lpfnWNetEnumResource = (LPFNWNETENUMRESOURCE )
GetProcAddress((HMODULE)hLibrary,
L"WNetEnumResourceW");
lpfnWNetCloseEnum = (LPFNWNETCLOSEENUM )
GetProcAddress((HMODULE)hLibrary,
L"WNetCloseEnum");
#endif
}
#endif //OS_WIN32
/****************************************************************************/
/* Name: ExpandDomain */
/* */
/* Purpose: Enumerates the Hydra Servers in a Domain/workgroup, adds */
/* them to the linked-list and as items in the list box. */
/* */
/* Returns: */
/* */
/* Params: HWND hwndDlg Handle to the dialogwindow containing the list-box */
/****************************************************************************/
int CBrowseServersCtl::ExpandDomain(HWND hwndDlg, TCHAR *pDomainName,
ServerListItem *plbi, DWORD *pdwIndex)
{
//
// check to see we are expanding a DNS domain.
//
if( plbi->bDNSDomain ) {
return( UIExpandDNSDomain( hwndDlg, pDomainName, plbi, pdwIndex ) );
}
//
// check to we are running on Win9x machine.
//
#ifndef OS_WINCE
if( bIsWin95 == TRUE) {
return( ExpandDomain95(hwndDlg, pDomainName, plbi, pdwIndex) );
}
else {
return( ExpandDomainNT(hwndDlg, pDomainName, plbi, pdwIndex) );
}
#else
return ExpandDomainCE(hwndDlg, pDomainName, plbi, pdwIndex);
#endif
}//ExpandDomain
/****************************************************************************/
/* Name: ExpandDomain95 */
/* */
/* Purpose: Enumerates the Hydra Servers in a Domain/workgroup, adds */
/* them to the linked-list and as items in the list box. */
/* */
/* Returns: */
/* */
/* Params: HWND hwndDlg Handle to the dialogwindow containing the list-box */
/****************************************************************************/
#ifdef OS_WIN32
#ifndef OS_WINCE
int CBrowseServersCtl::ExpandDomain95(HWND hwndDlg, TCHAR *pDomainName,
ServerListItem *plbi, DWORD *pdwIndex)
{
UNREFERENCED_PARAMETER(pDomainName);
DWORD dwIndex = *pdwIndex;
unsigned short AvailCount = 0, TotalEntries = 0;
ServerListItem *plbistore = NULL, *pItemsStore = NULL;
DCUINT index = 0, cb = 0;
struct server_info_1 *pInfo1 = NULL;
int err = 0;
int nCount = 0;
HWND hTree = NULL;
if(NULL == lpfnNetServerEnum2)
return 0;
SetCursor(LoadCursor(NULL, IDC_WAIT));
if(!plbi->ServerItems)
{
// Determine how much information is available
err = (*lpfnNetServerEnum2)(NULL, 1, NULL, 0, &AvailCount,
&TotalEntries, HYDRA_SERVER_LANMAN_BITS, NULL);
if(err != ERROR_MORE_DATA)
return 0;
// Allocate memory to receive the information
// Give a little extra, since sometimes one is missed
cb = (TotalEntries + 1) * sizeof(struct server_info_1);
pInfo1 = (struct server_info_1 *)LocalAlloc(0, cb);
if ( pInfo1 == NULL )
{
goto done1;
}
memset(pInfo1,0,cb);
//
// lpfnNetServerEnum2 is going to take a long time,
// Retrieve the information
err = (*lpfnNetServerEnum2)(
NULL,
1,
(char far *)pInfo1,
(unsigned short)cb,
&AvailCount,
&TotalEntries,
HYDRA_SERVER_LANMAN_BITS,
NULL);
// Due to the dynamic nature of the network, we may get
// ERROR_MORE_DATA, but that means we got the bulk of the
// correct values, and we should display them
if ((err != NERR_Success) && (err != ERROR_MORE_DATA))
goto done1;
//Allocate memory.
cb = sizeof(ServerListItem)*AvailCount;
plbi->ServerItems = (ServerListItem *)LocalAlloc(0, (sizeof(ServerListItem)*AvailCount));
if ( plbi->ServerItems == NULL )
{
goto done1;
}
memset(plbi->ServerItems,0,sizeof(ServerListItem)*AvailCount);
pItemsStore = plbi->ServerItems;
if(IsBadWritePtr((LPVOID)plbi->ServerItems,sizeof(ServerListItem)*AvailCount))
goto done1;
// Traverse list, copy servers to plbi.
for( index = 0; index < AvailCount; index++ )
{
if( ((pInfo1[index].sv1_version_major & MAJOR_VERSION_MASK) >=
4) && (pInfo1[index].sv1_version_minor >= 0) )
{
#ifdef UNICODE
nCount =
MultiByteToWideChar(
CP_ACP,
MB_COMPOSITE,
(LPSTR)pInfo1[index].sv1_name,
-1,
pItemsStore->ContainerName,
sizeof(pItemsStore->ContainerName)/sizeof(WCHAR));
if( nCount == 0 )
{
return 0;
}
#else
_tcscpy(pItemsStore->ContainerName, pInfo1[index].sv1_name);
#endif
if(pInfo1[index].sv1_comment != NULL)
{
#ifdef UNICODE
nCount =
MultiByteToWideChar(
CP_ACP,
MB_COMPOSITE,
(LPSTR)pInfo1[index].sv1_comment,
-1,
pItemsStore->Comment,
sizeof(pItemsStore->Comment)/sizeof(WCHAR));
if( nCount == 0 )
{
return 0;
}
#else
_tcscpy(pItemsStore->Comment, pInfo1[index].sv1_comment);
#endif
}
pItemsStore->bContainsServers = FALSE;
pItemsStore++;
plbi->nServerCount++;
}
}
done1:
if ( AvailCount && pInfo1 )
{
LocalFree( pInfo1 );
}
if(!plbi->ServerItems)
{
return 0;
}
}
else
AvailCount = (unsigned short)plbi->nServerCount;
// Traverse the plbi>ServerItems and add the servers to the List-box:
pItemsStore = plbi->ServerItems;
hTree = GetDlgItem( hwndDlg, UI_IDC_SERVERS_TREE );
HTREEITEM hTreeParentNode = plbi->hTreeItem;
for (index = 0; index < plbi->nServerCount; ++index)
{
if(hwndDlg)
{
if (DC_TSTRCMP(pItemsStore->ContainerName, _T("")))
{
pItemsStore->hTreeParentItem = hTreeParentNode;
pItemsStore->hTreeItem =
AddItemToTree(hTree, pItemsStore->ContainerName,
hTreeParentNode,
pItemsStore, SRV_TREE_SERVERLEVEL);
}
}
pItemsStore++;
}
plbi->bServersExpandedOnce = TRUE;
*pdwIndex = dwIndex;
if(hwndDlg)
{
InvalidateRect(hwndDlg, NULL, TRUE);
}
SetCursor(LoadCursor(NULL, IDC_ARROW));
return AvailCount;
}/* ExpandDomain95 */
/****************************************************************************/
/* Name: ExpandDomainNT */
/* */
/* Purpose: Enumerates the Hydra Servers in a Domain/workgroup, adds */
/* them to the linked-list and as items in the list box. */
/* */
/* Returns: */
/* */
/* Params: HWND hwndDlg Handle to the dialogwindow containing the list-box */
/****************************************************************************/
int CBrowseServersCtl::ExpandDomainNT(HWND hwndDlg, TCHAR *pDomainName,
ServerListItem *plbi, DWORD *pdwIndex)
{
DWORD dwIndex = *pdwIndex, AvailCount = 0, TotalEntries = 0;
SERVER_INFO_101 *pInfo = NULL;
DCUINT index = 0;
ServerListItem *plbistore = NULL, *pItemsStore = NULL;
WCHAR pDomain[BROWSE_MAX_ADDRESS_LENGTH];
int nCount = 0;
HWND hTree = NULL;
if(NULL == lpfnNetServerEnum)
return 0;
if(NULL == lpfnNetApiBufferFree)
return 0;
SetCursor(LoadCursor(NULL, IDC_WAIT));
if(plbi->ServerItems)
{
AvailCount = plbi->nServerCount;
}
else
{
//
//enumerate the servers in the primary domain if not already present
//
if(pDomainName)
{
#ifndef UNICODE
nCount = MultiByteToWideChar(CP_ACP,
MB_COMPOSITE,
pDomainName,
lstrlen(pDomainName) * sizeof(TCHAR),
(LPWSTR)pDomain,
sizeof(pDomain) / sizeof(TCHAR));
if(nCount)
{
pDomain[nCount] = 0;
}
else
{
AvailCount = 0;
goto done;
}
#else
_tcsncpy( pDomain, (LPTSTR)pDomainName,
sizeof(pDomain)/sizeof(TCHAR) - 1);
pDomain[sizeof(pDomain)/sizeof(TCHAR) - 1] = 0;
#endif
}
//
// lpfnNetServerEnum is going to take a long time,
//
if ((*lpfnNetServerEnum)(NULL,
101,
(LPBYTE *)&pInfo,
(DWORD) -1,
&AvailCount,
&TotalEntries,
HYDRA_SERVER_LANMAN_BITS,
pDomainName ?
(LPTSTR)pDomain :
NULL,
NULL ) || !AvailCount )
{
AvailCount = 0;
goto done;
}
//Allocate memory.
if ( (plbi->ServerItems = (ServerListItem *)LocalAlloc(0,
(sizeof(ServerListItem)*AvailCount))) == NULL )
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto done;
}
memset(plbi->ServerItems,0,sizeof(ServerListItem)*AvailCount);
pItemsStore = plbi->ServerItems;
// Traverse list, copy servers to plbi.
for( index = 0; index < AvailCount; index++ )
{
if( ((pInfo[index].sv101_version_major & MAJOR_VERSION_MASK) >=
4) )
{
#ifdef UNICODE
lstrcpy(pItemsStore->ContainerName, pInfo[index].sv101_name);
lstrcpy(pItemsStore->Comment, pInfo[index].sv101_comment);
#else
WideCharToMultiByte(CP_ACP,
WC_COMPOSITECHECK|WC_SEPCHARS,
(LPCWSTR)pInfo[index].sv101_name,
wcslen((const wchar_t *)pInfo[index].sv101_name),
pItemsStore->ContainerName,
sizeof(pItemsStore->ContainerName),
NULL,
NULL);
WideCharToMultiByte(CP_ACP,
WC_COMPOSITECHECK|WC_SEPCHARS,
(LPCWSTR)pInfo[index].sv101_comment,
wcslen((const wchar_t *)pInfo[index].sv101_comment),
pItemsStore->Comment,
sizeof(pItemsStore->Comment),
NULL,
NULL);
#endif
pItemsStore->bContainsServers = FALSE;
pItemsStore++;
plbi->nServerCount ++;
}
}
done:
if ( AvailCount && pInfo )
{
(*lpfnNetApiBufferFree)( pInfo );
}
}
// Traverse the plbi>ServerItems and add the servers to the List-box:
pItemsStore = plbi->ServerItems;
hTree = GetDlgItem( hwndDlg, UI_IDC_SERVERS_TREE );
HTREEITEM hTreeParentNode = plbi->hTreeItem;
for (index = 0; index < plbi->nServerCount;++index)
{
if(hwndDlg)
{
if (DC_TSTRCMP(pItemsStore->ContainerName, _T("")))
{
pItemsStore->hTreeParentItem = hTreeParentNode;
pItemsStore->hTreeItem =
AddItemToTree(hTree, pItemsStore->ContainerName,
hTreeParentNode,
pItemsStore, SRV_TREE_SERVERLEVEL);
}
}
plbi->bServersExpandedOnce = TRUE;
pItemsStore++;
}
*pdwIndex = dwIndex;
SetCursor(LoadCursor(NULL, IDC_ARROW));
return AvailCount;
} /* ExpandDomainNT */
#else
/****************************************************************************/
/* Name: ExpandDomainCE */
/* */
/* Purpose: Enumerates the Hydra Servers in a Domain/workgroup, adds */
/* them to the linked-list and as items in the list box. */
/* */
/* Returns: */
/* */
/* Params: HWND hwndDlg Handle to the dialogwindow containing the list-box */
/****************************************************************************/
int CBrowseServersCtl::ExpandDomainCE(HWND hwndDlg, TCHAR *pDomainName,
ServerListItem *plbi, DWORD *pdwIndex)
{
DWORD AvailCount = 0;
NETRESOURCE *pNetRsrc = NULL;
HWND hTree = NULL;
DWORD dwInitBufSize = 16*1024;
if((NULL == lpfnWNetOpenEnum) || (NULL == lpfnWNetCloseEnum) || (NULL == lpfnWNetEnumResource))
return 0;
SetCursor(LoadCursor(NULL, IDC_WAIT));
if(plbi->ServerItems)
{
AvailCount = plbi->nServerCount;
}
else
{
NETRESOURCE netrsrc;
HANDLE hEnum = NULL;
DWORD dwRet = NO_ERROR;
netrsrc.dwScope = RESOURCE_GLOBALNET;
netrsrc.dwType = RESOURCETYPE_ANY;
netrsrc.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
netrsrc.dwUsage = RESOURCEUSAGE_CONTAINER;
netrsrc.lpLocalName = NULL;
netrsrc.lpRemoteName = pDomainName;
netrsrc.lpComment = NULL;
netrsrc.lpProvider = NULL;
hTree = GetDlgItem( hwndDlg, UI_IDC_SERVERS_TREE );
dwRet = lpfnWNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_RESERVED, HYDRA_SERVER_LANMAN_BITS, &netrsrc, &hEnum);
if ((dwRet != NO_ERROR) || (hEnum == NULL))
return 0;
AvailCount = 0;
pNetRsrc = (NETRESOURCE *)LocalAlloc(0, dwInitBufSize);
if (!pNetRsrc)
goto done;
while(dwRet == NO_ERROR)
{
DWORD dwCount, dwTempSize;
dwCount = 0xffffffff;
dwTempSize = dwInitBufSize;
dwRet = lpfnWNetEnumResource(hEnum, &dwCount, pNetRsrc, &dwTempSize);
if (dwRet == NO_ERROR)
{
AvailCount += dwCount;
for (DWORD i=0; i<dwCount; i++)
{
AddItemToTree(hTree, pNetRsrc[i].lpRemoteName,
plbi->hTreeItem,
NULL, SRV_TREE_SERVERLEVEL);
}
}
}
lpfnWNetCloseEnum(hEnum);
hEnum = NULL;
done:
if (pNetRsrc)
LocalFree(pNetRsrc);
lpfnWNetCloseEnum(hEnum);
}
SetCursor(LoadCursor(NULL, IDC_ARROW));
return AvailCount;
} /* ExpandDomainCE */
#endif
#endif //OS_WIN32
/****************************************************************************/
/* Name: UIGetTrustedDomains */
/* */
/* Purpose: Queries teh registry for a list of the Trusted Domains */
/* */
/* Returns: */
/* */
/* Params: HWND hwndDlg Handle to the dialogwindow containing the list-box */
/****************************************************************************/
#ifdef OS_WIN32
#ifndef OS_WINCE
PDCTCHAR CBrowseServersCtl::UIGetTrustedDomains()
{
HKEY hKey = NULL;
DWORD size = 0 , size1 = 0;
PDCTCHAR pTrustedDomains = NULL;
PDCTCHAR pPutHere = NULL;
PDCTCHAR szPrimaryDomain = NULL;
PDCTCHAR szWkstaDomainName = NULL;
PDCTCHAR pDomain = NULL;
BOOL bGetTrustedDomains = FALSE;
OSVERSIONINFOA OsVer;
memset(&OsVer, 0x0, sizeof(OSVERSIONINFOA));
OsVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
GetVersionExA(&OsVer);
if(OsVer.dwMajorVersion <= 4)
{
// Get the current domain information from the winlogon settings.
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, DOMAIN_KEY, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
DWORD dwResult = 0;
dwResult = RegQueryValueEx(hKey, PRIMARY_VAL, NULL, NULL, NULL, &size);
if (dwResult == ERROR_SUCCESS && size > 0)
{
szPrimaryDomain = (PDCTCHAR)LocalAlloc(LPTR, (size + 1)*sizeof(TCHAR));
if (szPrimaryDomain == NULL)
{
goto Cleanup;
}
if ((RegQueryValueEx(
hKey,
PRIMARY_VAL,
NULL, NULL,
(LPBYTE)szPrimaryDomain,
&size
) == ERROR_SUCCESS) &&
szPrimaryDomain[0])
{
pDomain = szPrimaryDomain;
}
}
}
}
else
{
if(NULL == lpfnDsGetDcName)
return 0;
DOMAIN_CONTROLLER_INFO *pDCI = NULL;
// this section gets the current domain the app is running on
if((*lpfnDsGetDcName)(NULL, NULL, NULL,
NULL, DS_RETURN_FLAT_NAME,
&pDCI ) == NO_ERROR)
{
pDomain = pDCI->DomainName;
}
}
// Get the domain/work group information from NetWkStaGetInfo
if (lpfnNetWkStaGetInfo_NT)
{
LPBYTE buffer = NULL;
if ((*lpfnNetWkStaGetInfo_NT)(NULL, 100, &buffer) == NERR_Success && buffer)
{
LPWSTR langroup = ((WKSTA_INFO_100 *)buffer)->wki100_langroup;
DWORD langroupLen = (langroup) ? wcslen(langroup) : 0;
if (langroupLen)
{
szWkstaDomainName = (PDCTCHAR)LocalAlloc(LPTR, (langroupLen + 1)*sizeof(TCHAR));
if (szWkstaDomainName == NULL)
{
goto Cleanup;
}
#ifdef UNICODE
_tcscpy(szWkstaDomainName,langroup);
pDomain = szWkstaDomainName;
#else
// convert the unicode string to ansi
if (WideCharToMultiByte(CP_ACP,
0,
langroup,
-1,
szWkstaDomainName,
(langroupLen + 1) * sizeof(TCHAR),
NULL,
NULL))
{
pDomain = szWkstaDomainName;
}
#endif
}
if (lpfnNetApiBufferFree)
{
(*lpfnNetApiBufferFree)(buffer);
}
}
}
//
// We should get the list of trusted domains only when the machine belongs to a domain, not a workgroup
// We determine that the machine belongs to a domain if the winlogon cached information, and the langroup from
// NetWkstaGetInfo match.
//
if (szPrimaryDomain &&
szPrimaryDomain[0] &&
szWkstaDomainName &&
_tcscmp(szPrimaryDomain, szWkstaDomainName) == 0)
{
bGetTrustedDomains = TRUE;
}
size = (pDomain) ? _tcslen(pDomain) : 0;
if(size > 0)
{
if (bGetTrustedDomains && hKey != NULL && (OsVer.dwMajorVersion < 4))
{
if(ERROR_SUCCESS == RegQueryValueEx(hKey, CACHE_VAL_NT351,
NULL, NULL,
NULL, &size1))
{
pTrustedDomains = (PDCTCHAR)LocalAlloc(LPTR, (size + size1 + 2) * sizeof(TCHAR));
if(NULL == pTrustedDomains)
goto Cleanup;
_tcscpy(pTrustedDomains, pDomain);
pPutHere = pTrustedDomains;
pPutHere += (_tcslen(pTrustedDomains) + 1);
*pPutHere = _T('\0');
}
else
{
goto Cleanup;
}
}
else if (bGetTrustedDomains && hKey != NULL && (4 == OsVer.dwMajorVersion) )
{
if(ERROR_SUCCESS == RegQueryValueEx(hKey, CACHE_VAL,
NULL, NULL,
NULL, &size1))
{
pTrustedDomains = (PDCTCHAR)LocalAlloc(LPTR, (size + size1 + 2) * sizeof(TCHAR));
if(NULL == pTrustedDomains)
goto Cleanup;
_tcscpy(pTrustedDomains, pDomain);
pPutHere = pTrustedDomains;
pPutHere += (_tcslen(pTrustedDomains) + 1);
*pPutHere = _T('\0');
RegQueryValueEx(hKey, CACHE_VAL, NULL, NULL, (LPBYTE)pPutHere, &size1);
}
}
else if (5 <= OsVer.dwMajorVersion)
{
LPWSTR szDomainNames = NULL;
if(NULL == lpfnNetEnumerateTrustedDomains)
goto Cleanup;
size1 = 0;
DWORD dwCount;
LPWSTR szWideBuf = NULL;
if( (*lpfnNetEnumerateTrustedDomains)(NULL,
&szDomainNames ) == ERROR_SUCCESS )
{
szWideBuf = szDomainNames;
while(*szWideBuf && (*szWideBuf+1))
{
size1 += wcslen(szWideBuf) + 1;
szWideBuf += wcslen(szWideBuf) + 1;
}
szWideBuf = szDomainNames;
}
pTrustedDomains = (PDCTCHAR)LocalAlloc(LPTR, (size + size1 + 2) * sizeof(TCHAR));
if(NULL == pTrustedDomains)
goto Cleanup;
_tcscpy(pTrustedDomains, pDomain);
pPutHere = pTrustedDomains + _tcslen(pTrustedDomains) + 1;
*pPutHere = _T('\0');
if(size1)
{
//
// CONVERT unicode domain name to ansi.
//
while(*szWideBuf && (*szWideBuf+1))
{
#ifndef UNICODE
WideCharToMultiByte(CP_ACP, 0, szWideBuf, -1,
pPutHere, wcslen(szWideBuf) * sizeof(TCHAR), NULL, NULL );
#else // UNICODE
lstrcpy(pPutHere, szWideBuf);
#endif //UNICODE
pPutHere += _tcslen(pPutHere);
*pPutHere++ = 0;
szWideBuf += wcslen(szWideBuf) + 1;
}
if(NULL == lpfnNetApiBufferFree)
return 0;
(*lpfnNetApiBufferFree)( szDomainNames );
}
}
}
Cleanup:
if (hKey)
{
RegCloseKey(hKey);
}
if (szPrimaryDomain)
{
LocalFree(szPrimaryDomain);
}
if (szWkstaDomainName)
{
LocalFree(szWkstaDomainName);
}
return pTrustedDomains;
}
#else
PDCTCHAR CBrowseServersCtl::UIGetTrustedDomains()
{
HKEY hKey = NULL;
DWORD size = 0;
PDCTCHAR szPrimaryDomain = NULL;
PDCTCHAR pTrustedDomains = NULL;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, DOMAIN_KEY, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
DWORD dwResult = 0;
dwResult = RegQueryValueEx(hKey, PRIMARY_VAL, NULL, NULL, NULL, &size);
if (dwResult == ERROR_SUCCESS && size > 0)
{
szPrimaryDomain = (PDCTCHAR)LocalAlloc(LPTR, (size + 1)*sizeof(TCHAR));
if (szPrimaryDomain == NULL)
{
RegCloseKey(hKey);
return NULL;
}
if ((RegQueryValueEx(
hKey,
PRIMARY_VAL,
NULL, NULL,
(LPBYTE)szPrimaryDomain,
&size
) == ERROR_SUCCESS) &&
szPrimaryDomain[0])
{
pTrustedDomains = szPrimaryDomain;
}
else
{
LocalFree(szPrimaryDomain);
}
}
}
return pTrustedDomains;
}
#endif
#endif //OS_WIN32
/* UIGetTrustedDomains */
/****************************************************************************/
/* Name: UIExpandDNSDomain */
/* */
/* Purpose: Enumerates the Hydra Servers in a DNS Domain, adds */
/* them to the linked-list and as items in the list box. */
/* */
/* Returns: numbers of server expanded */
/* */
/* Params: HWND hwndDlg Handle to the dialogwindow containing the list-box */
/****************************************************************************/
int
CBrowseServersCtl::UIExpandDNSDomain(
HWND hwndDlg,
TCHAR *pDomainName,
ServerListItem *plbi,
DWORD *pdwIndex
)
{
DWORD dwError;
LPHOSTENT lpHostEnt;
LPHOSTENT lpRevHostEnt;
DWORD dwIPEntries;
LPSTR FAR *lplpIPEntry;
DWORD FAR *lpIPAddrsAlloted = NULL;
DWORD FAR *lpIPAddrs;
ServerListItem *lpServerListItem = NULL;
ServerListItem *lpLBItem;
DWORD i;
DWORD dwEntriesDisplayed = 0;
HWND hTree = NULL;
HTREEITEM hTreeParentNode = NULL;
//
// set cursor to wait cursor while we do this.
//
SetCursor(LoadCursor(NULL, IDC_WAIT));
//
// check to see the specified list box entry is server entry.
//
// TRC_ASSERT((plbi->bContainsServers == TRUE),
// (TB,"Not a server entry"));
if( plbi->bContainsServers == FALSE ) {
dwError = ERROR_INVALID_DATA;
goto Cleanup;
}
if( hwndDlg == NULL ) {
dwError = ERROR_INVALID_DATA;
goto Cleanup;
}
//
// resolve the DNS domain name if it is not done before.
//
if( plbi->ServerItems == NULL ) {
#ifdef UNICODE
WCHAR achDomainName[BROWSE_MAX_ADDRESS_LENGTH];
DWORD dwCount;
//
// CONVERT unicode domain name to ansi.
//
dwCount =
WideCharToMultiByte(
CP_ACP,
WC_COMPOSITECHECK | WC_SEPCHARS,
pDomainName,
-1,
(LPSTR)achDomainName,
sizeof(achDomainName),
NULL,
NULL);
if( dwCount == 0 ) {
dwError = GetLastError();
goto Cleanup;
}
achDomainName[dwCount/sizeof(TCHAR)]= '\0';
lpHostEnt = gethostbyname( (LPSTR)achDomainName );
#else // UNICODE
//
// resolve the domain name to ip address list.
//
lpHostEnt = gethostbyname( pDomainName );
#endif // UNICODE
if( lpHostEnt == NULL ) {
dwError = GetLastError();
goto Cleanup;
}
//
// we handle only IP address type.
//
/*
TRC_ASSERT((lpHostEnt->h_addrtype == PF_INET),
(TB,"Invalid address type"));
TRC_ASSERT((lpHostEnt->h_length == 4),
(TB,"Invalid address length"));
*/
if( (lpHostEnt->h_addrtype != PF_INET) ||
(lpHostEnt->h_length != 4) ) {
dwError = ERROR_INVALID_DATA;
goto Cleanup;
}
dwIPEntries = 0;
lplpIPEntry = lpHostEnt->h_addr_list;
while( *lplpIPEntry != NULL ) {
dwIPEntries++;
lplpIPEntry++;
}
//
// allocate memory for the ip address list and
// save for further use in this routine (only).
//
// Note: lpHostEnt points to a thread storeage
// which is reused by gethostbyname() and
// gethostbyaddr() calls with in the same
// thread, since we need to call gethostbyaddr()
// we better save the address list.
//
lpIPAddrsAlloted =
lpIPAddrs = (DWORD FAR *)
LocalAlloc( LMEM_FIXED, sizeof(DWORD) * dwIPEntries );
if( lpIPAddrs == NULL ) {
dwError = ERROR_OUTOFMEMORY;
goto Cleanup;
}
lplpIPEntry = lpHostEnt->h_addr_list;
while( *lplpIPEntry != NULL ) {
*lpIPAddrs = *(DWORD *)(*lplpIPEntry);
lpIPAddrs++;
lplpIPEntry++;
}
//
// allocate memory for domain ServerListItem array.
//
lpLBItem =
lpServerListItem = (ServerListItem *)
LocalAlloc( LMEM_FIXED, dwIPEntries * sizeof(ServerListItem) );
if( lpServerListItem == NULL ) {
dwError = ERROR_OUTOFMEMORY;
goto Cleanup;
}
//
// reverse resolve each ip address and get the name.
//
lpIPAddrs = lpIPAddrsAlloted;
for( i = 0; i < dwIPEntries; i++ ) {
CHAR achContainerName[BROWSE_MAX_ADDRESS_LENGTH];
int nCount;
BOOL bIPAddressString = FALSE;
lpRevHostEnt =
gethostbyaddr(
(LPSTR)lpIPAddrs,
sizeof(*lpIPAddrs),
PF_INET );
//
// if we can not reverse resolve the address or
// if the host name is too long, or
// display the ipaddress.
//
if( (lpRevHostEnt == NULL) ||
((strlen(lpRevHostEnt->h_name) + 1) >
(BROWSE_MAX_ADDRESS_LENGTH/sizeof(TCHAR)) ) ) {
bIPAddressString = TRUE;
}
else {
LPSTR lpszDomainName;
#ifdef UNICODE
lpszDomainName = (LPSTR)achDomainName;
#else // UNICODE
lpszDomainName = pDomainName;
#endif // UNICODE
//
// the resolved name is same of the orginal name,
// display the ipaddress.
//
//
// compare the entire name first.
//
if( _stricmp(
lpRevHostEnt->h_name,
lpszDomainName ) != 0 ) {
LPSTR lpszDotPostion1;
LPSTR lpszDotPostion2;
DWORD dwCmpLen = 0;
//
// compare the only the first part of the name.
//
lpszDotPostion1 = strchr( lpRevHostEnt->h_name, '.');
lpszDotPostion2 = strchr( lpszDomainName, '.');
if( (lpszDotPostion1 == NULL) &&
(lpszDotPostion2 != NULL) ) {
dwCmpLen = (DWORD)(lpszDotPostion2 - lpszDomainName);
}
else if( (lpszDotPostion1 != NULL) &&
(lpszDotPostion2 == NULL) ) {
dwCmpLen = (DWORD)(lpszDotPostion1 -
lpRevHostEnt->h_name);
}
if( dwCmpLen != 0 ) {
if( _strnicmp(
lpRevHostEnt->h_name,
lpszDomainName,
(size_t)dwCmpLen ) == 0 ) {
bIPAddressString = TRUE;
}
}
}
else {
bIPAddressString = TRUE;
}
}
if( bIPAddressString ) {
strcpy(
(LPSTR)achContainerName,
inet_ntoa( *(struct in_addr *)lpIPAddrs ));
}
else {
strcpy( (LPSTR)achContainerName, lpRevHostEnt->h_name);
}
#ifdef UNICODE
//
// convert to UNICODE.
//
nCount =
MultiByteToWideChar(
CP_ACP,
MB_COMPOSITE,
(LPSTR)achContainerName,
-1,
lpLBItem->ContainerName,
sizeof(lpLBItem->ContainerName)/sizeof(WCHAR));
if( nCount == 0 ) {
dwError = GetLastError();
goto Cleanup;
}
//
// terminate converted string.
//
lpLBItem->ContainerName[nCount] = _T('\0');
#else // UNICODE
strcpy( lpLBItem->ContainerName, (LPSTR)achContainerName );
#endif // UNICODE
lpLBItem->Comment[0] = _T('\0');
lpLBItem->bContainsServers = FALSE;;
lpLBItem->bServersExpandedOnce = FALSE;
lpLBItem->bDNSDomain = FALSE;
lpLBItem->nServerCount = 0;
lpLBItem->ServerItems = NULL;
//
// move to next entry.
//
lpLBItem++;
lpIPAddrs++;
}
//
// Hook the allotted ServerListItem to the server
// structure, it will be used in future.
//
plbi->ServerItems = lpServerListItem;
plbi->nServerCount = dwIPEntries;
//
// set lpServerListItem to NULL, so that
// it will not get freed.
//
lpServerListItem = NULL;
}
//
// When we are here ..
//
// plbi->ServerItems points to the servers ServerListItem array
// and plbi->nServerCount has the count.
//
//
// display entires.
//
lpLBItem = plbi->ServerItems;
hTree = GetDlgItem( hwndDlg, UI_IDC_SERVERS_TREE );
hTreeParentNode = plbi->hTreeItem;
for( i = 0; i < plbi->nServerCount; i++ ) {
lpLBItem->hTreeParentItem = hTreeParentNode;
lpLBItem->hTreeItem =
AddItemToTree(hTree, lpLBItem->ContainerName,
hTreeParentNode,
lpLBItem, SRV_TREE_SERVERLEVEL);
lpLBItem++;
}
//
// Refresh the dialog box.
//
InvalidateRect(hwndDlg, NULL, TRUE);
plbi->bServersExpandedOnce = TRUE;
dwEntriesDisplayed = plbi->nServerCount;
//
// We are done.
//
dwError = ERROR_SUCCESS;
Cleanup:
if( lpIPAddrsAlloted != NULL ) {
LocalFree( lpIPAddrsAlloted );
}
if( lpServerListItem != NULL ) {
LocalFree( lpServerListItem );
}
if( dwError != ERROR_SUCCESS ) {
//TRC_NRM((TB, "UIExpandDNSDomain failed, %ld", dwError));
}
SetLastError( dwError );
SetCursor(LoadCursor(NULL, IDC_ARROW));
return( dwEntriesDisplayed );
}
#ifdef OS_WIN32
DWORD WINAPI CBrowseServersCtl::UIStaticPopListBoxThread(LPVOID lpvThreadParm)
{
DWORD dwRetVal=0;
//TRC_ASSERT(lpvThreadParm, (TB, "Thread param is NULL (instance pointer should be set)\n"));
if(lpvThreadParm)
{
CBrowseServersCtl* pBrowseSrv = (CBrowseServersCtl*)lpvThreadParm;
dwRetVal = pBrowseSrv->UIPopListBoxThread(NULL);
}
return dwRetVal;
}
/****************************************************************************/
/* Name: UIPopListBoxThread */
/* */
/* Purpose: Thread function to populate the list box. */
/* */
/* Returns: Success/Failure of the function */
/* */
/* Params: */
/* */
/****************************************************************************/
DWORD WINAPI CBrowseServersCtl::UIPopListBoxThread(LPVOID lpvThreadParm)
{
DWORD dwResult = 0;
ServerListItem *pBrowsePlbi = NULL, *ptempList = NULL;
DCUINT browseCount = 0;
DC_IGNORE_PARAMETER(lpvThreadParm);
// TRC_ASSERT( _hwndDialog, (TB, "_hwndDialog is not set\n"));
PostMessage(_hwndDialog, UI_LB_POPULATE_START, 0, 0);
LoadLibraries();
pBrowsePlbi = PopulateListBox( _hwndDialog, &browseCount);
//message is posted to the main thread to notify that the listbox has been populated
PostMessage(_hwndDialog, UI_LB_POPULATE_END, 0, 0);
//wait for the event to be signalled when the "connect server" dialog box is destroyed
if(_hEvent)
{
DWORD dwRetVal;
dwRetVal = WaitForSingleObject(_hEvent, INFINITE);
if(WAIT_FAILED == dwRetVal)
{
/// TRC_ASSERT(WAIT_FAILED != dwRetVal, (TB, "Wait failed\n"));
}
if(!CloseHandle(_hEvent))
{
DWORD dwLastErr = GetLastError();
// TRC_ABORT((TB, "Close handle failed: GetLastError=%d\n",dwLastErr));
}
}
ptempList = pBrowsePlbi;
//free the ServerListItems and memory to linked-list
if(pBrowsePlbi)
{
while(browseCount)
{
if(ptempList->ServerItems)
{
LocalFree((HANDLE)ptempList->ServerItems);
}
ptempList++;
browseCount --;
}
LocalFree((HLOCAL)pBrowsePlbi);
}
//decrement ref count for this object held by this thread
Release();
return (dwResult);
} /*UIPopListBoxThread*/
#endif /* OS_WIN32 */
HTREEITEM CBrowseServersCtl::AddItemToTree( HWND hwndTV, LPTSTR lpszItem,
HTREEITEM hParent,
ServerListItem* pItem,
int nLevel)
{
TVITEM tvi;
TVINSERTSTRUCT tvins;
#ifndef OS_WINCE
HTREEITEM hti;
#endif
tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE |TVIF_SELECTEDIMAGE;
if(nLevel == SRV_TREE_DOMAINLEVEL)
{
//
// Assume all domains have child servers
// they won't actually be enumerated until
// the user tries to expand the nodes
//
tvi.mask |= TVIF_CHILDREN;
tvi.cChildren = 1; //min number of children, will be updated
tvi.iImage = _nDomainImage;
tvi.iSelectedImage = _nDomainImage;
}
else
{
tvi.iImage = _nServerImage;
tvi.iSelectedImage = _nServerImage;
}
// Set the text of the item.
tvi.pszText = lpszItem;
tvi.cchTextMax = lstrlen(lpszItem);
// Save the ServerListItem info in the user defined area
// data area.
tvi.lParam = (LPARAM) pItem;
tvins.item = tvi;
tvins.hInsertAfter = _hPrev;
// Set the parent item based on the specified level.
tvins.hParent = hParent;
// Add the item to the tree view control.
_hPrev = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0,
(LPARAM) (LPTVINSERTSTRUCT) &tvins);
// Save the handle to the item.
if (nLevel == SRV_TREE_DOMAINLEVEL)
_hPrevRootItem = _hPrev;
else if (nLevel == SRV_TREE_SERVERLEVEL)
_hPrevLev2Item = _hPrev;
return _hPrev;
}
//
//Handle TVN_ITEMEXPANDING
//
// On first expansion of a domain node, enumerate
// all the servers in that node and add them to the
// tree. Subsequent expands/collapses will just be handled
// by the tree.
//
// Return TRUE to allow expansion
// false otherwise
//
BOOL CBrowseServersCtl::OnItemExpanding(HWND hwndDlg, LPNMTREEVIEW nmTv)
{
ServerListItem* pSrvItem = NULL;
if(nmTv &&
(TVE_EXPAND == nmTv->action) &&
(nmTv->itemNew.mask & TVIF_PARAM))
{
//
// Expanding, need to build the list
// of servers for this domain
//
pSrvItem = (ServerListItem*)nmTv->itemNew.lParam;
if(pSrvItem)
{
//
// Only expanddomain if we've never expanded this node
// before
//
if(!pSrvItem->bServersExpandedOnce)
{
//Attempt to expand the domain
DWORD cItems = 0;
if(ExpandDomain( hwndDlg, pSrvItem->ContainerName,
pSrvItem, (DWORD*)&cItems))
{
return TRUE;
}
else
{
//
// Pop a message explaining that
// there are no TS's in this domain
//
UINT intRC;
TCHAR noTerminalServer[MAX_PATH];
intRC = LoadString(_hInst,
UI_IDS_NO_TERMINAL_SERVER,
noTerminalServer,
MAX_PATH);
if(intRC)
{
TCHAR title[MAX_PATH];
intRC = LoadString(_hInst,
UI_IDS_APP_NAME,
title,
MAX_PATH);
if(intRC)
{
DCTCHAR szBuffer[MAX_PATH +
BROWSE_MAX_ADDRESS_LENGTH];
_stprintf(szBuffer, noTerminalServer,
pSrvItem->ContainerName);
MessageBox( hwndDlg, szBuffer, title,
MB_OK | MB_ICONINFORMATION);
}
}
return FALSE;
}
}
else
{
//Already expanded so everythign is cached
//and ready to go, allow expansion
return TRUE;
}
}
else
{
return FALSE;
}
}
else
{
//Allow everythign else to expand
return TRUE;
}
}
BOOL CBrowseServersCtl::OnNotify( HWND hwndDlg, WPARAM wParam, LPARAM lParam)
{
LPNMHDR pnmh = (LPNMHDR) lParam;
if(pnmh)
{
switch( pnmh->code)
{
case TVN_ITEMEXPANDING:
{
return OnItemExpanding(
hwndDlg, (LPNMTREEVIEW) lParam);
}
break;
}
}
return TRUE;
}
#ifndef OS_WINCE
//
// Returns currently selected server
// or false if current selection is not a server but a domain
//
BOOL CBrowseServersCtl::GetServer(LPTSTR szServer, int cchLen)
{
HTREEITEM hti;
HWND hTree;
if(!_hwndDialog)
{
return FALSE;
}
hTree = GetDlgItem( _hwndDialog, UI_IDC_SERVERS_TREE );
hti = TreeView_GetSelection( hTree );
if( hti )
{
TVITEM item;
item.hItem = hti;
item.mask = TVIF_PARAM;
if(TreeView_GetItem( hTree, &item))
{
ServerListItem* ps = (ServerListItem*)item.lParam;
if(ps && !ps->bContainsServers)
{
_tcsncpy( szServer, ps->ContainerName, cchLen);
return TRUE;
}
}
}
return FALSE;
}
#else
BOOL CBrowseServersCtl::GetServer(LPTSTR szServer, int cchLen)
{
HTREEITEM hti;
HWND hTree;
if(!_hwndDialog)
{
return FALSE;
}
hTree = GetDlgItem( _hwndDialog, UI_IDC_SERVERS_TREE );
hti = TreeView_GetSelection( hTree );
if( hti )
{
TVITEM item;
item.hItem = hti;
item.mask = TVIF_TEXT | TVIF_PARAM;;
item.pszText = szServer;
item.cchTextMax = cchLen;
if(TreeView_GetItem( hTree, &item))
{
_tcsncpy( szServer, item.pszText, item.cchTextMax);
return TRUE;
}
}
return FALSE;
}
#endif