Sync up to trunk head.
[reactos.git] / dll / win32 / netshell / lanstatusui.c
1 #include <precomp.h>
2
3 /// CLSID
4 /// HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{7007ACCF-3202-11D1-AAD2-00805FC1270E}
5 // IID B722BCCB-4E68-101B-A2BC-00AA00404770
6
7 #define WM_SHOWSTATUSDLG (WM_USER+10)
8
9 typedef struct tagNotificationItem
10 {
11 struct tagNotificationItem *pNext;
12 CLSID guidItem;
13 UINT uID;
14 HWND hwndDlg;
15 INetConnection *pNet;
16 }NOTIFICATION_ITEM;
17
18 typedef struct
19 {
20 IOleCommandTarget * lpVtbl;
21 INetConnectionManager * lpNetMan;
22 LONG ref;
23 NOTIFICATION_ITEM * pHead;
24 }ILanStatusImpl, *LPILanStatusImpl;
25
26 typedef struct
27 {
28 INetConnection *pNet;
29 HWND hwndStatusDlg; /* LanStatusDlg window */
30 HWND hwndDlg; /* status dialog window */
31 DWORD dwAdapterIndex;
32 UINT_PTR nIDEvent;
33 UINT DHCPEnabled;
34 DWORD dwInOctets;
35 DWORD dwOutOctets;
36 DWORD IpAddress;
37 DWORD SubnetMask;
38 DWORD Gateway;
39 UINT uID;
40 UINT Status;
41 }LANSTATUSUI_CONTEXT;
42
43 VOID
44 UpdateLanStatusUiDlg(
45 HWND hwndDlg,
46 MIB_IFROW * IfEntry,
47 LANSTATUSUI_CONTEXT * pContext)
48 {
49 WCHAR szFormat[MAX_PATH] = {0};
50 WCHAR szBuffer[MAX_PATH] = {0};
51 SYSTEMTIME TimeConnected;
52 DWORD DurationSeconds;
53 WCHAR Buffer[100];
54 WCHAR DayBuffer[30];
55 WCHAR LocBuffer[50];
56
57 #if 0
58 ULONGLONG Ticks;
59 #else
60 DWORD Ticks;
61 #endif
62
63 if (IfEntry->dwSpeed < 1000)
64 {
65 if (LoadStringW(netshell_hInstance, IDS_FORMAT_BIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
66 {
67 swprintf(szBuffer, szFormat, IfEntry->dwSpeed);
68 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
69 }
70 }
71 else if (IfEntry->dwSpeed < 1000000)
72 {
73 if (LoadStringW(netshell_hInstance, IDS_FORMAT_KBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
74 {
75 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000);
76 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
77 }
78 }
79 else if (IfEntry->dwSpeed < 1000000000)
80 {
81 if (LoadStringW(netshell_hInstance, IDS_FORMAT_MBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
82 {
83 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000000);
84 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
85 }
86 }
87 else
88 {
89 if (LoadStringW(netshell_hInstance, IDS_FORMAT_KBIT, szFormat, sizeof(szFormat)/sizeof(WCHAR)))
90 {
91 swprintf(szBuffer, szFormat, IfEntry->dwSpeed/1000000000);
92 SendDlgItemMessageW(hwndDlg, IDC_SPEED, WM_SETTEXT, 0, (LPARAM)szBuffer);
93 }
94 }
95
96 if (StrFormatByteSizeW(IfEntry->dwInOctets, szBuffer, sizeof(szFormat)/sizeof(WCHAR)))
97 {
98 SendDlgItemMessageW(hwndDlg, IDC_RECEIVED, WM_SETTEXT, 0, (LPARAM)szBuffer);
99 }
100
101 if (StrFormatByteSizeW(IfEntry->dwOutOctets, szBuffer, sizeof(szFormat)/sizeof(WCHAR)))
102 {
103 SendDlgItemMessageW(hwndDlg, IDC_SEND, WM_SETTEXT, 0, (LPARAM)szBuffer);
104 }
105
106 #if 0
107 Ticks = GetTickCount64();
108 #else
109 Ticks = GetTickCount();
110 #endif
111
112 DurationSeconds = Ticks / 1000;
113 TimeConnected.wSecond = (DurationSeconds % 60);
114 TimeConnected.wMinute = (DurationSeconds / 60) % 60;
115 TimeConnected.wHour = (DurationSeconds / (60 * 60)) % 24;
116 TimeConnected.wDay = DurationSeconds / (60 * 60 * 24);
117
118 if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &TimeConnected, L"HH':'mm':'ss", LocBuffer, sizeof(LocBuffer) / sizeof(LocBuffer[0])))
119 return;
120
121 if (!TimeConnected.wDay)
122 {
123 SendDlgItemMessageW(hwndDlg, IDC_DURATION, WM_SETTEXT, 0, (LPARAM)LocBuffer);
124 }
125 else
126 {
127 if (TimeConnected.wDay == 1)
128 {
129 if (!LoadStringW(netshell_hInstance, IDS_DURATION_DAY, DayBuffer, sizeof(DayBuffer) / sizeof(DayBuffer[0])))
130 DayBuffer[0] = L'\0';
131 }
132 else
133 {
134 if (!LoadStringW(netshell_hInstance, IDS_DURATION_DAYS, DayBuffer, sizeof(DayBuffer) / sizeof(DayBuffer[0])))
135 DayBuffer[0] = L'\0';
136 }
137 swprintf(Buffer, DayBuffer, TimeConnected.wDay, LocBuffer);
138 SendDlgItemMessageW(hwndDlg, IDC_DURATION, WM_SETTEXT, 0, (LPARAM)Buffer);
139 }
140
141 }
142
143 VOID
144 UpdateLanStatus(HWND hwndDlg, LANSTATUSUI_CONTEXT * pContext)
145 {
146 MIB_IFROW IfEntry;
147 HICON hIcon, hOldIcon = NULL;
148 NOTIFYICONDATAW nid;
149 NETCON_PROPERTIES * pProperties = NULL;
150
151 ZeroMemory(&IfEntry, sizeof(IfEntry));
152 IfEntry.dwIndex = pContext->dwAdapterIndex;
153 if(GetIfEntry(&IfEntry) != NO_ERROR)
154 {
155 return;
156 }
157
158 hIcon = NULL;
159 if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
160 {
161 if (pContext->dwInOctets == IfEntry.dwInOctets && pContext->dwOutOctets == IfEntry.dwOutOctets && pContext->Status != 0)
162 {
163 hIcon = LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
164 pContext->Status = 0;
165 }
166 else if (pContext->dwInOctets != IfEntry.dwInOctets && pContext->dwOutOctets != IfEntry.dwOutOctets && pContext->Status != 1)
167 {
168 hIcon = LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_TRANSREC), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
169 pContext->Status = 1;
170 }
171 else if (pContext->dwInOctets != IfEntry.dwInOctets && pContext->Status != 2)
172 {
173 hIcon = LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_REC), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
174 pContext->Status = 2;
175 }
176 else if (pContext->dwOutOctets != IfEntry.dwOutOctets && pContext->Status != 3)
177 {
178 hIcon = LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_TRANS), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
179 pContext->Status = 3;
180 }
181 }
182 else if (IfEntry.dwOperStatus == MIB_IF_OPER_STATUS_UNREACHABLE || MIB_IF_OPER_STATUS_DISCONNECTED)
183 {
184 if (pContext->Status != 4)
185 {
186 hIcon = LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
187 pContext->Status = 4;
188 }
189 }
190 else if (MIB_IF_OPER_STATUS_NON_OPERATIONAL)
191 {
192 if (pContext->Status != 5)
193 {
194 hIcon = LoadImage(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
195 pContext->Status = 5;
196 }
197 }
198
199 if (hwndDlg && hIcon)
200 {
201 hOldIcon = (HICON)SendDlgItemMessageW(hwndDlg, IDC_NETSTAT, STM_SETICON, (WPARAM)hIcon, 0);
202 if (hOldIcon)
203 DestroyIcon(hOldIcon);
204 }
205
206 ZeroMemory(&nid, sizeof(nid));
207 nid.cbSize = sizeof(nid);
208 nid.uID = pContext->uID;
209 nid.hWnd = pContext->hwndStatusDlg;
210 nid.u.uVersion = 3;
211
212 if (INetConnection_GetProperties(pContext->pNet, &pProperties) == NOERROR)
213 {
214 if (pProperties->dwCharacter & NCCF_SHOW_ICON)
215 {
216 if (hwndDlg)
217 nid.hIcon = CopyImage(hIcon, IMAGE_ICON, 16, 16, 0);
218 else
219 nid.hIcon = hIcon;
220
221 if (nid.hIcon)
222 nid.uFlags |= NIF_ICON;
223
224 nid.uFlags |= NIF_STATE;
225 nid.dwState = 0;
226 nid.dwStateMask = NIS_HIDDEN;
227
228 if (pProperties->pszwName)
229 {
230 if (wcslen(pProperties->pszwName) * sizeof(WCHAR) < sizeof(nid.szTip))
231 {
232 nid.uFlags |= NIF_TIP;
233 wcscpy(nid.szTip, pProperties->pszwName);
234 }
235 else
236 {
237 CopyMemory(nid.szTip, pProperties->pszwName, sizeof(nid.szTip) - sizeof(WCHAR));
238 nid.szTip[(sizeof(nid.szTip)/sizeof(WCHAR))-1] = L'\0';
239 nid.uFlags |= NIF_TIP;
240 }
241 }
242 }
243 else
244 {
245 nid.uFlags |= NIF_STATE;
246 nid.dwState = NIS_HIDDEN;
247 nid.dwStateMask = NIS_HIDDEN;
248
249 }
250 NcFreeNetconProperties(pProperties);
251 }
252
253 Shell_NotifyIconW(NIM_MODIFY, &nid);
254
255 pContext->dwInOctets = IfEntry.dwInOctets;
256 pContext->dwOutOctets = IfEntry.dwOutOctets;
257
258 if (hwndDlg)
259 UpdateLanStatusUiDlg(hwndDlg, &IfEntry, pContext);
260 }
261
262
263 VOID
264 InitializeLANStatusUiDlg(HWND hwndDlg, LANSTATUSUI_CONTEXT * pContext)
265 {
266 WCHAR szBuffer[MAX_PATH] = {0};
267 NETCON_PROPERTIES * pProperties;
268
269 if (INetConnection_GetProperties(pContext->pNet, &pProperties) != NOERROR)
270 return;
271
272 if (pProperties->Status == NCS_DISCONNECTED)
273 LoadStringW(netshell_hInstance, IDS_STATUS_UNREACHABLE, szBuffer, MAX_PATH);
274 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED)
275 LoadStringW(netshell_hInstance, IDS_STATUS_DISCONNECTED, szBuffer, MAX_PATH);
276 else if (pProperties->Status == NCS_CONNECTING)
277 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTING, szBuffer, MAX_PATH);
278 else if (pProperties->Status == NCS_CONNECTED)
279 LoadStringW(netshell_hInstance, IDS_STATUS_CONNECTED, szBuffer, MAX_PATH);
280
281 SendDlgItemMessageW(hwndDlg, IDC_STATUS, WM_SETTEXT, 0, (LPARAM)szBuffer);
282
283 pContext->dwInOctets = 0;
284 pContext->dwOutOctets = 0;
285
286 /* update adapter info */
287 pContext->Status = -1;
288 UpdateLanStatus(hwndDlg, pContext);
289 NcFreeNetconProperties(pProperties);
290 }
291
292 VOID
293 InsertColumnToListView(
294 HWND hDlgCtrl,
295 UINT ResId,
296 UINT SubItem,
297 UINT Size)
298 {
299 WCHAR szBuffer[200];
300 LVCOLUMNW lc;
301
302 if (!LoadStringW(netshell_hInstance, ResId, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
303 return;
304
305 memset(&lc, 0, sizeof(LV_COLUMN) );
306 lc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
307 lc.iSubItem = SubItem;
308 lc.fmt = LVCFMT_FIXED_WIDTH;
309 lc.cx = Size;
310 lc.cchTextMax = wcslen(szBuffer);
311 lc.pszText = szBuffer;
312
313 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, SubItem, (LPARAM)&lc);
314 }
315
316 VOID
317 AddIPAddressToListView(
318 HWND hDlgCtrl,
319 PIP_ADDR_STRING pAddr,
320 INT Index)
321 {
322 LVITEMW li;
323 PIP_ADDR_STRING pCur;
324 WCHAR szBuffer[100];
325 UINT SubIndex;
326
327 ZeroMemory(&li, sizeof(LVITEMW));
328 li.mask = LVIF_TEXT;
329 li.iItem = Index;
330 pCur = pAddr;
331 SubIndex = 0;
332
333 do
334 {
335 if (SubIndex)
336 {
337 ZeroMemory(&li, sizeof(LVITEMW));
338 li.mask = LVIF_TEXT;
339 li.iItem = Index;
340 li.iSubItem = 0;
341 li.pszText = L"";
342 li.iItem = SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
343 }
344
345 if (MultiByteToWideChar(CP_ACP, 0, pCur->IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
346 {
347 li.pszText = szBuffer;
348 li.iSubItem = 1;
349 li.iItem = Index++;
350 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
351 }
352 SubIndex++;
353 pCur = pCur->Next;
354 }while(pCur && pCur->IpAddress.String[0]);
355 }
356
357 INT
358 InsertItemToListView(
359 HWND hDlgCtrl,
360 UINT ResId)
361 {
362 LVITEMW li;
363 WCHAR szBuffer[100];
364
365 ZeroMemory(&li, sizeof(LVITEMW));
366 li.mask = LVIF_TEXT;
367 li.iItem = ListView_GetItemCount(hDlgCtrl);
368 if (LoadStringW(netshell_hInstance, ResId, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
369 {
370 li.pszText = szBuffer;
371 return (INT)SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&li);
372 }
373 return -1;
374 }
375
376
377 INT_PTR
378 CALLBACK
379 LANStatusUiDetailsDlg(
380 HWND hwndDlg,
381 UINT uMsg,
382 WPARAM wParam,
383 LPARAM lParam
384 )
385 {
386 LANSTATUSUI_CONTEXT * pContext;
387 LVITEMW li;
388 WCHAR szBuffer[100];
389 PIP_ADAPTER_INFO pAdapterInfo, pCurAdapter;
390 PIP_PER_ADAPTER_INFO pPerAdapter;
391 DWORD dwSize;
392 HWND hDlgCtrl;
393
394 switch(uMsg)
395 {
396 case WM_INITDIALOG:
397 pContext = (LANSTATUSUI_CONTEXT*)lParam;
398
399 hDlgCtrl = GetDlgItem(hwndDlg, IDC_DETAILS);
400 InsertColumnToListView(hDlgCtrl, IDS_PROPERTY, 0, 80);
401 InsertColumnToListView(hDlgCtrl, IDS_VALUE, 1, 80);
402
403 dwSize = 0;
404 pCurAdapter = NULL;
405 pAdapterInfo = NULL;
406 if (GetAdaptersInfo(NULL, &dwSize) == ERROR_BUFFER_OVERFLOW)
407 {
408 pAdapterInfo = (PIP_ADAPTER_INFO)CoTaskMemAlloc(dwSize);
409 if (pAdapterInfo)
410 {
411 if (GetAdaptersInfo(pAdapterInfo, &dwSize) == NO_ERROR)
412 {
413 pCurAdapter = pAdapterInfo;
414 while(pCurAdapter && pCurAdapter->Index != pContext->dwAdapterIndex)
415 pCurAdapter = pCurAdapter->Next;
416
417 if(pCurAdapter->Index != pContext->dwAdapterIndex)
418 pCurAdapter = NULL;
419 }
420 }
421 }
422
423 ZeroMemory(&li, sizeof(LVITEMW));
424 li.mask = LVIF_TEXT;
425 li.iSubItem = 1;
426 li.pszText = szBuffer;
427
428 if (pCurAdapter)
429 {
430 li.iItem = InsertItemToListView(hDlgCtrl, IDS_PHYSICAL_ADDRESS);
431 if (li.iItem >= 0)
432 {
433 swprintf(szBuffer, L"%02x-%02x-%02x-%02x-%02x-%02x",pCurAdapter->Address[0], pCurAdapter->Address[1],
434 pCurAdapter->Address[2], pCurAdapter->Address[3], pCurAdapter->Address[4], pCurAdapter->Address[5]);
435 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
436 }
437 li.iItem = InsertItemToListView(hDlgCtrl, IDS_IP_ADDRESS);
438 if (li.iItem >= 0)
439 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
440 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
441
442 li.iItem = InsertItemToListView(hDlgCtrl, IDS_SUBNET_MASK);
443 if (li.iItem >= 0)
444 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->IpAddressList.IpMask.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
445 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
446
447 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DEF_GATEWAY);
448 if (li.iItem >= 0 && pCurAdapter->GatewayList.IpAddress.String[0] != '0')
449 {
450 if (MultiByteToWideChar(CP_ACP, 0, pCurAdapter->GatewayList.IpAddress.String, -1, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
451 SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
452 }
453 #if 0
454 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_OBTAINED);
455 li.iItem = InsertItemToListView(hDlgCtrl, IDS_LEASE_EXPIRES);
456 #endif
457 }
458
459 dwSize = 0;
460 if (GetPerAdapterInfo(pContext->dwAdapterIndex, NULL, &dwSize) == ERROR_BUFFER_OVERFLOW)
461 {
462 pPerAdapter = (PIP_PER_ADAPTER_INFO)CoTaskMemAlloc(dwSize);
463 if (pPerAdapter)
464 {
465 if (GetPerAdapterInfo(pContext->dwAdapterIndex, pPerAdapter, &dwSize) == ERROR_SUCCESS)
466 {
467 li.iItem = InsertItemToListView(hDlgCtrl, IDS_DNS_SERVERS);
468 if (li.iItem >= 0)
469 AddIPAddressToListView(hDlgCtrl, &pPerAdapter->DnsServerList, li.iItem);
470 }
471 CoTaskMemFree(pPerAdapter);
472 }
473 }
474 #if 0
475 if (pCurAdapter)
476 {
477 li.iItem = InsertItemToListView(hDlgCtrl, IDS_WINS_SERVERS);
478 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->PrimaryWinsServer, li.iItem);
479 AddIPAddressToListView(hDlgCtrl, &pCurAdapter->SecondaryWinsServer, li.iItem+1);
480 }
481 #endif
482 CoTaskMemFree(pAdapterInfo);
483 break;
484 case WM_COMMAND:
485 if (LOWORD(wParam) == IDC_CLOSE)
486 {
487 EndDialog(hwndDlg, FALSE);
488 break;
489 }
490 }
491 return FALSE;
492 }
493
494 INT_PTR
495 CALLBACK
496 LANStatusUiAdvancedDlg(
497 HWND hwndDlg,
498 UINT uMsg,
499 WPARAM wParam,
500 LPARAM lParam
501 )
502 {
503 WCHAR szBuffer[100] = {0};
504 PROPSHEETPAGE *page;
505 LANSTATUSUI_CONTEXT * pContext;
506 DWORD dwIpAddr;
507
508
509 switch(uMsg)
510 {
511 case WM_INITDIALOG:
512 page = (PROPSHEETPAGE*)lParam;
513 pContext = (LANSTATUSUI_CONTEXT*)page->lParam;
514 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
515 if (pContext->DHCPEnabled)
516 LoadStringW(netshell_hInstance, IDS_ASSIGNED_DHCP, szBuffer, sizeof(szBuffer)/sizeof(WCHAR));
517 else
518 LoadStringW(netshell_hInstance, IDS_ASSIGNED_MANUAL, szBuffer, sizeof(szBuffer)/sizeof(WCHAR));
519
520 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
521 SendDlgItemMessageW(hwndDlg, IDC_DETAILSTYPE, WM_SETTEXT, 0, (LPARAM)szBuffer);
522
523
524 dwIpAddr = ntohl(pContext->IpAddress);
525 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
526 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
527 SendDlgItemMessageW(hwndDlg, IDC_DETAILSIP, WM_SETTEXT, 0, (LPARAM)szBuffer);
528
529 dwIpAddr = ntohl(pContext->SubnetMask);
530 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
531 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
532 SendDlgItemMessageW(hwndDlg, IDC_DETAILSSUBNET, WM_SETTEXT, 0, (LPARAM)szBuffer);
533
534 dwIpAddr = ntohl(pContext->Gateway);
535 if (dwIpAddr)
536 {
537 swprintf(szBuffer, L"%u.%u.%u.%u", FIRST_IPADDRESS(dwIpAddr), SECOND_IPADDRESS(dwIpAddr),
538 THIRD_IPADDRESS(dwIpAddr), FOURTH_IPADDRESS(dwIpAddr));
539 SendDlgItemMessageW(hwndDlg, IDC_DETAILSGATEWAY, WM_SETTEXT, 0, (LPARAM)szBuffer);
540 }
541 return TRUE;
542 case WM_COMMAND:
543 if (LOWORD(wParam) == IDC_DETAILS)
544 {
545 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
546 if (pContext)
547 {
548 DialogBoxParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_LAN_NETSTATUSDETAILS), GetParent(hwndDlg),
549 LANStatusUiDetailsDlg, (LPARAM)pContext);
550 }
551 }
552 break;
553 default:
554 break;
555 }
556 return FALSE;
557 }
558
559 BOOL
560 FindNetworkAdapter(HDEVINFO hInfo, SP_DEVINFO_DATA *pDevInfo, LPWSTR pGuid)
561 {
562 DWORD dwIndex, dwSize;
563 HKEY hSubKey;
564 WCHAR szNetCfg[50];
565 WCHAR szDetail[200] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\";
566
567 dwIndex = 0;
568 do
569 {
570
571 ZeroMemory(pDevInfo, sizeof(SP_DEVINFO_DATA));
572 pDevInfo->cbSize = sizeof(SP_DEVINFO_DATA);
573
574 /* get device info */
575 if (!SetupDiEnumDeviceInfo(hInfo, dwIndex++, pDevInfo))
576 break;
577
578 /* get device software registry path */
579 if (!SetupDiGetDeviceRegistryPropertyW(hInfo, pDevInfo, SPDRP_DRIVER, NULL, (LPBYTE)&szDetail[39], sizeof(szDetail)/sizeof(WCHAR) - 40, &dwSize))
580 break;
581
582 /* open device registry key */
583 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szDetail, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS)
584 break;
585
586 /* query NetCfgInstanceId for current device */
587 dwSize = sizeof(szNetCfg);
588 if (RegQueryValueExW(hSubKey, L"NetCfgInstanceId", NULL, NULL, (LPBYTE)szNetCfg, &dwSize) != ERROR_SUCCESS)
589 {
590 RegCloseKey(hSubKey);
591 break;
592 }
593 RegCloseKey(hSubKey);
594 if (!_wcsicmp(pGuid, szNetCfg))
595 {
596 return TRUE;
597 }
598 }
599 while(TRUE);
600
601 return FALSE;
602 }
603
604
605
606 VOID
607 DisableNetworkAdapter(INetConnection * pNet, LANSTATUSUI_CONTEXT * pContext, HWND hwndDlg)
608 {
609 HKEY hKey;
610 NETCON_PROPERTIES * pProperties;
611 LPOLESTR pDisplayName;
612 WCHAR szPath[200];
613 DWORD dwSize, dwType;
614 LPWSTR pPnp;
615 HDEVINFO hInfo;
616 SP_DEVINFO_DATA DevInfo;
617 SP_PROPCHANGE_PARAMS PropChangeParams;
618 BOOL bClose = FALSE;
619 NOTIFYICONDATAW nid;
620
621 if (FAILED(INetConnection_GetProperties(pNet, &pProperties)))
622 return;
623
624
625 hInfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT );
626 if (!hInfo)
627 {
628 NcFreeNetconProperties(pProperties);
629 return;
630 }
631
632 if (FAILED(StringFromCLSID(&pProperties->guidId, &pDisplayName)))
633 {
634 NcFreeNetconProperties(pProperties);
635 SetupDiDestroyDeviceInfoList(hInfo);
636 return;
637 }
638 NcFreeNetconProperties(pProperties);
639
640 if (FindNetworkAdapter(hInfo, &DevInfo, pDisplayName))
641 {
642 PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
643 PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; //;
644 PropChangeParams.StateChange = DICS_DISABLE;
645 PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;
646 PropChangeParams.HwProfile = 0;
647
648 if (SetupDiSetClassInstallParams(hInfo, &DevInfo, &PropChangeParams.ClassInstallHeader, sizeof(SP_PROPCHANGE_PARAMS)))
649 {
650 if (SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hInfo, &DevInfo))
651 bClose = TRUE;
652 }
653 }
654 SetupDiDestroyDeviceInfoList(hInfo);
655
656 swprintf(szPath, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pDisplayName);
657 CoTaskMemFree(pDisplayName);
658
659 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
660 return;
661
662 dwSize = 0;
663 if (RegQueryValueExW(hKey, L"PnpInstanceID", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS || dwType != REG_SZ)
664 {
665 RegCloseKey(hKey);
666 return;
667 }
668
669 pPnp = (LPWSTR)CoTaskMemAlloc(dwSize);
670 if (!pPnp)
671 {
672 RegCloseKey(hKey);
673 return;
674 }
675
676 if (RegQueryValueExW(hKey, L"PnpInstanceID", NULL, &dwType, (LPBYTE)pPnp, &dwSize) != ERROR_SUCCESS)
677 {
678 CoTaskMemFree(pPnp);
679 RegCloseKey(hKey);
680 return;
681 }
682 RegCloseKey(hKey);
683
684 swprintf(szPath, L"System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Enum\\%s", pPnp);
685 CoTaskMemFree(pPnp);
686
687 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szPath, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
688 return;
689
690 dwSize = 1; /* enable = 0, disable = 1 */
691 RegSetValueExW(hKey, L"CSConfigFlags", 0, REG_DWORD, (LPBYTE)&dwSize, sizeof(DWORD));
692 RegCloseKey(hKey);
693
694 if (!bClose)
695 return;
696
697 PropSheet_PressButton(GetParent(hwndDlg), PSBTN_CANCEL);
698 ZeroMemory(&nid, sizeof(nid));
699 nid.cbSize = sizeof(nid);
700 nid.uID = pContext->uID;
701 nid.hWnd = pContext->hwndDlg;
702 nid.uFlags = NIF_STATE;
703 nid.dwState = NIS_HIDDEN;
704 nid.dwStateMask = NIS_HIDDEN;
705
706 Shell_NotifyIconW(NIM_MODIFY, &nid);
707 }
708
709
710 INT_PTR
711 CALLBACK
712 LANStatusUiDlg(
713 HWND hwndDlg,
714 UINT uMsg,
715 WPARAM wParam,
716 LPARAM lParam
717 )
718 {
719 PROPSHEETPAGE *page;
720 LANSTATUSUI_CONTEXT * pContext;
721 LPPSHNOTIFY lppsn;
722
723 switch(uMsg)
724 {
725 case WM_INITDIALOG:
726 page = (PROPSHEETPAGE*)lParam;
727 pContext = (LANSTATUSUI_CONTEXT*)page->lParam;
728 pContext->hwndDlg = hwndDlg;
729 InitializeLANStatusUiDlg(hwndDlg, pContext);
730 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pContext);
731 return TRUE;
732 case WM_COMMAND:
733 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
734 if (LOWORD(wParam) == IDC_STATUS_PROPERTIES)
735 {
736 if (pContext)
737 {
738 ShowNetConnectionProperties(pContext->pNet, GetParent(pContext->hwndDlg));
739 BringWindowToTop(GetParent(pContext->hwndDlg));
740 }
741 break;
742 }
743 else if (LOWORD(wParam) == IDC_ENDISABLE)
744 {
745 DisableNetworkAdapter(pContext->pNet, pContext, hwndDlg);
746 break;
747 }
748 case WM_NOTIFY:
749 lppsn = (LPPSHNOTIFY) lParam;
750 if (lppsn->hdr.code == PSN_APPLY || lppsn->hdr.code == PSN_RESET)
751 {
752 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
753 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
754 pContext->hwndDlg = NULL;
755 return TRUE;
756 }
757 break;
758 }
759 return FALSE;
760 }
761
762 VOID
763 InitializePropertyDialog(
764 LANSTATUSUI_CONTEXT * pContext,
765 NETCON_PROPERTIES * pProperties)
766 {
767 DWORD dwSize, dwAdapterIndex, dwResult;
768 LPOLESTR pStr;
769 IP_ADAPTER_INFO * pAdapterInfo, *pCurAdapter;
770
771 if (FAILED(StringFromCLSID(&pProperties->guidId, &pStr)))
772 {
773 return;
774 }
775
776 /* get the IfTable */
777 dwSize = 0;
778 dwResult = GetAdaptersInfo(NULL, &dwSize);
779 if (dwResult!= ERROR_BUFFER_OVERFLOW)
780 {
781 CoTaskMemFree(pStr);
782 return;
783 }
784
785 pAdapterInfo = (PIP_ADAPTER_INFO)CoTaskMemAlloc(dwSize);
786 if (!pAdapterInfo)
787 {
788 CoTaskMemFree(pAdapterInfo);
789 CoTaskMemFree(pStr);
790 return;
791 }
792
793 if (GetAdaptersInfo(pAdapterInfo, &dwSize) != NO_ERROR)
794 {
795 CoTaskMemFree(pAdapterInfo);
796 CoTaskMemFree(pStr);
797 return;
798 }
799
800 if (!GetAdapterIndexFromNetCfgInstanceId(pAdapterInfo, pStr, &dwAdapterIndex))
801 {
802 CoTaskMemFree(pAdapterInfo);
803 CoTaskMemFree(pStr);
804 return;
805 }
806
807 pCurAdapter = pAdapterInfo;
808 while(pCurAdapter->Index != dwAdapterIndex)
809 pCurAdapter = pCurAdapter->Next;
810
811
812 pContext->IpAddress = inet_addr(pCurAdapter->IpAddressList.IpAddress.String);
813 pContext->SubnetMask = inet_addr(pCurAdapter->IpAddressList.IpMask.String);
814 pContext->Gateway = inet_addr(pCurAdapter->GatewayList.IpAddress.String);
815 pContext->DHCPEnabled = pCurAdapter->DhcpEnabled;
816 CoTaskMemFree(pStr);
817 CoTaskMemFree(pAdapterInfo);
818 pContext->dwAdapterIndex = dwAdapterIndex;
819 }
820
821 VOID
822 ShowStatusPropertyDialog(
823 LANSTATUSUI_CONTEXT * pContext,
824 HWND hwndDlg)
825 {
826 HPROPSHEETPAGE hppages[2];
827 PROPSHEETHEADERW pinfo;
828 NETCON_PROPERTIES * pProperties = NULL;
829
830 ZeroMemory(&pinfo, sizeof(PROPSHEETHEADERW));
831 ZeroMemory(hppages, sizeof(hppages));
832 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
833 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_NOAPPLYNOW;
834 pinfo.u3.phpage = hppages;
835 pinfo.hwndParent = hwndDlg;
836
837 if (INetConnection_GetProperties(pContext->pNet, &pProperties) == NOERROR)
838 {
839 if (pProperties->pszwName)
840 {
841 pinfo.pszCaption = pProperties->pszwName;
842 pinfo.dwFlags |= PSH_PROPTITLE;
843 }
844 InitializePropertyDialog(pContext, pProperties);
845 if (pProperties->MediaType == NCM_LAN && pProperties->Status == NCS_CONNECTED)
846 {
847 hppages[0] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUS), LANStatusUiDlg, (LPARAM)pContext, NULL);
848 if (hppages[0])
849 pinfo.nPages++;
850
851 hppages[pinfo.nPages] = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_LAN_NETSTATUSADVANCED), LANStatusUiAdvancedDlg, (LPARAM)pContext, NULL);
852 if (hppages[pinfo.nPages])
853 pinfo.nPages++;
854
855 if (pinfo.nPages)
856 {
857 PropertySheetW(&pinfo);
858 }
859 }
860 else if (pProperties->Status == NCS_MEDIA_DISCONNECTED || pProperties->Status == NCS_DISCONNECTED ||
861 pProperties->Status == NCS_HARDWARE_DISABLED)
862 {
863 ShowNetConnectionProperties(pContext->pNet, pContext->hwndDlg);
864 }
865
866 NcFreeNetconProperties(pProperties);
867 }
868 }
869
870 INT_PTR
871 CALLBACK
872 LANStatusDlg(
873 HWND hwndDlg,
874 UINT uMsg,
875 WPARAM wParam,
876 LPARAM lParam
877 )
878 {
879 LANSTATUSUI_CONTEXT * pContext;
880
881 switch(uMsg)
882 {
883 case WM_INITDIALOG:
884 pContext = (LANSTATUSUI_CONTEXT *)lParam;
885 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
886 pContext->nIDEvent = SetTimer(hwndDlg, 0xFABC, 1000, NULL);
887 return TRUE;
888 case WM_TIMER:
889 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
890 if (wParam == (WPARAM)pContext->nIDEvent)
891 {
892 UpdateLanStatus(pContext->hwndDlg, pContext);
893 }
894 break;
895 case WM_SHOWSTATUSDLG:
896 if (LOWORD(lParam) == WM_LBUTTONDOWN)
897 {
898 pContext = (LANSTATUSUI_CONTEXT*)GetWindowLongPtr(hwndDlg, DWLP_USER);
899 if (!pContext)
900 break;
901
902 if (pContext->hwndDlg)
903 {
904 ShowWindow(GetParent(pContext->hwndDlg), SW_SHOW);
905 BringWindowToTop(GetParent(pContext->hwndDlg));
906 }
907 else
908 {
909 ShowStatusPropertyDialog(pContext, hwndDlg);
910 }
911 break;
912 }
913 break;
914 }
915 return FALSE;
916 }
917 static
918 HRESULT
919 InitializeNetTaskbarNotifications(
920 ILanStatusImpl * This)
921 {
922 NOTIFYICONDATAW nid;
923 HWND hwndDlg;
924 INetConnectionManager * INetConMan;
925 IEnumNetConnection * IEnumCon;
926 INetConnection * INetCon;
927 NETCON_PROPERTIES* pProps;
928 HRESULT hr;
929 ULONG Count;
930 ULONG Index;
931 NOTIFICATION_ITEM * pItem, *pLast = NULL;
932 LANSTATUSUI_CONTEXT * pContext;
933
934 if (This->pHead)
935 {
936 pItem = This->pHead;
937 while(pItem)
938 {
939 hr = INetConnection_GetProperties(pItem->pNet, &pProps);
940 if (SUCCEEDED(hr))
941 {
942 ZeroMemory(&nid, sizeof(nid));
943 nid.cbSize = sizeof(nid);
944 nid.uID = pItem->uID;
945 nid.hWnd = pItem->hwndDlg;
946 nid.uFlags = NIF_STATE;
947 if (pProps->dwCharacter & NCCF_SHOW_ICON)
948 nid.dwState = 0;
949 else
950 nid.dwState = NIS_HIDDEN;
951
952 nid.dwStateMask = NIS_HIDDEN;
953 Shell_NotifyIconW(NIM_MODIFY, &nid);
954 NcFreeNetconProperties(pProps);
955 }
956 pItem = pItem->pNext;
957 }
958 return S_OK;
959 }
960 /* get an instance to of IConnectionManager */
961
962 //hr = CoCreateInstance(&CLSID_ConnectionManager, NULL, CLSCTX_INPROC_SERVER, &IID_INetConnectionManager, (LPVOID*)&INetConMan);
963
964 hr = INetConnectionManager_Constructor(NULL, &IID_INetConnectionManager, (LPVOID*)&INetConMan);
965 if (FAILED(hr))
966 return hr;
967
968 hr = INetConnectionManager_EnumConnections(INetConMan, NCME_DEFAULT, &IEnumCon);
969 if (FAILED(hr))
970 {
971 INetConnectionManager_Release(INetConMan);
972 return hr;
973 }
974
975 Index = 1;
976 do
977 {
978 hr = IEnumNetConnection_Next(IEnumCon, 1, &INetCon, &Count);
979 if (hr == S_OK)
980 {
981 pItem = (NOTIFICATION_ITEM*)CoTaskMemAlloc(sizeof(NOTIFICATION_ITEM));
982 if (!pItem)
983 break;
984
985 pContext = (LANSTATUSUI_CONTEXT*)CoTaskMemAlloc(sizeof(LANSTATUSUI_CONTEXT));
986 if (!pContext)
987 {
988 CoTaskMemFree(pItem);
989 break;
990 }
991
992
993 ZeroMemory(pContext, sizeof(LANSTATUSUI_CONTEXT));
994 pContext->uID = Index;
995 pContext->pNet = INetCon;
996 pItem->uID = Index;
997 pItem->pNext = NULL;
998 pItem->pNet = INetCon;
999 hwndDlg = CreateDialogParamW(netshell_hInstance, MAKEINTRESOURCEW(IDD_STATUS), NULL, LANStatusDlg, (LPARAM)pContext);
1000 if (hwndDlg)
1001 {
1002 ZeroMemory(&nid, sizeof(nid));
1003 nid.cbSize = sizeof(nid);
1004 nid.uID = Index++;
1005 nid.uFlags = NIF_ICON | NIF_MESSAGE;
1006 nid.u.uVersion = 3;
1007 nid.uCallbackMessage = WM_SHOWSTATUSDLG;
1008 nid.hWnd = hwndDlg;
1009
1010 hr = INetConnection_GetProperties(INetCon, &pProps);
1011 if (SUCCEEDED(hr))
1012 {
1013 CopyMemory(&pItem->guidItem, &pProps->guidId, sizeof(GUID));
1014 if (!(pProps->dwCharacter & NCCF_SHOW_ICON))
1015 {
1016 nid.dwState = NIS_HIDDEN;
1017 nid.dwStateMask = NIS_HIDDEN;
1018 nid.uFlags |= NIF_STATE;
1019 }
1020 if (pProps->Status == NCS_MEDIA_DISCONNECTED || pProps->Status == NCS_DISCONNECTED || pProps->Status == NCS_HARDWARE_DISABLED)
1021 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_OFF));
1022 else if (pProps->Status == NCS_CONNECTED)
1023 nid.hIcon = LoadIcon(netshell_hInstance, MAKEINTRESOURCE(IDI_NET_IDLE));
1024
1025
1026 wcscpy(nid.szTip, pProps->pszwName);
1027 nid.uFlags |= NIF_TIP;
1028 }
1029 pContext->hwndStatusDlg = hwndDlg;
1030 pItem->hwndDlg = hwndDlg;
1031
1032 if (Shell_NotifyIconW(NIM_ADD, &nid))
1033 {
1034 if (pLast)
1035 pLast->pNext = pItem;
1036 else
1037 This->pHead = pItem;
1038
1039 pLast = pItem;
1040 Index++;
1041 }
1042 else
1043 {
1044 CoTaskMemFree(pItem);
1045 }
1046 }
1047 }
1048 }while(hr == S_OK);
1049
1050 This->lpNetMan = INetConMan;
1051 IEnumNetConnection_Release(IEnumCon);
1052 return S_OK;
1053 }
1054
1055 HRESULT
1056 ShowStatusDialogByCLSID(
1057 ILanStatusImpl * This,
1058 const GUID *pguidCmdGroup)
1059 {
1060 NOTIFICATION_ITEM * pItem;
1061
1062 pItem = This->pHead;
1063 while(pItem)
1064 {
1065 if (IsEqualGUID(&pItem->guidItem, pguidCmdGroup))
1066 {
1067 SendMessageW(pItem->hwndDlg, WM_SHOWSTATUSDLG, 0, WM_LBUTTONDOWN);
1068 return S_OK;
1069 }
1070 pItem = pItem->pNext;
1071 }
1072 return E_FAIL;
1073 }
1074 static
1075 HRESULT
1076 WINAPI
1077 IOleCommandTarget_fnQueryInterface(
1078 IOleCommandTarget * iface,
1079 REFIID iid,
1080 LPVOID * ppvObj)
1081 {
1082 ILanStatusImpl * This = (ILanStatusImpl*)iface;
1083 *ppvObj = NULL;
1084
1085 if (IsEqualIID (iid, &IID_IUnknown) ||
1086 IsEqualIID (iid, &IID_IOleCommandTarget))
1087 {
1088 *ppvObj = This;
1089 IUnknown_AddRef(iface);
1090 return S_OK;
1091 }
1092 MessageBoxW(NULL, L"IOleCommandTarget_fnQueryInterface", NULL, MB_OK);
1093 return E_NOINTERFACE;
1094 }
1095
1096 static
1097 ULONG
1098 WINAPI
1099 IOleCommandTarget_fnAddRef(
1100 IOleCommandTarget * iface)
1101 {
1102 ILanStatusImpl * This = (ILanStatusImpl*)iface;
1103 ULONG refCount = InterlockedIncrement(&This->ref);
1104
1105 return refCount;
1106 }
1107
1108 static
1109 ULONG
1110 WINAPI
1111 IOleCommandTarget_fnRelease(
1112 IOleCommandTarget * iface)
1113 {
1114 #if 0
1115 ILanStatusImpl * This = (ILanStatusImpl*)iface;
1116 ULONG refCount = InterlockedDecrement(&This->ref);
1117
1118 if (!refCount)
1119 {
1120 CoTaskMemFree (This);
1121 }
1122 return refCount;
1123 #else
1124 return 1;
1125 #endif
1126 }
1127
1128 static
1129 HRESULT
1130 WINAPI
1131 IOleCommandTarget_fnQueryStatus(
1132 IOleCommandTarget * iface,
1133 const GUID *pguidCmdGroup,
1134 ULONG cCmds,
1135 OLECMD *prgCmds,
1136 OLECMDTEXT *pCmdText)
1137 {
1138 MessageBoxW(NULL, pCmdText->rgwz, L"IOleCommandTarget_fnQueryStatus", MB_OK);
1139 return E_NOTIMPL;
1140 }
1141
1142 static
1143 HRESULT
1144 WINAPI
1145 IOleCommandTarget_fnExec(
1146 IOleCommandTarget * iface,
1147 const GUID *pguidCmdGroup,
1148 DWORD nCmdID,
1149 DWORD nCmdexecopt,
1150 VARIANT *pvaIn,
1151 VARIANT *pvaOut)
1152 {
1153 ILanStatusImpl * This = (ILanStatusImpl*)iface;
1154
1155 if (pguidCmdGroup)
1156 {
1157 if (IsEqualIID(pguidCmdGroup, &CGID_ShellServiceObject))
1158 {
1159 return InitializeNetTaskbarNotifications(This);
1160 }
1161 else
1162 {
1163 /* invoke status dialog */
1164 return ShowStatusDialogByCLSID(This, pguidCmdGroup);
1165 }
1166 }
1167 return S_OK;
1168 }
1169
1170
1171 static const IOleCommandTargetVtbl vt_OleCommandTarget =
1172 {
1173 IOleCommandTarget_fnQueryInterface,
1174 IOleCommandTarget_fnAddRef,
1175 IOleCommandTarget_fnRelease,
1176 IOleCommandTarget_fnQueryStatus,
1177 IOleCommandTarget_fnExec,
1178 };
1179
1180
1181 HRESULT WINAPI LanConnectStatusUI_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
1182 {
1183 ILanStatusImpl * This;
1184 static volatile ILanStatusImpl *cached_This = NULL;
1185
1186 if (!ppv)
1187 return E_POINTER;
1188
1189 if (pUnkOuter)
1190 return CLASS_E_NOAGGREGATION;
1191
1192 This = (ILanStatusImpl *) CoTaskMemAlloc(sizeof (ILanStatusImpl));
1193 if (!This)
1194 return E_OUTOFMEMORY;
1195
1196 This->ref = 1;
1197 This->lpVtbl = (IOleCommandTarget*)&vt_OleCommandTarget;
1198 This->lpNetMan = NULL;
1199 This->pHead = NULL;
1200
1201 if (InterlockedCompareExchangePointer((void **)&cached_This, This, NULL) != NULL)
1202 {
1203 CoTaskMemFree(This);
1204 }
1205
1206 return IOleCommandTarget_fnQueryInterface ((IOleCommandTarget*)cached_This, riid, ppv);
1207 }
1208