c7630ee73be4c65ab93c529b8a01aa53d0a83b32
[reactos.git] / reactos / dll / win32 / netshell / shfldr_netconnect.cpp
1 /*
2 * Network Connections Shell Folder
3 *
4 * Copyright 2008 Johannes Anderwald <johannes.anderwald@reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "precomp.h"
22
23 #define MAX_PROPERTY_SHEET_PAGE (10)
24
25 /***********************************************************************
26 * IShellFolder implementation
27 */
28
29 class CNetworkConnections final :
30 public IShellFolder2,
31 public IPersistFolder2,
32 public IShellExecuteHookW
33 {
34 public:
35 CNetworkConnections();
36
37 /* IUnknown */
38 virtual HRESULT WINAPI QueryInterface(REFIID riid, LPVOID *ppvOut);
39 virtual ULONG WINAPI AddRef();
40 virtual ULONG WINAPI Release();
41
42 // IShellFolder
43 virtual HRESULT WINAPI ParseDisplayName (HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, LPITEMIDLIST *ppidl, DWORD *pdwAttributes);
44 virtual HRESULT WINAPI EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList);
45 virtual HRESULT WINAPI BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut);
46 virtual HRESULT WINAPI BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut);
47 virtual HRESULT WINAPI CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
48 virtual HRESULT WINAPI CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut);
49 virtual HRESULT WINAPI GetAttributesOf (UINT cidl, LPCITEMIDLIST *apidl, DWORD *rgfInOut);
50 virtual HRESULT WINAPI GetUIObjectOf(HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut);
51 virtual HRESULT WINAPI GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet);
52 virtual HRESULT WINAPI SetNameOf(HWND hwndOwner, LPCITEMIDLIST pidl, LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST *pPidlOut);
53
54 /* ShellFolder2 */
55 virtual HRESULT WINAPI GetDefaultSearchGUID(GUID *pguid);
56 virtual HRESULT WINAPI EnumSearches(IEnumExtraSearch **ppenum);
57 virtual HRESULT WINAPI GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay);
58 virtual HRESULT WINAPI GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags);
59 virtual HRESULT WINAPI GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv);
60 virtual HRESULT WINAPI GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd);
61 virtual HRESULT WINAPI MapColumnToSCID(UINT column, SHCOLUMNID *pscid);
62
63 // IPersistFolder2
64 virtual HRESULT WINAPI GetClassID(CLSID *lpClassId);
65 virtual HRESULT WINAPI Initialize(LPCITEMIDLIST pidl);
66 virtual HRESULT WINAPI GetCurFolder(LPITEMIDLIST *pidl);
67
68 // IShellExecuteHookW
69 virtual HRESULT WINAPI Execute(LPSHELLEXECUTEINFOW pei);
70
71 private:
72 LONG ref;
73 /* both paths are parsible from the desktop */
74 LPITEMIDLIST pidlRoot; /* absolute pidl */
75 LPITEMIDLIST pidl; /* enumerated pidl */
76 IOleCommandTarget * lpOleCmd;
77 };
78
79 class CNetConUiObject final :
80 public IContextMenu3,
81 public IObjectWithSite,
82 public IQueryInfo,
83 public IExtractIconW
84 {
85 public:
86 CNetConUiObject(LPCITEMIDLIST apidl, IOleCommandTarget *lpOleCmd);
87
88 // IUnknown
89 virtual HRESULT WINAPI QueryInterface(REFIID riid, LPVOID *ppvOut);
90 virtual ULONG WINAPI AddRef();
91 virtual ULONG WINAPI Release();
92
93 // IContextMenu3
94 virtual HRESULT WINAPI QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
95 virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpici);
96 virtual HRESULT WINAPI GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax);
97 virtual HRESULT WINAPI HandleMenuMsg( UINT uMsg, WPARAM wParam, LPARAM lParam);
98 virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
99
100 // IObjectWithSite
101 virtual HRESULT WINAPI SetSite(IUnknown *punk);
102 virtual HRESULT WINAPI GetSite(REFIID iid, void **ppvSite);
103
104 // IQueryInfo
105 virtual HRESULT WINAPI GetInfoFlags(DWORD *pdwFlags);
106 virtual HRESULT WINAPI GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip);
107
108 // IExtractIconW
109 virtual HRESULT STDMETHODCALLTYPE GetIconLocation(UINT uFlags, LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags);
110 virtual HRESULT STDMETHODCALLTYPE Extract(LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
111
112 private:
113 LONG ref;
114 LPCITEMIDLIST apidl;
115 IUnknown *pUnknown;
116 IOleCommandTarget * lpOleCmd;
117 };
118
119 static const shvheader NetConnectSFHeader[] = {
120 {IDS_SHV_COLUMN_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 20},
121 {IDS_SHV_COLUMN_TYPE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 8},
122 {IDS_SHV_COLUMN_STATE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
123 {IDS_SHV_COLUMN_DEVNAME, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
124 {IDS_SHV_COLUMN_PHONE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
125 {IDS_SHV_COLUMN_OWNER, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
126 };
127
128 #define NETCONNECTSHELLVIEWCOLUMNS 6
129
130 #define COLUMN_NAME 0
131 #define COLUMN_TYPE 1
132 #define COLUMN_STATUS 2
133 #define COLUMN_DEVNAME 3
134 #define COLUMN_PHONE 4
135 #define COLUMN_OWNER 5
136
137 HRESULT ShowNetConnectionStatus(IOleCommandTarget * lpOleCmd, INetConnection * pNetConnect, HWND hwnd);
138
139 CNetworkConnections::CNetworkConnections()
140 {
141 ref = 0;
142 HRESULT hr = CoCreateInstance(CLSID_LanConnectStatusUI, NULL, CLSCTX_INPROC_SERVER, IID_IOleCommandTarget, (LPVOID*)&lpOleCmd);
143 if (FAILED(hr))
144 {
145 ERR("CoCreateInstance failed\n");
146 lpOleCmd = NULL;
147 }
148 else
149 {
150 hr = lpOleCmd->Exec(&CGID_ShellServiceObject, 2, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
151 if (FAILED(hr))
152 ERR("Exec CGID_ShellServiceObject failed\n");
153 }
154
155 pidlRoot = _ILCreateNetConnect(); /* my qualified pidl */
156 }
157
158 /**************************************************************************
159 * ISF_NetConnect_fnQueryInterface
160 *
161 * NOTE
162 * supports not IPersist/IPersistFolder
163 */
164 HRESULT WINAPI CNetworkConnections::QueryInterface(REFIID riid, LPVOID *ppvObj)
165 {
166 *ppvObj = NULL;
167
168 if (IsEqualIID(riid, IID_IUnknown) ||
169 IsEqualIID(riid, IID_IShellFolder) ||
170 IsEqualIID(riid, IID_IShellFolder2))
171 {
172 *ppvObj = (IShellFolder2*)this;
173 }
174 else if (IsEqualIID (riid, IID_IPersistFolder) ||
175 IsEqualIID (riid, IID_IPersistFolder2))
176 {
177 *ppvObj = (IPersistFolder2*)this;
178 }
179 else if (IsEqualIID(riid, IID_IShellExecuteHookW))
180 {
181 *ppvObj = (IShellExecuteHookW*)this;
182 }
183 #if 0
184 else if (IsEqualIID(riid, IID_IPersistIDList))
185 {
186 //*ppvObj = (IPersistIDList*)this;
187 }
188 #endif
189 if (*ppvObj)
190 {
191 AddRef();
192 return S_OK;
193 }
194
195 /* TODO:
196 * IID_IPersistFreeThreadedObject
197 * IID_IBrowserFrameOptions
198 * IID_IShellIconOverlay
199 * IID_IPersistIDList
200 * IID_IPersist
201 */
202
203 return E_NOINTERFACE;
204 }
205
206 ULONG WINAPI CNetworkConnections::AddRef()
207 {
208 ULONG refCount = InterlockedIncrement(&ref);
209
210 return refCount;
211 }
212
213 ULONG WINAPI CNetworkConnections::Release()
214 {
215 ULONG refCount = InterlockedDecrement(&ref);
216
217 if (!refCount)
218 {
219 SHFree(pidlRoot);
220 delete this;
221 }
222 return refCount;
223 }
224
225 /**************************************************************************
226 * ISF_NetConnect_fnParseDisplayName
227 */
228 HRESULT WINAPI CNetworkConnections::ParseDisplayName (
229 HWND hwndOwner, LPBC pbcReserved, LPOLESTR lpszDisplayName,
230 DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
231 {
232 HRESULT hr = E_UNEXPECTED;
233
234 *ppidl = 0;
235 if (pchEaten)
236 *pchEaten = 0; /* strange but like the original */
237
238 return hr;
239 }
240
241 /**************************************************************************
242 * CreateNetConnectEnumListss()
243 */
244 static BOOL CreateNetConnectEnumList(CEnumIDList *list, DWORD dwFlags)
245 {
246 HRESULT hr;
247 INetConnectionManager *pNetConMan;
248 IEnumNetConnection *pEnumCon;
249 INetConnection *INetCon;
250 ULONG Count;
251 LPITEMIDLIST pidl;
252
253 /* get an instance to of IConnectionManager */
254 hr = INetConnectionManager_Constructor(NULL, IID_INetConnectionManager, (LPVOID*)&pNetConMan);
255 if (FAILED(hr))
256 return FALSE;
257
258 hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon);
259 if (FAILED(hr))
260 {
261 pNetConMan->Release();
262 return FALSE;
263 }
264
265 do
266 {
267 hr = pEnumCon->Next(1, &INetCon, &Count);
268 if (hr == S_OK)
269 {
270 pidl = ILCreateNetConnectItem(INetCon);
271 if (pidl)
272 {
273 list->AddToEnumList(pidl);
274 }
275 }
276 else
277 {
278 break;
279 }
280 }while(TRUE);
281
282 pEnumCon->Release();
283 pNetConMan->Release();
284
285 return TRUE;
286 }
287
288 /**************************************************************************
289 * ISF_NetConnect_fnEnumObjects
290 */
291 HRESULT WINAPI CNetworkConnections::EnumObjects(
292 HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
293 {
294 CEnumIDList *pList = new CEnumIDList;
295 *ppEnumIDList = (LPENUMIDLIST)pList;
296 if (!pList)
297 return E_OUTOFMEMORY;
298
299 pList->AddRef();
300 CreateNetConnectEnumList(pList, dwFlags);
301 return S_OK;
302 }
303
304 /**************************************************************************
305 * ISF_NetConnect_fnBindToObject
306 */
307 HRESULT WINAPI CNetworkConnections::BindToObject (
308 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
309 {
310 return E_NOTIMPL;
311 }
312
313 /**************************************************************************
314 * ISF_NetConnect_fnBindToStorage
315 */
316 HRESULT WINAPI CNetworkConnections::BindToStorage(
317 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
318 {
319 *ppvOut = NULL;
320 return E_NOTIMPL;
321 }
322
323 /**************************************************************************
324 * ISF_NetConnect_fnCompareIDs
325 */
326
327 HRESULT WINAPI CNetworkConnections::CompareIDs(
328 LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
329 {
330 //IGenericSFImpl *This = (IGenericSFImpl *)iface;
331
332
333
334 return E_NOTIMPL;
335 }
336
337 /**************************************************************************
338 * ISF_NetConnect_fnCreateViewObject
339 */
340 HRESULT WINAPI CNetworkConnections::CreateViewObject(
341 HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
342 {
343 CSFV cvf;
344 HRESULT hr = E_NOINTERFACE;
345
346 if (!ppvOut)
347 return hr;
348
349 *ppvOut = NULL;
350
351 if (IsEqualIID(riid, IID_IShellView))
352 {
353 ZeroMemory(&cvf, sizeof(cvf));
354 cvf.cbSize = sizeof(cvf);
355 cvf.pshf = (IShellFolder*)this;
356
357 IShellView* pShellView;
358 hr = SHCreateShellFolderViewEx(&cvf, &pShellView);
359 if (SUCCEEDED(hr))
360 {
361 hr = pShellView->QueryInterface(riid, ppvOut);
362 pShellView->Release();
363 }
364 }
365
366 return hr;
367 }
368
369 /**************************************************************************
370 * ISF_NetConnect_fnGetAttributesOf
371 */
372 HRESULT WINAPI CNetworkConnections::GetAttributesOf(
373 UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
374 {
375 //IGenericSFImpl *This = (IGenericSFImpl *)iface;
376 HRESULT hr = S_OK;
377 static const DWORD dwNetConnectAttributes = SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
378 SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
379
380 static const DWORD dwNetConnectItemAttributes = SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
381 SFGAO_FILESYSANCESTOR | SFGAO_CANRENAME;
382
383 if (!rgfInOut)
384 return E_INVALIDARG;
385
386 if (cidl && !apidl)
387 return E_INVALIDARG;
388
389 if (*rgfInOut == 0)
390 *rgfInOut = ~0;
391
392 if(cidl == 0)
393 *rgfInOut = dwNetConnectAttributes;
394 else
395 *rgfInOut = dwNetConnectItemAttributes;
396
397 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
398 *rgfInOut &= ~SFGAO_VALIDATE;
399
400 return hr;
401 }
402
403 /**************************************************************************
404 * ISF_NetConnect_fnGetUIObjectOf
405 *
406 * PARAMETERS
407 * hwndOwner [in] Parent window for any output
408 * cidl [in] array size
409 * apidl [in] simple pidl array
410 * riid [in] Requested Interface
411 * prgfInOut [ ] reserved
412 * ppvObject [out] Resulting Interface
413 *
414 */
415
416 HRESULT IContextMenuImpl_Constructor(REFIID riid, LPCITEMIDLIST apidl, LPVOID * ppvOut, IOleCommandTarget * lpOleCmd)
417 {
418 CNetConUiObject *pMenu = new CNetConUiObject(apidl, lpOleCmd);
419 if (!pMenu)
420 return E_OUTOFMEMORY;
421
422 pMenu->AddRef();
423 HRESULT hr = pMenu->QueryInterface(riid, ppvOut);
424 pMenu->Release();
425 return hr;
426 }
427
428 HRESULT WINAPI CNetworkConnections::GetUIObjectOf(
429 HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid,
430 UINT * prgfInOut, LPVOID * ppvOut)
431 {
432 IUnknown *pObj = NULL;
433 HRESULT hr = E_INVALIDARG;
434
435 if (!ppvOut)
436 return hr;
437
438 *ppvOut = NULL;
439
440 if ((IsEqualIID (riid, IID_IContextMenu) || IsEqualIID (riid, IID_IContextMenu2) || IsEqualIID(riid, IID_IContextMenu3) ||
441 IsEqualIID(riid, IID_IQueryInfo) || IsEqualIID(riid, IID_IExtractIconW)) && cidl >= 1)
442 {
443 return IContextMenuImpl_Constructor(riid, apidl[0], ppvOut, lpOleCmd);
444 }
445 else
446 hr = E_NOINTERFACE;
447
448 *ppvOut = pObj;
449 return hr;
450 }
451
452 /**************************************************************************
453 * ISF_NetConnect_fnGetDisplayNameOf
454 *
455 */
456 HRESULT WINAPI CNetworkConnections::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
457 {
458 LPWSTR pszName;
459 HRESULT hr = E_FAIL;
460 NETCON_PROPERTIES * pProperties;
461 VALUEStruct * val;
462
463 if (!strRet)
464 return E_INVALIDARG;
465
466 pszName = (WCHAR*)CoTaskMemAlloc(MAX_PATH * sizeof(WCHAR));
467 if (!pszName)
468 return E_OUTOFMEMORY;
469
470 if (_ILIsNetConnect(pidl))
471 {
472 if (LoadStringW(netshell_hInstance, IDS_NETWORKCONNECTION, pszName, MAX_PATH))
473 {
474 pszName[MAX_PATH-1] = L'\0';
475 hr = S_OK;
476 }
477 }
478 else
479 {
480 val = _ILGetValueStruct(pidl);
481 if (val)
482 {
483 if (val->pItem->GetProperties(&pProperties) == S_OK)
484 {
485 if (pProperties->pszwName)
486 {
487 wcscpy(pszName, pProperties->pszwName);
488 hr = S_OK;
489 }
490 NcFreeNetconProperties(pProperties);
491 }
492 }
493
494 }
495
496 if (SUCCEEDED(hr))
497 {
498 strRet->uType = STRRET_WSTR;
499 strRet->pOleStr = pszName;
500 }
501 else
502 {
503 CoTaskMemFree(pszName);
504 }
505
506 return hr;
507 }
508
509 /**************************************************************************
510 * ISF_NetConnect_fnSetNameOf
511 * Changes the name of a file object or subfolder, possibly changing its item
512 * identifier in the process.
513 *
514 * PARAMETERS
515 * hwndOwner [in] Owner window for output
516 * pidl [in] simple pidl of item to change
517 * lpszName [in] the items new display name
518 * dwFlags [in] SHGNO formatting flags
519 * ppidlOut [out] simple pidl returned
520 */
521 HRESULT WINAPI CNetworkConnections::SetNameOf (
522 HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */
523 LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
524 {
525 return E_NOTIMPL;
526 }
527
528 HRESULT WINAPI CNetworkConnections::GetDefaultSearchGUID(GUID * pguid)
529 {
530 return E_NOTIMPL;
531 }
532
533 HRESULT WINAPI CNetworkConnections::EnumSearches(IEnumExtraSearch ** ppenum)
534 {
535 return E_NOTIMPL;
536 }
537
538 HRESULT WINAPI CNetworkConnections::GetDefaultColumn(DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
539 {
540 if (pSort)
541 *pSort = 0;
542 if (pDisplay)
543 *pDisplay = 0;
544
545 return S_OK;
546 }
547
548 HRESULT WINAPI CNetworkConnections::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags)
549 {
550 if (!pcsFlags || iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
551 return E_INVALIDARG;
552 *pcsFlags = NetConnectSFHeader[iColumn].pcsFlags;
553 return S_OK;
554 }
555
556 HRESULT WINAPI CNetworkConnections::GetDetailsEx(
557 LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
558 {
559 return E_NOTIMPL;
560 }
561
562 HRESULT WINAPI CNetworkConnections::GetDetailsOf(
563 LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
564 {
565 WCHAR buffer[MAX_PATH] = {0};
566 HRESULT hr = E_FAIL;
567 VALUEStruct * val;
568 NETCON_PROPERTIES * pProperties;
569
570 if (iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
571 return E_FAIL;
572
573 psd->fmt = NetConnectSFHeader[iColumn].fmt;
574 psd->cxChar = NetConnectSFHeader[iColumn].cxChar;
575 if (pidl == NULL)
576 {
577 psd->str.uType = STRRET_WSTR;
578 if (LoadStringW(netshell_hInstance, NetConnectSFHeader[iColumn].colnameid, buffer, MAX_PATH))
579 hr = SHStrDupW(buffer, &psd->str.pOleStr);
580
581 return hr;
582 }
583
584 if (iColumn == COLUMN_NAME)
585 {
586 psd->str.uType = STRRET_WSTR;
587 return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
588 }
589
590 val = _ILGetValueStruct(pidl);
591 if (!val)
592 return E_FAIL;
593
594 if (!val->pItem)
595 return E_FAIL;
596
597 if (val->pItem->GetProperties(&pProperties) != S_OK)
598 return E_FAIL;
599
600
601 switch(iColumn)
602 {
603 case COLUMN_TYPE:
604 if (pProperties->MediaType == NCM_LAN || pProperties->MediaType == NCM_SHAREDACCESSHOST_RAS)
605 {
606 if (LoadStringW(netshell_hInstance, IDS_TYPE_ETHERNET, buffer, MAX_PATH))
607 {
608 psd->str.uType = STRRET_WSTR;
609 hr = SHStrDupW(buffer, &psd->str.pOleStr);
610 }
611 }
612 break;
613 case COLUMN_STATUS:
614 buffer[0] = L'\0';
615 if (pProperties->Status == NCS_HARDWARE_DISABLED)
616 LoadStringW(netshell_hInstance, IDS_STATUS_NON_OPERATIONAL, buffer, MAX_PATH);
617 else if (pProperties->Status == NCS_DISCONNECTED)
618 LoadStringW(netshell_hInstance, IDS_STATUS_UNREACHABLE, buffer, MAX_PATH);
619 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED)
620 LoadStringW(netshell_hInstance, IDS_STATUS_DISCONNECTED, buffer, MAX_PATH);
621 else if (pProperties->Status == NCS_CONNECTING)
622 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTING, buffer, MAX_PATH);
623 else if (pProperties->Status == NCS_CONNECTED)
624 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTED, buffer, MAX_PATH);
625
626 if (buffer[0])
627 {
628 buffer[MAX_PATH-1] = L'\0';
629 psd->str.uType = STRRET_WSTR;
630 hr = SHStrDupW(buffer, &psd->str.pOleStr);
631 }
632 break;
633 case COLUMN_DEVNAME:
634 if (pProperties->pszwDeviceName)
635 {
636 wcscpy(buffer, pProperties->pszwDeviceName);
637 buffer[MAX_PATH-1] = L'\0';
638 psd->str.uType = STRRET_WSTR;
639 hr = SHStrDupW(buffer, &psd->str.pOleStr);
640 }
641 else
642 {
643 psd->str.cStr[0] = '\0';
644 psd->str.uType = STRRET_CSTR;
645 }
646 break;
647 case COLUMN_PHONE:
648 case COLUMN_OWNER:
649 psd->str.cStr[0] = '\0';
650 psd->str.uType = STRRET_CSTR;
651 break;
652 }
653
654 NcFreeNetconProperties(pProperties);
655 return hr;
656 }
657
658 HRESULT WINAPI CNetworkConnections::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
659 {
660 return E_NOTIMPL;
661 }
662
663 //IObjectWithSite
664 //IInternetSecurityManager
665
666 /**************************************************************************
667 * IContextMenu2 Implementation
668 */
669
670 CNetConUiObject::CNetConUiObject(LPCITEMIDLIST apidl, IOleCommandTarget *lpOleCmd)
671 {
672 this->apidl = apidl;
673 pUnknown = NULL;
674 this->lpOleCmd = lpOleCmd;
675 ref = 0;
676 }
677
678 /************************************************************************
679 * ISF_NetConnect_IContextMenu_QueryInterface
680 */
681 HRESULT WINAPI CNetConUiObject::QueryInterface(REFIID iid, LPVOID *ppvObject)
682 {
683 *ppvObject = NULL;
684
685 if (IsEqualIID(iid, IID_IContextMenu) || IsEqualIID(iid, IID_IContextMenu2) || IsEqualIID(iid, IID_IContextMenu3))
686 *ppvObject = (IContextMenu3*)this;
687 else if (IsEqualIID(iid, IID_IObjectWithSite))
688 *ppvObject = (IObjectWithSite*)this;
689 else if (IsEqualIID(iid, IID_IQueryInfo))
690 *ppvObject = (IQueryInfo*)this;
691 else if(IsEqualIID(iid, IID_IExtractIconW))
692 *ppvObject = (IExtractIconW*)this;
693
694 if (*ppvObject)
695 {
696 InterlockedIncrement(&ref);
697 return S_OK;
698 }
699
700 //LPOLESTR pStr;
701 //StringFromCLSID(iid, &pStr);
702 //MessageBoxW(NULL, L"ISF_NetConnect_IContextMenu2_QueryInterface unhandled", pStr, MB_OK);
703 return E_NOINTERFACE;
704 }
705
706 /************************************************************************
707 * ISF_NetConnect_IContextMenu_AddRef
708 */
709 ULONG WINAPI CNetConUiObject::AddRef()
710 {
711 ULONG refCount;
712
713 refCount = InterlockedIncrement(&ref);
714
715 return refCount;
716 }
717
718 /************************************************************************
719 * ISF_NetConnect_IContextMenu_Release
720 */
721 ULONG WINAPI CNetConUiObject::Release()
722 {
723 ULONG refCount;
724
725 refCount = InterlockedDecrement(&ref);
726 if (!refCount)
727 delete this;
728
729 return refCount;
730 }
731
732 void WINAPI _InsertMenuItemW (
733 HMENU hmenu,
734 UINT indexMenu,
735 BOOL fByPosition,
736 UINT wID,
737 UINT fType,
738 LPCWSTR dwTypeData,
739 UINT fState)
740 {
741 MENUITEMINFOW mii;
742 WCHAR szText[100];
743
744 ZeroMemory(&mii, sizeof(mii));
745 mii.cbSize = sizeof(mii);
746 if (fType == MFT_SEPARATOR)
747 {
748 mii.fMask = MIIM_ID | MIIM_TYPE;
749 }
750 else if (fType == MFT_STRING)
751 {
752 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
753 if ((ULONG_PTR)HIWORD((ULONG_PTR)dwTypeData) == 0)
754 {
755 if (LoadStringW(netshell_hInstance, LOWORD((ULONG_PTR)dwTypeData), szText, sizeof(szText)/sizeof(WCHAR)))
756 {
757 szText[(sizeof(szText)/sizeof(WCHAR))-1] = 0;
758 mii.dwTypeData = szText;
759 }
760 else
761 {
762 return;
763 }
764 }
765 else
766 {
767 mii.dwTypeData = (LPWSTR) dwTypeData;
768 }
769 mii.fState = fState;
770 }
771
772 mii.wID = wID;
773 mii.fType = fType;
774 InsertMenuItemW( hmenu, indexMenu, fByPosition, &mii);
775 }
776
777 /**************************************************************************
778 * ISF_NetConnect_IContextMenu_QueryContextMenu()
779 */
780 HRESULT WINAPI CNetConUiObject::QueryContextMenu(
781 HMENU hMenu,
782 UINT indexMenu,
783 UINT idCmdFirst,
784 UINT idCmdLast,
785 UINT uFlags)
786 {
787 VALUEStruct * val;
788 NETCON_PROPERTIES * pProperties;
789
790 val = _ILGetValueStruct(apidl);
791 if (!val)
792 return E_FAIL;
793
794 if (val->pItem->GetProperties(&pProperties) != S_OK)
795 return E_FAIL;
796
797 if (pProperties->Status == NCS_HARDWARE_DISABLED)
798 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_ACTIVATE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_ACTIVATE), MFS_DEFAULT);
799 else
800 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_DEACTIVATE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DEACTIVATE), MFS_ENABLED);
801
802 if (pProperties->Status == NCS_HARDWARE_DISABLED || pProperties->Status == NCS_MEDIA_DISCONNECTED || pProperties->Status == NCS_DISCONNECTED)
803 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_STATUS, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_GRAYED);
804 else if (pProperties->Status == NCS_CONNECTED)
805 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_STATUS, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_DEFAULT);
806 else
807 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_STATUS, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_ENABLED);
808
809 if (pProperties->Status == NCS_HARDWARE_DISABLED || pProperties->Status == NCS_MEDIA_DISCONNECTED)
810 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_REPAIR, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_GRAYED);
811 else
812 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_REPAIR, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_ENABLED);
813
814 _InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
815 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_CREATELINK, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_CREATELINK), MFS_ENABLED);
816
817 if (pProperties->dwCharacter & NCCF_ALLOW_REMOVAL)
818 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_ENABLED);
819 else
820 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_GRAYED);
821
822 if (pProperties->dwCharacter & NCCF_ALLOW_RENAME)
823 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_ENABLED);
824 else
825 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_GRAYED);
826
827 _InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
828 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_PROPERTIES), MFS_ENABLED);
829 NcFreeNetconProperties(pProperties);
830 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 9);
831 }
832
833 BOOL
834 CALLBACK
835 PropSheetExCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
836 {
837 PROPSHEETHEADERW *pinfo = (PROPSHEETHEADERW *)lParam;
838
839 if (pinfo->nPages < MAX_PROPERTY_SHEET_PAGE)
840 {
841 pinfo->phpage[pinfo->nPages++] = hPage;
842 return TRUE;
843 }
844 return FALSE;
845 }
846
847 HRESULT
848 ShowNetConnectionStatus(
849 IOleCommandTarget *lpOleCmd,
850 INetConnection *pNetConnect,
851 HWND hwnd)
852 {
853 NETCON_PROPERTIES *pProperties;
854 HRESULT hr;
855
856 if (!lpOleCmd)
857 return E_FAIL;
858
859 if (pNetConnect->GetProperties(&pProperties) != S_OK)
860 return E_FAIL;
861
862 hr = lpOleCmd->Exec(&pProperties->guidId, 2, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
863
864 NcFreeNetconProperties(pProperties);
865 return hr;
866 }
867
868 HRESULT
869 ShowNetConnectionProperties(
870 INetConnection *pNetConnect,
871 HWND hwnd)
872 {
873 HRESULT hr;
874 CLSID ClassID;
875 PROPSHEETHEADERW pinfo;
876 HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
877 INetConnectionPropertyUi * pNCP;
878 NETCON_PROPERTIES * pProperties;
879
880 if (pNetConnect->GetProperties(&pProperties) != S_OK)
881 return E_FAIL;
882
883 hr = pNetConnect->GetUiObjectClassId(&ClassID);
884 if (FAILED(hr))
885 {
886 NcFreeNetconProperties(pProperties);
887 return hr;
888 }
889
890 hr = CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER, IID_INetConnectionPropertyUi, (LPVOID*)&pNCP);
891 if (FAILED(hr))
892 {
893 NcFreeNetconProperties(pProperties);
894 return hr;
895 }
896
897 hr = pNCP->SetConnection(pNetConnect);
898 if (SUCCEEDED(hr))
899 {
900 ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
901 ZeroMemory(hppages, sizeof(hppages));
902 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
903 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW;
904 pinfo.phpage = hppages;
905 pinfo.hwndParent = hwnd;
906
907 pinfo.pszCaption = pProperties->pszwName;
908 hr = pNCP->AddPages(hwnd, PropSheetExCallback, (LPARAM)&pinfo);
909 if (SUCCEEDED(hr))
910 {
911 if(PropertySheetW(&pinfo) < 0)
912 hr = E_FAIL;
913 }
914 }
915 pNCP->Release();
916 NcFreeNetconProperties(pProperties);
917 return hr;
918 }
919
920
921 /**************************************************************************
922 * ISF_NetConnect_IContextMenu_InvokeCommand()
923 */
924 HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
925 {
926 VALUEStruct * val;
927
928 val = _ILGetValueStruct(apidl);
929 if (!val)
930 return E_FAIL;
931
932 if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_NET_STATUS) ||
933 lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_NET_STATUS-1)) //HACK for Windows XP
934 {
935 return ShowNetConnectionStatus(lpOleCmd, val->pItem, lpcmi->hwnd);
936 }
937 else if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_NET_PROPERTIES) ||
938 lpcmi->lpVerb == MAKEINTRESOURCEA(10099)) //HACK for Windows XP
939 {
940 /* FIXME perform version checks */
941 return ShowNetConnectionProperties(val->pItem, lpcmi->hwnd);
942 }
943
944 return S_OK;
945 }
946
947 /**************************************************************************
948 * ISF_NetConnect_IContextMenu_GetCommandString()
949 *
950 */
951 HRESULT WINAPI CNetConUiObject::GetCommandString(
952 UINT_PTR idCommand,
953 UINT uFlags,
954 UINT* lpReserved,
955 LPSTR lpszName,
956 UINT uMaxNameLen)
957 {
958 return E_FAIL;
959 }
960
961 /**************************************************************************
962 * ISF_NetConnect_IContextMenu_HandleMenuMsg()
963 */
964 HRESULT WINAPI CNetConUiObject::HandleMenuMsg(
965 UINT uMsg,
966 WPARAM wParam,
967 LPARAM lParam)
968 {
969 return E_NOTIMPL;
970 }
971
972 HRESULT WINAPI CNetConUiObject::HandleMenuMsg2(
973 UINT uMsg,
974 WPARAM wParam,
975 LPARAM lParam,
976 LRESULT *plResult)
977 {
978 return E_NOTIMPL;
979 }
980
981 HRESULT WINAPI CNetConUiObject::GetSite(REFIID riid, PVOID *ppvSite)
982 {
983 HRESULT hr;
984 IUnknown *pUnknown;
985
986 if (!this->pUnknown)
987 {
988 *ppvSite = NULL;
989 return E_FAIL;
990 }
991
992 hr = this->pUnknown->QueryInterface(riid, (LPVOID*)&pUnknown);
993 if (SUCCEEDED(hr))
994 {
995 pUnknown->AddRef();
996 *ppvSite = pUnknown;
997 return S_OK;
998 }
999
1000 *ppvSite = NULL;
1001 return hr;
1002 }
1003
1004 HRESULT WINAPI CNetConUiObject::SetSite(IUnknown *pUnkSite)
1005 {
1006 if(!pUnkSite)
1007 {
1008 if (this->pUnknown)
1009 {
1010 this->pUnknown->Release();
1011 this->pUnknown = NULL;
1012 }
1013 }
1014 else
1015 {
1016 pUnkSite->AddRef();
1017 if (this->pUnknown)
1018 this->pUnknown->Release();
1019 this->pUnknown = pUnkSite;
1020 }
1021
1022 return S_OK;
1023 }
1024
1025 /************************************************************************
1026 * ISF_NetConnect_IExtractIcon_GetIconLocation
1027 */
1028 HRESULT WINAPI CNetConUiObject::GetIconLocation(
1029 UINT uFlags,
1030 LPWSTR szIconFile,
1031 UINT cchMax,
1032 int *piIndex,
1033 UINT *pwFlags)
1034 {
1035 VALUEStruct *val;
1036 NETCON_PROPERTIES *pProperties;
1037
1038 *pwFlags = 0;
1039 if (!GetModuleFileNameW(netshell_hInstance, szIconFile, cchMax))
1040 {
1041 ERR("GetModuleFileNameW failed\n");
1042 return E_FAIL;
1043 }
1044
1045 val = _ILGetValueStruct(apidl);
1046 if (!val)
1047 {
1048 ERR("_ILGetValueStruct failed\n");
1049 return E_FAIL;
1050 }
1051
1052 if (val->pItem->GetProperties(&pProperties) != NOERROR)
1053 {
1054 ERR("INetConnection_GetProperties failed\n");
1055 return E_FAIL;
1056 }
1057
1058 if (pProperties->Status == NCS_CONNECTED || pProperties->Status == NCS_CONNECTING)
1059 *piIndex = -IDI_NET_IDLE;
1060 else
1061 *piIndex = -IDI_NET_OFF;
1062
1063 NcFreeNetconProperties(pProperties);
1064
1065 return NOERROR;
1066 }
1067
1068 /************************************************************************
1069 * ISF_NetConnect_IExtractIcon_Extract
1070 */
1071 HRESULT WINAPI CNetConUiObject::Extract(
1072 LPCWSTR pszFile,
1073 UINT nIconIndex,
1074 HICON *phiconLarge,
1075 HICON *phiconSmall,
1076 UINT nIconSize)
1077 {
1078 //IContextMenuImpl * This = impl_from_IExtractIcon(iface);
1079 if (nIconIndex == IDI_NET_IDLE)
1080 {
1081 *phiconLarge = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
1082 *phiconSmall = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1083 return NOERROR;
1084 }
1085 else if (nIconIndex == IDI_NET_OFF)
1086 {
1087 *phiconLarge = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
1088 *phiconSmall = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1089 return NOERROR;
1090 }
1091
1092 return S_FALSE;
1093 }
1094
1095 /************************************************************************
1096 * ISF_NetConnect_PersistFolder2_GetClassID
1097 */
1098 HRESULT WINAPI CNetworkConnections::GetClassID(CLSID *lpClassId)
1099 {
1100 if (!lpClassId)
1101 return E_POINTER;
1102
1103 *lpClassId = CLSID_NetworkConnections;
1104
1105 return S_OK;
1106 }
1107
1108 /************************************************************************
1109 * ISF_NetConnect_PersistFolder2_Initialize
1110 *
1111 * NOTES: it makes no sense to change the pidl
1112 */
1113 HRESULT WINAPI CNetworkConnections::Initialize(LPCITEMIDLIST pidl)
1114 {
1115 SHFree(pidlRoot);
1116 pidlRoot = ILClone(pidl);
1117
1118 return S_OK;
1119 }
1120
1121 /**************************************************************************
1122 * ISF_NetConnect_PersistFolder2_GetCurFolder
1123 */
1124 HRESULT WINAPI CNetworkConnections::GetCurFolder(LPITEMIDLIST *pidl)
1125 {
1126 if (!pidl)
1127 return E_POINTER;
1128
1129 *pidl = ILClone(pidlRoot);
1130
1131 return S_OK;
1132 }
1133
1134 /************************************************************************
1135 * ISF_NetConnect_ShellExecuteHookW_Execute
1136 */
1137 HRESULT WINAPI CNetworkConnections::Execute(LPSHELLEXECUTEINFOW pei)
1138 {
1139 VALUEStruct *val;
1140 NETCON_PROPERTIES * pProperties;
1141
1142 val = _ILGetValueStruct(ILFindLastID((ITEMIDLIST*)pei->lpIDList));
1143 if (!val)
1144 return E_FAIL;
1145
1146 if (val->pItem->GetProperties(&pProperties) != NOERROR)
1147 return E_FAIL;
1148
1149 if (pProperties->Status == NCS_CONNECTED)
1150 {
1151 NcFreeNetconProperties(pProperties);
1152 return ShowNetConnectionStatus(lpOleCmd, val->pItem, pei->hwnd);
1153 }
1154
1155 NcFreeNetconProperties(pProperties);
1156
1157 return S_OK;
1158 }
1159
1160 HRESULT WINAPI CNetConUiObject::GetInfoFlags(DWORD *pdwFlags)
1161 {
1162 *pdwFlags = 0;
1163
1164 return S_OK;
1165 }
1166
1167 /************************************************************************
1168 * ISF_NetConnect_PersistFolder2_Initialize
1169 *
1170 * NOTES: it makes no sense to change the pidl
1171 */
1172 HRESULT WINAPI CNetConUiObject::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
1173 {
1174 *ppwszTip = NULL;
1175 return S_OK;
1176 }
1177
1178 /**************************************************************************
1179 * ISF_NetConnect_Constructor
1180 */
1181 HRESULT WINAPI ISF_NetConnect_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv)
1182 {
1183 TRACE("ISF_NetConnect_Constructor\n");
1184
1185 if (!ppv)
1186 return E_POINTER;
1187 if (pUnkOuter)
1188 return CLASS_E_NOAGGREGATION;
1189
1190 CNetworkConnections *pnc = new CNetworkConnections;
1191 if (!pnc)
1192 return E_OUTOFMEMORY;
1193
1194 pnc->AddRef();
1195 HRESULT hr = pnc->QueryInterface(riid, ppv);
1196 pnc->Release();
1197
1198 return hr;
1199 }