Leaked source code of windows server 2003
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.

2417 lines
45 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1998 - 1999
  3. All rights reserved.
  4. Module Name:
  5. findloc.cxx
  6. Abstract:
  7. This module provides all the functions for browsing the
  8. physical location tree stored in an Active Directory
  9. Author:
  10. Lazar Ivanov (LazarI) 23-Nov-1998
  11. Steve Kiraly (SteveKi) 24-Nov-1998
  12. Lazar Ivanov (LazarI) Nov-28-2000 - redesign the tokenizer
  13. Weihai Chen (WeihaiC) Mar-28-2001 - use DS search to enumerate location data
  14. Revision History:
  15. --*/
  16. #include "precomp.hxx"
  17. #pragma hdrstop
  18. #include "dsinterf.hxx"
  19. #include "findloc.hxx"
  20. #include "physloc.hxx"
  21. enum
  22. {
  23. kDSIconIndex = 1,
  24. };
  25. /******************************************************************************
  26. Utility functions
  27. ******************************************************************************/
  28. /*++
  29. Name:
  30. vRecursiveGetSel
  31. Description:
  32. Finds the selecton string denoted by parent nodes
  33. of the current treeview item, then appends
  34. string of the current item
  35. Arguments:
  36. hTree - handle to treeview control
  37. pItem - pointer to current item
  38. strSel - reference to string to fill in
  39. hStop - tree item to stop recursing
  40. Return Value:
  41. None
  42. Notes:
  43. --*/
  44. VOID
  45. vRecursiveGetSel (
  46. IN HWND hTree,
  47. IN const TVITEM *pItem,
  48. OUT TString &strSel,
  49. IN HTREEITEM hStop
  50. )
  51. {
  52. TVITEM tvParent;
  53. TCHAR szItem[TPhysicalLocation::kMaxPhysicalLocation];
  54. TStatusB bStatus;
  55. tvParent.mask = TVIF_TEXT|TVIF_HANDLE;
  56. tvParent.pszText = szItem;
  57. tvParent.cchTextMax = TPhysicalLocation::kMaxPhysicalLocation;
  58. //
  59. // If we're at the root, init the string
  60. //
  61. if ((tvParent.hItem = TreeView_GetParent (hTree, pItem->hItem))==hStop)
  62. {
  63. bStatus DBGCHK = strSel.bUpdate (pItem->pszText);
  64. }
  65. else
  66. {
  67. //
  68. // Get the string denoted by my parent nodes, then append my string
  69. //
  70. TreeView_GetItem (hTree, &tvParent);
  71. vRecursiveGetSel (hTree, &tvParent, strSel, hStop);
  72. bStatus DBGCHK = strSel.bCat (pItem->pszText);
  73. }
  74. //
  75. // Append a slash
  76. //
  77. bStatus DBGCHK = strSel.bCat (gszSlash);
  78. }
  79. /*++
  80. Name:
  81. Tokenize
  82. Description:
  83. Replace any valid separators with NULL in the dest string
  84. Arguments:
  85. LPTSTR pszDest - where to put the dest string
  86. UNIT nMaxLength - size of the buffer of dest
  87. LPCTSTR pszSrc - source string
  88. LPTSTR *pszStart - start markup
  89. LPTSTR *pszEnd - end markup
  90. Return Value:
  91. None
  92. --*/
  93. VOID
  94. Tokenize(
  95. OUT LPTSTR pszDest,
  96. IN UINT nMaxLength,
  97. IN LPCTSTR pszSrc,
  98. OUT LPTSTR *pszStart,
  99. OUT LPTSTR *pszEnd
  100. )
  101. {
  102. ASSERT(pszDest);
  103. ASSERT(nMaxLength);
  104. ASSERT(pszSrc);
  105. ASSERT(pszStart);
  106. ASSERT(pszEnd);
  107. // make a copy
  108. lstrcpyn(pszDest, pszSrc, nMaxLength);
  109. // replace all the valid separators with zeros
  110. int i, iLen = lstrlen(pszDest);
  111. for( i=0; i<iLen; i++ )
  112. {
  113. if( TEXT('\\') == pszDest[i] || TEXT('/') == pszDest[i] )
  114. {
  115. pszDest[i] = 0;
  116. }
  117. }
  118. // initialize the walk pointers
  119. *pszStart = pszDest;
  120. *pszEnd = pszDest + iLen;
  121. }
  122. /******************************************************************************
  123. TLocData methods
  124. ******************************************************************************/
  125. /*++
  126. Name:
  127. TLocData constructor
  128. Description:
  129. Creates the TLocData, the TLocData is the data that is shared between
  130. the UI thread and the background thread. To ensure the data's life time
  131. refrence counting is used.
  132. Arguments:
  133. pszClassName
  134. pszWindowName - the class name and window name of toplevel window
  135. where the message will be posted when data is ready
  136. uMsgDataReady - the user message posted, which should be posted
  137. bFindPhysicalLocation - should expand default
  138. Return Value:
  139. None
  140. Notes:
  141. --*/
  142. TLocData::
  143. TLocData(
  144. IN LPCTSTR pszClassName,
  145. IN LPCTSTR pszPropertyName,
  146. IN UINT uMsgDataReady,
  147. IN BOOL bFindPhysicalLocation
  148. ) :
  149. _uMsgDataReady(uMsgDataReady),
  150. _bFindPhysicalLocation(bFindPhysicalLocation),
  151. _bIsDataReady(FALSE),
  152. _strWindowClass( pszClassName ),
  153. _strPropertyName( pszPropertyName )
  154. {
  155. _bValid = _strWindowClass.bValid() && _strPropertyName.bValid();
  156. }
  157. /*++
  158. Name:
  159. TLocData destructor
  160. Description:
  161. Deletes the linked list nodes
  162. Arguments:
  163. None
  164. Return Value:
  165. None
  166. Notes:
  167. --*/
  168. TLocData::
  169. ~TLocData(
  170. VOID
  171. )
  172. {
  173. //
  174. // Free the locations list
  175. //
  176. TLoc *pLoc;
  177. while( !_LocationList_bEmpty() )
  178. {
  179. pLoc = _LocationList_pHead();
  180. pLoc->_Location_vDelinkSelf();
  181. delete pLoc;
  182. }
  183. }
  184. /*++
  185. Name:
  186. bValid
  187. Description:
  188. Class valid check routine.
  189. Arguments:
  190. None
  191. Return Value:
  192. TRUE - class is valid and usable,
  193. FALSE - class is not usable.
  194. Notes:
  195. --*/
  196. BOOL
  197. TLocData::
  198. bValid(
  199. VOID
  200. ) const
  201. {
  202. return _bValid;
  203. }
  204. /*++
  205. Name:
  206. TLocData::vNotifyUIDataIsReady
  207. Description:
  208. Notify the UI the background work is done
  209. Arguments:
  210. None
  211. Return Value:
  212. None
  213. Notes:
  214. --*/
  215. VOID
  216. TLocData::
  217. vNotifyUIDataIsReady(
  218. VOID
  219. )
  220. {
  221. //
  222. // Check if the data is ready first
  223. //
  224. if( _bIsDataReady )
  225. {
  226. for (HWND hWnd = FindWindow(_strWindowClass, NULL); hWnd; hWnd = GetWindow(hWnd, GW_HWNDNEXT))
  227. {
  228. TCHAR szBuffer[MAX_PATH];
  229. if( !GetClassName(hWnd, szBuffer, COUNTOF(szBuffer)) )
  230. {
  231. continue;
  232. }
  233. //
  234. // check again ensure that class name is same
  235. // if we obtained this handle from GetWindow( ... )
  236. //
  237. if( !_tcsicmp( szBuffer, _strWindowClass ) )
  238. {
  239. HANDLE hProp = GetProp( hWnd, _strPropertyName );
  240. //
  241. // Just verify who we are?
  242. //
  243. if( hProp == reinterpret_cast<HANDLE>(this) )
  244. {
  245. //
  246. // Apropriate window found - post the message
  247. //
  248. PostMessage( hWnd, _uMsgDataReady, 0, reinterpret_cast<LPARAM>(this) );
  249. break;
  250. }
  251. }
  252. }
  253. }
  254. }
  255. /*++
  256. Name:
  257. TLocData::FindLocationsThread
  258. Description:
  259. static thread procedure, invokes the real worker proc
  260. Arguments:
  261. pData - TLocData object pointer to call
  262. Return Value:
  263. None
  264. Notes:
  265. --*/
  266. VOID
  267. TLocData::
  268. FindLocationsThread (
  269. IN TLocData *pData
  270. )
  271. {
  272. //
  273. // Explore the locations (this is a
  274. // slow resource access operation)
  275. //
  276. pData->vDoTheWork();
  277. //
  278. // Data is consistent to be used here
  279. //
  280. pData->_bIsDataReady = TRUE;
  281. //
  282. // Notify UI we are ready
  283. //
  284. pData->vNotifyUIDataIsReady();
  285. //
  286. // Unhook from data
  287. //
  288. pData->cDecRef();
  289. }
  290. /*++
  291. Name:
  292. TLocData::vRefZeroed
  293. Description:
  294. Called when ref count reaches zero. Deletes the object
  295. Arguments:
  296. None
  297. Return Value:
  298. None
  299. Notes:
  300. --*/
  301. VOID
  302. TLocData::
  303. vRefZeroed(
  304. VOID
  305. )
  306. {
  307. //
  308. // No more clients - just kill myself, game over
  309. //
  310. delete this;
  311. }
  312. /*++
  313. Name:
  314. TLocData::bSearchLocations
  315. Description:
  316. Opens the Active Directory and searches the configuration
  317. container to find the location property of each Subnet.
  318. Arguments:
  319. ds - The active directory object
  320. Return Value:
  321. TRUE - on success
  322. FALSE - on failure
  323. Notes:
  324. --*/
  325. BOOL
  326. TLocData::
  327. bSearchLocations(
  328. IN TDirectoryService &ds
  329. )
  330. {
  331. static const DWORD kMaxPageSize = 10000;
  332. static ADS_SEARCHPREF_INFO prefInfo[3];
  333. static LPWSTR ppszPropertyName[] = {
  334. const_cast<LPWSTR>(gszLocation)
  335. };
  336. TString strConfig;
  337. TString strSubnet;
  338. ADS_SEARCH_HANDLE hSearch = NULL;
  339. ADS_SEARCH_COLUMN column;
  340. IDirectorySearch* pDsSearch = NULL;
  341. TStatusB bStatus;
  342. TStatusH hResult;
  343. DWORD cItems;
  344. //
  345. // Set search preferences
  346. //
  347. //
  348. // one level search
  349. //
  350. prefInfo[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  351. prefInfo[0].vValue.dwType = ADSTYPE_INTEGER;
  352. prefInfo[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  353. //
  354. // async search
  355. //
  356. prefInfo[1].dwSearchPref = ADS_SEARCHPREF_ASYNCHRONOUS;
  357. prefInfo[1].vValue.dwType = ADSTYPE_BOOLEAN;
  358. prefInfo[1].vValue.Boolean = TRUE;
  359. //
  360. // paged results
  361. //
  362. prefInfo[2].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  363. prefInfo[2].vValue.dwType = ADSTYPE_INTEGER;
  364. prefInfo[2].vValue.Integer = kMaxPageSize;
  365. //
  366. // Get the configuration path
  367. //
  368. bStatus DBGCHK = ds.GetConfigurationContainer (strConfig);
  369. if (bStatus)
  370. {
  371. TString strLDAPPrefix;
  372. //
  373. // Append config path to the subnet string
  374. //
  375. bStatus DBGCHK = strSubnet.bUpdate( gszLdapPrefix ) &&
  376. strSubnet.bCat( gszSubnetContainter ) &&
  377. strSubnet.bCat( gszComma ) &&
  378. strSubnet.bCat( strConfig );
  379. if(bStatus)
  380. {
  381. //
  382. // Get container interface for the subnets object
  383. //
  384. hResult DBGCHK = ds.ADsGetObject ( const_cast<LPTSTR>(static_cast<LPCTSTR>(strSubnet)),
  385. IID_IDirectorySearch,
  386. reinterpret_cast<LPVOID*>(&pDsSearch));
  387. if (SUCCEEDED(hResult))
  388. {
  389. //
  390. // Search for the subnet objects
  391. //
  392. hResult DBGCHK = pDsSearch->SetSearchPreference(prefInfo, ARRAYSIZE(prefInfo));
  393. }
  394. if (SUCCEEDED (hResult))
  395. {
  396. hResult DBGCHK = pDsSearch->ExecuteSearch(L"(Objectclass=*)",
  397. ppszPropertyName,
  398. ARRAYSIZE (ppszPropertyName),
  399. &hSearch);
  400. }
  401. for (cItems = 0 ; cItems < kMaxPageSize && SUCCEEDED (hResult); cItems++)
  402. {
  403. hResult DBGCHK = pDsSearch->GetNextRow(hSearch);
  404. if (hResult == S_ADS_NOMORE_ROWS)
  405. {
  406. //
  407. // we have more data so lets continue
  408. //
  409. hResult DBGCHK = S_OK;
  410. break;
  411. }
  412. //
  413. // Get the Name and display it in the list.
  414. //
  415. hResult DBGCHK = pDsSearch->GetColumn( hSearch, ppszPropertyName[0], &column );
  416. if (SUCCEEDED(hResult))
  417. {
  418. switch (column.dwADsType)
  419. {
  420. case ADSTYPE_CASE_IGNORE_STRING:
  421. if (column.pADsValues->CaseIgnoreString && column.pADsValues->CaseIgnoreString[0])
  422. {
  423. //
  424. // This subnet has a location property
  425. //
  426. TLoc *pLoc = new TLoc();
  427. if( VALID_PTR(pLoc) )
  428. {
  429. pLoc->strLocation.bUpdate( column.pADsValues->CaseIgnoreString );
  430. _LocationList_vAppend(pLoc);
  431. }
  432. else
  433. {
  434. hResult DBGCHK = E_OUTOFMEMORY;
  435. break;
  436. }
  437. }
  438. break;
  439. default:
  440. hResult DBGCHK = E_INVALIDARG;
  441. break;
  442. }
  443. pDsSearch->FreeColumn(&column);
  444. }
  445. else if (hResult == E_ADS_COLUMN_NOT_SET)
  446. {
  447. //
  448. // The location data is not available for this subnet, ignore
  449. //
  450. hResult DBGCHK = S_OK;
  451. }
  452. }
  453. if (hSearch)
  454. {
  455. pDsSearch->CloseSearchHandle (hSearch);
  456. }
  457. if (pDsSearch)
  458. {
  459. pDsSearch->Release();
  460. }
  461. }
  462. }
  463. //
  464. // Make this final check
  465. //
  466. if(bStatus)
  467. {
  468. bStatus DBGCHK = SUCCEEDED(hResult);
  469. }
  470. return bStatus;
  471. }
  472. /*++
  473. Name:
  474. TLocData::vDoTheWork
  475. Description:
  476. Opens the Active Directory and searches the configuration
  477. container to find the location property of each Subnet.
  478. Arguments:
  479. None
  480. Return Value:
  481. None
  482. Notes:
  483. --*/
  484. VOID
  485. TLocData::
  486. vDoTheWork(
  487. VOID
  488. )
  489. {
  490. TStatusB bStatus;
  491. TDirectoryService ds;
  492. bStatus DBGCHK = ds.bValid();
  493. //
  494. // Lookup for the DS name first
  495. //
  496. if( bStatus )
  497. {
  498. bStatus DBGCHK = ds.bGetDirectoryName( _strDSName );
  499. }
  500. //
  501. // Enumerate the subnet objects
  502. //
  503. if( bStatus )
  504. {
  505. bStatus DBGCHK = bSearchLocations (ds);
  506. }
  507. //
  508. // Find out the exact location of the current machine
  509. //
  510. if( bStatus )
  511. {
  512. TPhysicalLocation physLoc;
  513. if (_bFindPhysicalLocation && physLoc.Discover())
  514. {
  515. physLoc.GetExact (_strDefault);
  516. }
  517. }
  518. }
  519. /******************************************************************************
  520. TLocData::TLoc
  521. ******************************************************************************/
  522. TLocData::
  523. TLoc::
  524. TLoc(
  525. VOID
  526. )
  527. {
  528. }
  529. TLocData::
  530. TLoc::
  531. ~TLoc(
  532. VOID
  533. )
  534. {
  535. }
  536. /******************************************************************************
  537. TLocTree methods
  538. ******************************************************************************/
  539. /*++
  540. Name:
  541. TLocTree constructor
  542. Description:
  543. Creates the imagelist for the tree control and inserts the
  544. root string that describes the choices.
  545. Arguments:
  546. None
  547. Return Value:
  548. None
  549. Notes:
  550. --*/
  551. TLocTree::
  552. TLocTree(
  553. IN HWND hwnd
  554. )
  555. {
  556. HICON hIcon;
  557. TCHAR szIconLocation[MAX_PATH];
  558. INT iIconIndex;
  559. TStatusB bStatus;
  560. _hwndTree = hwnd;
  561. _iGlobe = 0;
  562. _iSite = 0;
  563. _bWaitData = TRUE;
  564. _hCursorWait = LoadCursor(NULL, IDC_WAIT);
  565. _DefProc = NULL;
  566. //
  567. // Create the simple imagelist
  568. // If this fails, the tree items just won't have icons
  569. //
  570. bStatus DBGCHK = Shell_GetImageLists( NULL, &_hIml );
  571. if (_hIml)
  572. {
  573. IDsDisplaySpecifier *pDisplay = NULL;
  574. //
  575. // Use IDsDisplaySpecifier::GetIcon to find path to the icons
  576. // for sites and subnets.
  577. //
  578. if (SUCCEEDED(CoCreateInstance(CLSID_DsDisplaySpecifier,
  579. NULL,
  580. CLSCTX_INPROC_SERVER,
  581. IID_IDsDisplaySpecifier,
  582. reinterpret_cast<LPVOID *>(&pDisplay))))
  583. {
  584. _iGlobe = Shell_GetCachedImageIndex (gszDSIconFile,
  585. kDSIconIndex,
  586. 0);
  587. pDisplay->GetIconLocation (gszSiteIconClass,
  588. DSGIF_GETDEFAULTICON,
  589. szIconLocation,
  590. MAX_PATH,
  591. &iIconIndex);
  592. _iSite = Shell_GetCachedImageIndex (szIconLocation,
  593. iIconIndex,
  594. 0);
  595. pDisplay->Release();
  596. TreeView_SetImageList (_hwndTree, _hIml, TVSIL_NORMAL);
  597. }
  598. }
  599. //
  600. // Subclass tree control to handle WM_SETCURSOR message
  601. //
  602. _DefProc = reinterpret_cast<WNDPROC>( GetWindowLongPtr( _hwndTree, GWLP_WNDPROC ) );
  603. SetWindowLongPtr( _hwndTree, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this) );
  604. SetWindowLongPtr( _hwndTree, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&TLocTree::ThunkProc) );
  605. }
  606. /*++
  607. Name:
  608. TLocTree destructor
  609. Description:
  610. Destroys the image list
  611. Arguments:
  612. None
  613. Return Value:
  614. None
  615. Notes:
  616. --*/
  617. TLocTree::
  618. ~TLocTree(
  619. VOID
  620. )
  621. {
  622. //
  623. // Unsubclass here
  624. //
  625. SetWindowLongPtr( _hwndTree, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(_DefProc) );
  626. SetWindowLongPtr( _hwndTree, GWLP_USERDATA, 0 );
  627. //
  628. // No longer need the shared image list
  629. //
  630. if (_hIml)
  631. {
  632. TreeView_SetImageList (_hwndTree, NULL, TVSIL_NORMAL);
  633. }
  634. }
  635. /*++
  636. Name:
  637. TLocTree::vResetTree
  638. Description:
  639. Resets the tree content
  640. Arguments:
  641. None
  642. Return Value:
  643. None
  644. Notes:
  645. --*/
  646. VOID
  647. TLocTree::
  648. vResetTree(
  649. VOID
  650. )
  651. {
  652. //
  653. // Delete all items and start waiting
  654. // new data
  655. //
  656. TreeView_DeleteAllItems( _hwndTree );
  657. _bWaitData = TRUE;
  658. }
  659. /*++
  660. Name:
  661. TLocTree::vBuildTree
  662. Description:
  663. Build the tree control from a ready data
  664. Arguments:
  665. pLocData - Where to get data from
  666. Return Value:
  667. None
  668. Notes:
  669. --*/
  670. VOID
  671. TLocTree::
  672. vBuildTree(
  673. IN const TLocData *pLocData
  674. )
  675. {
  676. //
  677. // Check to reset the data
  678. //
  679. if( !_bWaitData )
  680. {
  681. vResetTree( );
  682. }
  683. if( !pLocData->_LocationList_bEmpty() )
  684. {
  685. //
  686. // Build the tree and Fill the tree with the data.
  687. //
  688. vInsertRootString( pLocData );
  689. vFillTree( pLocData );
  690. }
  691. //
  692. // Stop waiting data
  693. //
  694. _bWaitData = FALSE;
  695. }
  696. /*++
  697. Name:
  698. TLocTree::vInsertRootString
  699. Description:
  700. Inserts the root string in the tree control
  701. Arguments:
  702. None
  703. Return Value:
  704. None
  705. Notes:
  706. --*/
  707. VOID
  708. TLocTree::
  709. vInsertRootString(
  710. IN const TLocData *pLocData
  711. )
  712. {
  713. TVINSERTSTRUCT tviStruct;
  714. TString strRoot;
  715. TStatusB bStatus;
  716. TDirectoryService ds;
  717. TString strDSName;
  718. //
  719. // Insert the Root-level string that describes the control
  720. // This will be a combination of "Entire " + <directory name>
  721. //
  722. tviStruct.hParent = NULL;
  723. tviStruct.hInsertAfter = TVI_ROOT;
  724. tviStruct.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
  725. tviStruct.item.iImage = _iGlobe;
  726. tviStruct.item.iSelectedImage = _iGlobe;
  727. bStatus DBGCHK = strRoot.bLoadString( ghInst, IDS_LOCTREEROOT ) &&
  728. strRoot.bCat( pLocData->_strDSName );
  729. tviStruct.item.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(strRoot));
  730. tviStruct.item.cchTextMax = strRoot.uLen();
  731. _hRoot = TreeView_InsertItem (_hwndTree, &tviStruct);
  732. }
  733. /*++
  734. Name:
  735. TLocTree::bInsertLocString
  736. Description:
  737. Add the given location string to the tree control.
  738. Each level of the hierarchy is indicated by the '/'
  739. delimiter. Prevents duplicate entries at each level of
  740. the tree.
  741. Arguments:
  742. strLoc - location string to insert, Must be '/' delimited
  743. Return Value:
  744. TRUE - on success
  745. FALSE - on failure
  746. Notes:
  747. --*/
  748. BOOL
  749. TLocTree::
  750. bInsertLocString(
  751. IN const TString &strLoc
  752. ) const
  753. {
  754. // Start at the root.
  755. // For each '/' delimited string in szLoc,
  756. // add a level to the tree and insert the
  757. // string as a child node of the current node.
  758. // At each level don't insert duplicates.
  759. //
  760. HTREEITEM hCurrent, hChild;
  761. TVINSERTSTRUCT tviItem;
  762. TVITEM* pItem = &tviItem.item;
  763. DWORD dwErr;
  764. TCHAR szBuffer[512];
  765. LPTSTR psz, pszMax;
  766. if (!_hwndTree)
  767. {
  768. return FALSE;
  769. }
  770. // tokenize the input string
  771. Tokenize(szBuffer, ARRAYSIZE(szBuffer), strLoc, &psz, &pszMax);
  772. // initialize the item to insert
  773. memset(pItem, 0, sizeof(TVITEM));
  774. pItem->mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
  775. pItem->iImage = _iSite;
  776. pItem->iSelectedImage = _iSite;
  777. tviItem.hInsertAfter = TVI_SORT;
  778. hCurrent = _hRoot;
  779. while( hCurrent )
  780. {
  781. // find a valid token
  782. while( 0 == *psz && psz < pszMax )
  783. {
  784. psz++;
  785. }
  786. // if we've gone past the buffer break the loop
  787. if( psz >= pszMax )
  788. {
  789. break;
  790. }
  791. pItem->pszText = psz;
  792. tviItem.hParent = hCurrent;
  793. // if the current name already exists at this level don't insert
  794. if( hChild = IsAChild(psz, hCurrent) )
  795. {
  796. hCurrent = hChild;
  797. }
  798. else
  799. {
  800. hCurrent = TreeView_InsertItem (_hwndTree, &tviItem);
  801. }
  802. // advance the token pointer
  803. psz += lstrlen(psz);
  804. }
  805. return hCurrent ? TRUE : FALSE;
  806. }
  807. /*++
  808. Name:
  809. TLocTree::IsAChild
  810. Description:
  811. Determines if szLoc exists at the level of the
  812. tree whose parent is hParent. If so, return
  813. the handle of the node containing szLoc
  814. Arguments:
  815. szLoc - string to search for
  816. hParent - parent node
  817. Return Value:
  818. Handle to treeview item matching szLoc, or NULL if not found
  819. Notes:
  820. --*/
  821. HTREEITEM
  822. TLocTree::
  823. IsAChild(
  824. IN LPCTSTR szLoc,
  825. IN HTREEITEM hParent
  826. ) const
  827. {
  828. TVITEM tvItem;
  829. HTREEITEM hItem;
  830. TCHAR szItemText[TPhysicalLocation::kMaxPhysicalLocation];
  831. BOOL bMatch = FALSE;
  832. tvItem.mask = TVIF_TEXT | TVIF_HANDLE;
  833. tvItem.pszText = szItemText;
  834. tvItem.cchTextMax = TPhysicalLocation::kMaxPhysicalLocation;
  835. hItem = TreeView_GetChild (_hwndTree, hParent);
  836. while (hItem && !bMatch)
  837. {
  838. tvItem.hItem = hItem;
  839. TreeView_GetItem (_hwndTree, &tvItem);
  840. bMatch = !_tcsicmp (szLoc, szItemText);
  841. if (bMatch)
  842. {
  843. break;
  844. }
  845. hItem = TreeView_GetNextSibling (_hwndTree, hItem);
  846. }
  847. if (!bMatch)
  848. {
  849. hItem = NULL;
  850. }
  851. return hItem;
  852. }
  853. /*++
  854. Name:
  855. TLocTree::uGetSelectedLocation
  856. Description:
  857. Walks the tree control from the selected item to
  858. the root, building the slash-delimited location
  859. string name.
  860. Arguments:
  861. strLoc - string to update
  862. Return Value:
  863. TRUE - on success
  864. FALSE - otherwise
  865. Notes:
  866. --*/
  867. BOOL
  868. TLocTree::
  869. bGetSelectedLocation(
  870. OUT TString &strLoc
  871. ) const
  872. {
  873. TVITEM tvItem;
  874. TStatusB status;
  875. TCHAR szTemp[TPhysicalLocation::kMaxPhysicalLocation];
  876. tvItem.mask = TVIF_TEXT|TVIF_HANDLE;
  877. tvItem.cchTextMax = TPhysicalLocation::kMaxPhysicalLocation;
  878. tvItem.pszText = szTemp;
  879. //
  880. // Get the selected item
  881. //
  882. tvItem.hItem = TreeView_GetSelection (_hwndTree);
  883. if (tvItem.hItem == _hRoot)
  884. {
  885. status DBGCHK = strLoc.bUpdate(_T("\0"));
  886. return status;
  887. }
  888. status DBGCHK = TreeView_GetItem (_hwndTree, &tvItem);
  889. if (status)
  890. {
  891. vRecursiveGetSel (_hwndTree, &tvItem, strLoc, _hRoot);
  892. }
  893. return status;
  894. }
  895. /*++
  896. Name:
  897. TLocTree::vExpandTree
  898. Description:
  899. Expands the tree view control to make visible the node
  900. corresponding to the given location string
  901. Arguments:
  902. strExpand - slash-delimited location string to expand tree by
  903. Return Value:
  904. None
  905. Notes:
  906. --*/
  907. VOID
  908. TLocTree::
  909. vExpandTree(
  910. IN const TString &strExpand
  911. ) const
  912. {
  913. if( strExpand.uLen() )
  914. {
  915. HTREEITEM hParent, hItem;
  916. TCHAR szBuffer[512];
  917. LPTSTR psz, pszMax;
  918. // tokenize the input string
  919. Tokenize(szBuffer, ARRAYSIZE(szBuffer), strExpand, &psz, &pszMax);
  920. hParent = _hRoot;
  921. for( ;; )
  922. {
  923. // find a valid token
  924. while( 0 == *psz && psz < pszMax )
  925. {
  926. psz++;
  927. }
  928. // if we've gone past the buffer break the loop
  929. if( psz >= pszMax )
  930. {
  931. break;
  932. }
  933. if( hItem = IsAChild(psz, hParent) )
  934. {
  935. // a valid child - remember
  936. hParent = hItem;
  937. // advance to the next token
  938. psz += lstrlen(psz);
  939. }
  940. else
  941. {
  942. // not a child, bail out
  943. break;
  944. }
  945. }
  946. if (hParent)
  947. {
  948. TreeView_EnsureVisible(_hwndTree, hParent);
  949. TreeView_SelectItem(_hwndTree, hParent);
  950. }
  951. }
  952. }
  953. /*++
  954. Name:
  955. vFillTree
  956. Description:
  957. Walks through the linked list and adds strings to the TLocTree object
  958. Arguments:
  959. pLocData - Where to get data from
  960. Return Value:
  961. None
  962. Notes:
  963. --*/
  964. VOID
  965. TLocTree::
  966. vFillTree(
  967. IN const TLocData *pLocData
  968. ) const
  969. {
  970. TIter Iter;
  971. TLocData::TLoc *pLoc;
  972. TStatusB status = TRUE;
  973. for( pLocData->_LocationList_vIterInit(Iter), Iter.vNext(); Iter.bValid(); Iter.vNext() )
  974. {
  975. pLoc = pLocData->_LocationList_pConvert( Iter );
  976. status DBGCHK = bInsertLocString( pLoc->strLocation );
  977. }
  978. }
  979. /*++
  980. Name:
  981. TLocTree::ThunkProc
  982. Description:
  983. Thunk control proc (for subclassing)
  984. Arguments:
  985. Standard window proc parameters
  986. Return Value:
  987. None
  988. Notes:
  989. --*/
  990. LRESULT CALLBACK
  991. TLocTree::
  992. ThunkProc(
  993. IN HWND hwnd,
  994. IN UINT uMsg,
  995. IN WPARAM wParam,
  996. IN LPARAM lParam
  997. )
  998. {
  999. LRESULT lResult = 0;
  1000. TLocTree *This = reinterpret_cast<TLocTree*>( GetWindowLongPtr( hwnd, GWLP_USERDATA ) );
  1001. if( This )
  1002. {
  1003. if( WM_DESTROY == uMsg || WM_NCDESTROY == uMsg )
  1004. {
  1005. lResult = This->nHandleMessage( uMsg, wParam, lParam );
  1006. SetWindowLongPtr( hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(This->_DefProc) );
  1007. SetWindowLongPtr( hwnd, GWLP_USERDATA, 0 );
  1008. }
  1009. else
  1010. {
  1011. SPLASSERT( hwnd == This->_hwndTree );
  1012. lResult = This->nHandleMessage( uMsg, wParam, lParam );
  1013. if( !lResult )
  1014. {
  1015. //
  1016. // Message is not handled go to
  1017. // default processing
  1018. //
  1019. lResult = This->_DefProc( hwnd, uMsg, wParam, lParam );
  1020. }
  1021. }
  1022. }
  1023. return lResult;
  1024. }
  1025. /*++
  1026. Name:
  1027. TLocTree::nHandleMessage
  1028. Description:
  1029. Message handler function
  1030. Arguments:
  1031. Standard window proc parameters
  1032. Return Value:
  1033. None
  1034. Notes:
  1035. --*/
  1036. LRESULT
  1037. TLocTree::
  1038. nHandleMessage(
  1039. IN UINT uMsg,
  1040. IN WPARAM wParam,
  1041. IN LPARAM lParam
  1042. )
  1043. {
  1044. //
  1045. // assume message is processed
  1046. //
  1047. LRESULT lResult = 1;
  1048. switch( uMsg )
  1049. {
  1050. case WM_SETCURSOR:
  1051. {
  1052. if( _bWaitData )
  1053. {
  1054. //
  1055. // Set hourglass cursor
  1056. //
  1057. SetCursor( _hCursorWait );
  1058. }
  1059. else
  1060. {
  1061. //
  1062. // Message is not processed - go default processing
  1063. //
  1064. lResult = 0;
  1065. }
  1066. }
  1067. break;
  1068. default:
  1069. {
  1070. //
  1071. // Message is not processed - go default processing
  1072. //
  1073. lResult = 0;
  1074. }
  1075. break;
  1076. }
  1077. return lResult;
  1078. }
  1079. /******************************************************************************
  1080. TFindLocDlg functions
  1081. ******************************************************************************/
  1082. /*++
  1083. Name:
  1084. TFindLocDlg::bGenerateGUIDAsString
  1085. Description:
  1086. This function will generate a GUID,
  1087. convert it to string and return it
  1088. Arguments:
  1089. pstrGUID - where to place the genearted GUID
  1090. Return Value:
  1091. TRUE on success
  1092. FALSE on failure
  1093. Notes:
  1094. --*/
  1095. BOOL
  1096. TFindLocDlg::
  1097. bGenerateGUIDAsString(
  1098. OUT TString *pstrGUID
  1099. )
  1100. {
  1101. static const TCHAR szRegFormat[] = _T("{%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}");
  1102. //
  1103. // Assume failue
  1104. //
  1105. TStatusB bStatus = FALSE;
  1106. HRESULT hResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  1107. if( SUCCEEDED(hResult) )
  1108. {
  1109. GUID guid;
  1110. bStatus DBGCHK = SUCCEEDED(CoCreateGuid(&guid));
  1111. if( bStatus )
  1112. {
  1113. //
  1114. // Generate a registry format GUID string
  1115. //
  1116. bStatus DBGCHK = pstrGUID->bFormat( szRegFormat,
  1117. // first copy...
  1118. guid.Data1, guid.Data2, guid.Data3,
  1119. guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
  1120. guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7],
  1121. // second copy...
  1122. guid.Data1, guid.Data2, guid.Data3,
  1123. guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
  1124. guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
  1125. }
  1126. //
  1127. // Uninitialize COM after we finish
  1128. //
  1129. CoUninitialize( );
  1130. }
  1131. return bStatus;
  1132. }
  1133. /*++
  1134. Name:
  1135. TFindLocDlg constructor
  1136. Description:
  1137. Constructs TFindLocDlg object
  1138. Arguments:
  1139. flags - UI controlling flags (show/hide help button)
  1140. Return Value:
  1141. None
  1142. Notes:
  1143. --*/
  1144. TFindLocDlg::
  1145. TFindLocDlg(
  1146. IN ELocationUI flags
  1147. ) :
  1148. _pLocData(NULL),
  1149. _pTree(NULL),
  1150. _UIFlags(flags),
  1151. _bValid(TRUE),
  1152. _uMsgDataReady(0)
  1153. {
  1154. }
  1155. /*++
  1156. Name:
  1157. TFindLocDlg destructor
  1158. Description:
  1159. Releases refcount on the location object
  1160. Arguments:
  1161. None
  1162. Return Value:
  1163. None
  1164. Notes:
  1165. --*/
  1166. TFindLocDlg::
  1167. ~TFindLocDlg(
  1168. VOID
  1169. )
  1170. {
  1171. if (VALID_PTR(_pLocData))
  1172. {
  1173. _pLocData->cDecRef();
  1174. }
  1175. }
  1176. /*++
  1177. Name:
  1178. TFindLocDlg::bDoModal
  1179. Description:
  1180. Invokes the browse location dialog
  1181. Arguments:
  1182. hParent - hwnd of parent window
  1183. pstrDefault - default selection string, this is optional
  1184. Return Value:
  1185. TRUE - if dialog creation succeeds
  1186. FALSE - otherwise
  1187. Notes:
  1188. pstrDefault has NULL default value
  1189. --*/
  1190. BOOL
  1191. TFindLocDlg::
  1192. bDoModal(
  1193. IN HWND hParent,
  1194. OUT TString *pstrDefault OPTIONAL
  1195. )
  1196. {
  1197. TStatusB bStatus;
  1198. bStatus DBGNOCHK = TRUE;
  1199. if (pstrDefault)
  1200. {
  1201. bStatus DBGCHK = _strDefault.bUpdate( *pstrDefault );
  1202. }
  1203. //
  1204. // Register the window message, this message is used to inform the
  1205. // UI thread that the data fetched by the background thread is ready.
  1206. //
  1207. _uMsgDataReady = RegisterWindowMessage( _T("WM_BACKGROUNDTASKISREADY") );
  1208. //
  1209. // Check if we succeeded to register the message
  1210. // and update the default location
  1211. //
  1212. if( _bValid && _uMsgDataReady && bStatus )
  1213. {
  1214. //
  1215. // Check if data is not obtained from a previous call
  1216. // of bDoModal() function - if not then start background
  1217. // thread to explore locations from the directory
  1218. // service
  1219. //
  1220. if( !_pLocData )
  1221. {
  1222. //
  1223. // Generate the special property name
  1224. //
  1225. bStatus DBGCHK = bGenerateGUIDAsString( &_strPropertyName );
  1226. if( bStatus )
  1227. {
  1228. _pLocData = new TLocData( _T("#32770"), _strPropertyName, _uMsgDataReady, _strDefault.bEmpty() );
  1229. bStatus DBGCHK = VALID_PTR( _pLocData );
  1230. if( bStatus )
  1231. {
  1232. _pLocData->vIncRef( );
  1233. //
  1234. // Spin the background explorer thread here
  1235. //
  1236. bStatus DBGCHK = bStartTheBackgroundThread();
  1237. }
  1238. else
  1239. {
  1240. delete _pLocData;
  1241. _pLocData = NULL;
  1242. }
  1243. }
  1244. }
  1245. //
  1246. // Data is expected to be ready here or to be in
  1247. // process of exploration in background
  1248. //
  1249. if( bStatus )
  1250. {
  1251. //
  1252. // Everything looks fine - just show the UI
  1253. //
  1254. bStatus DBGCHK= (BOOL)DialogBoxParam( ghInst,
  1255. MAKEINTRESOURCE(DLG_BROWSE_LOC),
  1256. hParent,
  1257. MGenericDialog::SetupDlgProc,
  1258. reinterpret_cast<LPARAM>(this) );
  1259. }
  1260. }
  1261. return bStatus;
  1262. }
  1263. /*++
  1264. Name:
  1265. TFindLocDlg::uGetLocation
  1266. Description:
  1267. Fills in the location string selected when the dialog was open.
  1268. Arguments:
  1269. strLocation - TString to update
  1270. Return Value:
  1271. TRUE - on success,
  1272. FALSE - otherwise
  1273. Notes:
  1274. --*/
  1275. BOOL
  1276. TFindLocDlg::
  1277. bGetLocation(
  1278. OUT TString &strLocation
  1279. )
  1280. {
  1281. TStatusB bStatus;
  1282. bStatus DBGCHK = strLocation.bUpdate ((LPCTSTR)_strSelLocation);
  1283. return bStatus;
  1284. }
  1285. /*++
  1286. Name:
  1287. TFindLocDlg::vDataIsReady
  1288. Description:
  1289. Called when the background thread completes its work.
  1290. Always stops the wait cursor.
  1291. Arguments:
  1292. None
  1293. Return Value:
  1294. None
  1295. Notes:
  1296. --*/
  1297. VOID
  1298. TFindLocDlg::
  1299. vDataIsReady(
  1300. VOID
  1301. )
  1302. {
  1303. //
  1304. // Make sure the animation stops
  1305. //
  1306. vStopAnim();
  1307. //
  1308. // Fill in the tree control, and select the default string
  1309. //
  1310. _pTree->vBuildTree( _pLocData );
  1311. if( !_pLocData->_LocationList_bEmpty() )
  1312. {
  1313. //
  1314. // Expand the default location here
  1315. //
  1316. if (!_strDefault.bEmpty())
  1317. {
  1318. _pTree->vExpandTree(_strDefault);
  1319. }
  1320. else
  1321. {
  1322. _pTree->vExpandTree(_pLocData->_strDefault);
  1323. }
  1324. //
  1325. // Enable the OK button
  1326. //
  1327. EnableWindow (GetDlgItem (_hDlg, IDOK), TRUE);
  1328. }
  1329. //
  1330. // Place the focus in the tree control
  1331. //
  1332. PostMessage( _hDlg, WM_NEXTDLGCTL, reinterpret_cast<WPARAM>( GetDlgItem(_hDlg, IDC_LOCTREE) ), 1L );
  1333. }
  1334. /*++
  1335. Name:
  1336. TFindLocDlg::vOnOK
  1337. Description:
  1338. Called when the OK button is pressed.
  1339. Updates current selection string
  1340. Arguments:
  1341. None
  1342. Return Value:
  1343. None
  1344. Notes:
  1345. --*/
  1346. VOID
  1347. TFindLocDlg::
  1348. vOnOK(
  1349. VOID
  1350. )
  1351. {
  1352. //
  1353. // Get the selected location and close the dialog
  1354. //
  1355. _pTree->bGetSelectedLocation (_strSelLocation);
  1356. EndDialog (_hDlg, IDOK);
  1357. }
  1358. /*++
  1359. Name:
  1360. TFindLocDlg::vOnDestroy
  1361. Description:
  1362. Cleans up data allocated for current
  1363. dialog window instance
  1364. Arguments:
  1365. None
  1366. Return Value:
  1367. None
  1368. Notes:
  1369. --*/
  1370. VOID
  1371. TFindLocDlg::
  1372. vOnDestroy(
  1373. VOID
  1374. )
  1375. {
  1376. if (VALID_PTR(_pTree))
  1377. {
  1378. delete _pTree;
  1379. _pTree = NULL;
  1380. }
  1381. }
  1382. /*++
  1383. Name:
  1384. TFindLocDlg::bHandleMessage
  1385. Description:
  1386. Dispatches messages to appropriate handlers.
  1387. Arguments:
  1388. uMsg - message value
  1389. wParam, lParam - message params
  1390. Return Value:
  1391. TRUE - if message is handled,
  1392. FALSE - otherwise
  1393. Notes:
  1394. --*/
  1395. BOOL
  1396. TFindLocDlg::
  1397. bHandleMessage(
  1398. IN UINT uMsg,
  1399. IN WPARAM wParam,
  1400. IN LPARAM lParam
  1401. )
  1402. {
  1403. BOOL bHandled = TRUE;
  1404. //
  1405. // Check our registered message first
  1406. //
  1407. if( _uMsgDataReady == uMsg && reinterpret_cast<LPARAM>(_pLocData) == lParam )
  1408. {
  1409. vDataIsReady( );
  1410. bHandled = TRUE;
  1411. }
  1412. else
  1413. {
  1414. //
  1415. // Standard message processing
  1416. //
  1417. switch (uMsg)
  1418. {
  1419. case WM_INITDIALOG:
  1420. {
  1421. bHandled = bOnInitDialog();
  1422. }
  1423. break;
  1424. case WM_COMMAND:
  1425. {
  1426. //
  1427. // Handle WM_COMMAND messages
  1428. //
  1429. bHandled = bOnCommand( LOWORD(wParam) );
  1430. }
  1431. break;
  1432. case WM_NOTIFY:
  1433. {
  1434. //
  1435. // The only WM_NOTIFY source on the dialog is the TreeView
  1436. //
  1437. bHandled = bOnTreeNotify (reinterpret_cast<LPNMTREEVIEW>(lParam));
  1438. }
  1439. break;
  1440. case WM_HELP:
  1441. case WM_CONTEXTMENU:
  1442. {
  1443. //
  1444. // Help messages
  1445. //
  1446. PrintUIHelp( uMsg, _hDlg, wParam, lParam );
  1447. }
  1448. break;
  1449. case WM_DESTROY:
  1450. {
  1451. vOnDestroy ();
  1452. }
  1453. break;
  1454. case WM_CTLCOLORSTATIC:
  1455. {
  1456. bHandled = bOnCtlColorStatic( reinterpret_cast<HDC>(wParam),
  1457. reinterpret_cast<HWND>(lParam) );
  1458. }
  1459. break;
  1460. default:
  1461. {
  1462. bHandled = FALSE;
  1463. }
  1464. break;
  1465. }
  1466. }
  1467. return bHandled;
  1468. }
  1469. /*++
  1470. Name:
  1471. TFindLocDlg::bOnInitDialog
  1472. Description:
  1473. Instantiates the TLocTree object and attempts to
  1474. initialize it if needed. Disable the OK button until
  1475. the worker thread completes.
  1476. Arguments:
  1477. None
  1478. Return Value:
  1479. TRUE - on success
  1480. FALSE - on failure
  1481. Notes:
  1482. --*/
  1483. BOOL
  1484. TFindLocDlg::
  1485. bOnInitDialog(
  1486. VOID
  1487. )
  1488. {
  1489. DWORD dwResult;
  1490. TStatusB bStatus;
  1491. _pTree = new TLocTree (GetDlgItem(_hDlg, IDC_LOCTREE));
  1492. bStatus DBGCHK = VALID_PTR(_pTree);
  1493. if( !bStatus )
  1494. {
  1495. delete _pTree;
  1496. _pTree = NULL;
  1497. }
  1498. else
  1499. {
  1500. //
  1501. // Set some special property value to us, so the
  1502. // worker thread could recognize us
  1503. //
  1504. bStatus DBGCHK = SetProp( _hDlg, _strPropertyName, static_cast<HANDLE>(_pLocData) );
  1505. if( bStatus )
  1506. {
  1507. //
  1508. // Hide the help button as requested
  1509. //
  1510. if (!(_UIFlags & kLocationShowHelp))
  1511. {
  1512. ShowWindow (GetDlgItem(_hDlg, IDC_LOCATION_HELP), SW_HIDE);
  1513. }
  1514. //
  1515. // Let the user know we're busy
  1516. //
  1517. EnableWindow (GetDlgItem (_hDlg, IDOK), FALSE);
  1518. vStartAnim();
  1519. //
  1520. // Just verify if the data is ready
  1521. //
  1522. _pLocData->vNotifyUIDataIsReady();
  1523. }
  1524. }
  1525. return bStatus;
  1526. }
  1527. /*++
  1528. Name:
  1529. TFindLocDlg::bOnTreeNotify
  1530. Description:
  1531. When the selection is changed on the tree control, update
  1532. the static control that displays the currently selected location
  1533. Arguments:
  1534. pTreeNotify - pointer to NMTREEVIEW struct
  1535. Return Value:
  1536. TRUE - if message is handled
  1537. FALSE - otherwise
  1538. Notes:
  1539. --*/
  1540. BOOL
  1541. TFindLocDlg::
  1542. bOnTreeNotify(
  1543. IN LPNMTREEVIEW pTreeNotify
  1544. )
  1545. {
  1546. TStatusB bStatus = TRUE;
  1547. TString strSel;
  1548. switch (pTreeNotify->hdr.code)
  1549. {
  1550. case TVN_SELCHANGED:
  1551. {
  1552. bStatus DBGCHK = _pTree->bGetSelectedLocation (strSel);
  1553. if (strSel.bEmpty())
  1554. {
  1555. strSel.bLoadString (ghInst,IDS_NO_LOCATION);
  1556. }
  1557. bStatus DBGCHK = bSetEditText (_hDlg, IDC_CHOSEN_LOCATION, strSel);
  1558. }
  1559. break;
  1560. default:
  1561. {
  1562. bStatus DBGNOCHK = FALSE;
  1563. }
  1564. break;
  1565. }
  1566. return bStatus;
  1567. }
  1568. /*++
  1569. Name:
  1570. TFindLocDlg::vStartAnim
  1571. Description:
  1572. Show the animation window
  1573. Arguments:
  1574. None
  1575. Return Value:
  1576. None
  1577. Notes:
  1578. --*/
  1579. VOID
  1580. TFindLocDlg::
  1581. vStartAnim(
  1582. VOID
  1583. )
  1584. {
  1585. HWND hwndAni = GetDlgItem (_hDlg, IDC_BROWSELOC_ANIM);
  1586. SetWindowPos (hwndAni,
  1587. HWND_TOP,
  1588. 0,0,0,0,
  1589. SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
  1590. Animate_Open(hwndAni, MAKEINTRESOURCE (IDA_SEARCH));
  1591. Animate_Play(hwndAni, 0, -1, -1);
  1592. }
  1593. /*++
  1594. Name:
  1595. TFindLocDlg::vStopAnim
  1596. Description:
  1597. Hide the animation window
  1598. Arguments:
  1599. None
  1600. Return Value:
  1601. None
  1602. Notes:
  1603. --*/
  1604. VOID
  1605. TFindLocDlg::
  1606. vStopAnim(
  1607. VOID
  1608. )
  1609. {
  1610. //
  1611. // Call LockWindowUpdate() to prevent default drawing of the
  1612. // animation control after stop playing - which is gray rect
  1613. //
  1614. LockWindowUpdate( _hDlg );
  1615. HWND hwndAni = GetDlgItem (_hDlg, IDC_BROWSELOC_ANIM);
  1616. SetWindowPos (hwndAni,
  1617. HWND_BOTTOM,
  1618. 0,0,0,0,
  1619. SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW);
  1620. Animate_Stop(hwndAni);
  1621. //
  1622. // Unlock window update - tree control will
  1623. // repaint its content
  1624. //
  1625. LockWindowUpdate( NULL );
  1626. }
  1627. /*++
  1628. Name:
  1629. TFindLocDlg::bOnCtlColorStatic
  1630. Description:
  1631. Used to set background color of the animation window
  1632. to the same color as the treeview window
  1633. Arguments:
  1634. hdc - DC to set background color
  1635. Return Value:
  1636. color value used to draw background
  1637. Notes:
  1638. --*/
  1639. BOOL
  1640. TFindLocDlg::
  1641. bOnCtlColorStatic(
  1642. IN HDC hdc,
  1643. IN HWND hStatic
  1644. )
  1645. {
  1646. //
  1647. // Assume default processing of this message
  1648. //
  1649. BOOL bResult = FALSE;
  1650. if (hStatic == GetDlgItem (_hDlg, IDC_BROWSELOC_ANIM))
  1651. {
  1652. //
  1653. // We process this message only to have
  1654. // opportunity to patch the animation control
  1655. // dc just before paint.
  1656. //
  1657. // We do not return a brush here!
  1658. // (which means that we return a NULL brush)
  1659. //
  1660. // We should just return TRUE here to prevent the
  1661. // default message processing of this msg, which will
  1662. // revert the backgound color to gray.
  1663. //
  1664. SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1665. //
  1666. // Message is processed. Do not perform default
  1667. // processing!
  1668. //
  1669. bResult = TRUE;
  1670. }
  1671. return bResult;
  1672. }
  1673. /*++
  1674. Name:
  1675. TFindLocDlg::bStartTheBackgroundThread
  1676. Description:
  1677. Starts the background thread for reading the subnet locations
  1678. Arguments:
  1679. None
  1680. Return Value:
  1681. TRUE - on success
  1682. FALSE - on failure
  1683. Notes:
  1684. --*/
  1685. BOOL
  1686. TFindLocDlg::
  1687. bStartTheBackgroundThread(
  1688. VOID
  1689. )
  1690. {
  1691. TStatusB bStatus;
  1692. DWORD dwThreadID;
  1693. HANDLE hThread;
  1694. //
  1695. // You want to make sure the data is protected for the worker thread.
  1696. //
  1697. _pLocData->vIncRef();
  1698. //
  1699. // Spin the background thread here
  1700. //
  1701. hThread = TSafeThread::Create ( NULL,
  1702. 0,
  1703. (LPTHREAD_START_ROUTINE)TLocData::FindLocationsThread,
  1704. _pLocData,
  1705. 0,
  1706. &dwThreadID );
  1707. if( hThread )
  1708. {
  1709. //
  1710. // We don't need this handle any more.
  1711. // Just leave the thread running untill
  1712. // it stops
  1713. //
  1714. CloseHandle( hThread );
  1715. }
  1716. else
  1717. {
  1718. //
  1719. // Ensure the data is release if the thread creation fails.
  1720. //
  1721. _pLocData->cDecRef();
  1722. }
  1723. bStatus DBGCHK = !!hThread;
  1724. return bStatus;
  1725. }
  1726. /*++
  1727. Name:
  1728. TFindLocDlg::bOnCommand
  1729. Description:
  1730. Handles WM_COMMAND messages
  1731. Arguments:
  1732. None
  1733. Return Value:
  1734. TRUE - on success
  1735. FALSE - on failure
  1736. Notes:
  1737. --*/
  1738. BOOL
  1739. TFindLocDlg::
  1740. bOnCommand(
  1741. IN UINT uCmdID
  1742. )
  1743. {
  1744. //
  1745. // Assume message is handled
  1746. //
  1747. BOOL bHandled = TRUE;
  1748. switch (uCmdID)
  1749. {
  1750. case IDOK:
  1751. vOnOK ();
  1752. break;
  1753. case IDCANCEL:
  1754. EndDialog (_hDlg, 0);
  1755. break;
  1756. case IDC_LOCATION_HELP:
  1757. PrintUIHtmlHelp (_hDlg,
  1758. gszHtmlPrintingHlp,
  1759. HH_DISPLAY_TOPIC,
  1760. reinterpret_cast<ULONG_PTR>(gszLocationHtmFile));
  1761. break;
  1762. default:
  1763. {
  1764. bHandled = FALSE;
  1765. }
  1766. break;
  1767. }
  1768. return bHandled;
  1769. }