// // 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; ihTreeItem, 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