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