Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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