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