Sync with trunk r63786.
[reactos.git] / 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 VALUEStruct * val;
526
527 val = _ILGetValueStruct(pidl);
528 if (!val)
529 return E_FAIL;
530
531 if (!val->pItem)
532 return E_FAIL;
533
534 return val->pItem->Rename(lpName);
535 }
536
537 HRESULT WINAPI CNetworkConnections::GetDefaultSearchGUID(GUID * pguid)
538 {
539 return E_NOTIMPL;
540 }
541
542 HRESULT WINAPI CNetworkConnections::EnumSearches(IEnumExtraSearch ** ppenum)
543 {
544 return E_NOTIMPL;
545 }
546
547 HRESULT WINAPI CNetworkConnections::GetDefaultColumn(DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
548 {
549 if (pSort)
550 *pSort = 0;
551 if (pDisplay)
552 *pDisplay = 0;
553
554 return S_OK;
555 }
556
557 HRESULT WINAPI CNetworkConnections::GetDefaultColumnState(UINT iColumn, DWORD * pcsFlags)
558 {
559 if (!pcsFlags || iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
560 return E_INVALIDARG;
561 *pcsFlags = NetConnectSFHeader[iColumn].pcsFlags;
562 return S_OK;
563 }
564
565 HRESULT WINAPI CNetworkConnections::GetDetailsEx(
566 LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
567 {
568 return E_NOTIMPL;
569 }
570
571 HRESULT WINAPI CNetworkConnections::GetDetailsOf(
572 LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
573 {
574 WCHAR buffer[MAX_PATH] = {0};
575 HRESULT hr = E_FAIL;
576 VALUEStruct * val;
577 NETCON_PROPERTIES * pProperties;
578
579 if (iColumn >= NETCONNECTSHELLVIEWCOLUMNS)
580 return E_FAIL;
581
582 psd->fmt = NetConnectSFHeader[iColumn].fmt;
583 psd->cxChar = NetConnectSFHeader[iColumn].cxChar;
584 if (pidl == NULL)
585 {
586 psd->str.uType = STRRET_WSTR;
587 if (LoadStringW(netshell_hInstance, NetConnectSFHeader[iColumn].colnameid, buffer, MAX_PATH))
588 hr = SHStrDupW(buffer, &psd->str.pOleStr);
589
590 return hr;
591 }
592
593 if (iColumn == COLUMN_NAME)
594 {
595 psd->str.uType = STRRET_WSTR;
596 return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
597 }
598
599 val = _ILGetValueStruct(pidl);
600 if (!val)
601 return E_FAIL;
602
603 if (!val->pItem)
604 return E_FAIL;
605
606 if (val->pItem->GetProperties(&pProperties) != S_OK)
607 return E_FAIL;
608
609
610 switch(iColumn)
611 {
612 case COLUMN_TYPE:
613 if (pProperties->MediaType == NCM_LAN || pProperties->MediaType == NCM_SHAREDACCESSHOST_RAS)
614 {
615 if (LoadStringW(netshell_hInstance, IDS_TYPE_ETHERNET, buffer, MAX_PATH))
616 {
617 psd->str.uType = STRRET_WSTR;
618 hr = SHStrDupW(buffer, &psd->str.pOleStr);
619 }
620 }
621 break;
622 case COLUMN_STATUS:
623 buffer[0] = L'\0';
624 if (pProperties->Status == NCS_HARDWARE_DISABLED)
625 LoadStringW(netshell_hInstance, IDS_STATUS_NON_OPERATIONAL, buffer, MAX_PATH);
626 else if (pProperties->Status == NCS_DISCONNECTED)
627 LoadStringW(netshell_hInstance, IDS_STATUS_UNREACHABLE, buffer, MAX_PATH);
628 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED)
629 LoadStringW(netshell_hInstance, IDS_STATUS_DISCONNECTED, buffer, MAX_PATH);
630 else if (pProperties->Status == NCS_CONNECTING)
631 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTING, buffer, MAX_PATH);
632 else if (pProperties->Status == NCS_CONNECTED)
633 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTED, buffer, MAX_PATH);
634
635 if (buffer[0])
636 {
637 buffer[MAX_PATH-1] = L'\0';
638 psd->str.uType = STRRET_WSTR;
639 hr = SHStrDupW(buffer, &psd->str.pOleStr);
640 }
641 break;
642 case COLUMN_DEVNAME:
643 if (pProperties->pszwDeviceName)
644 {
645 wcscpy(buffer, pProperties->pszwDeviceName);
646 buffer[MAX_PATH-1] = L'\0';
647 psd->str.uType = STRRET_WSTR;
648 hr = SHStrDupW(buffer, &psd->str.pOleStr);
649 }
650 else
651 {
652 psd->str.cStr[0] = '\0';
653 psd->str.uType = STRRET_CSTR;
654 }
655 break;
656 case COLUMN_PHONE:
657 case COLUMN_OWNER:
658 psd->str.cStr[0] = '\0';
659 psd->str.uType = STRRET_CSTR;
660 break;
661 }
662
663 NcFreeNetconProperties(pProperties);
664 return hr;
665 }
666
667 HRESULT WINAPI CNetworkConnections::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
668 {
669 return E_NOTIMPL;
670 }
671
672 //IObjectWithSite
673 //IInternetSecurityManager
674
675 /**************************************************************************
676 * IContextMenu2 Implementation
677 */
678
679 CNetConUiObject::CNetConUiObject(LPCITEMIDLIST apidl, IOleCommandTarget *lpOleCmd)
680 {
681 this->apidl = apidl;
682 pUnknown = NULL;
683 this->lpOleCmd = lpOleCmd;
684 ref = 0;
685 }
686
687 /************************************************************************
688 * ISF_NetConnect_IContextMenu_QueryInterface
689 */
690 HRESULT WINAPI CNetConUiObject::QueryInterface(REFIID iid, LPVOID *ppvObject)
691 {
692 *ppvObject = NULL;
693
694 if (IsEqualIID(iid, IID_IContextMenu) || IsEqualIID(iid, IID_IContextMenu2) || IsEqualIID(iid, IID_IContextMenu3))
695 *ppvObject = (IContextMenu3*)this;
696 else if (IsEqualIID(iid, IID_IObjectWithSite))
697 *ppvObject = (IObjectWithSite*)this;
698 else if (IsEqualIID(iid, IID_IQueryInfo))
699 *ppvObject = (IQueryInfo*)this;
700 else if(IsEqualIID(iid, IID_IExtractIconW))
701 *ppvObject = (IExtractIconW*)this;
702
703 if (*ppvObject)
704 {
705 InterlockedIncrement(&ref);
706 return S_OK;
707 }
708
709 //LPOLESTR pStr;
710 //StringFromCLSID(iid, &pStr);
711 //MessageBoxW(NULL, L"ISF_NetConnect_IContextMenu2_QueryInterface unhandled", pStr, MB_OK);
712 return E_NOINTERFACE;
713 }
714
715 /************************************************************************
716 * ISF_NetConnect_IContextMenu_AddRef
717 */
718 ULONG WINAPI CNetConUiObject::AddRef()
719 {
720 ULONG refCount;
721
722 refCount = InterlockedIncrement(&ref);
723
724 return refCount;
725 }
726
727 /************************************************************************
728 * ISF_NetConnect_IContextMenu_Release
729 */
730 ULONG WINAPI CNetConUiObject::Release()
731 {
732 ULONG refCount;
733
734 refCount = InterlockedDecrement(&ref);
735 if (!refCount)
736 delete this;
737
738 return refCount;
739 }
740
741 void WINAPI _InsertMenuItemW (
742 HMENU hmenu,
743 UINT indexMenu,
744 BOOL fByPosition,
745 UINT wID,
746 UINT fType,
747 LPCWSTR dwTypeData,
748 UINT fState)
749 {
750 MENUITEMINFOW mii;
751 WCHAR szText[100];
752
753 ZeroMemory(&mii, sizeof(mii));
754 mii.cbSize = sizeof(mii);
755 if (fType == MFT_SEPARATOR)
756 {
757 mii.fMask = MIIM_ID | MIIM_TYPE;
758 }
759 else if (fType == MFT_STRING)
760 {
761 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
762 if ((ULONG_PTR)HIWORD((ULONG_PTR)dwTypeData) == 0)
763 {
764 if (LoadStringW(netshell_hInstance, LOWORD((ULONG_PTR)dwTypeData), szText, sizeof(szText)/sizeof(WCHAR)))
765 {
766 szText[(sizeof(szText)/sizeof(WCHAR))-1] = 0;
767 mii.dwTypeData = szText;
768 }
769 else
770 {
771 return;
772 }
773 }
774 else
775 {
776 mii.dwTypeData = (LPWSTR) dwTypeData;
777 }
778 mii.fState = fState;
779 }
780
781 mii.wID = wID;
782 mii.fType = fType;
783 InsertMenuItemW( hmenu, indexMenu, fByPosition, &mii);
784 }
785
786 /**************************************************************************
787 * ISF_NetConnect_IContextMenu_QueryContextMenu()
788 */
789 HRESULT WINAPI CNetConUiObject::QueryContextMenu(
790 HMENU hMenu,
791 UINT indexMenu,
792 UINT idCmdFirst,
793 UINT idCmdLast,
794 UINT uFlags)
795 {
796 VALUEStruct * val;
797 NETCON_PROPERTIES * pProperties;
798
799 val = _ILGetValueStruct(apidl);
800 if (!val)
801 return E_FAIL;
802
803 if (val->pItem->GetProperties(&pProperties) != S_OK)
804 return E_FAIL;
805
806 if (pProperties->Status == NCS_HARDWARE_DISABLED)
807 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_ACTIVATE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_ACTIVATE), MFS_DEFAULT);
808 else
809 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_DEACTIVATE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DEACTIVATE), MFS_ENABLED);
810
811 if (pProperties->Status == NCS_HARDWARE_DISABLED || pProperties->Status == NCS_MEDIA_DISCONNECTED || pProperties->Status == NCS_DISCONNECTED)
812 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_STATUS, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_GRAYED);
813 else if (pProperties->Status == NCS_CONNECTED)
814 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_STATUS, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_DEFAULT);
815 else
816 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_STATUS, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_STATUS), MFS_ENABLED);
817
818 if (pProperties->Status == NCS_HARDWARE_DISABLED || pProperties->Status == NCS_MEDIA_DISCONNECTED)
819 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_REPAIR, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_GRAYED);
820 else
821 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_REPAIR, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_REPAIR), MFS_ENABLED);
822
823 _InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
824 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_CREATELINK, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_CREATELINK), MFS_ENABLED);
825
826 if (pProperties->dwCharacter & NCCF_ALLOW_REMOVAL)
827 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_ENABLED);
828 else
829 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_DELETE), MFS_GRAYED);
830
831 if (pProperties->dwCharacter & NCCF_ALLOW_RENAME)
832 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_ENABLED);
833 else
834 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_RENAME), MFS_GRAYED);
835
836 _InsertMenuItemW(hMenu, indexMenu++, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
837 _InsertMenuItemW(hMenu, indexMenu++, TRUE, IDS_NET_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_NET_PROPERTIES), MFS_ENABLED);
838 NcFreeNetconProperties(pProperties);
839 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 9);
840 }
841
842 BOOL
843 CALLBACK
844 PropSheetExCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
845 {
846 PROPSHEETHEADERW *pinfo = (PROPSHEETHEADERW *)lParam;
847
848 if (pinfo->nPages < MAX_PROPERTY_SHEET_PAGE)
849 {
850 pinfo->phpage[pinfo->nPages++] = hPage;
851 return TRUE;
852 }
853 return FALSE;
854 }
855
856 HRESULT
857 ShowNetConnectionStatus(
858 IOleCommandTarget *lpOleCmd,
859 INetConnection *pNetConnect,
860 HWND hwnd)
861 {
862 NETCON_PROPERTIES *pProperties;
863 HRESULT hr;
864
865 if (!lpOleCmd)
866 return E_FAIL;
867
868 if (pNetConnect->GetProperties(&pProperties) != S_OK)
869 return E_FAIL;
870
871 hr = lpOleCmd->Exec(&pProperties->guidId, 2, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
872
873 NcFreeNetconProperties(pProperties);
874 return hr;
875 }
876
877 HRESULT
878 ShowNetConnectionProperties(
879 INetConnection *pNetConnect,
880 HWND hwnd)
881 {
882 HRESULT hr;
883 CLSID ClassID;
884 PROPSHEETHEADERW pinfo;
885 HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
886 INetConnectionPropertyUi * pNCP;
887 NETCON_PROPERTIES * pProperties;
888
889 if (pNetConnect->GetProperties(&pProperties) != S_OK)
890 return E_FAIL;
891
892 hr = pNetConnect->GetUiObjectClassId(&ClassID);
893 if (FAILED(hr))
894 {
895 NcFreeNetconProperties(pProperties);
896 return hr;
897 }
898
899 hr = CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER, IID_INetConnectionPropertyUi, (LPVOID*)&pNCP);
900 if (FAILED(hr))
901 {
902 NcFreeNetconProperties(pProperties);
903 return hr;
904 }
905
906 hr = pNCP->SetConnection(pNetConnect);
907 if (SUCCEEDED(hr))
908 {
909 ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
910 ZeroMemory(hppages, sizeof(hppages));
911 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
912 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW;
913 pinfo.phpage = hppages;
914 pinfo.hwndParent = hwnd;
915
916 pinfo.pszCaption = pProperties->pszwName;
917 hr = pNCP->AddPages(hwnd, PropSheetExCallback, (LPARAM)&pinfo);
918 if (SUCCEEDED(hr))
919 {
920 if(PropertySheetW(&pinfo) < 0)
921 hr = E_FAIL;
922 }
923 }
924 pNCP->Release();
925 NcFreeNetconProperties(pProperties);
926 return hr;
927 }
928
929
930 /**************************************************************************
931 * ISF_NetConnect_IContextMenu_InvokeCommand()
932 */
933 HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
934 {
935 VALUEStruct * val;
936
937 val = _ILGetValueStruct(apidl);
938 if (!val)
939 return E_FAIL;
940
941 if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_NET_STATUS) ||
942 lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_NET_STATUS-1)) //HACK for Windows XP
943 {
944 return ShowNetConnectionStatus(lpOleCmd, val->pItem, lpcmi->hwnd);
945 }
946 else if (lpcmi->lpVerb == MAKEINTRESOURCEA(IDS_NET_PROPERTIES) ||
947 lpcmi->lpVerb == MAKEINTRESOURCEA(10099)) //HACK for Windows XP
948 {
949 /* FIXME perform version checks */
950 return ShowNetConnectionProperties(val->pItem, lpcmi->hwnd);
951 }
952
953 return S_OK;
954 }
955
956 /**************************************************************************
957 * ISF_NetConnect_IContextMenu_GetCommandString()
958 *
959 */
960 HRESULT WINAPI CNetConUiObject::GetCommandString(
961 UINT_PTR idCommand,
962 UINT uFlags,
963 UINT* lpReserved,
964 LPSTR lpszName,
965 UINT uMaxNameLen)
966 {
967 return E_FAIL;
968 }
969
970 /**************************************************************************
971 * ISF_NetConnect_IContextMenu_HandleMenuMsg()
972 */
973 HRESULT WINAPI CNetConUiObject::HandleMenuMsg(
974 UINT uMsg,
975 WPARAM wParam,
976 LPARAM lParam)
977 {
978 return E_NOTIMPL;
979 }
980
981 HRESULT WINAPI CNetConUiObject::HandleMenuMsg2(
982 UINT uMsg,
983 WPARAM wParam,
984 LPARAM lParam,
985 LRESULT *plResult)
986 {
987 return E_NOTIMPL;
988 }
989
990 HRESULT WINAPI CNetConUiObject::GetSite(REFIID riid, PVOID *ppvSite)
991 {
992 HRESULT hr;
993 IUnknown *pUnknown;
994
995 if (!this->pUnknown)
996 {
997 *ppvSite = NULL;
998 return E_FAIL;
999 }
1000
1001 hr = this->pUnknown->QueryInterface(riid, (LPVOID*)&pUnknown);
1002 if (SUCCEEDED(hr))
1003 {
1004 pUnknown->AddRef();
1005 *ppvSite = pUnknown;
1006 return S_OK;
1007 }
1008
1009 *ppvSite = NULL;
1010 return hr;
1011 }
1012
1013 HRESULT WINAPI CNetConUiObject::SetSite(IUnknown *pUnkSite)
1014 {
1015 if(!pUnkSite)
1016 {
1017 if (this->pUnknown)
1018 {
1019 this->pUnknown->Release();
1020 this->pUnknown = NULL;
1021 }
1022 }
1023 else
1024 {
1025 pUnkSite->AddRef();
1026 if (this->pUnknown)
1027 this->pUnknown->Release();
1028 this->pUnknown = pUnkSite;
1029 }
1030
1031 return S_OK;
1032 }
1033
1034 /************************************************************************
1035 * ISF_NetConnect_IExtractIcon_GetIconLocation
1036 */
1037 HRESULT WINAPI CNetConUiObject::GetIconLocation(
1038 UINT uFlags,
1039 LPWSTR szIconFile,
1040 UINT cchMax,
1041 int *piIndex,
1042 UINT *pwFlags)
1043 {
1044 VALUEStruct *val;
1045 NETCON_PROPERTIES *pProperties;
1046
1047 *pwFlags = 0;
1048 if (!GetModuleFileNameW(netshell_hInstance, szIconFile, cchMax))
1049 {
1050 ERR("GetModuleFileNameW failed\n");
1051 return E_FAIL;
1052 }
1053
1054 val = _ILGetValueStruct(apidl);
1055 if (!val)
1056 {
1057 ERR("_ILGetValueStruct failed\n");
1058 return E_FAIL;
1059 }
1060
1061 if (val->pItem->GetProperties(&pProperties) != NOERROR)
1062 {
1063 ERR("INetConnection_GetProperties failed\n");
1064 return E_FAIL;
1065 }
1066
1067 if (pProperties->Status == NCS_CONNECTED || pProperties->Status == NCS_CONNECTING)
1068 *piIndex = -IDI_NET_IDLE;
1069 else
1070 *piIndex = -IDI_NET_OFF;
1071
1072 NcFreeNetconProperties(pProperties);
1073
1074 return NOERROR;
1075 }
1076
1077 /************************************************************************
1078 * ISF_NetConnect_IExtractIcon_Extract
1079 */
1080 HRESULT WINAPI CNetConUiObject::Extract(
1081 LPCWSTR pszFile,
1082 UINT nIconIndex,
1083 HICON *phiconLarge,
1084 HICON *phiconSmall,
1085 UINT nIconSize)
1086 {
1087 //IContextMenuImpl * This = impl_from_IExtractIcon(iface);
1088 if (nIconIndex == IDI_NET_IDLE)
1089 {
1090 *phiconLarge = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
1091 *phiconSmall = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1092 return NOERROR;
1093 }
1094 else if (nIconIndex == IDI_NET_OFF)
1095 {
1096 *phiconLarge = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
1097 *phiconSmall = (HICON)LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1098 return NOERROR;
1099 }
1100
1101 return S_FALSE;
1102 }
1103
1104 /************************************************************************
1105 * ISF_NetConnect_PersistFolder2_GetClassID
1106 */
1107 HRESULT WINAPI CNetworkConnections::GetClassID(CLSID *lpClassId)
1108 {
1109 if (!lpClassId)
1110 return E_POINTER;
1111
1112 *lpClassId = CLSID_NetworkConnections;
1113
1114 return S_OK;
1115 }
1116
1117 /************************************************************************
1118 * ISF_NetConnect_PersistFolder2_Initialize
1119 *
1120 * NOTES: it makes no sense to change the pidl
1121 */
1122 HRESULT WINAPI CNetworkConnections::Initialize(LPCITEMIDLIST pidl)
1123 {
1124 SHFree(pidlRoot);
1125 pidlRoot = ILClone(pidl);
1126
1127 return S_OK;
1128 }
1129
1130 /**************************************************************************
1131 * ISF_NetConnect_PersistFolder2_GetCurFolder
1132 */
1133 HRESULT WINAPI CNetworkConnections::GetCurFolder(LPITEMIDLIST *pidl)
1134 {
1135 if (!pidl)
1136 return E_POINTER;
1137
1138 *pidl = ILClone(pidlRoot);
1139
1140 return S_OK;
1141 }
1142
1143 /************************************************************************
1144 * ISF_NetConnect_ShellExecuteHookW_Execute
1145 */
1146 HRESULT WINAPI CNetworkConnections::Execute(LPSHELLEXECUTEINFOW pei)
1147 {
1148 VALUEStruct *val;
1149 NETCON_PROPERTIES * pProperties;
1150
1151 val = _ILGetValueStruct(ILFindLastID((ITEMIDLIST*)pei->lpIDList));
1152 if (!val)
1153 return E_FAIL;
1154
1155 if (val->pItem->GetProperties(&pProperties) != NOERROR)
1156 return E_FAIL;
1157
1158 if (pProperties->Status == NCS_CONNECTED)
1159 {
1160 NcFreeNetconProperties(pProperties);
1161 return ShowNetConnectionStatus(lpOleCmd, val->pItem, pei->hwnd);
1162 }
1163
1164 NcFreeNetconProperties(pProperties);
1165
1166 return S_OK;
1167 }
1168
1169 HRESULT WINAPI CNetConUiObject::GetInfoFlags(DWORD *pdwFlags)
1170 {
1171 *pdwFlags = 0;
1172
1173 return S_OK;
1174 }
1175
1176 /************************************************************************
1177 * ISF_NetConnect_PersistFolder2_Initialize
1178 *
1179 * NOTES: it makes no sense to change the pidl
1180 */
1181 HRESULT WINAPI CNetConUiObject::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
1182 {
1183 *ppwszTip = NULL;
1184 return S_OK;
1185 }
1186
1187 /**************************************************************************
1188 * ISF_NetConnect_Constructor
1189 */
1190 HRESULT WINAPI ISF_NetConnect_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv)
1191 {
1192 TRACE("ISF_NetConnect_Constructor\n");
1193
1194 if (!ppv)
1195 return E_POINTER;
1196 if (pUnkOuter)
1197 return CLASS_E_NOAGGREGATION;
1198
1199 CNetworkConnections *pnc = new CNetworkConnections;
1200 if (!pnc)
1201 return E_OUTOFMEMORY;
1202
1203 pnc->AddRef();
1204 HRESULT hr = pnc->QueryInterface(riid, ppv);
1205 pnc->Release();
1206
1207 return hr;
1208 }