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 static int CALLBACK
553 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
554 {
555     // NOTE: This callback is needed to set large icon correctly.
556     HICON hIcon;
557     switch (uMsg)
558     {
559         case PSCB_INITIALIZED:
560         {
561             hIcon = LoadIconW(netshell_hInstance, MAKEINTRESOURCEW(IDI_SHELL_NETWORK_FOLDER));
562             SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
563             break;
564         }
565     }
566     return 0;
567 }
568 
569 HRESULT
570 ShowNetConnectionProperties(
571     INetConnection *pNetConnect,
572     HWND hwnd)
573 {
574     HRESULT hr;
575     CLSID ClassID;
576     PROPSHEETHEADERW pinfo;
577     HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
578     CComPtr<INetConnectionPropertyUi> pNCP;
579     NETCON_PROPERTIES * pProperties;
580 
581     if (pNetConnect->GetProperties(&pProperties) != S_OK)
582         return E_FAIL;
583 
584     hr = pNetConnect->GetUiObjectClassId(&ClassID);
585     if (FAILED(hr))
586     {
587         NcFreeNetconProperties(pProperties);
588         return hr;
589     }
590 
591     hr = CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER, IID_INetConnectionPropertyUi, (LPVOID*)&pNCP);
592     if (FAILED(hr))
593     {
594         NcFreeNetconProperties(pProperties);
595         return hr;
596     }
597 
598     hr = pNCP->SetConnection(pNetConnect);
599     if (SUCCEEDED(hr))
600     {
601         ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
602         ZeroMemory(hppages, sizeof(hppages));
603         pinfo.dwSize = sizeof(PROPSHEETHEADERW);
604         pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW |
605                         PSH_USEICONID | PSH_USECALLBACK;
606         pinfo.hInstance = netshell_hInstance;
607         pinfo.pszIcon = MAKEINTRESOURCEW(IDI_SHELL_NETWORK_FOLDER);
608         pinfo.phpage = hppages;
609         pinfo.hwndParent = hwnd;
610         pinfo.pfnCallback = PropSheetProc;
611 
612         pinfo.pszCaption = pProperties->pszwName;
613         hr = pNCP->AddPages(hwnd, PropSheetExCallback, (LPARAM)&pinfo);
614         if (SUCCEEDED(hr))
615         {
616             if (PropertySheetW(&pinfo) < 0)
617                 hr = E_FAIL;
618         }
619     }
620     NcFreeNetconProperties(pProperties);
621     return hr;
622 }
623 
624 
625 /**************************************************************************
626 * ISF_NetConnect_IContextMenu_InvokeCommand()
627 */
628 HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
629 {
630     UINT CmdId;
631 
632     /* We should get this when F2 is pressed in explorer */
633     if (HIWORD(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, "rename"))
634         lpcmi->lpVerb = MAKEINTRESOURCEA(IDS_NET_RENAME);
635 
636     if (HIWORD(lpcmi->lpVerb) || LOWORD(lpcmi->lpVerb) > 7)
637     {
638         FIXME("Got invalid command\n");
639         return E_NOTIMPL;
640     }
641 
642     CmdId = LOWORD(lpcmi->lpVerb) + IDS_NET_ACTIVATE;
643 
644     switch(CmdId)
645     {
646         case IDS_NET_RENAME:
647         {
648             HRESULT hr;
649             CComPtr<IShellView> psv;
650             hr = IUnknown_QueryService(m_pUnknown, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
651             if (SUCCEEDED(hr))
652             {
653                 SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT;
654                 psv->SelectItem(m_pidl, selFlags);
655             }
656 
657             return S_OK;
658         }
659         case IDS_NET_STATUS:
660         {
661             return ShowNetConnectionStatus(m_lpOleCmd, m_pidl, lpcmi->hwnd);
662         }
663         case IDS_NET_REPAIR:
664         case IDS_NET_CREATELINK:
665         case IDS_NET_DELETE:
666             FIXME("Command %u is not implemented\n", CmdId);
667             return E_NOTIMPL;
668     }
669 
670     HRESULT hr;
671     CComPtr<INetConnection> pCon;
672 
673     hr = ILGetConnection(m_pidl, &pCon);
674     if (FAILED_UNEXPECTEDLY(hr))
675         return hr;
676 
677     switch(CmdId)
678     {
679         case IDS_NET_ACTIVATE:
680             return pCon->Connect();
681         case IDS_NET_DEACTIVATE:
682             return pCon->Disconnect();
683         case IDS_NET_PROPERTIES:
684             return ShowNetConnectionProperties(pCon, lpcmi->hwnd);
685     }
686 
687     return E_NOTIMPL;
688 }
689 
690 /**************************************************************************
691  *  ISF_NetConnect_IContextMenu_GetCommandString()
692  *
693  */
694 HRESULT WINAPI CNetConUiObject::GetCommandString(
695 	UINT_PTR idCommand,
696 	UINT uFlags,
697 	UINT* lpReserved,
698 	LPSTR lpszName,
699 	UINT uMaxNameLen)
700 {
701 	return E_FAIL;
702 }
703 
704 /**************************************************************************
705 * ISF_NetConnect_IContextMenu_HandleMenuMsg()
706 */
707 HRESULT WINAPI CNetConUiObject::HandleMenuMsg(
708 	UINT uMsg,
709 	WPARAM wParam,
710 	LPARAM lParam)
711 {
712     return E_NOTIMPL;
713 }
714 
715 HRESULT WINAPI CNetConUiObject::HandleMenuMsg2(
716     UINT uMsg,
717     WPARAM wParam,
718     LPARAM lParam,
719     LRESULT *plResult)
720 {
721     return E_NOTIMPL;
722 }
723 
724 HRESULT WINAPI CNetConUiObject::GetSite(REFIID riid, PVOID *ppvSite)
725 {
726     if (!m_pUnknown)
727     {
728         *ppvSite = NULL;
729         return E_FAIL;
730     }
731 
732     return m_pUnknown->QueryInterface(riid, ppvSite);
733 }
734 
735 HRESULT WINAPI CNetConUiObject::SetSite(IUnknown *pUnkSite)
736 {
737     m_pUnknown = pUnkSite;
738     return S_OK;
739 }
740 
741 /************************************************************************
742  *	ISF_NetConnect_IExtractIcon_GetIconLocation
743  */
744 HRESULT WINAPI CNetConUiObject::GetIconLocation(
745     UINT uFlags,
746     LPWSTR szIconFile,
747     UINT cchMax,
748     int *piIndex,
749     UINT *pwFlags)
750 {
751     *pwFlags = 0;
752     if (!GetModuleFileNameW(netshell_hInstance, szIconFile, cchMax))
753     {
754         ERR("GetModuleFileNameW failed\n");
755         return E_FAIL;
756     }
757 
758     PNETCONIDSTRUCT pdata = ILGetConnData(m_pidl);
759     if (!pdata)
760     {
761         ERR("Got invalid pidl!\n");
762         return E_FAIL;
763     }
764 
765     if (pdata->Status == NCS_CONNECTED || pdata->Status == NCS_CONNECTING)
766         *piIndex = -IDI_NET_IDLE;
767     else
768         *piIndex = -IDI_NET_OFF;
769 
770     return S_OK;
771 }
772 
773 /************************************************************************
774  *	ISF_NetConnect_IExtractIcon_Extract
775  */
776 HRESULT WINAPI CNetConUiObject::Extract(
777     LPCWSTR pszFile,
778     UINT nIconIndex,
779     HICON *phiconLarge,
780     HICON *phiconSmall,
781     UINT nIconSize)
782 {
783     return SHDefExtractIconW(pszFile, nIconIndex, 0, phiconLarge, phiconSmall, nIconSize);
784 }
785 
786 /************************************************************************
787  *	ISF_NetConnect_PersistFolder2_GetClassID
788  */
789 HRESULT WINAPI CNetworkConnections::GetClassID(CLSID *lpClassId)
790 {
791     if (!lpClassId)
792         return E_POINTER;
793 
794     *lpClassId = CLSID_ConnectionFolder;
795 
796     return S_OK;
797 }
798 
799 /************************************************************************
800  *	ISF_NetConnect_PersistFolder2_Initialize
801  *
802  * NOTES: it makes no sense to change the pidl
803  */
804 HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidl)
805 {
806     if (m_pidlRoot)
807         SHFree(m_pidlRoot);
808     m_pidlRoot = ILClone(pidl);
809 
810     return S_OK;
811 }
812 
813 /**************************************************************************
814  *	ISF_NetConnect_PersistFolder2_GetCurFolder
815  */
816 HRESULT WINAPI CNetworkConnections::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
817 {
818     if (!pidl)
819         return E_POINTER;
820 
821     *pidl = ILClone(m_pidlRoot);
822 
823     return S_OK;
824 }
825 
826 /************************************************************************
827  *	ISF_NetConnect_ShellExecuteHookW_Execute
828  */
829 HRESULT WINAPI CNetworkConnections::Execute(LPSHELLEXECUTEINFOW pei)
830 {
831     PCUITEMID_CHILD pidl = ILFindLastID((ITEMIDLIST*)pei->lpIDList);
832     PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
833     if (!pdata)
834     {
835         ERR("Got invalid pidl!\n");
836         return E_FAIL;
837     }
838 
839     if (pdata->Status == NCS_CONNECTED)
840     {
841         return ShowNetConnectionStatus(m_lpOleCmd, pidl, pei->hwnd);
842     }
843 
844     return S_OK;
845 }
846 
847 HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
848 {
849     FIXME("CNetworkConnections::Initialize()\n");
850     return E_NOTIMPL;
851 }
852 
853 HRESULT WINAPI CNetworkConnections::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
854 {
855     FIXME("CNetworkConnections::Exec()\n");
856     return E_NOTIMPL;
857 }
858 
859 HRESULT WINAPI CNetworkConnections::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
860 {
861     FIXME("CNetworkConnections::QueryStatus()\n");
862     return E_NOTIMPL;
863 }
864 
865 HRESULT WINAPI CNetworkConnections::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
866 {
867     FIXME("CNetworkConnections::MessageSFVCB()\n");
868     return E_NOTIMPL;
869 }
870 
871 HRESULT WINAPI CNetConUiObject::GetInfoFlags(DWORD *pdwFlags)
872 {
873     *pdwFlags = 0;
874 
875     return S_OK;
876 }
877 
878 /************************************************************************
879  *	ISF_NetConnect_PersistFolder2_Initialize
880  *
881  * NOTES: it makes no sense to change the pidl
882  */
883 HRESULT WINAPI CNetConUiObject::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
884 {
885     *ppwszTip = NULL;
886     return S_OK;
887 }
888