Source code of Windows XP (NT5)
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.

862 lines
22 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. DfsShPrp.cpp
  5. Abstract:
  6. This module contains the implementation for CDfsShellExtProp
  7. This is used to implement the property page for Shell Extension.
  8. Author:
  9. Constancio Fernandes (ferns@qspl.stpp.soft.net) 12-Jan-1998
  10. Environment:
  11. Revision History:
  12. --*/
  13. #include "stdafx.h"
  14. #include "resource.h"
  15. #include "DfsShlEx.h"
  16. #include "DfsPath.h"
  17. #include "DfsShPrp.h"
  18. #include "DfsShell.h"
  19. #include <lmcons.h>
  20. #include <lmerr.h>
  21. #include <lmdfs.h>
  22. #include "dfshelp.h"
  23. CDfsShellExtProp::CDfsShellExtProp():CQWizardPageImpl<CDfsShellExtProp>(false)
  24. /*++
  25. Routine Description:
  26. Ctor of CDfsShellExtProp.
  27. Calls the ctor of it's parent
  28. --*/
  29. {
  30. m_pIShProp = NULL;
  31. LoadStringFromResource(IDS_ALTERNATE_LIST_PATH, &m_bstrAlternateListPath);
  32. LoadStringFromResource(IDS_ALTERNATE_LIST_ACTIVE, &m_bstrAlternateListActive);
  33. LoadStringFromResource(IDS_ALTERNATE_LIST_STATUS, &m_bstrAlternateListStatus);
  34. LoadStringFromResource(IDS_ALTERNATE_LIST_YES, &m_bstrAlternateListYes);
  35. LoadStringFromResource(IDS_ALTERNATE_LIST_NO, &m_bstrAlternateListNo);
  36. LoadStringFromResource(IDS_ALTERNATE_LIST_OK, &m_bstrAlternateListOK);
  37. LoadStringFromResource(IDS_ALTERNATE_LIST_UNREACHABLE, &m_bstrAlternateListUnreachable);
  38. }
  39. CDfsShellExtProp::~CDfsShellExtProp(
  40. )
  41. /*++
  42. Routine Description:
  43. dtor of CDfsShellExtProp.
  44. Free the notify handle.
  45. --*/
  46. {
  47. /* ImageList_Destroy already called by the desctructor of list control
  48. if (NULL != m_hImageList)
  49. ImageList_Destroy(m_hImageList);
  50. */
  51. }
  52. LRESULT
  53. CDfsShellExtProp::OnInitDialog(
  54. IN UINT i_uMsg,
  55. IN WPARAM i_wParam,
  56. LPARAM i_lParam,
  57. IN OUT BOOL& io_bHandled
  58. )
  59. /*++
  60. Routine Description:
  61. Called at the start. Used to set dialog defaults
  62. --*/
  63. {
  64. SetDlgItemText(IDC_DIR_PATH, m_bstrDirPath);
  65. _SetImageList();
  66. _SetAlternateList();
  67. return TRUE;
  68. }
  69. HRESULT
  70. CDfsShellExtProp::put_DfsShellPtr(
  71. IN IShellPropSheetExt* i_pDfsShell
  72. )
  73. /*++
  74. Routine Description:
  75. Called at the start by CDfsShell. Used to set a back pointer to CDfsShell object to call Release().
  76. --*/
  77. {
  78. if (!i_pDfsShell)
  79. return(E_INVALIDARG);
  80. if (m_pIShProp)
  81. m_pIShProp->Release();
  82. m_pIShProp = i_pDfsShell;
  83. m_pIShProp->AddRef();
  84. return(S_OK);
  85. }
  86. HRESULT
  87. CDfsShellExtProp::put_DirPaths(
  88. IN BSTR i_bstrDirPath,
  89. IN BSTR i_bstrEntryPath
  90. )
  91. /*++
  92. Routine Description:
  93. Set the value of Directory Path for this directory. and the largest entrypath.
  94. Arguments:
  95. i_bstrDirPath - Contains the new value for Entry Path
  96. i_bstrEntryPath - The largest Dfs entry path that matches this directory.
  97. --*/
  98. {
  99. if (!i_bstrDirPath)
  100. return(E_INVALIDARG);
  101. m_bstrDirPath = i_bstrDirPath;
  102. m_bstrEntryPath = i_bstrEntryPath;
  103. if (!m_bstrDirPath || !i_bstrEntryPath)
  104. return(E_OUTOFMEMORY);
  105. return S_OK;
  106. }
  107. LRESULT
  108. CDfsShellExtProp::OnApply(
  109. )
  110. {
  111. return TRUE;
  112. }
  113. LRESULT
  114. CDfsShellExtProp::OnParentClosing(
  115. IN UINT i_uMsg,
  116. IN WPARAM i_wParam,
  117. LPARAM i_lParam,
  118. IN OUT BOOL& io_bHandled
  119. )
  120. /*++
  121. Routine Description:
  122. Used by the node to tell the propery page to close.
  123. --*/
  124. {
  125. return TRUE;
  126. }
  127. void
  128. CDfsShellExtProp::Delete()
  129. /*++
  130. Routine Description:
  131. Called when property sheet is release to do clean up.
  132. */
  133. {
  134. if (m_pIShProp)
  135. m_pIShProp->Release();
  136. }
  137. LRESULT
  138. CDfsShellExtProp::OnFlushPKT(
  139. IN WORD i_wNotifyCode,
  140. IN WORD i_wID,
  141. IN HWND i_hWndCtl,
  142. IN OUT BOOL& io_bHandled
  143. )
  144. /*++
  145. Routine Description:
  146. Called when Flush PKT table is called.
  147. Flushes client PKT table.
  148. */
  149. {
  150. if (!m_bstrEntryPath)
  151. return(E_FAIL);
  152. NET_API_STATUS nstatRetVal = 0;
  153. DFS_INFO_102 DfsInfoLevel102;
  154. // Set timeout = 0 to flush local PKT.
  155. DfsInfoLevel102.Timeout = 0;
  156. // Display hour glass.
  157. CWaitCursor WaitCursor;
  158. nstatRetVal = NetDfsSetClientInfo(
  159. m_bstrEntryPath,
  160. NULL,
  161. NULL,
  162. 102,
  163. (LPBYTE) &DfsInfoLevel102
  164. );
  165. if (nstatRetVal != NERR_Success)
  166. DisplayMessageBoxForHR(HRESULT_FROM_WIN32(nstatRetVal));
  167. return(true);
  168. }
  169. void
  170. CDfsShellExtProp::_UpdateTextForReplicaState(
  171. IN HWND hwndControl,
  172. IN int nIndex,
  173. IN enum SHL_DFS_REPLICA_STATE ReplicaState
  174. )
  175. {
  176. LVITEM lvi = {0};
  177. lvi.iItem = nIndex;
  178. lvi.mask = LVIF_TEXT;
  179. // insert the 2nd column "Active"
  180. lvi.iSubItem = 1;
  181. if (ReplicaState == SHL_DFS_REPLICA_STATE_ACTIVE_UNKNOWN ||
  182. ReplicaState == SHL_DFS_REPLICA_STATE_ACTIVE_OK ||
  183. ReplicaState == SHL_DFS_REPLICA_STATE_ACTIVE_UNREACHABLE )
  184. lvi.pszText = m_bstrAlternateListYes;
  185. else
  186. lvi.pszText = m_bstrAlternateListNo;
  187. ListView_SetItem(hwndControl, &lvi);
  188. // insert the 3rd column "Status"
  189. lvi.iSubItem = 2;
  190. switch (ReplicaState)
  191. {
  192. case SHL_DFS_REPLICA_STATE_ACTIVE_UNKNOWN:
  193. case SHL_DFS_REPLICA_STATE_UNKNOWN:
  194. lvi.pszText = _T("");
  195. break;
  196. case SHL_DFS_REPLICA_STATE_ACTIVE_OK:
  197. case SHL_DFS_REPLICA_STATE_OK:
  198. lvi.pszText = m_bstrAlternateListOK;
  199. break;
  200. case SHL_DFS_REPLICA_STATE_ACTIVE_UNREACHABLE:
  201. case SHL_DFS_REPLICA_STATE_UNREACHABLE:
  202. lvi.pszText = m_bstrAlternateListUnreachable;
  203. break;
  204. }
  205. ListView_SetItem(hwndControl, &lvi);
  206. }
  207. void
  208. CDfsShellExtProp::_SetAlternateList()
  209. /*++
  210. Routine Description:
  211. Finds out if the given path is a Dfs Path, and if it is
  212. then finds out the alternates available for this path up to
  213. the last directory. These are then added to the alternate list.
  214. */
  215. {
  216. HWND hwndControl = ::GetDlgItem(m_hWnd, IDC_ALTERNATE_LIST);
  217. if (NULL == ((CDfsShell *)m_pIShProp)->m_ppDfsAlternates)
  218. return;
  219. //
  220. // calculate the listview column width
  221. //
  222. RECT rect;
  223. ZeroMemory(&rect, sizeof(rect));
  224. ::GetWindowRect(hwndControl, &rect);
  225. int nControlWidth = rect.right - rect.left;
  226. int nVScrollbarWidth = GetSystemMetrics(SM_CXVSCROLL);
  227. int nBorderWidth = GetSystemMetrics(SM_CXBORDER);
  228. int nControlNetWidth = nControlWidth - nVScrollbarWidth - 4 * nBorderWidth;
  229. int nWidth1 = nControlNetWidth / 2;
  230. int nWidth2 = nControlNetWidth / 4;
  231. int nWidth3 = nControlNetWidth - nWidth1 - nWidth2;
  232. //
  233. // insert columns
  234. //
  235. LV_COLUMN col;
  236. ZeroMemory(&col, sizeof(col));
  237. col.mask = LVCF_TEXT | LVCF_WIDTH;
  238. col.cx = nWidth1;
  239. col.pszText = m_bstrAlternateListPath;
  240. ListView_InsertColumn(hwndControl, 0, &col);
  241. col.cx = nWidth2;
  242. col.pszText = m_bstrAlternateListActive;
  243. ListView_InsertColumn(hwndControl, 1, &col);
  244. col.cx = nWidth3;
  245. col.pszText = m_bstrAlternateListStatus;
  246. ListView_InsertColumn(hwndControl, 2, &col);
  247. //
  248. // Set full row selection style
  249. //
  250. ListView_SetExtendedListViewStyleEx(hwndControl, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
  251. // For each alternate stored in the parent shell object
  252. // add to list.
  253. for (int i = 0; NULL != ((CDfsShell *)m_pIShProp)->m_ppDfsAlternates[i] ; i++)
  254. {
  255. int nIndex = 0;
  256. LVITEM lvi = {0};
  257. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  258. lvi.pszText = (((CDfsShell *)m_pIShProp)->m_ppDfsAlternates[i])->bstrAlternatePath;
  259. lvi.iImage = (((CDfsShell *)m_pIShProp)->m_ppDfsAlternates[i])->ReplicaState;
  260. lvi.lParam = (LPARAM)(((CDfsShell *)m_pIShProp)->m_ppDfsAlternates[i]);
  261. lvi.iSubItem = 0;
  262. // Select the active replica.
  263. switch ((((CDfsShell *)m_pIShProp)->m_ppDfsAlternates[i])->ReplicaState)
  264. {
  265. case SHL_DFS_REPLICA_STATE_ACTIVE_UNKNOWN:
  266. case SHL_DFS_REPLICA_STATE_ACTIVE_OK:
  267. case SHL_DFS_REPLICA_STATE_ACTIVE_UNREACHABLE:
  268. lvi.mask |= LVIF_STATE;
  269. lvi.state = LVIS_SELECTED | LVIS_FOCUSED;
  270. nIndex = ListView_InsertItem(hwndControl, &lvi);
  271. break;
  272. case SHL_DFS_REPLICA_STATE_UNKNOWN:
  273. case SHL_DFS_REPLICA_STATE_OK:
  274. case SHL_DFS_REPLICA_STATE_UNREACHABLE:
  275. nIndex = ListView_InsertItem(hwndControl, &lvi);
  276. break;
  277. default:
  278. _ASSERT(FALSE);
  279. break;
  280. }
  281. _UpdateTextForReplicaState(hwndControl, nIndex, (((CDfsShell *)m_pIShProp)->m_ppDfsAlternates[i])->ReplicaState);
  282. }
  283. }
  284. HRESULT
  285. CDfsShellExtProp::_SetImageList(
  286. )
  287. /*++
  288. Routine Description:
  289. Create and initialize the Imagelist for alternates.
  290. --*/
  291. {
  292. // Load bitmap from resource
  293. HBITMAP hBitmap = (HBITMAP)LoadImage(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDB_Replica),
  294. IMAGE_BITMAP, 0, 0, LR_SHARED | LR_LOADTRANSPARENT);
  295. if(!hBitmap)
  296. return HRESULT_FROM_WIN32(GetLastError());;
  297. // Try and get the exact bitmap size and number of bitmaps for
  298. // image list
  299. int icxBitmap = 16;
  300. int icyBitmap = 16;
  301. int iNoOfBitmaps = 6;
  302. BITMAP bmpRec;
  303. if (GetObject(hBitmap, sizeof(bmpRec), &bmpRec))
  304. {
  305. if (bmpRec.bmHeight > 0)
  306. {
  307. icyBitmap = bmpRec.bmHeight;
  308. // Since the bitmaps are squares
  309. icxBitmap = icyBitmap;
  310. // Since all the bitmaps are in a line in the original bitmap
  311. iNoOfBitmaps = bmpRec.bmWidth / bmpRec.bmHeight;
  312. }
  313. }
  314. // Create the image list
  315. HIMAGELIST hImageList = ImageList_Create(icxBitmap, icyBitmap, ILC_COLOR, iNoOfBitmaps, 0);
  316. if (NULL == hImageList)
  317. {
  318. DeleteObject(hBitmap);
  319. return E_FAIL;
  320. }
  321. ImageList_Add(hImageList, hBitmap, (HBITMAP)NULL);
  322. // The specified image list will be destroyed when the list view control is destroyed.
  323. SendDlgItemMessage( IDC_ALTERNATE_LIST, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)hImageList);
  324. DeleteObject(hBitmap);
  325. return S_OK;
  326. }
  327. LRESULT
  328. CDfsShellExtProp::OnNotify(
  329. IN UINT i_uMsg,
  330. IN WPARAM i_wParam,
  331. IN LPARAM i_lParam,
  332. IN OUT BOOL& io_bHandled
  333. )
  334. /*++
  335. Routine Description:
  336. Notify message for user actions. We handle only the mouse double click right now
  337. Arguments:
  338. i_lParam - Details about the control sending the notify
  339. io_bHandled - Whether we handled this message or not.
  340. --*/
  341. {
  342. io_bHandled = FALSE; // So that the base class gets this notify too
  343. NMHDR* pNMHDR = (NMHDR*)i_lParam;
  344. if (!pNMHDR)
  345. return FALSE;
  346. if (IDC_ALTERNATE_LIST == pNMHDR->idFrom)
  347. {
  348. if (NM_DBLCLK == pNMHDR->code)
  349. {
  350. SetActive();
  351. } else if (LVN_ITEMCHANGED == pNMHDR->code)
  352. {
  353. int n = ListView_GetSelectedCount(GetDlgItem(IDC_ALTERNATE_LIST));
  354. ::EnableWindow(GetDlgItem(IDC_SET_ACTIVE), (n == 1));
  355. }
  356. }
  357. return TRUE;
  358. }
  359. BOOL
  360. CDfsShellExtProp::SetActive()
  361. /*++
  362. Routine Description:
  363. Sets the first selected alternate to be active.
  364. --*/
  365. {
  366. HWND hwndAlternateLV = GetDlgItem(IDC_ALTERNATE_LIST);
  367. int iSelected = ListView_GetNextItem(hwndAlternateLV, -1, LVNI_ALL | LVNI_SELECTED);
  368. if (-1 == iSelected)
  369. return FALSE; // nothing selected
  370. LV_ITEM lvItem = {0};
  371. lvItem.mask = LVIF_PARAM;
  372. lvItem.iItem = iSelected;
  373. ListView_GetItem(hwndAlternateLV, &lvItem);
  374. LPDFS_ALTERNATES pDfsAlternate = (LPDFS_ALTERNATES)lvItem.lParam;
  375. if (!pDfsAlternate )
  376. return(FALSE);
  377. // set the item to be active
  378. DFS_INFO_101 DfsInfo101 = {0};
  379. DfsInfo101.State = DFS_STORAGE_STATE_ACTIVE;
  380. NET_API_STATUS nstatRetVal = NetDfsSetClientInfo(
  381. m_bstrEntryPath,
  382. pDfsAlternate->bstrServer,
  383. pDfsAlternate->bstrShare,
  384. 101,
  385. (LPBYTE) &DfsInfo101
  386. );
  387. if (nstatRetVal != NERR_Success)
  388. {
  389. DisplayMessageBoxForHR(HRESULT_FROM_WIN32(nstatRetVal));
  390. return FALSE;
  391. }
  392. // Reset the image of the last Active alternate/s to normal.
  393. int nIndex = -1;
  394. while ((nIndex = ListView_GetNextItem(hwndAlternateLV, nIndex, LVNI_ALL)) != -1)
  395. {
  396. ZeroMemory(&lvItem, sizeof(lvItem));
  397. lvItem.mask = LVIF_PARAM;
  398. lvItem.iItem = nIndex;
  399. ListView_GetItem(hwndAlternateLV, &lvItem);
  400. LPDFS_ALTERNATES pTempDfsAlternate = (LPDFS_ALTERNATES)lvItem.lParam;
  401. BOOL bActive = TRUE;
  402. switch (pTempDfsAlternate->ReplicaState)
  403. {
  404. case SHL_DFS_REPLICA_STATE_ACTIVE_UNKNOWN:
  405. pTempDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_UNKNOWN;
  406. break;
  407. case SHL_DFS_REPLICA_STATE_ACTIVE_OK:
  408. pTempDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_OK;
  409. break;
  410. case SHL_DFS_REPLICA_STATE_ACTIVE_UNREACHABLE:
  411. pTempDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_UNREACHABLE;
  412. break;
  413. case SHL_DFS_REPLICA_STATE_UNKNOWN:
  414. case SHL_DFS_REPLICA_STATE_OK:
  415. case SHL_DFS_REPLICA_STATE_UNREACHABLE:
  416. default:
  417. bActive = FALSE;
  418. break;
  419. }
  420. if (bActive)
  421. {
  422. lvItem.mask = LVIF_IMAGE | LVIF_STATE;
  423. lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
  424. lvItem.iImage = pTempDfsAlternate->ReplicaState;
  425. ListView_SetItem(hwndAlternateLV,&lvItem);
  426. _UpdateTextForReplicaState(hwndAlternateLV, nIndex, pTempDfsAlternate->ReplicaState);
  427. break;
  428. }
  429. }
  430. // set the new active alternate
  431. BOOL bActive = FALSE;
  432. switch (pDfsAlternate->ReplicaState)
  433. {
  434. case SHL_DFS_REPLICA_STATE_UNKNOWN:
  435. pDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_ACTIVE_UNKNOWN;
  436. break;
  437. case SHL_DFS_REPLICA_STATE_OK:
  438. pDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_ACTIVE_OK;
  439. break;
  440. case SHL_DFS_REPLICA_STATE_UNREACHABLE:
  441. pDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_ACTIVE_UNREACHABLE;
  442. break;
  443. case SHL_DFS_REPLICA_STATE_ACTIVE_UNKNOWN:
  444. case SHL_DFS_REPLICA_STATE_ACTIVE_OK:
  445. case SHL_DFS_REPLICA_STATE_ACTIVE_UNREACHABLE:
  446. default:
  447. bActive = TRUE;
  448. break;
  449. }
  450. if (!bActive)
  451. {
  452. lvItem.iItem = iSelected;
  453. lvItem.mask = LVIF_IMAGE;
  454. lvItem.iImage = pDfsAlternate->ReplicaState;
  455. ListView_SetItem(hwndAlternateLV,&lvItem);
  456. _UpdateTextForReplicaState(hwndAlternateLV, iSelected, pDfsAlternate->ReplicaState);
  457. }
  458. return TRUE;
  459. }
  460. /*++
  461. This function is called when a user clicks the ? in the top right of a property sheet
  462. and then clciks a control, or when they hit F1 in a control.
  463. --*/
  464. LRESULT CDfsShellExtProp::OnCtxHelp(
  465. IN UINT i_uMsg,
  466. IN WPARAM i_wParam,
  467. IN LPARAM i_lParam,
  468. IN OUT BOOL& io_bHandled
  469. )
  470. {
  471. LPHELPINFO lphi = (LPHELPINFO) i_lParam;
  472. if (!lphi || lphi->iContextType != HELPINFO_WINDOW || lphi->iCtrlId < 0)
  473. return FALSE;
  474. ::WinHelp((HWND)(lphi->hItemHandle),
  475. DFS_CTX_HELP_FILE,
  476. HELP_WM_HELP,
  477. (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_DFS_SHELL_PROP);
  478. return TRUE;
  479. }
  480. /*++
  481. This function handles "What's This" help when a user right clicks the control
  482. --*/
  483. LRESULT CDfsShellExtProp::OnCtxMenuHelp(
  484. IN UINT i_uMsg,
  485. IN WPARAM i_wParam,
  486. IN LPARAM i_lParam,
  487. IN OUT BOOL& io_bHandled
  488. )
  489. {
  490. ::WinHelp((HWND)i_wParam,
  491. DFS_CTX_HELP_FILE,
  492. HELP_CONTEXTMENU,
  493. (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_DFS_SHELL_PROP);
  494. return TRUE;
  495. }
  496. LRESULT CDfsShellExtProp::OnCheckStatus(
  497. IN WORD i_wNotifyCode,
  498. IN WORD i_wID,
  499. IN HWND i_hWndCtl,
  500. IN OUT BOOL& io_bHandled
  501. )
  502. /*++
  503. Routine Description:
  504. Checks the status of all selected alternates. If it is reachable then the
  505. reachable icon is displayed or the unreachable icon is displayed.
  506. --*/
  507. {
  508. CWaitCursor WaitCursor;
  509. HWND hwndAlternateLV = GetDlgItem(IDC_ALTERNATE_LIST);
  510. int nIndex = -1;
  511. while (-1 != (nIndex = ListView_GetNextItem(hwndAlternateLV, nIndex, LVNI_ALL | LVNI_SELECTED)))
  512. {
  513. LV_ITEM lvItem = {0};
  514. lvItem.mask = LVIF_PARAM;
  515. lvItem.iItem = nIndex;
  516. ListView_GetItem(hwndAlternateLV, &lvItem);
  517. LPDFS_ALTERNATES pDfsAlternate = (LPDFS_ALTERNATES)lvItem.lParam;
  518. if (!pDfsAlternate )
  519. return(FALSE);
  520. // See if the path actaully exists (reachable).
  521. DWORD dwErr = GetFileAttributes(pDfsAlternate->bstrAlternatePath);
  522. if (0xffffffff == dwErr)
  523. { // We failed to get the file attributes for entry path
  524. switch (pDfsAlternate->ReplicaState)
  525. {
  526. case SHL_DFS_REPLICA_STATE_ACTIVE_UNKNOWN:
  527. case SHL_DFS_REPLICA_STATE_ACTIVE_OK:
  528. case SHL_DFS_REPLICA_STATE_ACTIVE_UNREACHABLE:
  529. pDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_ACTIVE_UNREACHABLE;
  530. break;
  531. case SHL_DFS_REPLICA_STATE_UNKNOWN:
  532. case SHL_DFS_REPLICA_STATE_OK:
  533. case SHL_DFS_REPLICA_STATE_UNREACHABLE:
  534. pDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_UNREACHABLE;
  535. break;
  536. default:
  537. _ASSERT(FALSE);
  538. break;
  539. }
  540. }
  541. else
  542. {
  543. switch (pDfsAlternate->ReplicaState)
  544. {
  545. case SHL_DFS_REPLICA_STATE_ACTIVE_UNKNOWN:
  546. case SHL_DFS_REPLICA_STATE_ACTIVE_OK:
  547. case SHL_DFS_REPLICA_STATE_ACTIVE_UNREACHABLE:
  548. pDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_ACTIVE_OK;
  549. break;
  550. case SHL_DFS_REPLICA_STATE_UNKNOWN:
  551. case SHL_DFS_REPLICA_STATE_OK:
  552. case SHL_DFS_REPLICA_STATE_UNREACHABLE:
  553. pDfsAlternate->ReplicaState = SHL_DFS_REPLICA_STATE_OK;
  554. break;
  555. default:
  556. _ASSERT(FALSE);
  557. break;
  558. }
  559. }
  560. lvItem.mask = LVIF_IMAGE;
  561. lvItem.iImage = pDfsAlternate->ReplicaState;
  562. ListView_SetItem(hwndAlternateLV,&lvItem);
  563. _UpdateTextForReplicaState(hwndAlternateLV, nIndex, pDfsAlternate->ReplicaState);
  564. }
  565. return TRUE;
  566. }
  567. LRESULT CDfsShellExtProp::OnSetActiveReferral(
  568. IN WORD i_wNotifyCode,
  569. IN WORD i_wID,
  570. IN HWND i_hWndCtl,
  571. IN OUT BOOL& io_bHandled
  572. )
  573. {
  574. SetActive();
  575. return TRUE;
  576. }
  577. HRESULT
  578. LoadStringFromResource(
  579. IN const UINT i_uResourceID,
  580. OUT BSTR* o_pbstrReadValue
  581. )
  582. /*++
  583. Routine Description:
  584. This method returns a resource string.
  585. The method no longer uses a fixed string to read the resource.
  586. Inspiration from MFC's CString::LoadString.
  587. Arguments:
  588. i_uResourceID - The resource id
  589. o_pbstrReadValue - The BSTR* into which the value is copied
  590. --*/
  591. {
  592. if (!o_pbstrReadValue)
  593. return E_INVALIDARG;
  594. TCHAR szResString[1024];
  595. ULONG uCopiedLen = 0;
  596. szResString[0] = NULL;
  597. // Read the string from the resource
  598. uCopiedLen = ::LoadString(_Module.GetModuleInstance(), i_uResourceID, szResString, 1024);
  599. // If nothing was copied it is flagged as an error
  600. if(uCopiedLen <= 0)
  601. {
  602. return HRESULT_FROM_WIN32(::GetLastError());
  603. }
  604. else
  605. {
  606. *o_pbstrReadValue = ::SysAllocString(szResString);
  607. if (!*o_pbstrReadValue)
  608. return E_OUTOFMEMORY;
  609. }
  610. return S_OK;
  611. }
  612. HRESULT
  613. GetErrorMessage(
  614. IN DWORD i_dwError,
  615. OUT BSTR* o_pbstrErrorMsg
  616. )
  617. {
  618. if (0 == i_dwError || !o_pbstrErrorMsg)
  619. return E_INVALIDARG;
  620. HRESULT hr = S_OK;
  621. LPTSTR lpBuffer = NULL;
  622. DWORD dwRet = ::FormatMessage(
  623. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  624. NULL, i_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  625. (LPTSTR)&lpBuffer, 0, NULL);
  626. if (0 == dwRet)
  627. {
  628. // if no message is found, GetLastError will return ERROR_MR_MID_NOT_FOUND
  629. hr = HRESULT_FROM_WIN32(GetLastError());
  630. if (HRESULT_FROM_WIN32(ERROR_MR_MID_NOT_FOUND) == hr ||
  631. 0x80070000 == (i_dwError & 0xffff0000) ||
  632. 0 == (i_dwError & 0xffff0000) )
  633. { // Try locating the message from NetMsg.dll.
  634. hr = S_OK;
  635. DWORD dwNetError = i_dwError & 0x0000ffff;
  636. HINSTANCE hLib = LoadLibrary(_T("netmsg.dll"));
  637. if (!hLib)
  638. hr = HRESULT_FROM_WIN32(GetLastError());
  639. else
  640. {
  641. dwRet = ::FormatMessage(
  642. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
  643. hLib, dwNetError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  644. (LPTSTR)&lpBuffer, 0, NULL);
  645. if (0 == dwRet)
  646. hr = HRESULT_FROM_WIN32(GetLastError());
  647. FreeLibrary(hLib);
  648. }
  649. }
  650. }
  651. if (SUCCEEDED(hr))
  652. {
  653. *o_pbstrErrorMsg = SysAllocString(lpBuffer);
  654. LocalFree(lpBuffer);
  655. }
  656. else
  657. {
  658. // we failed to retrieve the error message from system/netmsg.dll,
  659. // report the error code directly to user
  660. hr = S_OK;
  661. TCHAR szString[32];
  662. _stprintf(szString, _T("0x%x"), i_dwError);
  663. *o_pbstrErrorMsg = SysAllocString(szString);
  664. }
  665. if (!*o_pbstrErrorMsg)
  666. hr = E_OUTOFMEMORY;
  667. return hr;
  668. }
  669. int
  670. DisplayMessageBox(
  671. IN HWND hwndParent,
  672. IN UINT uType, // style of message box
  673. IN DWORD dwErr,
  674. IN UINT iStringId, // OPTIONAL: String resource Id
  675. ...) // Optional arguments
  676. {
  677. _ASSERT(dwErr != 0 || iStringId != 0); // One of the parameter must be non-zero
  678. HRESULT hr = S_OK;
  679. TCHAR szCaption[1024], szString[1024];
  680. CComBSTR bstrErrorMsg, bstrResourceString, bstrMsg;
  681. ::LoadString(_Module.GetModuleInstance(), IDS_APPLICATION_NAME,
  682. szCaption, sizeof(szCaption)/sizeof(TCHAR));
  683. if (dwErr)
  684. hr = GetErrorMessage(dwErr, &bstrErrorMsg);
  685. if (SUCCEEDED(hr))
  686. {
  687. if (iStringId == 0)
  688. {
  689. bstrMsg = bstrErrorMsg;
  690. }
  691. else
  692. {
  693. ::LoadString(_Module.GetModuleInstance(), iStringId,
  694. szString, sizeof(szString)/sizeof(TCHAR));
  695. va_list arglist;
  696. va_start(arglist, iStringId);
  697. LPTSTR lpBuffer = NULL;
  698. DWORD dwRet = ::FormatMessage(
  699. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  700. szString,
  701. 0, // dwMessageId
  702. 0, // dwLanguageId, ignored
  703. (LPTSTR)&lpBuffer,
  704. 0, // nSize
  705. &arglist);
  706. va_end(arglist);
  707. if (dwRet == 0)
  708. {
  709. hr = HRESULT_FROM_WIN32(GetLastError());
  710. }
  711. else
  712. {
  713. bstrMsg = lpBuffer;
  714. if (dwErr)
  715. bstrMsg += bstrErrorMsg;
  716. LocalFree(lpBuffer);
  717. }
  718. }
  719. }
  720. if (FAILED(hr))
  721. {
  722. // Failed to retrieve the proper message, report the failure directly to user
  723. _stprintf(szString, _T("0x%x"), hr);
  724. bstrMsg = szString;
  725. }
  726. return ::MessageBox(hwndParent, bstrMsg, szCaption, uType);
  727. }
  728. HRESULT
  729. DisplayMessageBoxForHR(
  730. IN HRESULT i_hr
  731. )
  732. {
  733. DisplayMessageBox(::GetActiveWindow(), MB_OK, i_hr, 0);
  734. return S_OK;
  735. }