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