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
CNetworkConnections()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
~CNetworkConnections()50 CNetworkConnections::~CNetworkConnections()
51 {
52 if (m_pidlRoot)
53 SHFree(m_pidlRoot);
54 }
55
56 /**************************************************************************
57 * ISF_NetConnect_fnParseDisplayName
58 */
ParseDisplayName(HWND hwndOwner,LPBC pbcReserved,LPOLESTR lpszDisplayName,DWORD * pchEaten,PIDLIST_RELATIVE * ppidl,DWORD * pdwAttributes)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 */
EnumObjects(HWND hwndOwner,DWORD dwFlags,LPENUMIDLIST * ppEnumIDList)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 */
BindToObject(PCUIDLIST_RELATIVE pidl,LPBC pbcReserved,REFIID riid,LPVOID * ppvOut)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 */
BindToStorage(PCUIDLIST_RELATIVE pidl,LPBC pbcReserved,REFIID riid,LPVOID * ppvOut)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 */
CompareIDs(LPARAM lParam,PCUIDLIST_RELATIVE pidl1,PCUIDLIST_RELATIVE pidl2)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 */
CreateViewObject(HWND hwndOwner,REFIID riid,LPVOID * ppvOut)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 */
GetAttributesOf(UINT cidl,PCUITEMID_CHILD_ARRAY apidl,DWORD * rgfInOut)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
GetUIObjectOf(HWND hwndOwner,UINT cidl,PCUITEMID_CHILD_ARRAY apidl,REFIID riid,UINT * prgfInOut,LPVOID * ppvOut)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 */
GetDisplayNameOf(PCUITEMID_CHILD pidl,DWORD dwFlags,LPSTRRET strRet)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 */
SetNameOf(HWND hwndOwner,PCUITEMID_CHILD pidl,LPCOLESTR lpName,DWORD dwFlags,PITEMID_CHILD * pPidlOut)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
GetDefaultSearchGUID(GUID * pguid)303 HRESULT WINAPI CNetworkConnections::GetDefaultSearchGUID(GUID * pguid)
304 {
305 return E_NOTIMPL;
306 }
307
EnumSearches(IEnumExtraSearch ** ppenum)308 HRESULT WINAPI CNetworkConnections::EnumSearches(IEnumExtraSearch ** ppenum)
309 {
310 return E_NOTIMPL;
311 }
312
GetDefaultColumn(DWORD dwRes,ULONG * pSort,ULONG * pDisplay)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
GetDefaultColumnState(UINT iColumn,DWORD * pcsFlags)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
GetDetailsEx(PCUITEMID_CHILD pidl,const SHCOLUMNID * pscid,VARIANT * pv)331 HRESULT WINAPI CNetworkConnections::GetDetailsEx(
332 PCUITEMID_CHILD pidl, const SHCOLUMNID * pscid, VARIANT * pv)
333 {
334 return E_NOTIMPL;
335 }
336
GetDetailsOf(PCUITEMID_CHILD pidl,UINT iColumn,SHELLDETAILS * psd)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
MapColumnToSCID(UINT column,SHCOLUMNID * pscid)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
CNetConUiObject()405 CNetConUiObject::CNetConUiObject()
406 : m_pidl(NULL)
407 {
408 }
409
~CNetConUiObject()410 CNetConUiObject::~CNetConUiObject()
411 {
412 }
413
Initialize(PCUITEMID_CHILD pidl,IOleCommandTarget * lpOleCmd)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
_InsertMenuItemW(HMENU hmenu,UINT indexMenu,BOOL fByPosition,UINT wID,UINT fType,LPCWSTR dwTypeData,UINT fState)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 */
QueryContextMenu(HMENU hMenu,UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)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
PropSheetExCallback(HPROPSHEETPAGE hPage,LPARAM lParam)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
ShowNetConnectionStatus(IOleCommandTarget * lpOleCmd,PCUITEMID_CHILD pidl,HWND hwnd)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
PropSheetProc(HWND hwndDlg,UINT uMsg,LPARAM lParam)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
ShowNetConnectionProperties(INetConnection * pNetConnect,HWND hwnd)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 */
InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)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 */
GetCommandString(UINT_PTR idCommand,UINT uFlags,UINT * lpReserved,LPSTR lpszName,UINT uMaxNameLen)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 */
HandleMenuMsg(UINT uMsg,WPARAM wParam,LPARAM lParam)713 HRESULT WINAPI CNetConUiObject::HandleMenuMsg(
714 UINT uMsg,
715 WPARAM wParam,
716 LPARAM lParam)
717 {
718 return E_NOTIMPL;
719 }
720
HandleMenuMsg2(UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT * plResult)721 HRESULT WINAPI CNetConUiObject::HandleMenuMsg2(
722 UINT uMsg,
723 WPARAM wParam,
724 LPARAM lParam,
725 LRESULT *plResult)
726 {
727 return E_NOTIMPL;
728 }
729
GetSite(REFIID riid,PVOID * ppvSite)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
SetSite(IUnknown * pUnkSite)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 */
GetIconLocation(UINT uFlags,LPWSTR szIconFile,UINT cchMax,int * piIndex,UINT * pwFlags)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 */
Extract(LPCWSTR pszFile,UINT nIconIndex,HICON * phiconLarge,HICON * phiconSmall,UINT nIconSize)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 */
GetClassID(CLSID * lpClassId)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 */
Initialize(PCIDLIST_ABSOLUTE pidl)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 */
GetCurFolder(PIDLIST_ABSOLUTE * pidl)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 */
Execute(LPSHELLEXECUTEINFOW pei)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
Initialize(PCIDLIST_ABSOLUTE pidlFolder,IDataObject * pdtobj,HKEY hkeyProgID)853 HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
854 {
855 FIXME("CNetworkConnections::Initialize()\n");
856 return E_NOTIMPL;
857 }
858
Exec(const GUID * pguidCmdGroup,DWORD nCmdID,DWORD nCmdexecopt,VARIANT * pvaIn,VARIANT * pvaOut)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
QueryStatus(const GUID * pguidCmdGroup,ULONG cCmds,OLECMD prgCmds[],OLECMDTEXT * pCmdText)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
MessageSFVCB(UINT uMsg,WPARAM wParam,LPARAM lParam)871 HRESULT WINAPI CNetworkConnections::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
872 {
873 FIXME("CNetworkConnections::MessageSFVCB()\n");
874 return E_NOTIMPL;
875 }
876
GetInfoFlags(DWORD * pdwFlags)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 */
GetInfoTip(DWORD dwFlags,WCHAR ** ppwszTip)889 HRESULT WINAPI CNetConUiObject::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
890 {
891 *ppwszTip = NULL;
892 return S_OK;
893 }
894