1 /*
2  * PROJECT:     ReactOS Shell
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     CNetworkConnections Shell Folder
5  * COPYRIGHT:   Copyright 2008 Johannes Anderwald (johannes.anderwald@reactos.org)
6  */
7 
8 /*
9  * Network Connections Shell Folder
10  *
11  * Copyright 2008       Johannes Anderwald <johannes.anderwald@reactos.org>
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2.1 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public
24  * License along with this library; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26  */
27 
28 #include "precomp.h"
29 
30 #define MAX_PROPERTY_SHEET_PAGE (10)
31 
32 /***********************************************************************
33 *   IShellFolder implementation
34 */
35 
36 static const shvheader NetConnectSFHeader[] = {
37     {IDS_SHV_COLUMN_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 20},
38     {IDS_SHV_COLUMN_TYPE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 8},
39     {IDS_SHV_COLUMN_STATE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
40     {IDS_SHV_COLUMN_DEVNAME, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
41     {IDS_SHV_COLUMN_PHONE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
42     {IDS_SHV_COLUMN_OWNER, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
43 };
44 
45 #define NETCONNECTSHELLVIEWCOLUMNS 6
46 
47 #define COLUMN_NAME     0
48 #define COLUMN_TYPE     1
49 #define COLUMN_STATUS   2
50 #define COLUMN_DEVNAME  3
51 #define COLUMN_PHONE    4
52 #define COLUMN_OWNER    5
53 
54 HRESULT
55 ShowNetConnectionStatus(
56     IOleCommandTarget *lpOleCmd,
57     PCUITEMID_CHILD pidl,
58     HWND hwnd);
59 
60 CNetworkConnections::CNetworkConnections() :
61     m_pidlRoot(NULL)
62 {
63     HRESULT hr;
64     hr = CoCreateInstance(CLSID_ConnectionTray, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IOleCommandTarget, &m_lpOleCmd));
65     if (FAILED_UNEXPECTEDLY(hr))
66         m_lpOleCmd = NULL;
67 }
68 
69 CNetworkConnections::~CNetworkConnections()
70 {
71     if (m_pidlRoot)
72         SHFree(m_pidlRoot);
73 }
74 
75 /**************************************************************************
76 *	ISF_NetConnect_fnParseDisplayName
77 */
78 HRESULT WINAPI CNetworkConnections::ParseDisplayName (
79                HWND hwndOwner, LPBC pbcReserved, LPOLESTR lpszDisplayName,
80                DWORD * pchEaten, PIDLIST_RELATIVE * ppidl, DWORD * pdwAttributes)
81 {
82     HRESULT hr = E_UNEXPECTED;
83 
84     *ppidl = 0;
85     if (pchEaten)
86         *pchEaten = 0;		/* strange but like the original */
87 
88     return hr;
89 }
90 
91 /**************************************************************************
92 *		ISF_NetConnect_fnEnumObjects
93 */
94 HRESULT WINAPI CNetworkConnections::EnumObjects(
95                HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
96 {
97     return CEnumIDList_CreateInstance(hwndOwner, dwFlags, IID_PPV_ARG(IEnumIDList, ppEnumIDList));
98 }
99 
100 /**************************************************************************
101 *		ISF_NetConnect_fnBindToObject
102 */
103 HRESULT WINAPI CNetworkConnections::BindToObject (
104                PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
105 {
106     return E_NOTIMPL;
107 }
108 
109 /**************************************************************************
110 *	ISF_NetConnect_fnBindToStorage
111 */
112 HRESULT WINAPI CNetworkConnections::BindToStorage(
113                PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
114 {
115     *ppvOut = NULL;
116     return E_NOTIMPL;
117 }
118 
119 /**************************************************************************
120 * 	ISF_NetConnect_fnCompareIDs
121 */
122 
123 HRESULT WINAPI CNetworkConnections::CompareIDs(
124                LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
125 {
126     return E_NOTIMPL;
127 }
128 
129 /**************************************************************************
130 *	ISF_NetConnect_fnCreateViewObject
131 */
132 HRESULT WINAPI CNetworkConnections::CreateViewObject(
133                HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
134 {
135     HRESULT hr = E_NOINTERFACE;
136 
137     if (!ppvOut)
138         return hr;
139 
140     *ppvOut = NULL;
141 
142     if (IsEqualIID(riid, IID_IShellView))
143     {
144         CSFV cvf = {sizeof(cvf), this};
145         CComPtr<IShellView> pShellView;
146         hr = SHCreateShellFolderViewEx(&cvf, &pShellView);
147         if (FAILED_UNEXPECTEDLY(hr))
148             return hr;
149 
150         return pShellView->QueryInterface(riid, ppvOut);
151     }
152 
153     return hr;
154 }
155 
156 /**************************************************************************
157 *  ISF_NetConnect_fnGetAttributesOf
158 */
159 HRESULT WINAPI CNetworkConnections::GetAttributesOf(
160                UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD * rgfInOut)
161 {
162     //IGenericSFImpl *This = (IGenericSFImpl *)iface;
163     HRESULT hr = S_OK;
164     static const DWORD dwNetConnectAttributes = SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
165         SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
166 
167     static const DWORD dwNetConnectItemAttributes = SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
168         SFGAO_FILESYSANCESTOR | SFGAO_CANRENAME;
169 
170     if (!rgfInOut)
171         return E_INVALIDARG;
172 
173     if (cidl && !apidl)
174         return E_INVALIDARG;
175 
176     if (*rgfInOut == 0)
177         *rgfInOut = ~0;
178 
179     if (cidl == 0)
180     {
181         *rgfInOut = dwNetConnectAttributes;
182     }
183     else
184     {
185         *rgfInOut = dwNetConnectItemAttributes;
186 
187         while (cidl > 0 && *apidl)
188         {
189             PNETCONIDSTRUCT pdata = ILGetConnData(*apidl);
190             if (!pdata)
191                 continue;
192 
193             if (!(pdata->dwCharacter & NCCF_ALLOW_RENAME))
194                 *rgfInOut &= ~SFGAO_CANRENAME;
195 
196             apidl++;
197             cidl--;
198         }
199     }
200 
201     /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
202     *rgfInOut &= ~SFGAO_VALIDATE;
203 
204     return hr;
205 }
206 
207 /**************************************************************************
208 *	ISF_NetConnect_fnGetUIObjectOf
209 *
210 * PARAMETERS
211 *  hwndOwner [in]  Parent window for any output
212 *  cidl      [in]  array size
213 *  apidl     [in]  simple pidl array
214 *  riid      [in]  Requested Interface
215 *  prgfInOut [   ] reserved
216 *  ppvObject [out] Resulting Interface
217 *
218 */
219 
220 HRESULT WINAPI CNetworkConnections::GetUIObjectOf(
221                HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
222                UINT * prgfInOut, LPVOID * ppvOut)
223 {
224     IUnknown *pObj = NULL;
225     HRESULT hr = E_INVALIDARG;
226 
227     if (!ppvOut)
228         return hr;
229 
230     *ppvOut = NULL;
231 
232     if ((IsEqualIID(riid, IID_IContextMenu) || IsEqualIID (riid, IID_IContextMenu2) || IsEqualIID(riid, IID_IContextMenu3) ||
233          IsEqualIID(riid, IID_IQueryInfo) || IsEqualIID(riid, IID_IExtractIconW)) && cidl >= 1)
234     {
235         return ShellObjectCreatorInit<CNetConUiObject>(apidl[0], m_lpOleCmd, riid, ppvOut);
236     }
237     else
238         hr = E_NOINTERFACE;
239 
240     *ppvOut = pObj;
241     return hr;
242 }
243 
244 /**************************************************************************
245 *	ISF_NetConnect_fnGetDisplayNameOf
246 *
247 */
248 HRESULT WINAPI CNetworkConnections::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
249 {
250     if (!strRet)
251         return E_INVALIDARG;
252 
253     if (!pidl)
254         return SHSetStrRet(strRet, netshell_hInstance, IDS_NETWORKCONNECTION);
255 
256     PWCHAR pwchName = ILGetConnName(pidl);
257     if (!pwchName)
258     {
259         ERR("Got invalid pidl!\n");
260         return E_INVALIDARG;
261     }
262 
263     return SHSetStrRet(strRet, pwchName);
264 }
265 
266 /**************************************************************************
267 *  ISF_NetConnect_fnSetNameOf
268 *  Changes the name of a file object or subfolder, possibly changing its item
269 *  identifier in the process.
270 *
271 * PARAMETERS
272 *  hwndOwner [in]  Owner window for output
273 *  pidl      [in]  simple pidl of item to change
274 *  lpszName  [in]  the items new display name
275 *  dwFlags   [in]  SHGNO formatting flags
276 *  ppidlOut  [out] simple pidl returned
277 */
278 HRESULT WINAPI CNetworkConnections::SetNameOf (
279                HWND hwndOwner, PCUITEMID_CHILD pidl,	/*simple pidl */
280                LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD * pPidlOut)
281 {
282     HRESULT hr;
283     CComPtr<INetConnection> pCon;
284 
285     hr = ILGetConnection(pidl, &pCon);
286     if (FAILED_UNEXPECTEDLY(hr))
287         return hr;
288 
289     hr = pCon->Rename(lpName);
290     if (FAILED_UNEXPECTEDLY(hr))
291         return hr;
292 
293     *pPidlOut = ILCreateNetConnectItem(pCon);
294     if (*pPidlOut == NULL)
295         return E_FAIL;
296 
297     return S_OK;
298 }
299 
300 HRESULT WINAPI CNetworkConnections::GetDefaultSearchGUID(GUID * pguid)
301 {
302     return E_NOTIMPL;
303 }
304 
305 HRESULT WINAPI CNetworkConnections::EnumSearches(IEnumExtraSearch ** ppenum)
306 {
307     return E_NOTIMPL;
308 }
309 
310 HRESULT WINAPI CNetworkConnections::GetDefaultColumn(DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
311 {
312     if (pSort)
313         *pSort = 0;
314     if (pDisplay)
315         *pDisplay = 0;
316 
317     return S_OK;
318 }
319 
320 HRESULT WINAPI CNetworkConnections::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags)
321 {
322     if (!pcsFlags || iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
323         return E_INVALIDARG;
324     *pcsFlags = NetConnectSFHeader[iColumn].pcsFlags;
325     return S_OK;
326 }
327 
328 HRESULT WINAPI CNetworkConnections::GetDetailsEx(
329                PCUITEMID_CHILD pidl, const SHCOLUMNID * pscid, VARIANT * pv)
330 {
331     return E_NOTIMPL;
332 }
333 
334 HRESULT WINAPI CNetworkConnections::GetDetailsOf(
335                PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS * psd)
336 {
337     if (iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
338         return E_FAIL;
339 
340     psd->fmt = NetConnectSFHeader[iColumn].fmt;
341     psd->cxChar = NetConnectSFHeader[iColumn].cxChar;
342     if (pidl == NULL)
343         return SHSetStrRet(&psd->str, netshell_hInstance, NetConnectSFHeader[iColumn].colnameid);
344 
345     PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
346     if (!pdata)
347         return E_FAIL;
348 
349     switch (iColumn)
350     {
351         case COLUMN_NAME:
352             return SHSetStrRet(&psd->str, ILGetConnName(pidl));
353         case COLUMN_TYPE:
354             if (pdata->MediaType  == NCM_LAN || pdata->MediaType == NCM_SHAREDACCESSHOST_RAS)
355             {
356                 return SHSetStrRet(&psd->str, netshell_hInstance, IDS_TYPE_ETHERNET);
357             }
358             else
359             {
360                 return SHSetStrRet(&psd->str, "");
361             }
362             break;
363         case COLUMN_STATUS:
364             switch(pdata->Status)
365             {
366                 case NCS_HARDWARE_DISABLED:
367                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_NON_OPERATIONAL);
368                 case NCS_DISCONNECTED:
369                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_UNREACHABLE);
370                 case NCS_MEDIA_DISCONNECTED:
371                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_DISCONNECTED);
372                 case NCS_CONNECTING:
373                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_CONNECTING);
374                 case NCS_CONNECTED:
375                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_CONNECTED);
376                 default:
377                     return SHSetStrRet(&psd->str, "");
378             }
379             break;
380         case COLUMN_DEVNAME:
381             return SHSetStrRet(&psd->str, ILGetDeviceName(pidl));
382         case COLUMN_PHONE:
383         case COLUMN_OWNER:
384             return SHSetStrRet(&psd->str, "");
385     }
386 
387     return E_FAIL;
388 }
389 
390 HRESULT WINAPI CNetworkConnections::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
391 {
392     return E_NOTIMPL;
393 }
394 
395 //IObjectWithSite
396 //IInternetSecurityManager
397 
398 /**************************************************************************
399 * IContextMenu2 Implementation
400 */
401 
402 CNetConUiObject::CNetConUiObject()
403     : m_pidl(NULL)
404 {
405 }
406 
407 CNetConUiObject::~CNetConUiObject()
408 {
409 }
410 
411 HRESULT WINAPI CNetConUiObject::Initialize(PCUITEMID_CHILD pidl, IOleCommandTarget *lpOleCmd)
412 {
413     m_pidl = pidl;
414     m_lpOleCmd = lpOleCmd;
415     return S_OK;
416 }
417 
418 void WINAPI _InsertMenuItemW (
419     HMENU hmenu,
420     UINT indexMenu,
421     BOOL fByPosition,
422     UINT wID,
423     UINT fType,
424     LPCWSTR dwTypeData,
425     UINT fState)
426 {
427     MENUITEMINFOW mii;
428     WCHAR szText[100];
429 
430     ZeroMemory(&mii, sizeof(mii));
431     mii.cbSize = sizeof(mii);
432     if (fType == MFT_SEPARATOR)
433     {
434         mii.fMask = MIIM_ID | MIIM_TYPE;
435     }
436     else if (fType == MFT_STRING)
437     {
438         mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
439         if ((ULONG_PTR)HIWORD((ULONG_PTR)dwTypeData) == 0)
440         {
441             if (LoadStringW(netshell_hInstance, LOWORD((ULONG_PTR)dwTypeData), szText, sizeof(szText)/sizeof(WCHAR)))
442             {
443                 szText[(sizeof(szText)/sizeof(WCHAR))-1] = 0;
444                 mii.dwTypeData = szText;
445             }
446             else
447             {
448                 return;
449             }
450         }
451         else
452         {
453             mii.dwTypeData = (LPWSTR) dwTypeData;
454         }
455         mii.fState = fState;
456     }
457 
458     mii.wID = wID;
459     mii.fType = fType;
460     InsertMenuItemW( hmenu, indexMenu, fByPosition, &mii);
461 }
462 
463 /**************************************************************************
464 * ISF_NetConnect_IContextMenu_QueryContextMenu()
465 */
466 HRESULT WINAPI CNetConUiObject::QueryContextMenu(
467 	HMENU hMenu,
468 	UINT indexMenu,
469 	UINT idCmdFirst,
470 	UINT idCmdLast,
471 	UINT uFlags)
472 {
473     PNETCONIDSTRUCT pdata = ILGetConnData(m_pidl);
474     if (!pdata)
475     {
476         ERR("Got invalid pidl!\n");
477         return E_FAIL;
478     }
479 
480     if (pdata->Status == NCS_HARDWARE_DISABLED || pdata->Status == NCS_MEDIA_DISCONNECTED || pdata->Status == NCS_DISCONNECTED)
481         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_ACTIVATE), MFS_DEFAULT);
482     else
483         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 1, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DEACTIVATE), MFS_ENABLED);
484 
485     if (pdata->Status == NCS_HARDWARE_DISABLED || pdata->Status == NCS_MEDIA_DISCONNECTED || pdata->Status == NCS_DISCONNECTED)
486         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 2, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_GRAYED);
487     else if (pdata->Status == NCS_CONNECTED)
488         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 2, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_DEFAULT);
489     else
490         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 2, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_ENABLED);
491 
492     if (pdata->Status == NCS_HARDWARE_DISABLED || pdata->Status == NCS_MEDIA_DISCONNECTED)
493         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 3, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_GRAYED);
494     else
495         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 3, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_ENABLED);
496 
497     _InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
498     _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 4, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_CREATELINK), MFS_ENABLED);
499 
500     if (pdata->dwCharacter & NCCF_ALLOW_REMOVAL)
501         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 5, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_ENABLED);
502     else
503         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 5, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_GRAYED);
504 
505     if (pdata->dwCharacter & NCCF_ALLOW_RENAME)
506         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 6, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_ENABLED);
507     else
508         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 6, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_GRAYED);
509 
510     _InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
511     if (pdata->Status == NCS_CONNECTED)
512         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 7, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_PROPERTIES), MFS_ENABLED);
513     else
514         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 7, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_PROPERTIES),  MFS_DEFAULT);
515 
516     return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 9);
517 }
518 
519 BOOL
520 CALLBACK
521 PropSheetExCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
522 {
523     PROPSHEETHEADERW *pinfo = (PROPSHEETHEADERW *)lParam;
524 
525     if (pinfo->nPages < MAX_PROPERTY_SHEET_PAGE)
526     {
527         pinfo->phpage[pinfo->nPages++] = hPage;
528         return TRUE;
529     }
530     return FALSE;
531 }
532 
533 HRESULT
534 ShowNetConnectionStatus(
535     IOleCommandTarget *lpOleCmd,
536     PCUITEMID_CHILD pidl,
537     HWND hwnd)
538 {
539     if (!lpOleCmd)
540         return E_FAIL;
541 
542     PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
543     if (!pdata)
544     {
545         ERR("Got invalid pidl!\n");
546         return E_FAIL;
547     }
548 
549     return lpOleCmd->Exec(&pdata->guidId, OLECMDID_NEW, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
550 }
551 
552 HRESULT
553 ShowNetConnectionProperties(
554     INetConnection *pNetConnect,
555     HWND hwnd)
556 {
557     HRESULT hr;
558     CLSID ClassID;
559     PROPSHEETHEADERW pinfo;
560     HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
561     CComPtr<INetConnectionPropertyUi> pNCP;
562     NETCON_PROPERTIES * pProperties;
563 
564     if (pNetConnect->GetProperties(&pProperties) != S_OK)
565         return E_FAIL;
566 
567     hr = pNetConnect->GetUiObjectClassId(&ClassID);
568     if (FAILED(hr))
569     {
570         NcFreeNetconProperties(pProperties);
571         return hr;
572     }
573 
574     hr = CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER, IID_INetConnectionPropertyUi, (LPVOID*)&pNCP);
575     if (FAILED(hr))
576     {
577         NcFreeNetconProperties(pProperties);
578         return hr;
579     }
580 
581     hr = pNCP->SetConnection(pNetConnect);
582     if (SUCCEEDED(hr))
583     {
584         ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
585         ZeroMemory(hppages, sizeof(hppages));
586         pinfo.dwSize = sizeof(PROPSHEETHEADERW);
587         pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW;
588         pinfo.phpage = hppages;
589         pinfo.hwndParent = hwnd;
590 
591         pinfo.pszCaption = pProperties->pszwName;
592         hr = pNCP->AddPages(hwnd, PropSheetExCallback, (LPARAM)&pinfo);
593         if (SUCCEEDED(hr))
594         {
595             if (PropertySheetW(&pinfo) < 0)
596                 hr = E_FAIL;
597         }
598     }
599     NcFreeNetconProperties(pProperties);
600     return hr;
601 }
602 
603 
604 /**************************************************************************
605 * ISF_NetConnect_IContextMenu_InvokeCommand()
606 */
607 HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
608 {
609     UINT CmdId;
610 
611     /* We should get this when F2 is pressed in explorer */
612     if (HIWORD(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, "rename"))
613         lpcmi->lpVerb = MAKEINTRESOURCEA(IDS_NET_RENAME);
614 
615     if (HIWORD(lpcmi->lpVerb) || LOWORD(lpcmi->lpVerb) > 7)
616     {
617         FIXME("Got invalid command\n");
618         return E_NOTIMPL;
619     }
620 
621     CmdId = LOWORD(lpcmi->lpVerb) + IDS_NET_ACTIVATE;
622 
623     switch(CmdId)
624     {
625         case IDS_NET_RENAME:
626         {
627             HRESULT hr;
628             CComPtr<IShellView> psv;
629             hr = IUnknown_QueryService(m_pUnknown, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
630             if (SUCCEEDED(hr))
631             {
632                 SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT;
633                 psv->SelectItem(m_pidl, selFlags);
634             }
635 
636             return S_OK;
637         }
638         case IDS_NET_STATUS:
639         {
640             return ShowNetConnectionStatus(m_lpOleCmd, m_pidl, lpcmi->hwnd);
641         }
642         case IDS_NET_REPAIR:
643         case IDS_NET_CREATELINK:
644         case IDS_NET_DELETE:
645             FIXME("Command %u is not implemented\n", CmdId);
646             return E_NOTIMPL;
647     }
648 
649     HRESULT hr;
650     CComPtr<INetConnection> pCon;
651 
652     hr = ILGetConnection(m_pidl, &pCon);
653     if (FAILED_UNEXPECTEDLY(hr))
654         return hr;
655 
656     switch(CmdId)
657     {
658         case IDS_NET_ACTIVATE:
659             return pCon->Connect();
660         case IDS_NET_DEACTIVATE:
661             return pCon->Disconnect();
662         case IDS_NET_PROPERTIES:
663             return ShowNetConnectionProperties(pCon, lpcmi->hwnd);
664     }
665 
666     return E_NOTIMPL;
667 }
668 
669 /**************************************************************************
670  *  ISF_NetConnect_IContextMenu_GetCommandString()
671  *
672  */
673 HRESULT WINAPI CNetConUiObject::GetCommandString(
674 	UINT_PTR idCommand,
675 	UINT uFlags,
676 	UINT* lpReserved,
677 	LPSTR lpszName,
678 	UINT uMaxNameLen)
679 {
680 	return E_FAIL;
681 }
682 
683 /**************************************************************************
684 * ISF_NetConnect_IContextMenu_HandleMenuMsg()
685 */
686 HRESULT WINAPI CNetConUiObject::HandleMenuMsg(
687 	UINT uMsg,
688 	WPARAM wParam,
689 	LPARAM lParam)
690 {
691     return E_NOTIMPL;
692 }
693 
694 HRESULT WINAPI CNetConUiObject::HandleMenuMsg2(
695     UINT uMsg,
696     WPARAM wParam,
697     LPARAM lParam,
698     LRESULT *plResult)
699 {
700     return E_NOTIMPL;
701 }
702 
703 HRESULT WINAPI CNetConUiObject::GetSite(REFIID riid, PVOID *ppvSite)
704 {
705     if (!m_pUnknown)
706     {
707         *ppvSite = NULL;
708         return E_FAIL;
709     }
710 
711     return m_pUnknown->QueryInterface(riid, ppvSite);
712 }
713 
714 HRESULT WINAPI CNetConUiObject::SetSite(IUnknown *pUnkSite)
715 {
716     m_pUnknown = pUnkSite;
717     return S_OK;
718 }
719 
720 /************************************************************************
721  *	ISF_NetConnect_IExtractIcon_GetIconLocation
722  */
723 HRESULT WINAPI CNetConUiObject::GetIconLocation(
724     UINT uFlags,
725     LPWSTR szIconFile,
726     UINT cchMax,
727     int *piIndex,
728     UINT *pwFlags)
729 {
730     *pwFlags = 0;
731     if (!GetModuleFileNameW(netshell_hInstance, szIconFile, cchMax))
732     {
733         ERR("GetModuleFileNameW failed\n");
734         return E_FAIL;
735     }
736 
737     PNETCONIDSTRUCT pdata = ILGetConnData(m_pidl);
738     if (!pdata)
739     {
740         ERR("Got invalid pidl!\n");
741         return E_FAIL;
742     }
743 
744     if (pdata->Status == NCS_CONNECTED || pdata->Status == NCS_CONNECTING)
745         *piIndex = -IDI_NET_IDLE;
746     else
747         *piIndex = -IDI_NET_OFF;
748 
749     return S_OK;
750 }
751 
752 /************************************************************************
753  *	ISF_NetConnect_IExtractIcon_Extract
754  */
755 HRESULT WINAPI CNetConUiObject::Extract(
756     LPCWSTR pszFile,
757     UINT nIconIndex,
758     HICON *phiconLarge,
759     HICON *phiconSmall,
760     UINT nIconSize)
761 {
762     return SHDefExtractIconW(pszFile, nIconIndex, 0, phiconLarge, phiconSmall, nIconSize);
763 }
764 
765 /************************************************************************
766  *	ISF_NetConnect_PersistFolder2_GetClassID
767  */
768 HRESULT WINAPI CNetworkConnections::GetClassID(CLSID *lpClassId)
769 {
770     if (!lpClassId)
771         return E_POINTER;
772 
773     *lpClassId = CLSID_ConnectionFolder;
774 
775     return S_OK;
776 }
777 
778 /************************************************************************
779  *	ISF_NetConnect_PersistFolder2_Initialize
780  *
781  * NOTES: it makes no sense to change the pidl
782  */
783 HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidl)
784 {
785     if (m_pidlRoot)
786         SHFree(m_pidlRoot);
787     m_pidlRoot = ILClone(pidl);
788 
789     return S_OK;
790 }
791 
792 /**************************************************************************
793  *	ISF_NetConnect_PersistFolder2_GetCurFolder
794  */
795 HRESULT WINAPI CNetworkConnections::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
796 {
797     if (!pidl)
798         return E_POINTER;
799 
800     *pidl = ILClone(m_pidlRoot);
801 
802     return S_OK;
803 }
804 
805 /************************************************************************
806  *	ISF_NetConnect_ShellExecuteHookW_Execute
807  */
808 HRESULT WINAPI CNetworkConnections::Execute(LPSHELLEXECUTEINFOW pei)
809 {
810     PCUITEMID_CHILD pidl = ILFindLastID((ITEMIDLIST*)pei->lpIDList);
811     PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
812     if (!pdata)
813     {
814         ERR("Got invalid pidl!\n");
815         return E_FAIL;
816     }
817 
818     if (pdata->Status == NCS_CONNECTED)
819     {
820         return ShowNetConnectionStatus(m_lpOleCmd, pidl, pei->hwnd);
821     }
822 
823     return S_OK;
824 }
825 
826 HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
827 {
828     FIXME("CNetworkConnections::Initialize()\n");
829     return E_NOTIMPL;
830 }
831 
832 HRESULT WINAPI CNetworkConnections::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
833 {
834     FIXME("CNetworkConnections::Exec()\n");
835     return E_NOTIMPL;
836 }
837 
838 HRESULT WINAPI CNetworkConnections::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
839 {
840     FIXME("CNetworkConnections::QueryStatus()\n");
841     return E_NOTIMPL;
842 }
843 
844 HRESULT WINAPI CNetworkConnections::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
845 {
846     FIXME("CNetworkConnections::MessageSFVCB()\n");
847     return E_NOTIMPL;
848 }
849 
850 HRESULT WINAPI CNetConUiObject::GetInfoFlags(DWORD *pdwFlags)
851 {
852     *pdwFlags = 0;
853 
854     return S_OK;
855 }
856 
857 /************************************************************************
858  *	ISF_NetConnect_PersistFolder2_Initialize
859  *
860  * NOTES: it makes no sense to change the pidl
861  */
862 HRESULT WINAPI CNetConUiObject::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
863 {
864     *ppwszTip = NULL;
865     return S_OK;
866 }
867