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     *pPidlOut = ILCreateNetConnectItem(pCon);
274     if (*pPidlOut == NULL)
275         return E_FAIL;
276 
277     return S_OK;
278 }
279 
280 HRESULT WINAPI CNetworkConnections::GetDefaultSearchGUID(GUID * pguid)
281 {
282     return E_NOTIMPL;
283 }
284 
285 HRESULT WINAPI CNetworkConnections::EnumSearches(IEnumExtraSearch ** ppenum)
286 {
287     return E_NOTIMPL;
288 }
289 
290 HRESULT WINAPI CNetworkConnections::GetDefaultColumn(DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
291 {
292     if (pSort)
293         *pSort = 0;
294     if (pDisplay)
295         *pDisplay = 0;
296 
297     return S_OK;
298 }
299 
300 HRESULT WINAPI CNetworkConnections::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags)
301 {
302     if (!pcsFlags || iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
303         return E_INVALIDARG;
304     *pcsFlags = NetConnectSFHeader[iColumn].pcsFlags;
305     return S_OK;
306 }
307 
308 HRESULT WINAPI CNetworkConnections::GetDetailsEx(
309                PCUITEMID_CHILD pidl, const SHCOLUMNID * pscid, VARIANT * pv)
310 {
311     return E_NOTIMPL;
312 }
313 
314 HRESULT WINAPI CNetworkConnections::GetDetailsOf(
315                PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS * psd)
316 {
317     if (iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
318         return E_FAIL;
319 
320     psd->fmt = NetConnectSFHeader[iColumn].fmt;
321     psd->cxChar = NetConnectSFHeader[iColumn].cxChar;
322     if (pidl == NULL)
323         return SHSetStrRet(&psd->str, netshell_hInstance, NetConnectSFHeader[iColumn].colnameid);
324 
325     PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
326     if (!pdata)
327         return E_FAIL;
328 
329     switch (iColumn)
330     {
331         case COLUMN_NAME:
332             return SHSetStrRet(&psd->str, ILGetConnName(pidl));
333         case COLUMN_TYPE:
334             if (pdata->MediaType  == NCM_LAN || pdata->MediaType == NCM_SHAREDACCESSHOST_RAS)
335             {
336                 return SHSetStrRet(&psd->str, netshell_hInstance, IDS_TYPE_ETHERNET);
337             }
338             else
339             {
340                 return SHSetStrRet(&psd->str, "");
341             }
342             break;
343         case COLUMN_STATUS:
344             switch(pdata->Status)
345             {
346                 case NCS_HARDWARE_DISABLED:
347                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_NON_OPERATIONAL);
348                 case NCS_DISCONNECTED:
349                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_UNREACHABLE);
350                 case NCS_MEDIA_DISCONNECTED:
351                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_DISCONNECTED);
352                 case NCS_CONNECTING:
353                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_CONNECTING);
354                 case NCS_CONNECTED:
355                     return SHSetStrRet(&psd->str, netshell_hInstance, IDS_STATUS_CONNECTED);
356                 default:
357                     return SHSetStrRet(&psd->str, "");
358             }
359             break;
360         case COLUMN_DEVNAME:
361             return SHSetStrRet(&psd->str, ILGetDeviceName(pidl));
362         case COLUMN_PHONE:
363         case COLUMN_OWNER:
364             return SHSetStrRet(&psd->str, "");
365     }
366 
367     return E_FAIL;
368 }
369 
370 HRESULT WINAPI CNetworkConnections::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
371 {
372     return E_NOTIMPL;
373 }
374 
375 //IObjectWithSite
376 //IInternetSecurityManager
377 
378 /**************************************************************************
379 * IContextMenu2 Implementation
380 */
381 
382 CNetConUiObject::CNetConUiObject()
383     : m_pidl(NULL)
384 {
385 }
386 
387 CNetConUiObject::~CNetConUiObject()
388 {
389 }
390 
391 HRESULT WINAPI CNetConUiObject::Initialize(PCUITEMID_CHILD pidl, IOleCommandTarget *lpOleCmd)
392 {
393     m_pidl = pidl;
394     m_lpOleCmd = lpOleCmd;
395     return S_OK;
396 }
397 
398 void WINAPI _InsertMenuItemW (
399     HMENU hmenu,
400     UINT indexMenu,
401     BOOL fByPosition,
402     UINT wID,
403     UINT fType,
404     LPCWSTR dwTypeData,
405     UINT fState)
406 {
407     MENUITEMINFOW mii;
408     WCHAR szText[100];
409 
410     ZeroMemory(&mii, sizeof(mii));
411     mii.cbSize = sizeof(mii);
412     if (fType == MFT_SEPARATOR)
413     {
414         mii.fMask = MIIM_ID | MIIM_TYPE;
415     }
416     else if (fType == MFT_STRING)
417     {
418         mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
419         if ((ULONG_PTR)HIWORD((ULONG_PTR)dwTypeData) == 0)
420         {
421             if (LoadStringW(netshell_hInstance, LOWORD((ULONG_PTR)dwTypeData), szText, sizeof(szText)/sizeof(WCHAR)))
422             {
423                 szText[(sizeof(szText)/sizeof(WCHAR))-1] = 0;
424                 mii.dwTypeData = szText;
425             }
426             else
427             {
428                 return;
429             }
430         }
431         else
432         {
433             mii.dwTypeData = (LPWSTR) dwTypeData;
434         }
435         mii.fState = fState;
436     }
437 
438     mii.wID = wID;
439     mii.fType = fType;
440     InsertMenuItemW( hmenu, indexMenu, fByPosition, &mii);
441 }
442 
443 /**************************************************************************
444 * ISF_NetConnect_IContextMenu_QueryContextMenu()
445 */
446 HRESULT WINAPI CNetConUiObject::QueryContextMenu(
447 	HMENU hMenu,
448 	UINT indexMenu,
449 	UINT idCmdFirst,
450 	UINT idCmdLast,
451 	UINT uFlags)
452 {
453     PNETCONIDSTRUCT pdata = ILGetConnData(m_pidl);
454     if (!pdata)
455     {
456         ERR("Got invalid pidl\n");
457         return E_FAIL;
458     }
459 
460     if (pdata->Status == NCS_HARDWARE_DISABLED || pdata->Status == NCS_MEDIA_DISCONNECTED || pdata->Status == NCS_DISCONNECTED)
461         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_ACTIVATE), MFS_DEFAULT);
462     else
463         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 1, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DEACTIVATE), MFS_ENABLED);
464 
465     if (pdata->Status == NCS_HARDWARE_DISABLED || pdata->Status == NCS_MEDIA_DISCONNECTED || pdata->Status == NCS_DISCONNECTED)
466         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 2, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_GRAYED);
467     else if (pdata->Status == NCS_CONNECTED)
468         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 2, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_DEFAULT);
469     else
470         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 2, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_ENABLED);
471 
472     if (pdata->Status == NCS_HARDWARE_DISABLED || pdata->Status == NCS_MEDIA_DISCONNECTED)
473         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 3, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_GRAYED);
474     else
475         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 3, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_ENABLED);
476 
477     _InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
478     _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 4, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_CREATELINK), MFS_ENABLED);
479 
480     if (pdata->dwCharacter & NCCF_ALLOW_REMOVAL)
481         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 5, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_ENABLED);
482     else
483         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 5, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_GRAYED);
484 
485     if (pdata->dwCharacter & NCCF_ALLOW_RENAME)
486         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 6, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_ENABLED);
487     else
488         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 6, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_GRAYED);
489 
490     _InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
491     if (pdata->Status == NCS_CONNECTED)
492         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 7, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_PROPERTIES), MFS_ENABLED);
493     else
494         _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + 7, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_PROPERTIES), MFS_DEFAULT);
495 
496     return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 9);
497 }
498 
499 BOOL
500 CALLBACK
501 PropSheetExCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
502 {
503     PROPSHEETHEADERW *pinfo = (PROPSHEETHEADERW *)lParam;
504 
505     if (pinfo->nPages < MAX_PROPERTY_SHEET_PAGE)
506     {
507         pinfo->phpage[pinfo->nPages++] = hPage;
508         return TRUE;
509     }
510     return FALSE;
511 }
512 
513 HRESULT
514 ShowNetConnectionStatus(
515     IOleCommandTarget *lpOleCmd,
516     PCUITEMID_CHILD pidl,
517     HWND hwnd)
518 {
519     if (!lpOleCmd)
520         return E_FAIL;
521 
522     PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
523     if (!pdata)
524     {
525         ERR("Got invalid pidl\n");
526         return E_FAIL;
527     }
528 
529     return lpOleCmd->Exec(&pdata->guidId, OLECMDID_NEW, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
530 }
531 
532 static int CALLBACK
533 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
534 {
535     // NOTE: This callback is needed to set large icon correctly.
536     HICON hIcon;
537     switch (uMsg)
538     {
539         case PSCB_INITIALIZED:
540         {
541             hIcon = LoadIconW(netshell_hInstance, MAKEINTRESOURCEW(IDI_SHELL_NETWORK_FOLDER));
542             SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
543             break;
544         }
545     }
546     return 0;
547 }
548 
549 HRESULT
550 ShowNetConnectionProperties(
551     INetConnection *pNetConnect,
552     HWND hwnd)
553 {
554     HRESULT hr;
555     CLSID ClassID;
556     PROPSHEETHEADERW pinfo;
557     HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
558     CComPtr<INetConnectionPropertyUi> pNCP;
559     NETCON_PROPERTIES * pProperties;
560 
561     if (pNetConnect->GetProperties(&pProperties) != S_OK)
562         return E_FAIL;
563 
564     hr = pNetConnect->GetUiObjectClassId(&ClassID);
565     if (FAILED(hr))
566     {
567         NcFreeNetconProperties(pProperties);
568         return hr;
569     }
570 
571     hr = CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER, IID_INetConnectionPropertyUi, (LPVOID*)&pNCP);
572     if (FAILED(hr))
573     {
574         NcFreeNetconProperties(pProperties);
575         return hr;
576     }
577 
578     hr = pNCP->SetConnection(pNetConnect);
579     if (SUCCEEDED(hr))
580     {
581         ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
582         ZeroMemory(hppages, sizeof(hppages));
583         pinfo.dwSize = sizeof(PROPSHEETHEADERW);
584         pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW |
585                         PSH_USEICONID | PSH_USECALLBACK;
586         pinfo.hInstance = netshell_hInstance;
587         pinfo.pszIcon = MAKEINTRESOURCEW(IDI_SHELL_NETWORK_FOLDER);
588         pinfo.phpage = hppages;
589         pinfo.hwndParent = hwnd;
590         pinfo.pfnCallback = PropSheetProc;
591 
592         pinfo.pszCaption = pProperties->pszwName;
593         hr = pNCP->AddPages(hwnd, PropSheetExCallback, (LPARAM)&pinfo);
594         if (SUCCEEDED(hr))
595         {
596             if (PropertySheetW(&pinfo) < 0)
597                 hr = E_FAIL;
598         }
599     }
600     NcFreeNetconProperties(pProperties);
601     return hr;
602 }
603 
604 
605 /**************************************************************************
606 * ISF_NetConnect_IContextMenu_InvokeCommand()
607 */
608 HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
609 {
610     UINT CmdId;
611 
612     /* We should get this when F2 is pressed in explorer */
613     if (HIWORD(lpcmi->lpVerb) && !strcmp(lpcmi->lpVerb, "rename"))
614         lpcmi->lpVerb = MAKEINTRESOURCEA(IDS_NET_RENAME);
615 
616     if (HIWORD(lpcmi->lpVerb) || LOWORD(lpcmi->lpVerb) > 7)
617     {
618         FIXME("Got invalid command\n");
619         return E_NOTIMPL;
620     }
621 
622     CmdId = LOWORD(lpcmi->lpVerb) + IDS_NET_ACTIVATE;
623 
624     switch(CmdId)
625     {
626         case IDS_NET_RENAME:
627         {
628             HRESULT hr;
629             CComPtr<IShellView> psv;
630             hr = IUnknown_QueryService(m_pUnknown, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
631             if (SUCCEEDED(hr))
632             {
633                 SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT;
634                 psv->SelectItem(m_pidl, selFlags);
635             }
636 
637             return S_OK;
638         }
639         case IDS_NET_STATUS:
640         {
641             return ShowNetConnectionStatus(m_lpOleCmd, m_pidl, lpcmi->hwnd);
642         }
643         case IDS_NET_REPAIR:
644         case IDS_NET_CREATELINK:
645         case IDS_NET_DELETE:
646             FIXME("Command %u is not implemented\n", CmdId);
647             return E_NOTIMPL;
648     }
649 
650     HRESULT hr;
651     CComPtr<INetConnection> pCon;
652 
653     hr = ILGetConnection(m_pidl, &pCon);
654     if (FAILED_UNEXPECTEDLY(hr))
655         return hr;
656 
657     switch(CmdId)
658     {
659         case IDS_NET_ACTIVATE:
660             return pCon->Connect();
661         case IDS_NET_DEACTIVATE:
662             return pCon->Disconnect();
663         case IDS_NET_PROPERTIES:
664             return ShowNetConnectionProperties(pCon, lpcmi->hwnd);
665     }
666 
667     return E_NOTIMPL;
668 }
669 
670 /**************************************************************************
671  *  ISF_NetConnect_IContextMenu_GetCommandString()
672  *
673  */
674 HRESULT WINAPI CNetConUiObject::GetCommandString(
675 	UINT_PTR idCommand,
676 	UINT uFlags,
677 	UINT* lpReserved,
678 	LPSTR lpszName,
679 	UINT uMaxNameLen)
680 {
681 	return E_FAIL;
682 }
683 
684 /**************************************************************************
685 * ISF_NetConnect_IContextMenu_HandleMenuMsg()
686 */
687 HRESULT WINAPI CNetConUiObject::HandleMenuMsg(
688 	UINT uMsg,
689 	WPARAM wParam,
690 	LPARAM lParam)
691 {
692     return E_NOTIMPL;
693 }
694 
695 HRESULT WINAPI CNetConUiObject::HandleMenuMsg2(
696     UINT uMsg,
697     WPARAM wParam,
698     LPARAM lParam,
699     LRESULT *plResult)
700 {
701     return E_NOTIMPL;
702 }
703 
704 HRESULT WINAPI CNetConUiObject::GetSite(REFIID riid, PVOID *ppvSite)
705 {
706     if (!m_pUnknown)
707     {
708         *ppvSite = NULL;
709         return E_FAIL;
710     }
711 
712     return m_pUnknown->QueryInterface(riid, ppvSite);
713 }
714 
715 HRESULT WINAPI CNetConUiObject::SetSite(IUnknown *pUnkSite)
716 {
717     m_pUnknown = pUnkSite;
718     return S_OK;
719 }
720 
721 /************************************************************************
722  *	ISF_NetConnect_IExtractIcon_GetIconLocation
723  */
724 HRESULT WINAPI CNetConUiObject::GetIconLocation(
725     UINT uFlags,
726     LPWSTR szIconFile,
727     UINT cchMax,
728     int *piIndex,
729     UINT *pwFlags)
730 {
731     *pwFlags = 0;
732     if (!GetModuleFileNameW(netshell_hInstance, szIconFile, cchMax))
733     {
734         ERR("GetModuleFileNameW failed\n");
735         return E_FAIL;
736     }
737 
738     PNETCONIDSTRUCT pdata = ILGetConnData(m_pidl);
739     if (!pdata)
740     {
741         ERR("Got invalid pidl\n");
742         return E_FAIL;
743     }
744 
745     if (pdata->Status == NCS_CONNECTED || pdata->Status == NCS_CONNECTING)
746         *piIndex = -IDI_NET_IDLE;
747     else
748         *piIndex = -IDI_NET_OFF;
749 
750     return S_OK;
751 }
752 
753 /************************************************************************
754  *	ISF_NetConnect_IExtractIcon_Extract
755  */
756 HRESULT WINAPI CNetConUiObject::Extract(
757     LPCWSTR pszFile,
758     UINT nIconIndex,
759     HICON *phiconLarge,
760     HICON *phiconSmall,
761     UINT nIconSize)
762 {
763     return SHDefExtractIconW(pszFile, nIconIndex, 0, phiconLarge, phiconSmall, nIconSize);
764 }
765 
766 /************************************************************************
767  *	ISF_NetConnect_PersistFolder2_GetClassID
768  */
769 HRESULT WINAPI CNetworkConnections::GetClassID(CLSID *lpClassId)
770 {
771     if (!lpClassId)
772         return E_POINTER;
773 
774     *lpClassId = CLSID_ConnectionFolder;
775 
776     return S_OK;
777 }
778 
779 /************************************************************************
780  *	ISF_NetConnect_PersistFolder2_Initialize
781  *
782  * NOTES: it makes no sense to change the pidl
783  */
784 HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidl)
785 {
786     if (m_pidlRoot)
787         SHFree(m_pidlRoot);
788     m_pidlRoot = ILClone(pidl);
789 
790     return S_OK;
791 }
792 
793 /**************************************************************************
794  *	ISF_NetConnect_PersistFolder2_GetCurFolder
795  */
796 HRESULT WINAPI CNetworkConnections::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
797 {
798     if (!pidl)
799         return E_POINTER;
800 
801     *pidl = ILClone(m_pidlRoot);
802 
803     return S_OK;
804 }
805 
806 /************************************************************************
807  *	ISF_NetConnect_ShellExecuteHookW_Execute
808  */
809 HRESULT WINAPI CNetworkConnections::Execute(LPSHELLEXECUTEINFOW pei)
810 {
811     PCUITEMID_CHILD pidl = ILFindLastID((ITEMIDLIST*)pei->lpIDList);
812     PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
813     if (!pdata)
814     {
815         ERR("Got invalid pidl\n");
816         return E_FAIL;
817     }
818 
819     if (pdata->Status == NCS_CONNECTED)
820     {
821         return ShowNetConnectionStatus(m_lpOleCmd, pidl, pei->hwnd);
822     }
823 
824     return S_OK;
825 }
826 
827 HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
828 {
829     FIXME("CNetworkConnections::Initialize()\n");
830     return E_NOTIMPL;
831 }
832 
833 HRESULT WINAPI CNetworkConnections::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
834 {
835     FIXME("CNetworkConnections::Exec()\n");
836     return E_NOTIMPL;
837 }
838 
839 HRESULT WINAPI CNetworkConnections::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
840 {
841     FIXME("CNetworkConnections::QueryStatus()\n");
842     return E_NOTIMPL;
843 }
844 
845 HRESULT WINAPI CNetworkConnections::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
846 {
847     FIXME("CNetworkConnections::MessageSFVCB()\n");
848     return E_NOTIMPL;
849 }
850 
851 HRESULT WINAPI CNetConUiObject::GetInfoFlags(DWORD *pdwFlags)
852 {
853     *pdwFlags = 0;
854 
855     return S_OK;
856 }
857 
858 /************************************************************************
859  *	ISF_NetConnect_PersistFolder2_Initialize
860  *
861  * NOTES: it makes no sense to change the pidl
862  */
863 HRESULT WINAPI CNetConUiObject::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
864 {
865     *ppwszTip = NULL;
866     return S_OK;
867 }
868