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.

3180 lines
98 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: O N C O M M A N D . C P P
  7. //
  8. // Contents: Command handlers for the context menus, etc.
  9. //
  10. // Notes:
  11. //
  12. // Author: jeffspr 4 Nov 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "foldinc.h" // Standard shell\folder includes
  18. #include "advcfg.h"
  19. #include "conprops.h"
  20. #include "foldres.h"
  21. #include "oncommand.h"
  22. #if DBG // Debug menu commands
  23. #include "oncommand_dbg.h" //
  24. #endif
  25. #include "shutil.h"
  26. #include "ncras.h"
  27. #include "traymsgs.h"
  28. #include <ncnetcon.h>
  29. #include <nsres.h>
  30. #include <wizentry.h>
  31. #include "disconnect.h"
  32. #include "ncperms.h"
  33. #include "smcent.h"
  34. #include "cfutils.h"
  35. #include "HNetCfg.h"
  36. #include "..\lanui\lanui.h"
  37. #include "repair.h"
  38. #include "iconhandler.h"
  39. #include "wzcdlg.h"
  40. //---[ Externs ]--------------------------------------------------------------
  41. extern HWND g_hwndTray;
  42. extern const WCHAR c_szNetShellDll[];
  43. //---[ Constants ]------------------------------------------------------------
  44. // Command-line for the control-panel applet.
  45. //
  46. static const WCHAR c_szRunDll32[] = L"rundll32.exe";
  47. static const WCHAR c_szNetworkIdCmdLine[] = L"shell32.dll,Control_RunDLL sysdm.cpl,,1";
  48. //---[ Local functions ]------------------------------------------------------
  49. // None
  50. class CCommandHandlerParams
  51. {
  52. public:
  53. const PCONFOLDPIDLVEC* apidl;
  54. HWND hwndOwner;
  55. LPSHELLFOLDER psf;
  56. UINT_PTR nAdditionalParam;
  57. } ;
  58. HRESULT HrCommandHandlerThread(
  59. FOLDERONCOMMANDPROC pfnCommandHandler,
  60. IN const PCONFOLDPIDLVEC& apidl,
  61. HWND hwndOwner,
  62. LPSHELLFOLDER psf)
  63. {
  64. HRESULT hr = S_OK;
  65. PCONFOLDPIDLVEC apidlCopy;
  66. // If there are pidls to copy, copy them
  67. //
  68. if (!apidl.empty())
  69. {
  70. hr = HrCloneRgIDL(apidl, FALSE, TRUE, apidlCopy);
  71. }
  72. // If either there were no pidls, or the Clone succeeded, then we want to continue
  73. //
  74. if (SUCCEEDED(hr))
  75. {
  76. PCONFOLDONCOMMANDPARAMS pcfocp = new CONFOLDONCOMMANDPARAMS;
  77. if (pcfocp)
  78. {
  79. pcfocp->pfnfocp = pfnCommandHandler;
  80. pcfocp->apidl = apidlCopy;
  81. pcfocp->hwndOwner = hwndOwner;
  82. pcfocp->psf = psf;
  83. pcfocp->hInstNetShell = NULL;
  84. // This should be Release'd in the thread called.
  85. //
  86. psf->AddRef();
  87. // This will always succeed in retail, but will test the flag in debug
  88. //
  89. if (!FIsDebugFlagSet (dfidDisableShellThreading))
  90. {
  91. // Run in a thread using the QueueUserWorkItem
  92. //
  93. HANDLE hthrd = NULL;
  94. HINSTANCE hInstNetShell = LoadLibrary(c_szNetShellDll);
  95. if (hInstNetShell)
  96. {
  97. pcfocp->hInstNetShell = hInstNetShell;
  98. DWORD dwThreadId;
  99. hthrd = CreateThread(NULL, STACK_SIZE_DEFAULT,
  100. (LPTHREAD_START_ROUTINE)FolderCommandHandlerThreadProc,
  101. (LPVOID)pcfocp, 0, &dwThreadId);
  102. }
  103. if (NULL != hthrd)
  104. {
  105. CloseHandle(hthrd);
  106. }
  107. else
  108. {
  109. pcfocp->hInstNetShell = NULL;
  110. FolderCommandHandlerThreadProc(pcfocp);
  111. }
  112. }
  113. else
  114. {
  115. // Run directly in this same thread
  116. //
  117. FolderCommandHandlerThreadProc((PVOID) pcfocp);
  118. }
  119. }
  120. else
  121. {
  122. hr = E_OUTOFMEMORY;
  123. }
  124. }
  125. // Don't release the psf here. This should have been taken care of by the called ThreadProc
  126. //
  127. return hr;
  128. }
  129. DWORD WINAPI FolderCommandHandlerThreadProc(LPVOID lpParam)
  130. {
  131. HRESULT hr = S_OK;
  132. PCONFOLDONCOMMANDPARAMS pcfocp = (PCONFOLDONCOMMANDPARAMS) lpParam;
  133. BOOL fCoInited = FALSE;
  134. IUnknown * punkExplorerProcess = NULL;
  135. Assert(pcfocp);
  136. SHGetInstanceExplorer(&punkExplorerProcess);
  137. hr = CoInitializeEx (NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED);
  138. if (SUCCEEDED(hr))
  139. {
  140. // We don't care if this is S_FALSE or not, since we'll soon
  141. // overwrite the hr. If it's already initialized, great...
  142. fCoInited = TRUE;
  143. // Call the specific handler
  144. //
  145. hr = pcfocp->pfnfocp(
  146. pcfocp->apidl,
  147. pcfocp->hwndOwner,
  148. pcfocp->psf);
  149. }
  150. // Remove the ref that we have on this object. The thread handler would have addref'd
  151. // this before queueing our action
  152. //
  153. if (pcfocp->psf)
  154. {
  155. ReleaseObj(pcfocp->psf);
  156. }
  157. // Remove this object. We're responsible for this now.
  158. //
  159. HINSTANCE hInstNetShell = pcfocp->hInstNetShell;
  160. pcfocp->hInstNetShell = NULL;
  161. delete pcfocp;
  162. if (fCoInited)
  163. {
  164. CoUninitialize();
  165. }
  166. ::ReleaseObj(punkExplorerProcess);
  167. if (hInstNetShell)
  168. FreeLibraryAndExitThread(hInstNetShell, hr);
  169. return hr;
  170. }
  171. //+---------------------------------------------------------------------------
  172. //
  173. // Function: HrCommandHomeNetWizard
  174. //
  175. // Purpose: Command handler to start the home networking wizard
  176. //
  177. // Arguments: none
  178. //
  179. // Returns: S_OK if succeeded
  180. // E_FAIL otherwise
  181. //
  182. // Author: deonb 10 Feb 2001
  183. //
  184. // Notes:
  185. //
  186. HRESULT HrCommandHomeNetWizard()
  187. {
  188. // ShellExecute returns <32 if an error
  189. if (ShellExecute(NULL, NULL, L"rundll32.exe", L"hnetwiz.dll,HomeNetWizardRunDll", NULL, SW_SHOWNORMAL) > reinterpret_cast<HINSTANCE>(32))
  190. {
  191. return S_OK;
  192. }
  193. else
  194. {
  195. return E_FAIL;
  196. }
  197. }
  198. //
  199. //
  200. //
  201. LONG
  202. TotalValidSelectedConnectionsForBridge(
  203. IN const PCONFOLDPIDLVEC& apidlSelected
  204. )
  205. {
  206. int nTotalValidCandidateForBridge = 0;
  207. //
  208. // Loop through each of the selected objects
  209. //
  210. for ( PCONFOLDPIDLVEC::const_iterator iterObjectLoop = apidlSelected.begin(); iterObjectLoop != apidlSelected.end(); iterObjectLoop++ )
  211. {
  212. // Validate the pidls
  213. //
  214. const PCONFOLDPIDL& pcfp = *iterObjectLoop;
  215. if ( !pcfp.empty() )
  216. {
  217. //
  218. // needs to be a LAN Adapter and NOT (Firewalled/Shared or Bridge)
  219. //
  220. if ( (NCM_LAN == pcfp->ncm) )
  221. if ( !( (NCCF_BRIDGED|NCCF_FIREWALLED|NCCF_SHARED) & pcfp->dwCharacteristics ) )
  222. {
  223. //
  224. // Ok we have a winner it's a nice clean adapter
  225. //
  226. nTotalValidCandidateForBridge ++;
  227. }
  228. }
  229. }
  230. return nTotalValidCandidateForBridge;
  231. }
  232. //+---------------------------------------------------------------------------
  233. //
  234. // Function: HrCommandNetworkDiagnostics
  235. //
  236. // Purpose: Command handler to start the Network Diagnostics page
  237. //
  238. // Arguments: none
  239. //
  240. // Returns: S_OK if succeeded
  241. // E_FAIL otherwise
  242. //
  243. // Author: deonb 10 Feb 2001
  244. //
  245. // Notes:
  246. //
  247. HRESULT HrCommandNetworkDiagnostics()
  248. {
  249. // ShellExecute returns <32 if an error
  250. if (ShellExecute(NULL, NULL, L"hcp://system/netdiag/dglogs.htm", L"", NULL, SW_SHOWNORMAL) > reinterpret_cast<HINSTANCE>(32))
  251. {
  252. return S_OK;
  253. }
  254. else
  255. {
  256. return E_FAIL;
  257. }
  258. }
  259. //+---------------------------------------------------------------------------
  260. //
  261. // Function: HrCommandNetworkTroubleShoot
  262. //
  263. // Purpose: Command handler to start the Network Troubleshooter page
  264. //
  265. // Arguments: none
  266. //
  267. // Returns: S_OK if succeeded
  268. // E_FAIL otherwise
  269. //
  270. // Author: deonb 4 April 2001
  271. //
  272. // Notes:
  273. //
  274. HRESULT HrCommandNetworkTroubleShoot()
  275. {
  276. // ShellExecute returns <32 if an error
  277. if (ShellExecute(NULL, NULL, L"hcp://system/panels/Topics.htm?path=TopLevelBucket_4/Fixing_a_problem/Home_Networking_and_network_problems", L"", NULL, SW_SHOWNORMAL) > reinterpret_cast<HINSTANCE>(32))
  278. {
  279. return S_OK;
  280. }
  281. else
  282. {
  283. return E_FAIL;
  284. }
  285. }
  286. //+---------------------------------------------------------------------------
  287. //
  288. // Function: HrFolderCommandHandler
  289. //
  290. // Purpose: Command handler switch -- all commands come through this
  291. // point.
  292. //
  293. // Arguments:
  294. // uiCommand [in] The command-id that's been invoked.
  295. // apidl [in] PIDL array (item 0 is our item to work on)
  296. // cidl [in] Size of the array
  297. // lpici [in] Command context info
  298. // hwndOwner [in] Owner hwnd
  299. //
  300. // Returns:
  301. //
  302. // Author: jeffspr 11 Feb 1998
  303. //
  304. // Notes:
  305. //
  306. HRESULT HrFolderCommandHandler(
  307. UINT uiCommand,
  308. IN const PCONFOLDPIDLVEC& apidl,
  309. HWND hwndOwner,
  310. LPCMINVOKECOMMANDINFO lpici,
  311. LPSHELLFOLDER psf)
  312. {
  313. HRESULT hr = S_OK;
  314. CWaitCursor wc; // Bring up wait cursor now. Remove when we go out of scope.
  315. // refresh all permission so subsequent calls can use cached value
  316. RefreshAllPermission();
  317. switch(uiCommand)
  318. {
  319. case CMIDM_ARRANGE_BY_NAME:
  320. ShellFolderView_ReArrange(hwndOwner, ICOL_NAME);
  321. break;
  322. case CMIDM_ARRANGE_BY_TYPE:
  323. ShellFolderView_ReArrange(hwndOwner, ICOL_TYPE);
  324. break;
  325. case CMIDM_ARRANGE_BY_STATUS:
  326. ShellFolderView_ReArrange(hwndOwner, ICOL_STATUS);
  327. break;
  328. case CMIDM_ARRANGE_BY_OWNER:
  329. ShellFolderView_ReArrange(hwndOwner, ICOL_OWNER);
  330. break;
  331. case CMIDM_ARRANGE_BY_PHONEORHOSTADDRESS:
  332. ShellFolderView_ReArrange(hwndOwner, ICOL_PHONEORHOSTADDRESS);
  333. break;
  334. case CMIDM_ARRANGE_BY_DEVICE_NAME:
  335. ShellFolderView_ReArrange(hwndOwner, ICOL_DEVICE_NAME);
  336. break;
  337. case CMIDM_NEW_CONNECTION:
  338. hr = HrCommandHandlerThread(HrOnCommandNewConnection, apidl, hwndOwner, psf);
  339. break;
  340. case CMIDM_HOMENET_WIZARD:
  341. hr = HrCommandHomeNetWizard();
  342. break;
  343. case CMIDM_NET_DIAGNOSTICS:
  344. hr = HrCommandNetworkDiagnostics();
  345. break;
  346. case CMIDM_NET_TROUBLESHOOT:
  347. hr = HrCommandNetworkTroubleShoot();
  348. break;
  349. case CMIDM_CONNECT:
  350. case CMIDM_ENABLE:
  351. hr = HrCommandHandlerThread(HrOnCommandConnect, apidl, hwndOwner, psf);
  352. break;
  353. case CMIDM_DISCONNECT:
  354. case CMIDM_DISABLE:
  355. hr = HrCommandHandlerThread(HrOnCommandDisconnect, apidl, hwndOwner, psf);
  356. break;
  357. case CMIDM_STATUS:
  358. // the status monitor is already on its own thread
  359. //
  360. hr = HrOnCommandStatus(apidl, hwndOwner, psf);
  361. break;
  362. case CMIDM_FIX:
  363. hr = HrCommandHandlerThread(HrOnCommandFix, apidl, hwndOwner, psf);
  364. break;
  365. case CMIDM_CREATE_SHORTCUT:
  366. hr = HrCommandHandlerThread(HrOnCommandCreateShortcut, apidl, hwndOwner, psf);
  367. break;
  368. case CMIDM_DELETE:
  369. hr = HrCommandHandlerThread(HrOnCommandDelete, apidl, hwndOwner, psf);
  370. break;
  371. case CMIDM_PROPERTIES:
  372. hr = HrCommandHandlerThread(HrOnCommandProperties, apidl, hwndOwner, psf);
  373. break;
  374. case CMIDM_WZCPROPERTIES:
  375. hr = HrCommandHandlerThread(HrOnCommandWZCProperties, apidl, hwndOwner, psf);
  376. break;
  377. case CMIDM_WZCDLG_SHOW:
  378. hr = HrCommandHandlerThread(HrOnCommandWZCDlgShow, apidl, hwndOwner, psf);
  379. break;
  380. case CMIDM_CREATE_COPY:
  381. hr = HrOnCommandCreateCopy(apidl, hwndOwner, psf);
  382. break;
  383. case CMIDM_CONMENU_ADVANCED_CONFIG:
  384. hr = HrCommandHandlerThread(HrOnCommandAdvancedConfig, apidl, hwndOwner, psf);
  385. break;
  386. case CMIDM_SET_DEFAULT:
  387. hr = HrOnCommandSetDefault(apidl, hwndOwner, psf);
  388. break;
  389. case CMIDM_UNSET_DEFAULT:
  390. hr = HrOnCommandUnsetDefault(apidl, hwndOwner, psf);
  391. break;
  392. case CMIDM_CREATE_BRIDGE:
  393. case CMIDM_CONMENU_CREATE_BRIDGE:
  394. if ( TotalValidSelectedConnectionsForBridge(apidl) < 2 )
  395. {
  396. // tell users that he/she needs select 2 or more valid connections in order to acomplish this
  397. NcMsgBox(
  398. _Module.GetResourceInstance(),
  399. NULL,
  400. IDS_CONFOLD_OBJECT_TYPE_BRIDGE,
  401. IDS_BRIDGE_EDUCATION,
  402. MB_ICONEXCLAMATION | MB_OK
  403. );
  404. }
  405. else
  406. HrOnCommandBridgeAddConnections(apidl, hwndOwner, psf);
  407. break;
  408. case CMIDM_ADD_TO_BRIDGE:
  409. HrOnCommandBridgeAddConnections(apidl, hwndOwner, psf);
  410. break;
  411. case CMIDM_REMOVE_FROM_BRIDGE:
  412. HrOnCommandBridgeRemoveConnections(apidl, hwndOwner, psf, CMIDM_REMOVE_FROM_BRIDGE);
  413. break;
  414. case CMIDM_CONMENU_NETWORK_ID:
  415. hr = HrOnCommandNetworkId(apidl, hwndOwner, psf);
  416. break;
  417. case CMIDM_CONMENU_OPTIONALCOMPONENTS:
  418. hr = HrOnCommandOptionalComponents(apidl, hwndOwner, psf);
  419. break;
  420. case CMIDM_CONMENU_DIALUP_PREFS:
  421. hr = HrCommandHandlerThread(HrOnCommandDialupPrefs, apidl, hwndOwner, psf);
  422. break;
  423. case CMIDM_CONMENU_OPERATOR_ASSIST:
  424. hr = HrOnCommandOperatorAssist(apidl, hwndOwner, psf);
  425. break;
  426. #if DBG
  427. case CMIDM_DEBUG_TRAY:
  428. hr = HrOnCommandDebugTray(apidl, hwndOwner, psf);
  429. break;
  430. case CMIDM_DEBUG_TRACING:
  431. hr = HrOnCommandDebugTracing(apidl, hwndOwner, psf);
  432. break;
  433. case CMIDM_DEBUG_NOTIFYADD:
  434. hr = HrOnCommandDebugNotifyAdd(apidl, hwndOwner, psf);
  435. break;
  436. case CMIDM_DEBUG_NOTIFYREMOVE:
  437. hr = HrOnCommandDebugNotifyRemove(apidl, hwndOwner, psf);
  438. break;
  439. case CMIDM_DEBUG_NOTIFYTEST:
  440. hr = HrOnCommandDebugNotifyTest(apidl, hwndOwner, psf);
  441. break;
  442. case CMIDM_DEBUG_REFRESH:
  443. hr = HrOnCommandDebugRefresh(apidl, hwndOwner, psf);
  444. break;
  445. case CMIDM_DEBUG_REFRESHNOFLUSH:
  446. hr = HrOnCommandDebugRefreshNoFlush(apidl, hwndOwner, psf);
  447. break;
  448. case CMIDM_DEBUG_REFRESHSELECTED:
  449. hr = HrCommandHandlerThread(HrOnCommandDebugRefreshSelected, apidl, hwndOwner, psf);
  450. break;
  451. case CMIDM_DEBUG_REMOVETRAYICONS:
  452. hr = HrCommandHandlerThread(HrOnCommandDebugRemoveTrayIcons, apidl, hwndOwner, psf);
  453. break;
  454. #endif
  455. default:
  456. #if DBG
  457. char sz[128];
  458. ZeroMemory(sz, 128);
  459. sprintf(sz, "Unknown command (%d) in HrFolderCommandHandler", uiCommand);
  460. TraceHr(ttidError, FAL, hr, FALSE, sz);
  461. #endif
  462. hr = E_INVALIDARG;
  463. }
  464. TraceHr(ttidError, FAL, hr, FALSE, "HrFolderCommandHandler");
  465. return hr;
  466. }
  467. //+---------------------------------------------------------------------------
  468. //
  469. // Function: HrOnCommandCreateCopy
  470. //
  471. // Purpose: Command handler for the CMIDM_CREATE_COPY command
  472. //
  473. // Arguments:
  474. // apidl [in] PIDL array (item 0 is our item to work on)
  475. // cidl [in] Size of the array
  476. // hwndOwner [in] Owner hwnd
  477. // psf [in] The shell folder interface
  478. //
  479. // Returns:
  480. //
  481. // Author: jeffspr 31 Jan 1998
  482. //
  483. // Notes:
  484. //
  485. HRESULT HrOnCommandCreateCopy(
  486. IN const PCONFOLDPIDLVEC& apidl,
  487. HWND hwndOwner,
  488. LPSHELLFOLDER psf)
  489. {
  490. HRESULT hr = S_OK;
  491. INetConnection * pNetCon = NULL;
  492. INetConnection * pNetConDupe = NULL;
  493. CConnectionFolder * pcf = static_cast<CConnectionFolder *>(psf);
  494. NETCFG_TRY
  495. PCONFOLDPIDLFOLDER pidlFolder;
  496. if (pcf)
  497. {
  498. pidlFolder = pcf->PidlGetFolderRoot();
  499. }
  500. PCONFOLDPIDL pidlConnection;
  501. PCONFOLDPIDLVEC::const_iterator iterLoop;
  502. for (iterLoop = apidl.begin(); iterLoop != apidl.end() ; iterLoop++)
  503. {
  504. // Get the INetConnection object from the persist data
  505. //
  506. hr = HrNetConFromPidl(*iterLoop, &pNetCon);
  507. if (SUCCEEDED(hr))
  508. {
  509. CONFOLDENTRY ccfe;
  510. Assert(pNetCon);
  511. hr = iterLoop->ConvertToConFoldEntry(ccfe);
  512. if (SUCCEEDED(hr))
  513. {
  514. if (ccfe.GetCharacteristics() & NCCF_ALLOW_DUPLICATION)
  515. {
  516. PWSTR pszDupeName = NULL;
  517. hr = g_ccl.HrSuggestNameForDuplicate(ccfe.GetName(), &pszDupeName);
  518. if (SUCCEEDED(hr))
  519. {
  520. Assert(pszDupeName);
  521. // Duplicate the connection
  522. //
  523. hr = pNetCon->Duplicate(pszDupeName, &pNetConDupe);
  524. if (SUCCEEDED(hr))
  525. {
  526. Assert(pNetConDupe);
  527. if (pNetConDupe)
  528. {
  529. hr = g_ccl.HrInsertFromNetCon(pNetConDupe,
  530. pidlConnection);
  531. if (SUCCEEDED(hr))
  532. {
  533. GenerateEvent(SHCNE_CREATE, pidlFolder, pidlConnection, NULL);
  534. pidlConnection.Clear();
  535. }
  536. ReleaseObj(pNetConDupe);
  537. pNetConDupe = NULL;
  538. }
  539. }
  540. delete pszDupeName;
  541. }
  542. }
  543. else
  544. {
  545. AssertSz(ccfe.GetCharacteristics() & NCCF_ALLOW_DUPLICATION,
  546. "What menu supported duplicating this connection?");
  547. }
  548. }
  549. ReleaseObj(pNetCon);
  550. pNetCon = NULL;
  551. }
  552. }
  553. NETCFG_CATCH(hr)
  554. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandCreateCopy");
  555. return hr;
  556. }
  557. //+---------------------------------------------------------------------------
  558. //
  559. // Function: HrOnCommandProperties
  560. //
  561. // Purpose: Command handler for the CMIDM_PROPERTIES command
  562. //
  563. // Arguments:
  564. // apidl [in] PIDL array (item 0 is our item to work on)
  565. // cidl [in] Size of the array
  566. // hwndOwner [in] Owner hwnd
  567. //
  568. // Returns:
  569. //
  570. // Author: jeffspr 4 Nov 1997
  571. //
  572. // Notes:
  573. //
  574. HRESULT HrOnCommandProperties(
  575. IN const PCONFOLDPIDLVEC& apidl,
  576. IN HWND hwndOwner,
  577. LPSHELLFOLDER psf)
  578. {
  579. INT cch;
  580. HRESULT hr = S_OK;
  581. HANDLE hMutex = NULL;
  582. INetConnection * pNetCon = NULL;
  583. WCHAR szConnectionGuid [c_cchGuidWithTerm];
  584. // Just skip out of here if no pidl was supplied
  585. if (apidl.empty())
  586. {
  587. return S_OK;
  588. }
  589. // We can only deal with a single connection. If we have
  590. // multiple, then just use the first one.
  591. //
  592. const PCONFOLDPIDL& pcfp = apidl[0];
  593. if (pcfp.empty())
  594. {
  595. hr = E_INVALIDARG;
  596. goto Error;
  597. }
  598. // If this is an individual incoming connection - disallow this:
  599. if ( (NCCF_INCOMING_ONLY & pcfp->dwCharacteristics) &&
  600. (NCM_NONE != pcfp->ncm) )
  601. {
  602. hr = E_UNEXPECTED;
  603. goto Error;
  604. }
  605. // If this is a LAN connection and the user doesn't have rights
  606. // then disallow properties
  607. //
  608. if ((IsMediaLocalType(pcfp->ncm)) &&
  609. !FHasPermission(NCPERM_LanProperties))
  610. {
  611. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  612. goto Error;
  613. }
  614. // If this is a RAS connection and the user doesn't have rights
  615. // then disallow properties
  616. //
  617. if (IsMediaRASType(pcfp->ncm))
  618. {
  619. BOOL fAllowProperties = (TRUE == ((pcfp->dwCharacteristics & NCCF_ALL_USERS) ?
  620. (FHasPermission(NCPERM_RasAllUserProperties)) :
  621. (FHasPermission(NCPERM_RasMyProperties))));
  622. if (!fAllowProperties)
  623. {
  624. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  625. goto Error;
  626. }
  627. }
  628. hr = HrNetConFromPidl(apidl[0], &pNetCon);
  629. if (FAILED(hr))
  630. {
  631. goto Error;
  632. }
  633. // Aquire a lock on this connection object
  634. //
  635. cch = StringFromGUID2 (pcfp->guidId, szConnectionGuid,
  636. c_cchGuidWithTerm);
  637. Assert (c_cchGuidWithTerm == cch);
  638. hMutex = CreateMutex(NULL, TRUE, szConnectionGuid);
  639. if ((NULL == hMutex) || (ERROR_ALREADY_EXISTS == GetLastError()))
  640. {
  641. // if the mutex already exists try to find the connection window
  642. //
  643. if (ERROR_ALREADY_EXISTS == GetLastError())
  644. {
  645. Assert(pNetCon);
  646. ActivatePropertyDialog(pNetCon);
  647. Assert(S_OK == hr);
  648. // Don't let the error reporting below display the error.
  649. // We want the user to acknowledge the message box above
  650. // then we'll be nice an bring the property page to the
  651. // foreground.
  652. goto Error;
  653. }
  654. hr = HrFromLastWin32Error();
  655. goto Error;
  656. }
  657. Assert(SUCCEEDED(hr));
  658. // Bring up the connection Properties UI.
  659. //
  660. hr = HrRaiseConnectionPropertiesInternal(
  661. NULL, // ISSUE: Going modal -- hwndOwner ? hwndOwner : GetDesktopWindow(),
  662. 0, // First page
  663. pNetCon);
  664. Error:
  665. if (FAILED(hr))
  666. {
  667. UINT ids = 0;
  668. switch(hr)
  669. {
  670. case E_UNEXPECTED:
  671. ids = IDS_CONFOLD_PROPERTIES_ON_RASSERVERINSTEAD;
  672. break;
  673. case HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED):
  674. ids = IDS_CONFOLD_PROPERTIES_NOACCESS;
  675. break;
  676. case HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY):
  677. ids = IDS_CONFOLD_OUTOFMEMORY;
  678. break;
  679. default:
  680. ids = IDS_CONFOLD_UNEXPECTED_ERROR;
  681. break;
  682. }
  683. NcMsgBox(_Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION,
  684. ids, MB_ICONEXCLAMATION | MB_OK);
  685. }
  686. if (hMutex)
  687. {
  688. ReleaseMutex(hMutex);
  689. CloseHandle(hMutex);
  690. }
  691. ReleaseObj(pNetCon);
  692. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandProperties");
  693. return hr;
  694. }
  695. //+---------------------------------------------------------------------------
  696. //
  697. // Function: HrOnCommandWZCProperties
  698. //
  699. // Purpose: Command handler for the CMIDM_WZCPROPERTIES command
  700. //
  701. // Arguments:
  702. // apidl [in] PIDL array (item 0 is our item to work on)
  703. // cidl [in] Size of the array
  704. // hwndOwner [in] Owner hwnd
  705. //
  706. // Returns:
  707. //
  708. // Author: deonb 5 Apr 2001
  709. //
  710. // Notes:
  711. //
  712. HRESULT HrOnCommandWZCProperties(
  713. IN const PCONFOLDPIDLVEC& apidl,
  714. IN HWND hwndOwner,
  715. LPSHELLFOLDER psf)
  716. {
  717. INT cch;
  718. HRESULT hr = S_OK;
  719. HANDLE hMutex = NULL;
  720. INetConnection * pNetCon = NULL;
  721. WCHAR szConnectionGuid [c_cchGuidWithTerm];
  722. // Just skip out of here if no pidl was supplied
  723. if (apidl.empty())
  724. {
  725. return S_OK;
  726. }
  727. // We can only deal with a single connection. If we have
  728. // multiple, then just use the first one.
  729. //
  730. const PCONFOLDPIDL& pcfp = apidl[0];
  731. if (pcfp.empty())
  732. {
  733. hr = E_INVALIDARG;
  734. goto Error;
  735. }
  736. // If this is a LAN connection and the user doesn't have rights
  737. // then disallow properties
  738. //
  739. if ((IsMediaLocalType(pcfp->ncm)) &&
  740. !FHasPermission(NCPERM_LanProperties))
  741. {
  742. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  743. goto Error;
  744. }
  745. // If this is a RAS connection and the user doesn't have rights
  746. // then disallow properties
  747. //
  748. if (IsMediaRASType(pcfp->ncm))
  749. {
  750. BOOL fAllowProperties = (TRUE == ((pcfp->dwCharacteristics & NCCF_ALL_USERS) ?
  751. (FHasPermission(NCPERM_RasAllUserProperties)) :
  752. (FHasPermission(NCPERM_RasMyProperties))));
  753. if (!fAllowProperties)
  754. {
  755. hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  756. goto Error;
  757. }
  758. }
  759. hr = HrNetConFromPidl(apidl[0], &pNetCon);
  760. if (FAILED(hr))
  761. {
  762. goto Error;
  763. }
  764. // Aquire a lock on this connection object
  765. //
  766. cch = StringFromGUID2 (pcfp->guidId, szConnectionGuid,
  767. c_cchGuidWithTerm);
  768. Assert (c_cchGuidWithTerm == cch);
  769. hMutex = CreateMutex(NULL, TRUE, szConnectionGuid);
  770. if ((NULL == hMutex) || (ERROR_ALREADY_EXISTS == GetLastError()))
  771. {
  772. // if the mutex already exists try to find the connection window
  773. //
  774. if (ERROR_ALREADY_EXISTS == GetLastError())
  775. {
  776. Assert(pNetCon);
  777. ActivatePropertyDialog(pNetCon);
  778. Assert(S_OK == hr);
  779. // Don't let the error reporting below display the error.
  780. // We want the user to acknowledge the message box above
  781. // then we'll be nice an bring the property page to the
  782. // foreground.
  783. goto Error;
  784. }
  785. hr = HrFromLastWin32Error();
  786. goto Error;
  787. }
  788. Assert(SUCCEEDED(hr));
  789. // Bring up the connection Properties UI.
  790. //
  791. hr = HrRaiseConnectionPropertiesInternal(
  792. NULL, // ISSUE: Going modal -- hwndOwner ? hwndOwner : GetDesktopWindow(),
  793. 1, // Second page
  794. pNetCon);
  795. Error:
  796. if (FAILED(hr))
  797. {
  798. UINT ids = 0;
  799. switch(hr)
  800. {
  801. case HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED):
  802. ids = IDS_CONFOLD_PROPERTIES_NOACCESS;
  803. break;
  804. case HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY):
  805. ids = IDS_CONFOLD_OUTOFMEMORY;
  806. break;
  807. default:
  808. ids = IDS_CONFOLD_UNEXPECTED_ERROR;
  809. break;
  810. }
  811. NcMsgBox(_Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION,
  812. ids, MB_ICONEXCLAMATION | MB_OK);
  813. }
  814. if (hMutex)
  815. {
  816. ReleaseMutex(hMutex);
  817. CloseHandle(hMutex);
  818. }
  819. ReleaseObj(pNetCon);
  820. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandProperties");
  821. return hr;
  822. }
  823. //+---------------------------------------------------------------------------
  824. //
  825. // Function: HrOnCommandWZCDlgShow
  826. //
  827. // Purpose: Command handler for the CMIDM_WZCDLG_SHOW command
  828. //
  829. // Arguments:
  830. // apidl [in] PIDL array (item 0 is our item to work on)
  831. // cidl [in] Size of the array
  832. // hwndOwner [in] Owner hwnd
  833. //
  834. // Returns:
  835. //
  836. // Author: deonb 15 May 2001
  837. //
  838. // Notes:
  839. //
  840. #define WZCDLG_FAILED 0x00010001 // 802.11 automatic configuration failed
  841. HRESULT HrOnCommandWZCDlgShow(
  842. IN const PCONFOLDPIDLVEC& apidl,
  843. IN HWND hwndOwner,
  844. LPSHELLFOLDER psf)
  845. {
  846. INT cch;
  847. HRESULT hr = S_OK;
  848. // Just skip out of here if no pidl was supplied
  849. if (apidl.empty())
  850. {
  851. return S_OK;
  852. }
  853. // We can only deal with a single connection. If we have
  854. // multiple, then just use the first one.
  855. //
  856. const PCONFOLDPIDL& pcfp = apidl[0];
  857. if (!pcfp.empty())
  858. {
  859. WZCDLG_DATA wzcDlgData = {0};
  860. wzcDlgData.dwCode = WZCDLG_FAILED;
  861. wzcDlgData.lParam = 1;
  862. BSTR szCookie = SysAllocStringByteLen(reinterpret_cast<LPSTR>(&wzcDlgData), sizeof(wzcDlgData));
  863. BSTR szName = SysAllocString(pcfp->PszGetNamePointer());
  864. if (szCookie && szName)
  865. {
  866. GUID gdGuid = pcfp->guidId;
  867. hr = WZCOnBalloonClick(&gdGuid, szName, szCookie);
  868. }
  869. else
  870. {
  871. hr = E_OUTOFMEMORY;
  872. }
  873. SysFreeString(szName);
  874. SysFreeString(szCookie);
  875. }
  876. else
  877. {
  878. hr = E_INVALIDARG;
  879. }
  880. return hr;
  881. }
  882. //+---------------------------------------------------------------------------
  883. //
  884. // Function: HrRaiseConnectionProperties
  885. //
  886. // Purpose: Public function for bringing up the propsheet page UI for
  887. // the passed in connection
  888. //
  889. // Arguments:
  890. // hwnd [in] Owner hwnd
  891. // pconn [in] Connection pointer passed in from the shell
  892. //
  893. // Returns:
  894. //
  895. // Author: scottbri 3 Nov 1998
  896. //
  897. // Notes: Needs to convert the INetConnection * below into suitable
  898. // parameters for a call to HrOnCommandProperties above.
  899. //
  900. HRESULT HrRaiseConnectionProperties(HWND hwnd, INetConnection * pConn)
  901. {
  902. HRESULT hr = S_OK;
  903. PCONFOLDPIDL pidl;
  904. PCONFOLDPIDLFOLDER pidlFolder;
  905. LPSHELLFOLDER psfConnections = NULL;
  906. if (NULL == pConn)
  907. {
  908. hr = E_INVALIDARG;
  909. goto Error;
  910. }
  911. // Create a pidl for the connection
  912. //
  913. hr = HrCreateConFoldPidl(WIZARD_NOT_WIZARD, pConn, pidl);
  914. if (SUCCEEDED(hr))
  915. {
  916. // Get the pidl for the Connections Folder
  917. //
  918. hr = HrGetConnectionsFolderPidl(pidlFolder);
  919. if (SUCCEEDED(hr))
  920. {
  921. // Get the Connections Folder object
  922. //
  923. hr = HrGetConnectionsIShellFolder(pidlFolder, &psfConnections);
  924. if (SUCCEEDED(hr))
  925. {
  926. PCONFOLDPIDLVEC vecPidls;
  927. vecPidls.push_back(pidl);
  928. hr = HrOnCommandProperties(vecPidls, hwnd, psfConnections);
  929. ReleaseObj(psfConnections);
  930. }
  931. }
  932. }
  933. Error:
  934. TraceHr(ttidError, FAL, hr, FALSE, "HrRaiseConnectionProperties");
  935. return hr;
  936. }
  937. //+---------------------------------------------------------------------------
  938. //
  939. // Function: HrOnCommandConnectInternal
  940. //
  941. // Purpose: The guts of the Connect code. This is called both from
  942. // HrOnCommandConnect and from HrOnCommandNewConnection, since
  943. // that now connects after creating the new connection
  944. //
  945. // Arguments:
  946. // pNetCon [in] INetConnection * of the connection to activate
  947. // hwndOwner [in] Our parent hwnd
  948. // pcfp [in] Our pidl structure
  949. // psf [in] Shell Folder
  950. //
  951. // Returns:
  952. //
  953. // Author: jeffspr 10 Jun 1998
  954. //
  955. // Notes:
  956. //
  957. HRESULT HrOnCommandConnectInternal(
  958. INetConnection * pNetCon,
  959. HWND hwndOwner,
  960. const PCONFOLDPIDL& pcfp,
  961. LPSHELLFOLDER psf)
  962. {
  963. HRESULT hr = S_OK;
  964. CConnectionFolder * pcf = static_cast<CConnectionFolder *>(psf);
  965. NETCFG_TRY
  966. PCONFOLDPIDLFOLDER pidlFolder;
  967. if (pcf)
  968. {
  969. pidlFolder = pcf->PidlGetFolderRoot();
  970. }
  971. BOOL fActivating = FALSE;
  972. // Use a separate var so we can keep track of the result of the connect
  973. // and the result of the get_Status.
  974. //
  975. HRESULT hrConnect = S_OK;
  976. Assert(pNetCon);
  977. Assert(psf);
  978. // Get current activation state
  979. //
  980. CONFOLDENTRY cfEmpty;
  981. (void) HrCheckForActivation(pcfp, cfEmpty, &fActivating);
  982. // Check for rights to connect
  983. //
  984. if (((IsMediaLocalType(pcfp->ncm)) && !FHasPermission(NCPERM_LanConnect)) ||
  985. ((IsMediaRASType(pcfp->ncm)) && !FHasPermission(NCPERM_RasConnect)))
  986. {
  987. (void) NcMsgBox(
  988. _Module.GetResourceInstance(),
  989. NULL,
  990. IDS_CONFOLD_WARNING_CAPTION,
  991. IDS_CONFOLD_CONNECT_NOACCESS,
  992. MB_OK | MB_ICONEXCLAMATION);
  993. }
  994. // Drop out of this call unless we're currently disconnected.
  995. //
  996. else if (pcfp->ncs == NCS_DISCONNECTED && !fActivating)
  997. {
  998. // Ignore the return code. Failing to set this flag shouldn't keep
  999. // us from attempting to connect.
  1000. //
  1001. (void) HrSetActivationFlag(pcfp, cfEmpty, TRUE);
  1002. // Get the INetConnectionConnectUi interface and make the connection
  1003. // Get the hr (for debugging), but we want to update the status
  1004. // of the connection even if the connect failed
  1005. //
  1006. hrConnect = HrConnectOrDisconnectNetConObject(
  1007. // It's OK if the hwnd is NULL. We don't want to go modal
  1008. // on the desktop.
  1009. NULL, // FIXED -- Was going modal with hwndOwner ? hwndOwner : GetDesktopWindow(),
  1010. pNetCon,
  1011. CD_CONNECT);
  1012. // Even on failure, we want to continue, because we might find that
  1013. // the device is now listed as unavailable. On cancel (S_FALSE), we
  1014. // don't have that concern.
  1015. //
  1016. if (S_FALSE != hrConnect)
  1017. {
  1018. // Even on failure, we want to continue, because we might find that
  1019. // the device is now listed as unavailable.
  1020. if (FAILED(hrConnect))
  1021. {
  1022. TraceTag(ttidShellFolder, "HrOnCommandConnect: Connect failed, 0x%08x", hrConnect);
  1023. }
  1024. #if 0 // (JEFFSPR) - 11/20/98 turning this on until the notify COM failures are worked out.
  1025. // Now taken care of by the notification engine.
  1026. //
  1027. // Get the new status from the connection
  1028. //
  1029. NETCON_PROPERTIES * pProps;
  1030. hr = pNetCon->GetProperties(&pProps);
  1031. if (SUCCEEDED(hr))
  1032. {
  1033. // This won't necessarily be connected -- we used to assert here, but it's
  1034. // actually possible for the connection to go dead between when we connect
  1035. // and when we ask for the status.
  1036. //
  1037. hr = HrUpdateConnectionStatus(pcfp, pProps->Status, pidlFolder, TRUE, pProps->dwCharacter);
  1038. FreeNetconProperties(pProps);
  1039. }
  1040. #endif
  1041. }
  1042. else
  1043. {
  1044. // hrConnect is S_FALSE. Pass that on.
  1045. //
  1046. hr = hrConnect;
  1047. }
  1048. // Set us as "not in the process of activating"
  1049. //
  1050. hr = HrSetActivationFlag(pcfp, cfEmpty, FALSE);
  1051. }
  1052. else
  1053. {
  1054. if ((IsMediaRASType(pcfp->ncm)) &&
  1055. (pcfp->ncm != NCM_NONE))
  1056. {
  1057. // For non-LAN connections, attempt to bring the RAS dialer UI
  1058. // into focus instead of putting up an error message
  1059. HWND hwndDialer;
  1060. LPWSTR pszTitle;
  1061. NETCON_PROPERTIES * pProps;
  1062. hr = pNetCon->GetProperties(&pProps);
  1063. if (SUCCEEDED(hr))
  1064. {
  1065. DwFormatStringWithLocalAlloc(SzLoadIds(IDS_CONFOLD_RAS_DIALER_TITLE_FMT),
  1066. &pszTitle, pProps->pszwName);
  1067. hwndDialer = FindWindowEx(NULL, NULL, L"#32770", pszTitle);
  1068. if (hwndDialer)
  1069. {
  1070. SetForegroundWindow(hwndDialer);
  1071. }
  1072. FreeNetconProperties(pProps);
  1073. MemFree(pszTitle);
  1074. }
  1075. }
  1076. else if (fActivating)
  1077. {
  1078. (void) NcMsgBox(
  1079. _Module.GetResourceInstance(),
  1080. NULL,
  1081. IDS_CONFOLD_WARNING_CAPTION,
  1082. IDS_CONFOLD_CONNECT_IN_PROGRESS,
  1083. MB_OK | MB_ICONEXCLAMATION);
  1084. }
  1085. }
  1086. NETCFG_CATCH(hr)
  1087. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandConnectInternal");
  1088. return hr;
  1089. }
  1090. //+---------------------------------------------------------------------------
  1091. //
  1092. // Function: HrOnCommandFixInternal
  1093. //
  1094. // Purpose: handle the fix and bring up the progress dialog
  1095. //
  1096. // Arguments:
  1097. // apidl [in] PIDL array (item 0 is our item to work on)
  1098. // cidl [in] Size of the array
  1099. // hwndOwner [in] Owner hwnd
  1100. //
  1101. // Returns:
  1102. //
  1103. HRESULT HrOnCommandFixInternal(
  1104. const CONFOLDENTRY& ccfe,
  1105. HWND hwndOwner,
  1106. LPSHELLFOLDER psf)
  1107. {
  1108. HRESULT hr = S_OK;
  1109. INetConnection * pNetCon = NULL;
  1110. CConnectionFolder * pcf = static_cast<CConnectionFolder *>(psf);
  1111. Assert(!ccfe.empty());
  1112. NETCON_MEDIATYPE ncmType = ccfe.GetNetConMediaType();
  1113. //fix is only avalable for LAN and bridge connections
  1114. if (NCM_LAN != ncmType && NCM_BRIDGE != ncmType)
  1115. {
  1116. return S_FALSE;
  1117. }
  1118. hr = ccfe.HrGetNetCon(IID_INetConnection, reinterpret_cast<VOID**>(&pNetCon));
  1119. if (SUCCEEDED(hr))
  1120. {
  1121. NETCON_PROPERTIES* pProps;
  1122. hr = pNetCon->GetProperties(&pProps);
  1123. if (SUCCEEDED(hr))
  1124. {
  1125. tstring strMessage = L"";
  1126. CLanConnectionUiDlg dlg;
  1127. HWND hwndDlg;
  1128. //bring up the dialog to tell the user we're doing the fix
  1129. dlg.SetConnection(pNetCon);
  1130. hwndDlg = dlg.Create(hwndOwner);
  1131. PCWSTR szw = SzLoadIds(IDS_FIX_REPAIRING);
  1132. SetDlgItemText(hwndDlg, IDC_TXT_Caption, szw);
  1133. //do the fix
  1134. hr = HrTryToFix(pProps->guidId, strMessage);
  1135. FreeNetconProperties(pProps);
  1136. if (NULL != hwndDlg)
  1137. {
  1138. DestroyWindow(hwndDlg);
  1139. }
  1140. //tell users the results
  1141. NcMsgBox(_Module.GetResourceInstance(),
  1142. NULL,
  1143. IDS_FIX_CAPTION,
  1144. IDS_FIX_MESSAGE,
  1145. MB_OK | MB_TOPMOST,
  1146. strMessage.c_str());
  1147. }
  1148. ReleaseObj(pNetCon);
  1149. }
  1150. TraceHr(ttidShellFolder, FAL, hr, (S_FALSE == hr), "HrOnCommandFixInternal");
  1151. return hr;
  1152. }
  1153. //+---------------------------------------------------------------------------
  1154. //
  1155. // Function: HrOnCommandFix
  1156. //
  1157. // Purpose: Command handler for the CMIDM_FIX command
  1158. //
  1159. // Arguments:
  1160. // apidl [in] PIDL array (item 0 is our item to work on)
  1161. // cidl [in] Size of the array
  1162. // hwndOwner [in] Owner hwnd
  1163. //
  1164. // Returns:
  1165. //
  1166. HRESULT HrOnCommandFix(
  1167. IN const PCONFOLDPIDLVEC& apidl,
  1168. HWND hwndOwner,
  1169. LPSHELLFOLDER psf)
  1170. {
  1171. HRESULT hr = S_OK;
  1172. CONFOLDENTRY ccfe;
  1173. if (!apidl.empty())
  1174. {
  1175. hr = apidl[0].ConvertToConFoldEntry(ccfe);
  1176. if (SUCCEEDED(hr))
  1177. {
  1178. if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL))
  1179. {
  1180. TraceTag(ttidError, "Could not set priority for Repair thread");
  1181. }
  1182. // We don't care if whether the fix succeeds or not
  1183. // if it fails, there will be a pop-up saying that
  1184. HrOnCommandFixInternal(ccfe, hwndOwner, psf);
  1185. }
  1186. }
  1187. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandFix");
  1188. return hr;
  1189. }
  1190. //+---------------------------------------------------------------------------
  1191. //
  1192. // Function: HrOnCommandConnect
  1193. //
  1194. // Purpose: Command handler for the CMIDM_CONNECT or CMIDM_ENABLE command
  1195. //
  1196. // Arguments:
  1197. // apidl [in] PIDL array (item 0 is our item to work on)
  1198. // cidl [in] Size of the array
  1199. // hwndOwner [in] Owner hwnd
  1200. //
  1201. // Returns:
  1202. //
  1203. // Author: jeffspr 12 Nov 1997
  1204. //
  1205. // Notes:
  1206. //
  1207. HRESULT HrOnCommandConnect(
  1208. IN const PCONFOLDPIDLVEC& apidl,
  1209. HWND hwndOwner,
  1210. LPSHELLFOLDER psf)
  1211. {
  1212. HRESULT hr = S_OK;
  1213. INetConnection * pNetCon = NULL;
  1214. NETCFG_TRY
  1215. if (apidl.size() == 1)
  1216. {
  1217. PCONFOLDPIDL pcfp = apidl[0];
  1218. if (!pcfp.empty())
  1219. {
  1220. // Get the cached pidl. If it's found, then use the copy. If not
  1221. // then use whatever info we have (but this might be outdated)
  1222. //
  1223. PCONFOLDPIDL pcfpCopy;
  1224. hr = g_ccl.HrGetCachedPidlCopyFromPidl(apidl[0], pcfpCopy);
  1225. if (S_OK == hr)
  1226. {
  1227. pcfp.Swop(pcfpCopy); // pcfp = pcfpCopy;
  1228. }
  1229. else
  1230. {
  1231. TraceHr(ttidShellFolder, FAL, hr, FALSE, "Cached pidl not retrievable in HrOnCommandConnect");
  1232. }
  1233. // Make sure that this connection is valid for connection (not a wizrd,
  1234. // and not already connected. If so, then connect.
  1235. //
  1236. if ( (WIZARD_NOT_WIZARD == pcfp->wizWizard) && !(fIsConnectedStatus(pcfp->ncs)) )
  1237. {
  1238. // Ignore this entry if we're getting a connect verb on an incoming connections
  1239. // object
  1240. //
  1241. if (pcfp->ncm != NCM_NONE && (!(pcfp->dwCharacteristics & NCCF_INCOMING_ONLY)))
  1242. {
  1243. // Get the INetConnection object from the persist data
  1244. //
  1245. hr = HrNetConFromPidl(apidl[0], &pNetCon);
  1246. if (SUCCEEDED(hr))
  1247. {
  1248. hr = HrOnCommandConnectInternal(pNetCon, hwndOwner, pcfp, psf);
  1249. ReleaseObj(pNetCon);
  1250. }
  1251. }
  1252. }
  1253. }
  1254. // else if (FIsConFoldPidl98(apidl[0]) && FALSE )
  1255. // {
  1256. // // ISSUE - FIsConFoldPidl98 doesn't give ua a wizWizard anymore! Used to be:
  1257. // // FIsConFoldPidl98(apidl[0], &fIsWizard) && !fIsWizard)
  1258. //
  1259. // // raise an error that the connection is not found
  1260. // //
  1261. // NcMsgBox(_Module.GetResourceInstance(), NULL,
  1262. // IDS_CONFOLD_WARNING_CAPTION,
  1263. // IDS_CONFOLD_NO_CONNECTION,
  1264. // MB_ICONEXCLAMATION | MB_OK);
  1265. // }
  1266. }
  1267. NETCFG_CATCH(hr)
  1268. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandConnect");
  1269. return hr;
  1270. }
  1271. //+---------------------------------------------------------------------------
  1272. //
  1273. // Function: HrOnCommandDisconnectInternal
  1274. //
  1275. // Purpose: Internal command handler for the CMIDM_DISCONNECT or CMIDM_DISABLE command.
  1276. // This function is callable by the tray, which doesn't have
  1277. // the data in pidls, but rather has the actual data that we're
  1278. // concerned with. HrOnCommandDisconnect retrieves this data
  1279. // and passes on the call to this function
  1280. //
  1281. // Arguments:
  1282. // ccfe [in] Our ConFoldEntry (our connection data)
  1283. // hwndOwner [in] Our parent hwnd
  1284. //
  1285. // Returns:
  1286. //
  1287. // Author: jeffspr 20 Mar 1998
  1288. //
  1289. // Notes:
  1290. //
  1291. HRESULT HrOnCommandDisconnectInternal(
  1292. const CONFOLDENTRY& ccfe,
  1293. HWND hwndOwner,
  1294. LPSHELLFOLDER psf)
  1295. {
  1296. HRESULT hr = S_OK;
  1297. INetConnection * pNetCon = NULL;
  1298. CConnectionFolder * pcf = static_cast<CConnectionFolder *>(psf);
  1299. Assert(!ccfe.empty());
  1300. // Check for rights to disconnect
  1301. //
  1302. if (((IsMediaLocalType(ccfe.GetNetConMediaType())) && !FHasPermission(NCPERM_LanConnect)) ||
  1303. ((IsMediaRASType(ccfe.GetNetConMediaType())) && !FHasPermission(NCPERM_RasConnect)))
  1304. {
  1305. (void) NcMsgBox(
  1306. _Module.GetResourceInstance(),
  1307. NULL,
  1308. IDS_CONFOLD_WARNING_CAPTION,
  1309. IDS_CONFOLD_DISCONNECT_NOACCESS,
  1310. MB_OK | MB_ICONEXCLAMATION);
  1311. }
  1312. else
  1313. {
  1314. PromptForSyncIfNeeded(ccfe, hwndOwner);
  1315. {
  1316. CWaitCursor wc; // Bring up wait cursor now. Remove when we go out of scope.
  1317. // Get the INetConnection object from the persist data
  1318. //
  1319. hr = ccfe.HrGetNetCon(IID_INetConnection, reinterpret_cast<VOID**>(&pNetCon));
  1320. if (SUCCEEDED(hr))
  1321. {
  1322. Assert(pNetCon);
  1323. hr = HrConnectOrDisconnectNetConObject (
  1324. hwndOwner, pNetCon, CD_DISCONNECT);
  1325. ReleaseObj(pNetCon);
  1326. }
  1327. }
  1328. }
  1329. TraceHr(ttidShellFolder, FAL, hr, (S_FALSE == hr), "HrOnCommandDisconnectInternal");
  1330. return hr;
  1331. }
  1332. //+---------------------------------------------------------------------------
  1333. //
  1334. // Function: HrOnCommandDisconnect
  1335. //
  1336. // Purpose: Command handler for the CMIDM_DISCONNECT or CMIDM_DISABLE command
  1337. //
  1338. // Arguments:
  1339. // apidl [in] PIDL array (item 0 is our item to work on)
  1340. // cidl [in] Size of the array
  1341. // hwndOwner [in] Owner hwnd
  1342. //
  1343. // Returns:
  1344. //
  1345. // Author: jeffspr 12 Nov 1997
  1346. //
  1347. // Notes: We only act on a single entry in this function
  1348. //
  1349. HRESULT HrOnCommandDisconnect(
  1350. IN const PCONFOLDPIDLVEC& apidl,
  1351. HWND hwndOwner,
  1352. LPSHELLFOLDER psf)
  1353. {
  1354. HRESULT hr = S_OK;
  1355. CONFOLDENTRY ccfe;
  1356. if (!apidl.empty())
  1357. {
  1358. hr = apidl[0].ConvertToConFoldEntry(ccfe);
  1359. if (SUCCEEDED(hr))
  1360. {
  1361. hr = HrOnCommandDisconnectInternal(ccfe, hwndOwner, psf);
  1362. // Normalize the return code. We don't care if whether the connection
  1363. // was actually disconnected or not (if canceled, it would have \
  1364. // returned S_FALSE;
  1365. //
  1366. if (SUCCEEDED(hr))
  1367. {
  1368. hr = S_OK;
  1369. }
  1370. }
  1371. }
  1372. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandDisconnect");
  1373. return hr;
  1374. }
  1375. //+---------------------------------------------------------------------------
  1376. //
  1377. // Function: HrOnCommandStatusInternal
  1378. //
  1379. // Purpose: Internal command handler for the CMIDM_STATUS command.
  1380. // This function is callable by the tray, which doesn't have
  1381. // the data in pidls, but rather has the actual data that we're
  1382. // concerned with. HrOnCommandStatus retrieves this data
  1383. // and passes on the call to this function
  1384. //
  1385. // Arguments:
  1386. // ccfe [in] ConFoldEntry for the connection in question
  1387. // fCreateEngine [in] Whether a status engine should be created if not exist
  1388. //
  1389. // Returns:
  1390. //
  1391. // Author: jeffspr 20 Mar 1998
  1392. //
  1393. // Notes:
  1394. //
  1395. HRESULT HrOnCommandStatusInternal(
  1396. const CONFOLDENTRY& ccfe,
  1397. BOOL fCreateEngine)
  1398. {
  1399. HRESULT hr = S_OK;
  1400. Assert(!ccfe.empty());
  1401. // see if we are in safe mode with networking
  1402. int iRet = GetSystemMetrics(SM_CLEANBOOT);
  1403. if (!iRet)
  1404. {
  1405. // normal boot
  1406. Assert(g_hwndTray);
  1407. // The permissions check will be done in the tray message processing.
  1408. //
  1409. PostMessage(g_hwndTray, MYWM_OPENSTATUS, (WPARAM) ccfe.TearOffItemIdList(), (LPARAM) fCreateEngine);
  1410. }
  1411. else if (2 == iRet)
  1412. {
  1413. // safemode with networking, statmon is not tied to tray icon
  1414. if (FHasPermission(NCPERM_Statistics))
  1415. {
  1416. INetStatisticsEngine* pnseNew;
  1417. hr = HrGetStatisticsEngineForEntry(ccfe, &pnseNew, TRUE);
  1418. if (SUCCEEDED(hr))
  1419. {
  1420. hr = pnseNew->ShowStatusMonitor();
  1421. ReleaseObj(pnseNew);
  1422. }
  1423. }
  1424. }
  1425. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandStatusInternal");
  1426. return hr;
  1427. }
  1428. //+---------------------------------------------------------------------------
  1429. //
  1430. // Function: HrOnCommandStatus
  1431. //
  1432. // Purpose: Command handler for the CMIDM_STATUS command
  1433. //
  1434. // Arguments:
  1435. // apidl [in] PIDL array (item 0 is our item to work on)
  1436. // cidl [in] Size of the array
  1437. // hwndOwner [in] Owner hwnd
  1438. //
  1439. // Returns:
  1440. //
  1441. // Author: jeffspr 12 Nov 1997
  1442. //
  1443. // Notes:
  1444. //
  1445. HRESULT HrOnCommandStatus(
  1446. IN const PCONFOLDPIDLVEC& apidl,
  1447. HWND hwndOwner,
  1448. LPSHELLFOLDER psf)
  1449. {
  1450. HRESULT hr = S_OK;
  1451. CONFOLDENTRY ccfe;
  1452. if (apidl[0].empty())
  1453. {
  1454. hr = E_INVALIDARG;
  1455. }
  1456. else
  1457. {
  1458. AssertSz(apidl.size() == 1, "We don't allow status on multi-selected items");
  1459. // Copy the pidl, as the PostMessage isn't sync, and the context menu's
  1460. // copy of the pidl could be destroyed before the tray processed the
  1461. // message. The tray is responsible for free'ing in the pidl.
  1462. //
  1463. hr = apidl[0].ConvertToConFoldEntry(ccfe);
  1464. if (SUCCEEDED(hr))
  1465. {
  1466. if (fIsConnectedStatus(ccfe.GetNetConStatus()) ||
  1467. ccfe.IsConnected() )
  1468. {
  1469. hr = HrOnCommandStatusInternal(ccfe, TRUE);
  1470. }
  1471. }
  1472. }
  1473. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandStatus");
  1474. return hr;
  1475. }
  1476. VOID SetICWComplete();
  1477. //+---------------------------------------------------------------------------
  1478. //
  1479. // Function: HrOnCommandNewConnection
  1480. //
  1481. // Purpose: Command handler for the CMIDM_NEW_CONNECTION command
  1482. //
  1483. // Arguments:
  1484. // apidl [in] PIDL array (item 0 is our item to work on)
  1485. // cidl [in] Size of the array
  1486. // hwndOwner [in] Owner hwnd
  1487. //
  1488. // Returns:
  1489. //
  1490. // Author: jeffspr 12 Nov 1997
  1491. //
  1492. // Notes:
  1493. //
  1494. HRESULT HrOnCommandNewConnection(
  1495. IN const PCONFOLDPIDLVEC& apidl,
  1496. HWND hwndOwner,
  1497. LPSHELLFOLDER psf)
  1498. {
  1499. HRESULT hr = S_OK;
  1500. INetConnection * pNetCon = NULL;
  1501. NETCFG_TRY
  1502. PCONFOLDPIDL pidlConnection;
  1503. // Don't use hwndOwner for anything. We shouldn't become modal!
  1504. //
  1505. hr = NetSetupAddRasConnection(NULL, &pNetCon);
  1506. if (S_OK == hr)
  1507. {
  1508. CConnectionFolder * pcf = static_cast<CConnectionFolder *>(psf);
  1509. PCONFOLDPIDLFOLDER pidlFolder;
  1510. if (pcf)
  1511. {
  1512. pidlFolder = pcf->PidlGetFolderRoot();
  1513. }
  1514. Assert(pNetCon);
  1515. hr = g_ccl.HrInsertFromNetCon(pNetCon, pidlConnection);
  1516. if (SUCCEEDED(hr) && (!pidlConnection.empty()) )
  1517. {
  1518. PCONFOLDPIDL pcfp = pidlConnection;
  1519. GenerateEvent(SHCNE_CREATE, pidlFolder, pidlConnection, NULL);
  1520. // Don't try to connect an object that's incoming only, and don't connect
  1521. // it unless we're listed as disconnected
  1522. //
  1523. if (!(pcfp->dwCharacteristics & NCCF_INCOMING_ONLY) && (pcfp->ncs == NCS_DISCONNECTED))
  1524. {
  1525. // If we have Ras connect permissions, then try to dial. Otherwise, don't
  1526. // force the user into a failure here.
  1527. //
  1528. if (FHasPermission(NCPERM_RasConnect))
  1529. {
  1530. hr = HrOnCommandConnectInternal(pNetCon, hwndOwner, pidlConnection, psf);
  1531. }
  1532. }
  1533. }
  1534. pNetCon->Release();
  1535. }
  1536. else if (SUCCEEDED(hr))
  1537. {
  1538. // Convert S_FALSE to S_OK
  1539. // S_FALSE means no pages were displayed but nothing failed.
  1540. // S_FALSE is returned when the wizard is already being displayed
  1541. //
  1542. hr = S_OK;
  1543. }
  1544. SetICWComplete();
  1545. NETCFG_CATCH(hr)
  1546. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandNewConnection");
  1547. return hr;
  1548. }
  1549. //+---------------------------------------------------------------------------
  1550. //
  1551. // Function: HrOnCommandAdvancedConfig
  1552. //
  1553. // Purpose: Command handler for the CMIDM_ADVANCED_CONFIG command
  1554. //
  1555. // Arguments:
  1556. // apidl [in] PIDL array (item 0 is our item to work on)
  1557. // cidl [in] Size of the array
  1558. // hwndOwner [in] Owner hwnd
  1559. //
  1560. // Returns:
  1561. //
  1562. // Author: jeffspr 3 Dec 1997
  1563. //
  1564. // Notes:
  1565. //
  1566. HRESULT HrOnCommandAdvancedConfig(
  1567. IN const PCONFOLDPIDLVEC& apidl,
  1568. HWND hwndOwner,
  1569. LPSHELLFOLDER psf)
  1570. {
  1571. HRESULT hr = S_OK;
  1572. hr = HrDoAdvCfgDlg(hwndOwner);
  1573. TraceError("HrOnCommandAdvancedConfig", hr);
  1574. return hr;
  1575. }
  1576. //+---------------------------------------------------------------------------
  1577. //
  1578. // Function: HrOnCommandDelete
  1579. //
  1580. // Purpose: Command handler for the CMIDM_DELETE command
  1581. //
  1582. // Arguments:
  1583. // apidl [in] PIDL array (item 0 is our item to work on)
  1584. // cidl [in] Size of the array
  1585. // hwndOwner [in] Owner hwnd
  1586. // psf [in] Our folder
  1587. //
  1588. // Returns:
  1589. //
  1590. // Author: jeffspr 3 Dec 1997
  1591. //
  1592. // Notes:
  1593. //
  1594. HRESULT HrOnCommandDelete(
  1595. IN const PCONFOLDPIDLVEC& apidl,
  1596. HWND hwndOwner,
  1597. LPSHELLFOLDER psf)
  1598. {
  1599. HRESULT hr = S_OK;
  1600. INetConnection * pNetCon = NULL;
  1601. INT iMBResult = 0;
  1602. BOOL fActivating = FALSE;
  1603. NETCFG_TRY
  1604. PCONFOLDPIDLVEC::const_iterator iterLoop;
  1605. HANDLE hMutex = NULL;
  1606. for (iterLoop = apidl.begin(); iterLoop != apidl.end(); iterLoop++)
  1607. {
  1608. CConFoldEntry cfe;
  1609. hr = iterLoop->ConvertToConFoldEntry(cfe);
  1610. WCHAR szConnectionGuid [c_cchGuidWithTerm];
  1611. INT cch = StringFromGUID2 (cfe.GetGuidID(), szConnectionGuid, c_cchGuidWithTerm);
  1612. Assert (c_cchGuidWithTerm == cch);
  1613. BOOL fDuplicateMutex = FALSE;
  1614. hMutex = CreateMutex(NULL, TRUE, szConnectionGuid);
  1615. if (hMutex)
  1616. {
  1617. fDuplicateMutex = (ERROR_ALREADY_EXISTS == GetLastError());
  1618. ReleaseMutex(hMutex);
  1619. CloseHandle(hMutex);
  1620. }
  1621. else
  1622. {
  1623. hr = E_ACCESSDENIED;
  1624. break;
  1625. }
  1626. if (fDuplicateMutex)
  1627. {
  1628. // if the mutex already exists try to find the connection window
  1629. //
  1630. NcMsgBox(
  1631. _Module.GetResourceInstance(),
  1632. NULL,
  1633. IDS_CONFOLD_ERROR_DELETE_CAPTION,
  1634. IDS_CONFOLD_ERROR_DELETE_PROPERTYPAGEOPEN,
  1635. MB_ICONEXCLAMATION);
  1636. hr = cfe.HrGetNetCon(IID_INetConnection, reinterpret_cast<VOID**>(&pNetCon));
  1637. if (FAILED(hr))
  1638. {
  1639. Assert(FALSE);
  1640. break;
  1641. }
  1642. else
  1643. {
  1644. ActivatePropertyDialog(pNetCon);
  1645. hr = E_ACCESSDENIED;
  1646. break;
  1647. }
  1648. }
  1649. }
  1650. if (FAILED(hr))
  1651. {
  1652. goto Exit;
  1653. }
  1654. // Bring up the prompt for the delete
  1655. //
  1656. if (apidl.size() > 1)
  1657. {
  1658. WCHAR wszItemCount[8];
  1659. // Convert the item count to a string
  1660. //
  1661. _itow( apidl.size(), wszItemCount, 10 );
  1662. // Bring up the message box
  1663. //
  1664. iMBResult = NcMsgBox(
  1665. _Module.GetResourceInstance(),
  1666. NULL,
  1667. IDS_CONFOLD_DELETE_CONFIRM_MULTI_CAPTION,
  1668. IDS_CONFOLD_DELETE_CONFIRM_MULTI,
  1669. MB_YESNO | MB_ICONQUESTION,
  1670. wszItemCount);
  1671. if (IDYES == iMBResult)
  1672. {
  1673. for (iterLoop = apidl.begin(); iterLoop != apidl.end(); iterLoop++)
  1674. {
  1675. CConFoldEntry cfe;
  1676. hr = iterLoop->ConvertToConFoldEntry(cfe);
  1677. if (SUCCEEDED(hr))
  1678. {
  1679. if ( (NCCF_INCOMING_ONLY & cfe.GetCharacteristics()) &&
  1680. (NCM_NONE == cfe.GetNetConMediaType()) )
  1681. {
  1682. DWORD dwActiveIncoming;
  1683. if (SUCCEEDED(g_ccl.HasActiveIncomingConnections(&dwActiveIncoming))
  1684. && dwActiveIncoming)
  1685. {
  1686. if (1 == dwActiveIncoming )
  1687. {
  1688. iMBResult = NcMsgBox(
  1689. _Module.GetResourceInstance(),
  1690. NULL,
  1691. IDS_CONFOLD_DELETE_CONFIRM_MULTI_CAPTION,
  1692. IDS_CONFOLD_DELETE_CONFIRM_RASSERVER,
  1693. MB_YESNO | MB_ICONQUESTION);
  1694. }
  1695. else
  1696. {
  1697. iMBResult = NcMsgBox(
  1698. _Module.GetResourceInstance(),
  1699. NULL,
  1700. IDS_CONFOLD_DELETE_CONFIRM_MULTI_CAPTION,
  1701. IDS_CONFOLD_DELETE_CONFIRM_RASSERVER_MULTI,
  1702. MB_YESNO | MB_ICONQUESTION,
  1703. dwActiveIncoming);
  1704. }
  1705. }
  1706. break;
  1707. }
  1708. }
  1709. }
  1710. }
  1711. }
  1712. else if (apidl.size() == 1)
  1713. {
  1714. CONFOLDENTRY ccfe;
  1715. // Convert the pidl to a confoldentry, and use the name
  1716. // to bring up the confirm message box
  1717. //
  1718. hr = apidl[0].ConvertToConFoldEntry(ccfe);
  1719. if (SUCCEEDED(hr))
  1720. {
  1721. // Don't let them try to delete a wizard
  1722. //
  1723. if (ccfe.GetWizard())
  1724. {
  1725. goto Exit;
  1726. }
  1727. else
  1728. {
  1729. // Check to see if this connection is in the process of activating.
  1730. // If so, then we won't allow the delete.
  1731. //
  1732. PCONFOLDPIDL pidlEmpty;
  1733. hr = HrCheckForActivation(pidlEmpty, ccfe, &fActivating);
  1734. if (S_OK == hr)
  1735. {
  1736. if (!fActivating)
  1737. {
  1738. if (FALSE == (ccfe.GetNetConMediaType() == NCM_BRIDGE) && // we do allow the bridge to be deleted
  1739. ((ccfe.GetNetConStatus() == NCS_CONNECTING) ||
  1740. fIsConnectedStatus(ccfe.GetNetConStatus()) ||
  1741. (ccfe.GetNetConStatus() == NCS_DISCONNECTING)) )
  1742. {
  1743. // You can't delete an active connection
  1744. //
  1745. NcMsgBox(
  1746. _Module.GetResourceInstance(),
  1747. NULL,
  1748. IDS_CONFOLD_ERROR_DELETE_CAPTION,
  1749. IDS_CONFOLD_ERROR_DELETE_ACTIVE,
  1750. MB_ICONEXCLAMATION);
  1751. goto Exit;
  1752. }
  1753. else
  1754. {
  1755. if ( (NCCF_INCOMING_ONLY & ccfe.GetCharacteristics()) &&
  1756. (NCM_NONE == ccfe.GetNetConMediaType()) )
  1757. {
  1758. DWORD dwActiveIncoming;
  1759. if (SUCCEEDED(g_ccl.HasActiveIncomingConnections(&dwActiveIncoming))
  1760. && dwActiveIncoming)
  1761. {
  1762. if (1 == dwActiveIncoming )
  1763. {
  1764. iMBResult = NcMsgBox(
  1765. _Module.GetResourceInstance(),
  1766. NULL,
  1767. IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION,
  1768. IDS_CONFOLD_DELETE_CONFIRM_RASSERVER,
  1769. MB_YESNO | MB_ICONQUESTION);
  1770. }
  1771. else
  1772. {
  1773. iMBResult = NcMsgBox(
  1774. _Module.GetResourceInstance(),
  1775. NULL,
  1776. IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION,
  1777. IDS_CONFOLD_DELETE_CONFIRM_RASSERVER_MULTI,
  1778. MB_YESNO | MB_ICONQUESTION,
  1779. dwActiveIncoming);
  1780. }
  1781. }
  1782. else
  1783. {
  1784. iMBResult = NcMsgBox(
  1785. _Module.GetResourceInstance(),
  1786. NULL,
  1787. IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION,
  1788. IDS_CONFOLD_DELETE_CONFIRM_SINGLE,
  1789. MB_YESNO | MB_ICONQUESTION,
  1790. ccfe.GetName());
  1791. }
  1792. }
  1793. else
  1794. {
  1795. // is it shared?
  1796. // if it is warn the user
  1797. RASSHARECONN rsc;
  1798. hr = ccfe.HrGetNetCon(IID_INetConnection, reinterpret_cast<VOID**>(&pNetCon));
  1799. if (SUCCEEDED(hr))
  1800. {
  1801. hr = HrNetConToSharedConnection(pNetCon, &rsc);
  1802. if (SUCCEEDED(hr))
  1803. {
  1804. BOOL pfShared;
  1805. hr = HrRasIsSharedConnection(&rsc, &pfShared);
  1806. if ((SUCCEEDED(hr)) && (pfShared == TRUE))
  1807. {
  1808. // tell the user they are deleting a
  1809. // shared connection and get confirmation
  1810. iMBResult = NcMsgBox(
  1811. _Module.GetResourceInstance(),
  1812. NULL,
  1813. IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION,
  1814. IDS_CONFOLD_DELETE_CONFIRM_SHARED,
  1815. MB_YESNO | MB_ICONQUESTION,
  1816. ccfe.GetName());
  1817. }
  1818. else
  1819. {
  1820. // Ask for delete confirmation
  1821. iMBResult = NcMsgBox(
  1822. _Module.GetResourceInstance(),
  1823. NULL,
  1824. IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION,
  1825. IDS_CONFOLD_DELETE_CONFIRM_SINGLE,
  1826. MB_YESNO | MB_ICONQUESTION,
  1827. ccfe.GetName());
  1828. }
  1829. }
  1830. else
  1831. {
  1832. // Ask for delete confirmation
  1833. iMBResult = NcMsgBox(
  1834. _Module.GetResourceInstance(),
  1835. NULL,
  1836. IDS_CONFOLD_DELETE_CONFIRM_SINGLE_CAPTION,
  1837. IDS_CONFOLD_DELETE_CONFIRM_SINGLE,
  1838. MB_YESNO | MB_ICONQUESTION,
  1839. ccfe.GetName());
  1840. }
  1841. }
  1842. }
  1843. }
  1844. }
  1845. else
  1846. {
  1847. // Bring up the MB about "Hey, you can't delete while
  1848. // the connection is activating."
  1849. //
  1850. iMBResult = NcMsgBox(
  1851. _Module.GetResourceInstance(),
  1852. NULL,
  1853. IDS_CONFOLD_ERROR_DELETE_CAPTION,
  1854. IDS_CONFOLD_ERROR_DELETE_ACTIVE,
  1855. MB_ICONEXCLAMATION);
  1856. goto Exit;
  1857. }
  1858. }
  1859. else
  1860. {
  1861. // If the connection wasn't found, then we should just drop out of here
  1862. // because we sure can't delete it.
  1863. //
  1864. if (S_FALSE == hr)
  1865. {
  1866. goto Exit;
  1867. }
  1868. }
  1869. }
  1870. }
  1871. else
  1872. {
  1873. AssertSz(FALSE, "Couldn't get ConFoldEntry from pidl in HrOnCommandDelete");
  1874. goto Exit;
  1875. }
  1876. }
  1877. else
  1878. {
  1879. // No connections were specified. Take a hike.
  1880. //
  1881. goto Exit;
  1882. }
  1883. // If the user said "Yes" to the prompt
  1884. //
  1885. if (iMBResult == IDYES)
  1886. {
  1887. CConnectionFolder * pcf = static_cast<CConnectionFolder *>(psf);
  1888. PCONFOLDPIDLFOLDER pidlFolder;
  1889. if (pcf)
  1890. {
  1891. pidlFolder = pcf->PidlGetFolderRoot();
  1892. }
  1893. BOOL fShowActivationWarning = FALSE;
  1894. BOOL fShowNotDeletableWarning = FALSE;
  1895. for (iterLoop = apidl.begin(); iterLoop != apidl.end(); iterLoop++)
  1896. {
  1897. CONFOLDENTRY ccfe;
  1898. hr = iterLoop->ConvertToConFoldEntry(ccfe);
  1899. if (SUCCEEDED(hr))
  1900. {
  1901. // If this is a LAN connection the user doesn't have rights
  1902. //
  1903. if ((NCM_LAN == ccfe.GetNetConMediaType()) || (ccfe.GetWizard()))
  1904. {
  1905. fShowNotDeletableWarning = TRUE;
  1906. continue;
  1907. }
  1908. // If this is a RAS connection and the user doesn't have rights
  1909. // then skip
  1910. //
  1911. if (IsMediaRASType(ccfe.GetNetConMediaType()))
  1912. {
  1913. if ((!FHasPermission(NCPERM_DeleteConnection)) ||
  1914. ((ccfe.GetCharacteristics() & NCCF_ALL_USERS) &&
  1915. !FHasPermission(NCPERM_DeleteAllUserConnection)))
  1916. {
  1917. fShowNotDeletableWarning = TRUE;
  1918. continue;
  1919. }
  1920. }
  1921. PCONFOLDPIDL pidlEmpty;
  1922. hr = HrCheckForActivation(pidlEmpty, ccfe, &fActivating);
  1923. if (S_OK == hr)
  1924. {
  1925. // Only allow deletion if this connection is inactive and
  1926. // it allows removal.
  1927. //
  1928. if (fActivating || ((FALSE == (ccfe.GetNetConMediaType() == NCM_BRIDGE))) &&
  1929. ((ccfe.GetNetConStatus() == NCS_CONNECTING) ||
  1930. fIsConnectedStatus(ccfe.GetNetConStatus()) ||
  1931. (ccfe.GetNetConStatus() == NCS_DISCONNECTING)) )
  1932. {
  1933. fShowActivationWarning = TRUE;
  1934. }
  1935. else if (ccfe.GetCharacteristics() & NCCF_ALLOW_REMOVAL)
  1936. {
  1937. hr = HrNetConFromPidl(*iterLoop, &pNetCon);
  1938. if (SUCCEEDED(hr))
  1939. {
  1940. if ( NCM_BRIDGE == ccfe.GetNetConMediaType() )
  1941. {
  1942. //
  1943. // Special delete case Removing the Network bridge take so long that we display a status dialog
  1944. // and prevent the user from changing anything will we process
  1945. //
  1946. hr = HrOnCommandBridgeRemoveConnections(
  1947. apidl,
  1948. hwndOwner,
  1949. psf,
  1950. 0 // Remove the Network bridge
  1951. );
  1952. }
  1953. else
  1954. {
  1955. hr = pNetCon->Delete();
  1956. }
  1957. if (SUCCEEDED(hr) && pcf)
  1958. {
  1959. hr = HrDeleteFromCclAndNotifyShell(pidlFolder, *iterLoop, ccfe);
  1960. }
  1961. else if(E_ACCESSDENIED == hr && NCM_BRIDGE == ccfe.GetNetConMediaType())
  1962. {
  1963. // can't delete the bridge while the netcfg lock is held
  1964. NcMsgBox(
  1965. _Module.GetResourceInstance(),
  1966. NULL, IDS_CONFOLD_ERROR_DELETE_CAPTION, IDS_CONFOLD_ERROR_DELETE_BRIDGE_ACCESS, MB_ICONEXCLAMATION);
  1967. }
  1968. ReleaseObj(pNetCon);
  1969. }
  1970. }
  1971. else
  1972. {
  1973. // The selected item is not deletable
  1974. //
  1975. fShowNotDeletableWarning = TRUE;
  1976. }
  1977. }
  1978. }
  1979. }
  1980. if (fShowNotDeletableWarning)
  1981. {
  1982. // You can't delete an item that doesn't support it
  1983. //
  1984. NcMsgBox(
  1985. _Module.GetResourceInstance(),
  1986. NULL,
  1987. IDS_CONFOLD_ERROR_DELETE_CAPTION,
  1988. (1 == apidl.size()) ?
  1989. IDS_CONFOLD_ERROR_DELETE_NOSUPPORT :
  1990. IDS_CONFOLD_ERROR_DELETE_NOSUPPORT_MULTI,
  1991. MB_ICONEXCLAMATION);
  1992. }
  1993. else if (fShowActivationWarning)
  1994. {
  1995. // You can't delete an active connection. Note, if more
  1996. // than one are being deleted, then we put up the warning
  1997. // that says 'one or more are being ignored'.
  1998. //
  1999. NcMsgBox(
  2000. _Module.GetResourceInstance(),
  2001. NULL,
  2002. IDS_CONFOLD_ERROR_DELETE_CAPTION,
  2003. (1 == apidl.size()) ?
  2004. IDS_CONFOLD_ERROR_DELETE_ACTIVE :
  2005. IDS_CONFOLD_ERROR_DELETE_ACTIVE_MULTI,
  2006. MB_ICONEXCLAMATION);
  2007. }
  2008. }
  2009. Exit:
  2010. NETCFG_CATCH(hr)
  2011. TraceError("HrOnCommandDelete", hr);
  2012. return hr;
  2013. }
  2014. //+---------------------------------------------------------------------------
  2015. //
  2016. // Function: HrOnCommandOptionalComponents
  2017. //
  2018. // Purpose: Command handler for the CMIDM_CONMENU_OPTIONALCOMPONENTS command.
  2019. // Bring up the network optional components UI.
  2020. //
  2021. // Arguments:
  2022. // apidl [in] PIDL array (item 0 is our item to work on)
  2023. // cidl [in] Size of the array
  2024. // hwndOwner [in] Owner hwnd
  2025. // psf [in] Our folder
  2026. //
  2027. // Returns:
  2028. //
  2029. // Author: scottbri 29 Oct 1998
  2030. //
  2031. // Notes:
  2032. //
  2033. HRESULT HrOnCommandOptionalComponents(IN const PCONFOLDPIDLVEC& apidl,
  2034. HWND hwndOwner,
  2035. LPSHELLFOLDER psf)
  2036. {
  2037. return HrLaunchNetworkOptionalComponents();
  2038. }
  2039. //+---------------------------------------------------------------------------
  2040. //
  2041. // Function: HrOnCommandNetworkId
  2042. //
  2043. // Purpose: Command handler for the CMIDM_CONMENU_NETORK_ID command.
  2044. // Bring up the network ID UI
  2045. //
  2046. // Arguments:
  2047. // apidl [in] PIDL array (item 0 is our item to work on)
  2048. // cidl [in] Size of the array
  2049. // hwndOwner [in] Owner hwnd
  2050. //
  2051. // Returns:
  2052. //
  2053. // Author: jeffspr 26 Feb 1998
  2054. //
  2055. // Notes:
  2056. //
  2057. HRESULT HrOnCommandNetworkId(
  2058. IN const PCONFOLDPIDLVEC& apidl,
  2059. HWND hwndOwner,
  2060. LPSHELLFOLDER psf)
  2061. {
  2062. TraceFileFunc(ttidShellFolder);
  2063. HRESULT hr = S_OK;
  2064. WCHAR szPath[MAX_PATH];
  2065. hr = SHGetFolderPath(
  2066. hwndOwner,
  2067. CSIDL_SYSTEM,
  2068. NULL,
  2069. SHGFP_TYPE_CURRENT,
  2070. szPath);
  2071. if (SUCCEEDED(hr))
  2072. {
  2073. HINSTANCE hInst = ::ShellExecute(hwndOwner, NULL, c_szRunDll32, c_szNetworkIdCmdLine, szPath, SW_SHOW );
  2074. if (hInst <= reinterpret_cast<HINSTANCE>(32))
  2075. {
  2076. hr = HRESULT_FROM_WIN32(static_cast<DWORD>(reinterpret_cast<DWORD_PTR>(hInst)));
  2077. }
  2078. }
  2079. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandNetworkId");
  2080. return hr;
  2081. }
  2082. //+---------------------------------------------------------------------------
  2083. //
  2084. // Function: HrOnCommandDialupPrefs
  2085. //
  2086. // Purpose: Command handler for the CMIDM_CONMENU_DIALUP_PREFS command.
  2087. // Bring up the dialup prefs dialog
  2088. //
  2089. // Arguments:
  2090. // apidl [in] PIDL array (item 0 is our item to work on)
  2091. // cidl [in] Size of the array
  2092. // hwndOwner [in] Owner hwnd
  2093. //
  2094. // Returns:
  2095. //
  2096. // Author: jeffspr 26 Feb 1998
  2097. //
  2098. // Notes:
  2099. //
  2100. HRESULT HrOnCommandDialupPrefs(
  2101. IN const PCONFOLDPIDLVEC& apidl,
  2102. HWND hwndOwner,
  2103. LPSHELLFOLDER psf)
  2104. {
  2105. HRESULT hr = S_OK;
  2106. DWORD dwErr = 0;
  2107. dwErr = RasUserPrefsDlg(hwndOwner);
  2108. hr = HRESULT_FROM_WIN32 (dwErr);
  2109. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandDialupPrefs");
  2110. return hr;
  2111. }
  2112. //+---------------------------------------------------------------------------
  2113. //
  2114. // Function: HrOnCommandOperatorAssist
  2115. //
  2116. // Purpose: Command handler for the CMIDM_CONMENU_OPERATOR_ASSIST command.
  2117. //
  2118. // Arguments:
  2119. // apidl [in] PIDL array (item 0 is our item to work on)
  2120. // cidl [in] Size of the array
  2121. // hwndOwner [in] Owner hwnd
  2122. //
  2123. // Returns:
  2124. //
  2125. // Author: jeffspr 26 Feb 1998
  2126. //
  2127. // Notes:
  2128. //
  2129. HRESULT HrOnCommandOperatorAssist(
  2130. IN const PCONFOLDPIDLVEC& apidl,
  2131. HWND hwndOwner,
  2132. LPSHELLFOLDER psf)
  2133. {
  2134. HRESULT hr = S_OK;
  2135. DWORD dwErr = 0;
  2136. // Swap the flag
  2137. //
  2138. g_fOperatorAssistEnabled = !g_fOperatorAssistEnabled;
  2139. // Set the state within RasDlg itself
  2140. //
  2141. dwErr = RasUserEnableManualDial(hwndOwner, FALSE, g_fOperatorAssistEnabled);
  2142. hr = HRESULT_FROM_WIN32 (dwErr);
  2143. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandDialupPrefs");
  2144. return hr;
  2145. }
  2146. //+---------------------------------------------------------------------------
  2147. //
  2148. // Function: HrOnCommandCreateShortcut
  2149. //
  2150. // Purpose: Command handler for the CMIDM_CREATE_SHORTCUT command.
  2151. //
  2152. // Arguments:
  2153. // apidl [in] PIDL array (item 0 is our item to work on)
  2154. // cidl [in] Size of the array
  2155. // hwndOwner [in] Owner hwnd
  2156. //
  2157. // Returns:
  2158. //
  2159. // Author: jeffspr 13 Mar 1998
  2160. //
  2161. // Notes:
  2162. //
  2163. HRESULT HrOnCommandCreateShortcut(
  2164. IN const PCONFOLDPIDLVEC& apidl,
  2165. HWND hwndOwner,
  2166. LPSHELLFOLDER psf)
  2167. {
  2168. HRESULT hr = S_OK;
  2169. hr = HrCreateShortcutWithPath( apidl,
  2170. hwndOwner,
  2171. psf,
  2172. NULL);
  2173. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandCreateShortcut");
  2174. return hr;
  2175. }
  2176. //+---------------------------------------------------------------------------
  2177. //
  2178. // Function: HrOnCommandSetDefault
  2179. //
  2180. // Purpose: Command handler for the CMIDM_SET_DEFAULT command
  2181. //
  2182. // Arguments:
  2183. // apidl [in] PIDL array (item 0 is our item to work on)
  2184. // cidl [in] Size of the array
  2185. // hwndOwner [in] Owner hwnd
  2186. //
  2187. // Returns:
  2188. //
  2189. // Author: deonb 27 Nov 2000
  2190. //
  2191. // Notes: We only act on a single entry in this function
  2192. //
  2193. HRESULT HrOnCommandSetDefault(
  2194. IN const PCONFOLDPIDLVEC& apidl,
  2195. HWND hwndOwner,
  2196. LPSHELLFOLDER psf)
  2197. {
  2198. HRESULT hr = S_OK;
  2199. CONFOLDENTRY ccfe;
  2200. if (!apidl.empty())
  2201. {
  2202. hr = apidl[0].ConvertToConFoldEntry(ccfe);
  2203. if (SUCCEEDED(hr))
  2204. {
  2205. INetDefaultConnection *pNetDefaultConnection = NULL;
  2206. // Get the INetDefaultConnection object from the persist data
  2207. //
  2208. hr = ccfe.HrGetNetCon(IID_INetDefaultConnection, reinterpret_cast<VOID**>(&pNetDefaultConnection));
  2209. if (SUCCEEDED(hr))
  2210. {
  2211. hr = pNetDefaultConnection->SetDefault(TRUE);
  2212. ReleaseObj(pNetDefaultConnection);
  2213. hr = S_OK;
  2214. }
  2215. else
  2216. {
  2217. if (E_NOINTERFACE == hr)
  2218. {
  2219. AssertSz(FALSE, "BUG: This connection type does not support INetDefaultConnection. Remove it from the menu");
  2220. }
  2221. }
  2222. }
  2223. }
  2224. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandSetDefault");
  2225. return hr;
  2226. }
  2227. //+---------------------------------------------------------------------------
  2228. //
  2229. // Function: HrOnCommandUnsetDefault
  2230. //
  2231. // Purpose: Command handler for the CMIDM_UNSET_DEFAULT command
  2232. //
  2233. // Arguments:
  2234. // apidl [in] PIDL array (item 0 is our item to work on)
  2235. // cidl [in] Size of the array
  2236. // hwndOwner [in] Owner hwnd
  2237. //
  2238. // Returns:
  2239. //
  2240. // Author: deonb 27 Nov 2000
  2241. //
  2242. // Notes: We only act on a single entry in this function
  2243. //
  2244. HRESULT HrOnCommandUnsetDefault(
  2245. IN const PCONFOLDPIDLVEC& apidl,
  2246. HWND hwndOwner,
  2247. LPSHELLFOLDER psf)
  2248. {
  2249. HRESULT hr = S_OK;
  2250. CONFOLDENTRY ccfe;
  2251. if (!apidl.empty())
  2252. {
  2253. hr = apidl[0].ConvertToConFoldEntry(ccfe);
  2254. if (SUCCEEDED(hr))
  2255. {
  2256. INetDefaultConnection *pNetDefaultConnection = NULL;
  2257. // Get the INetDefaultConnection object from the persist data
  2258. //
  2259. hr = ccfe.HrGetNetCon(IID_INetDefaultConnection, reinterpret_cast<VOID**>(&pNetDefaultConnection));
  2260. if (SUCCEEDED(hr))
  2261. {
  2262. hr = pNetDefaultConnection->SetDefault(FALSE);
  2263. ReleaseObj(pNetDefaultConnection);
  2264. hr = S_OK;
  2265. }
  2266. else
  2267. {
  2268. if (E_NOINTERFACE == hr)
  2269. {
  2270. AssertSz(FALSE, "BUG: This connection type does not support INetDefaultConnection. Remove it from the menu");
  2271. }
  2272. }
  2273. }
  2274. }
  2275. TraceHr(ttidError, FAL, hr, FALSE, "HrOnCommandUnsetDefault");
  2276. return hr;
  2277. }
  2278. HRESULT HrCreateShortcutWithPath(
  2279. IN const PCONFOLDPIDLVEC& apidl,
  2280. HWND hwndOwner,
  2281. LPSHELLFOLDER psf,
  2282. PCWSTR pszDir)
  2283. {
  2284. HRESULT hr = S_OK;
  2285. LPDATAOBJECT pdtobj = NULL;
  2286. LPCITEMIDLIST* apidlInternal = NULL;
  2287. ULONG cidlInternal = 0;
  2288. PCONFOLDPIDLVEC::const_iterator iterLoop;
  2289. if (!apidl.empty())
  2290. {
  2291. apidlInternal = new LPCITEMIDLIST[apidl.size()];
  2292. if (apidlInternal)
  2293. {
  2294. for (iterLoop = apidl.begin(); iterLoop != apidl.end(); iterLoop++)
  2295. {
  2296. const PCONFOLDPIDL& pcfp = *iterLoop;
  2297. if (!(pcfp->dwCharacteristics & NCCF_INCOMING_ONLY))
  2298. {
  2299. apidlInternal[cidlInternal++] = iterLoop->GetItemIdList();
  2300. }
  2301. }
  2302. hr = psf->GetUIObjectOf(
  2303. hwndOwner,
  2304. cidlInternal,
  2305. apidlInternal,
  2306. IID_IDataObject,
  2307. NULL,
  2308. (LPVOID *) &pdtobj);
  2309. if (SUCCEEDED(hr))
  2310. {
  2311. SHCreateLinks(hwndOwner, pszDir, pdtobj,
  2312. SHCL_USEDESKTOP | SHCL_USETEMPLATE | SHCL_CONFIRM,
  2313. NULL);
  2314. ReleaseObj(pdtobj);
  2315. }
  2316. delete apidlInternal;
  2317. }
  2318. }
  2319. TraceError("HrCreateShortcutWithPath", hr);
  2320. return hr;
  2321. }
  2322. //+---------------------------------------------------------------------------
  2323. //
  2324. // Function: RefreshFolderItem
  2325. //
  2326. // Purpose: Refresh an item within a connections folder. Mostly, this will
  2327. // be called after a connect or disconnect operation.
  2328. //
  2329. // Arguments:
  2330. // pidlFolder [in] PIDL for the connections folder
  2331. // pidlItemOld[in] PIDL for the item that's changed.
  2332. // pidlItemNew[in] PIDL for the item that it's changing to.
  2333. // fRestart [in] If this is called during system startup
  2334. //
  2335. // Returns:
  2336. //
  2337. // Author: jeffspr 13 Jun 1998
  2338. //
  2339. // Notes:
  2340. //
  2341. VOID RefreshFolderItem(const PCONFOLDPIDLFOLDER& pidlFolder, const PCONFOLDPIDL& pidlItemOld, const PCONFOLDPIDL& pidlItemNew, BOOL fRestart)
  2342. {
  2343. TraceTag(ttidShellFolder, "RefreshFolderItem");
  2344. NETCFG_TRY
  2345. HRESULT hr = S_OK;
  2346. INT iCachedImage = 0;
  2347. PCONFOLDPIDLFOLDER pidlFolderCopy;
  2348. // If a folder pidl wasn't passed in, try to get one
  2349. //
  2350. if (pidlFolder.empty())
  2351. {
  2352. hr = HrGetConnectionsFolderPidl(pidlFolderCopy);
  2353. }
  2354. else
  2355. {
  2356. pidlFolderCopy = pidlFolder;
  2357. }
  2358. // If we now have a pidl, send the GenerateEvent to update the item
  2359. //
  2360. if (SUCCEEDED(hr))
  2361. {
  2362. GenerateEvent(SHCNE_UPDATEITEM, pidlFolderCopy, pidlItemNew, NULL);
  2363. }
  2364. // If we have a old item pidl, try to update its icon (useful for
  2365. // shortcuts as well as folder items)
  2366. //
  2367. if (!pidlItemOld.empty())
  2368. {
  2369. const PCONFOLDPIDL& pcfp = pidlItemOld;
  2370. if (!pcfp.empty())
  2371. {
  2372. CConFoldEntry cfe;
  2373. hr = pcfp.ConvertToConFoldEntry(cfe);
  2374. if (SUCCEEDED(hr))
  2375. {
  2376. g_pNetConfigIcons->HrUpdateSystemImageListForPIDL(cfe);
  2377. }
  2378. if (fRestart)
  2379. {
  2380. TraceTag(ttidIcons, "Refreshing Icon Shortcuts for startup");
  2381. // RAS connection state will be changed between reboots,
  2382. // we need to make sure icons for previously connected
  2383. // or disconnected ras connections are also updated
  2384. // If it's a ras connection,
  2385. BOOL fInbound = !!(pidlItemOld->dwCharacteristics & NCCF_INCOMING_ONLY);
  2386. if ((IsMediaRASType(pidlItemOld->ncm)) && !fInbound)
  2387. {
  2388. PCONFOLDPIDL pcfpTemp = pidlItemOld;
  2389. if ((pcfpTemp->ncs == NCS_DISCONNECTED) ||
  2390. (pcfpTemp->ncs == NCS_CONNECTING))
  2391. {
  2392. // get the connected icon
  2393. pcfpTemp->ncs = NCS_CONNECTED;
  2394. }
  2395. else
  2396. {
  2397. // get the disconnected icon
  2398. pcfpTemp->ncs = NCS_DISCONNECTED;
  2399. }
  2400. cfe.clear();
  2401. hr = pcfpTemp.ConvertToConFoldEntry(cfe);
  2402. if (SUCCEEDED(hr))
  2403. {
  2404. g_pNetConfigIcons->HrUpdateSystemImageListForPIDL(cfe);
  2405. }
  2406. }
  2407. }
  2408. }
  2409. }
  2410. NETCFG_CATCH_NOHR
  2411. }
  2412. //
  2413. //
  2414. //
  2415. HRESULT
  2416. HrOnCommandCreateBridge(
  2417. IN const PCONFOLDPIDLVEC& apidl,
  2418. HWND hwndOwner,
  2419. LPSHELLFOLDER psf
  2420. )
  2421. {
  2422. HRESULT hResult;
  2423. IHNetCfgMgr* pHomeNetConfigManager;
  2424. CWaitCursor wc; // display wait cursor
  2425. hResult = HrCreateInstance(CLSID_HNetCfgMgr, CLSCTX_INPROC, &pHomeNetConfigManager); // REVIEW combine this with QI?
  2426. if(SUCCEEDED(hResult))
  2427. {
  2428. IHNetBridgeSettings* pNetBridgeSettings;
  2429. hResult = pHomeNetConfigManager->QueryInterface(IID_IHNetBridgeSettings, reinterpret_cast<void**>(&pNetBridgeSettings));
  2430. if(SUCCEEDED(hResult))
  2431. {
  2432. IHNetBridge* pNetBridge;
  2433. IEnumHNetBridges* pNetBridgeEnum;
  2434. hResult = pNetBridgeSettings->EnumBridges(&pNetBridgeEnum);
  2435. if(SUCCEEDED(hResult))
  2436. {
  2437. hResult = pNetBridgeEnum->Next(1, &pNetBridge, NULL);
  2438. if(S_FALSE == hResult) // no existing bridges, make a new one
  2439. {
  2440. hResult = pNetBridgeSettings->CreateBridge(&pNetBridge);
  2441. }
  2442. if(S_OK == hResult) // can't use SUCCEEDED because someone returns S_FALSE
  2443. {
  2444. Assert(pNetBridge); // we better have gotten one from somewhere
  2445. // Add any selected connections
  2446. for ( PCONFOLDPIDLVEC::const_iterator i = apidl.begin(); (i != apidl.end()) && SUCCEEDED(hResult); i++ )
  2447. {
  2448. const PCONFOLDPIDL& pcfp = *i;
  2449. if ( pcfp.empty() )
  2450. continue;
  2451. if ( NCM_LAN != pcfp->ncm )
  2452. continue;
  2453. if ( (NCCF_BRIDGED|NCCF_FIREWALLED|NCCF_SHARED) & pcfp->dwCharacteristics )
  2454. continue;
  2455. //
  2456. // Ok we now have a LAN adapter the is valid to bind to the bridge
  2457. //
  2458. INetConnection* pNetConnection;
  2459. hResult = HrNetConFromPidl(*i, &pNetConnection);
  2460. if(SUCCEEDED(hResult))
  2461. {
  2462. IHNetConnection* pHomeNetConnection;
  2463. hResult = pHomeNetConfigManager->GetIHNetConnectionForINetConnection(pNetConnection, &pHomeNetConnection);
  2464. if(SUCCEEDED(hResult))
  2465. {
  2466. IHNetBridgedConnection* pBridgedConnection;
  2467. hResult = pNetBridge->AddMember(pHomeNetConnection, &pBridgedConnection);
  2468. if(SUCCEEDED(hResult))
  2469. {
  2470. ReleaseObj(pBridgedConnection);
  2471. }
  2472. ReleaseObj(pHomeNetConnection);
  2473. }
  2474. ReleaseObj(pNetConnection);
  2475. }
  2476. // no cleanup needed
  2477. }
  2478. ReleaseObj(pNetBridge);
  2479. }
  2480. ReleaseObj(pNetBridgeEnum);
  2481. }
  2482. ReleaseObj(pNetBridgeSettings);
  2483. }
  2484. ReleaseObj(pHomeNetConfigManager);
  2485. }
  2486. SendMessage(hwndOwner, WM_COMMAND, IDCANCEL, 0); // destroy the status dialog
  2487. // Show an error dialog on failure
  2488. if( FAILED(hResult) )
  2489. {
  2490. UINT ids;
  2491. if( NETCFG_E_NO_WRITE_LOCK == hResult )
  2492. {
  2493. ids = IDS_CONFOLD_BRIDGE_NOLOCK;
  2494. }
  2495. else
  2496. {
  2497. ids = IDS_CONFOLD_BRIDGE_UNEXPECTED;
  2498. }
  2499. NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, ids, MB_ICONEXCLAMATION | MB_OK);
  2500. }
  2501. return hResult;
  2502. }
  2503. //
  2504. //
  2505. //
  2506. INT_PTR CALLBACK
  2507. CreateBridgeStatusDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2508. {
  2509. INT_PTR nResult = FALSE;
  2510. switch(uMsg)
  2511. {
  2512. case WM_INITDIALOG:
  2513. {
  2514. LPCWSTR pResourceStr = SzLoadIds(IDS_CONFOLD_OBJECT_TYPE_BRIDGE);
  2515. SetWindowText(hwndDlg, pResourceStr);
  2516. pResourceStr = SzLoadIds(IDS_STATUS_BRIDGE_CREATION);
  2517. SetDlgItemText(hwndDlg, IDC_TXT_STATUS, pResourceStr);
  2518. CCommandHandlerParams* pCreateBridgeParams = reinterpret_cast<CCommandHandlerParams*>(lParam);
  2519. HrCommandHandlerThread(HrOnCommandCreateBridge, *(pCreateBridgeParams->apidl), hwndDlg, pCreateBridgeParams->psf);
  2520. // HrOnCommandCreateBridge will send a message to kill this dialog
  2521. nResult = TRUE;
  2522. }
  2523. break;
  2524. case WM_COMMAND:
  2525. if(IDCANCEL == LOWORD(wParam))
  2526. {
  2527. EndDialog(hwndDlg, 0);
  2528. nResult = TRUE;
  2529. }
  2530. break;
  2531. }
  2532. return nResult;
  2533. }
  2534. //
  2535. //
  2536. //
  2537. HRESULT
  2538. HrOnCommandDeleteBridge(
  2539. IN const PCONFOLDPIDLVEC& apidl,
  2540. HWND hwndOwner,
  2541. LPSHELLFOLDER psf
  2542. )
  2543. {
  2544. HRESULT hr = S_FALSE;
  2545. PCONFOLDPIDLVEC::const_iterator iterator;
  2546. for ( iterator = apidl.begin(); iterator != apidl.end(); iterator++ )
  2547. {
  2548. CONFOLDENTRY ccfe;
  2549. hr = iterator->ConvertToConFoldEntry(ccfe);
  2550. if ( SUCCEEDED(hr) )
  2551. {
  2552. if ( NCM_BRIDGE == ccfe.GetNetConMediaType() )
  2553. {
  2554. //
  2555. // Stop at the first select BRIDGE item
  2556. // The delete of the bridge is part of a bigger FOR LOOP see HrOnCommandDelete()
  2557. //
  2558. INetConnection* pNetConnection;
  2559. hr = HrNetConFromPidl(*iterator, &pNetConnection);
  2560. if ( SUCCEEDED(hr) )
  2561. {
  2562. hr = pNetConnection->Delete();
  2563. ReleaseObj(pNetConnection);
  2564. }
  2565. break;
  2566. }
  2567. }
  2568. }
  2569. SendMessage(hwndOwner, WM_COMMAND, IDCANCEL, hr); // destroy the status dialog
  2570. // Show an error dialog on failure
  2571. if( FAILED(hr) )
  2572. {
  2573. UINT ids;
  2574. if( NETCFG_E_NO_WRITE_LOCK == hr )
  2575. {
  2576. ids = IDS_CONFOLD_BRIDGE_NOLOCK;
  2577. }
  2578. else
  2579. {
  2580. ids = IDS_CONFOLD_BRIDGE_UNEXPECTED;
  2581. }
  2582. NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, ids, MB_ICONEXCLAMATION | MB_OK);
  2583. }
  2584. return S_OK;
  2585. }
  2586. //
  2587. //
  2588. //
  2589. HRESULT
  2590. HrOnCommandDeleteBridgeConnections(
  2591. IN const PCONFOLDPIDLVEC& apidl,
  2592. HWND hwndOwner,
  2593. LPSHELLFOLDER psf
  2594. )
  2595. {
  2596. CWaitCursor wc; // display wait cursor
  2597. IHNetCfgMgr* pHomeNetConfigManager;
  2598. HRESULT hResult = HrCreateInstance(CLSID_HNetCfgMgr, CLSCTX_INPROC, &pHomeNetConfigManager); // REVIEW combine this with QI?
  2599. if ( SUCCEEDED(hResult) )
  2600. {
  2601. //
  2602. // Remove any selected connections
  2603. //
  2604. for ( PCONFOLDPIDLVEC::const_iterator i = apidl.begin(); i != apidl.end() && SUCCEEDED(hResult); i++ )
  2605. {
  2606. INetConnection* pNetConnection;
  2607. hResult = HrNetConFromPidl(*i, &pNetConnection);
  2608. if(SUCCEEDED(hResult))
  2609. {
  2610. IHNetConnection* pHomeNetConnection;
  2611. hResult = pHomeNetConfigManager->GetIHNetConnectionForINetConnection(pNetConnection, &pHomeNetConnection);
  2612. if(SUCCEEDED(hResult))
  2613. {
  2614. IHNetBridgedConnection* pBridgedConnection;
  2615. hResult = pHomeNetConnection->GetControlInterface(IID_IHNetBridgedConnection, reinterpret_cast<void**>(&pBridgedConnection));
  2616. if ( SUCCEEDED(hResult) )
  2617. {
  2618. hResult = pBridgedConnection->RemoveFromBridge();
  2619. ReleaseObj(pBridgedConnection);
  2620. }
  2621. ReleaseObj(pHomeNetConnection);
  2622. }
  2623. ReleaseObj(pNetConnection);
  2624. }
  2625. // no cleanup needed
  2626. }
  2627. ReleaseObj(pHomeNetConfigManager);
  2628. }
  2629. SendMessage(hwndOwner, WM_COMMAND, IDCANCEL, hResult); // destroy the status dialog
  2630. // Show an error dialog on failure
  2631. if( FAILED(hResult) )
  2632. {
  2633. UINT ids;
  2634. if( NETCFG_E_NO_WRITE_LOCK == hResult )
  2635. {
  2636. ids = IDS_CONFOLD_BRIDGE_NOLOCK;
  2637. }
  2638. else
  2639. {
  2640. ids = IDS_CONFOLD_BRIDGE_UNEXPECTED;
  2641. }
  2642. NcMsgBox( _Module.GetResourceInstance(), NULL, IDS_CONFOLD_WARNING_CAPTION, ids, MB_ICONEXCLAMATION | MB_OK);
  2643. }
  2644. return S_OK;
  2645. }
  2646. //
  2647. //
  2648. //
  2649. INT_PTR CALLBACK
  2650. DeleteBridgeStatusDialogProc(
  2651. HWND hwndDlg,
  2652. UINT uMsg,
  2653. WPARAM wParam,
  2654. LPARAM lParam
  2655. )
  2656. {
  2657. INT_PTR nResult = FALSE;
  2658. switch(uMsg)
  2659. {
  2660. case WM_INITDIALOG:
  2661. {
  2662. LPCWSTR pResourceStr = SzLoadIds(IDS_CONFOLD_OBJECT_TYPE_BRIDGE);
  2663. SetWindowText(hwndDlg, pResourceStr);
  2664. CCommandHandlerParams* pDeleteBridgeParams = reinterpret_cast<CCommandHandlerParams*>(lParam);
  2665. if ( pDeleteBridgeParams->nAdditionalParam == CMIDM_REMOVE_FROM_BRIDGE )
  2666. {
  2667. //
  2668. // Only remove the currently selected connections from the Network bridge
  2669. //
  2670. pResourceStr = SzLoadIds(IDS_STATUS_BRIDGE_REMOVE_MEMBER);
  2671. SetDlgItemText(hwndDlg, IDC_TXT_STATUS, pResourceStr);
  2672. HrCommandHandlerThread(HrOnCommandDeleteBridgeConnections, *(pDeleteBridgeParams->apidl), hwndDlg, pDeleteBridgeParams->psf);
  2673. }
  2674. else
  2675. {
  2676. //
  2677. // Full delete of the network bridge
  2678. //
  2679. pResourceStr = SzLoadIds(IDS_STATUS_BRIDGE_DELETING);
  2680. SetDlgItemText(hwndDlg, IDC_TXT_STATUS, pResourceStr);
  2681. HrCommandHandlerThread(HrOnCommandDeleteBridge, *(pDeleteBridgeParams->apidl), hwndDlg, pDeleteBridgeParams->psf);
  2682. }
  2683. // After the delete a HrOnCommandDeleteBridge will send a SendMessage(hwndOwner, WM_COMMAND, IDCANCEL, 0); // destroy the status dialog
  2684. nResult = TRUE;
  2685. }
  2686. break;
  2687. case WM_COMMAND:
  2688. if(IDCANCEL == LOWORD(wParam))
  2689. {
  2690. EndDialog(hwndDlg, lParam);
  2691. nResult = TRUE;
  2692. }
  2693. break;
  2694. }
  2695. return nResult;
  2696. }
  2697. //+---------------------------------------------------------------------------
  2698. //
  2699. // Function: HrOnCommandBridgeAddConnections
  2700. //
  2701. // Purpose: Command handler for the CMIDM_CREATE_BRIDGE, CMDIDM_CONMENU_CREATE_BRIDGE, CMIDM_ADD_TO_BRIDGE.
  2702. //
  2703. // Arguments:
  2704. // apidl [in] PIDL array (item 0 is our item to work on)
  2705. // psf [in] SHELLFOLDER
  2706. // hwndOwner [in] Owner hwnd
  2707. //
  2708. // Returns:
  2709. //
  2710. // Author: jpdup 6 March 2000
  2711. //
  2712. // Notes:
  2713. //
  2714. HRESULT
  2715. HrOnCommandBridgeAddConnections(
  2716. IN const PCONFOLDPIDLVEC& apidl,
  2717. HWND hwndOwner,
  2718. LPSHELLFOLDER psf
  2719. )
  2720. {
  2721. CCommandHandlerParams CreateBridgeParams;
  2722. CreateBridgeParams.apidl = &apidl;
  2723. CreateBridgeParams.hwndOwner = hwndOwner;
  2724. CreateBridgeParams.psf = psf;
  2725. HRESULT hr = DialogBoxParam(
  2726. _Module.GetResourceInstance(),
  2727. MAKEINTRESOURCE(IDD_STATUS),
  2728. hwndOwner,
  2729. CreateBridgeStatusDialogProc,
  2730. reinterpret_cast<LPARAM>(&CreateBridgeParams)
  2731. );
  2732. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandBridgeAddConnections");
  2733. return hr;
  2734. }
  2735. //+---------------------------------------------------------------------------
  2736. //
  2737. // Function: HrOnCommandBridgeRemoveConnections
  2738. //
  2739. // Purpose: Command handler for the CMIDM_REMOVE_FROM_BRIDGE and the DELETE command when done on the NetworkBridge object
  2740. //
  2741. // Arguments:
  2742. // apidl [in] PIDL array (item 0 is our item to work on)
  2743. // hwndOwner [in] Owner hwnd
  2744. // psf [in] SHELLFOLDER
  2745. // bDeleteTheNetworkBridge [in] true is the NetworkBridge needs to be totaly remove, false if only the currently select item found in apild needs to be remove
  2746. //
  2747. // Returns:
  2748. //
  2749. // Author: jpdup 6 March 2000
  2750. //
  2751. // Notes:
  2752. //
  2753. HRESULT
  2754. HrOnCommandBridgeRemoveConnections(
  2755. IN const PCONFOLDPIDLVEC& apidl,
  2756. HWND hwndOwner,
  2757. LPSHELLFOLDER psf,
  2758. UINT_PTR nDeleteTheNetworkBridgeMode
  2759. )
  2760. {
  2761. CCommandHandlerParams DeleteBridgeParams;
  2762. DeleteBridgeParams.apidl = &apidl;
  2763. DeleteBridgeParams.hwndOwner = hwndOwner;
  2764. DeleteBridgeParams.psf = psf;
  2765. DeleteBridgeParams.nAdditionalParam = nDeleteTheNetworkBridgeMode;
  2766. HRESULT hr = DialogBoxParam(
  2767. _Module.GetResourceInstance(),
  2768. MAKEINTRESOURCE(IDD_STATUS),
  2769. hwndOwner,
  2770. DeleteBridgeStatusDialogProc,
  2771. reinterpret_cast<LPARAM>(&DeleteBridgeParams)
  2772. );
  2773. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrOnCommandBridgeRemoveConnections");
  2774. return hr;
  2775. }