mshtml: Return referenced object in get_node_obj.
[wine] / dlls / wbemprox / builtin.c
1 /*
2  * Copyright 2012 Hans Leidekker for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #define COBJMACROS
20 #define NONAMELESSUNION
21 #define NONAMELESSSTRUCT
22
23 #include "config.h"
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wbemcli.h"
29 #include "winsock2.h"
30 #include "iphlpapi.h"
31 #include "tlhelp32.h"
32 #include "initguid.h"
33 #include "d3d10.h"
34 #include "winternl.h"
35
36 #include "wine/debug.h"
37 #include "wbemprox_private.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
40
41 static const WCHAR class_biosW[] =
42     {'W','i','n','3','2','_','B','I','O','S',0};
43 static const WCHAR class_compsysW[] =
44     {'W','i','n','3','2','_','C','o','m','p','u','t','e','r','S','y','s','t','e','m',0};
45 static const WCHAR class_networkadapterW[] =
46     {'W','i','n','3','2','_','N','e','t','w','o','r','k','A','d','a','p','t','e','r',0};
47 static const WCHAR class_osW[] =
48     {'W','i','n','3','2','_','O','p','e','r','a','t','i','n','g','S','y','s','t','e','m',0};
49 static const WCHAR class_processW[] =
50     {'W','i','n','3','2','_','P','r','o','c','e','s','s',0};
51 static const WCHAR class_processorW[] =
52     {'W','i','n','3','2','_','P','r','o','c','e','s','s','o','r',0};
53 static const WCHAR class_videocontrollerW[] =
54     {'W','i','n','3','2','_','V','i','d','e','o','C','o','n','t','r','o','l','l','e','r',0};
55
56 static const WCHAR prop_adapterramW[] =
57     {'A','d','a','p','t','e','r','R','A','M',0};
58 static const WCHAR prop_captionW[] =
59     {'C','a','p','t','i','o','n',0};
60 static const WCHAR prop_csdversionW[] =
61     {'C','S','D','V','e','r','s','i','o','n',0};
62 static const WCHAR prop_commandlineW[] =
63     {'C','o','m','m','a','n','d','L','i','n','e',0};
64 static const WCHAR prop_cpustatusW[] =
65     {'C','p','u','S','t','a','t','u','s',0};
66 static const WCHAR prop_currentbitsperpixelW[] =
67     {'C','u','r','r','e','n','t','B','i','t','s','P','e','r','P','i','x','e','l',0};
68 static const WCHAR prop_currenthorizontalresW[] =
69     {'C','u','r','r','e','n','t','H','o','r','i','z','o','n','t','a','l','R','e','s','o','l','u','t','i','o','n',0};
70 static const WCHAR prop_currentverticalresW[] =
71     {'C','u','r','r','e','n','t','V','e','r','t','i','c','a','l','R','e','s','o','l','u','t','i','o','n',0};
72 static const WCHAR prop_descriptionW[] =
73     {'D','e','s','c','r','i','p','t','i','o','n',0};
74 static const WCHAR prop_deviceidW[] =
75     {'D','e','v','i','c','e','I','d',0};
76 static const WCHAR prop_handleW[] =
77     {'H','a','n','d','l','e',0};
78 static const WCHAR prop_interfaceindexW[] =
79     {'I','n','t','e','r','f','a','c','e','I','n','d','e','x',0};
80 static const WCHAR prop_manufacturerW[] =
81     {'M','a','n','u','f','a','c','t','u','r','e','r',0};
82 static const WCHAR prop_modelW[] =
83     {'M','o','d','e','l',0};
84 static const WCHAR prop_nameW[] =
85     {'N','a','m','e',0};
86 static const WCHAR prop_netconnectionstatusW[] =
87     {'N','e','t','C','o','n','n','e','c','t','i','o','n','S','t','a','t','u','s',0};
88 static const WCHAR prop_numlogicalprocessorsW[] =
89     {'N','u','m','b','e','r','O','f','L','o','g','i','c','a','l','P','r','o','c','e','s','s','o','r','s',0};
90 static const WCHAR prop_numprocessorsW[] =
91     {'N','u','m','b','e','r','O','f','P','r','o','c','e','s','s','o','r','s',0};
92 static const WCHAR prop_osarchitectureW[] =
93     {'O','S','A','r','c','h','i','t','e','c','t','u','r','e',0};
94 static const WCHAR prop_oslanguageW[] =
95     {'O','S','L','a','n','g','u','a','g','e',0};
96 static const WCHAR prop_pprocessidW[] =
97     {'P','a','r','e','n','t','P','r','o','c','e','s','s','I','D',0};
98 static const WCHAR prop_processidW[] =
99     {'P','r','o','c','e','s','s','I','D',0};
100 static const WCHAR prop_releasedateW[] =
101     {'R','e','l','e','a','s','e','D','a','t','e',0};
102 static const WCHAR prop_serialnumberW[] =
103     {'S','e','r','i','a','l','N','u','m','b','e','r',0};
104 static const WCHAR prop_speedW[] =
105     {'S','p','e','e','d',0};
106 static const WCHAR prop_systemdirectoryW[] =
107     {'S','y','s','t','e','m','D','i','r','e','c','t','o','r','y',0};
108 static const WCHAR prop_threadcountW[] =
109     {'T','h','r','e','a','d','C','o','u','n','t',0};
110 static const WCHAR prop_totalphysicalmemoryW[] =
111     {'T','o','t','a','l','P','h','y','s','i','c','a','l','M','e','m','o','r','y',0};
112
113 /* column definitions must be kept in sync with record structures below */
114 static const struct column col_bios[] =
115 {
116     { prop_descriptionW,  CIM_STRING },
117     { prop_manufacturerW, CIM_STRING },
118     { prop_releasedateW,  CIM_DATETIME },
119     { prop_serialnumberW, CIM_STRING }
120 };
121 static const struct column col_compsys[] =
122 {
123     { prop_descriptionW,          CIM_STRING },
124     { prop_manufacturerW,         CIM_STRING },
125     { prop_modelW,                CIM_STRING },
126     { prop_numlogicalprocessorsW, CIM_UINT32 },
127     { prop_numprocessorsW,        CIM_UINT32 },
128     { prop_totalphysicalmemoryW,  CIM_UINT64 }
129 };
130 static const struct column col_networkadapter[] =
131 {
132     { prop_deviceidW,            CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
133     { prop_interfaceindexW,      CIM_SINT32 },
134     { prop_netconnectionstatusW, CIM_UINT16 },
135     { prop_speedW,               CIM_UINT64 }
136 };
137 static const struct column col_os[] =
138 {
139     { prop_captionW,         CIM_STRING },
140     { prop_csdversionW,      CIM_STRING },
141     { prop_osarchitectureW,  CIM_STRING },
142     { prop_oslanguageW,      CIM_UINT32 },
143     { prop_systemdirectoryW, CIM_STRING }
144 };
145 static const struct column col_process[] =
146 {
147     { prop_captionW,     CIM_STRING|COL_FLAG_DYNAMIC },
148     { prop_commandlineW, CIM_STRING|COL_FLAG_DYNAMIC },
149     { prop_descriptionW, CIM_STRING|COL_FLAG_DYNAMIC },
150     { prop_handleW,      CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
151     { prop_pprocessidW,  CIM_UINT32 },
152     { prop_processidW,   CIM_UINT32 },
153     { prop_threadcountW, CIM_UINT32 }
154 };
155 static const struct column col_processor[] =
156 {
157     { prop_cpustatusW,    CIM_UINT16 },
158     { prop_deviceidW,     CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
159     { prop_manufacturerW, CIM_STRING }
160 };
161 static const struct column col_videocontroller[] =
162 {
163     { prop_adapterramW,           CIM_UINT32 },
164     { prop_currentbitsperpixelW,  CIM_UINT32 },
165     { prop_currenthorizontalresW, CIM_UINT32 },
166     { prop_currentverticalresW,   CIM_UINT32 },
167     { prop_deviceidW,             CIM_STRING|COL_FLAG_KEY },
168     { prop_nameW,                 CIM_STRING|COL_FLAG_DYNAMIC }
169 };
170
171 static const WCHAR bios_descriptionW[] =
172     {'D','e','f','a','u','l','t',' ','S','y','s','t','e','m',' ','B','I','O','S',0};
173 static const WCHAR bios_manufacturerW[] =
174     {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0};
175 static const WCHAR bios_releasedateW[] =
176     {'2','0','1','2','0','6','0','8','0','0','0','0','0','0','.','0','0','0','0','0','0','+','0','0','0',0};
177 static const WCHAR bios_serialnumberW[] =
178     {'0',0};
179 static const WCHAR compsys_descriptionW[] =
180     {'A','T','/','A','T',' ','C','O','M','P','A','T','I','B','L','E',0};
181 static const WCHAR compsys_manufacturerW[] =
182     {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0};
183 static const WCHAR compsys_modelW[] =
184     {'W','i','n','e',0};
185 static const WCHAR os_captionW[] =
186     {'M','i','c','r','o','s','o','f','t',' ','W','i','n','d','o','w','s',' ','X','P',' ',
187      'V','e','r','s','i','o','n',' ','=',' ','5','.','1','.','2','6','0','0',0};
188 static const WCHAR os_csdversionW[] =
189     {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','3',0};
190 static const WCHAR os_32bitW[] =
191     {'3','2','-','b','i','t',0};
192 static const WCHAR os_64bitW[] =
193     {'6','4','-','b','i','t',0};
194 static const WCHAR processor_manufacturerW[] =
195     {'G','e','n','u','i','n','e','I','n','t','e','l',0};
196 static const WCHAR videocontroller_deviceidW[] =
197     {'V','i','d','e','o','C','o','n','t','r','o','l','l','e','r','1',0};
198
199 #include "pshpack1.h"
200 struct record_bios
201 {
202     const WCHAR *description;
203     const WCHAR *manufacturer;
204     const WCHAR *releasedate;
205     const WCHAR *serialnumber;
206 };
207 struct record_computersystem
208 {
209     const WCHAR *description;
210     const WCHAR *manufacturer;
211     const WCHAR *model;
212     UINT32       num_logical_processors;
213     UINT32       num_processors;
214     UINT64       total_physical_memory;
215 };
216 struct record_networkadapter
217 {
218     const WCHAR *device_id;
219     INT32        interface_index;
220     UINT16       netconnection_status;
221     UINT64       speed;
222 };
223 struct record_operatingsystem
224 {
225     const WCHAR *caption;
226     const WCHAR *csdversion;
227     const WCHAR *osarchitecture;
228     UINT32       oslanguage;
229     const WCHAR *systemdirectory;
230 };
231 struct record_process
232 {
233     const WCHAR *caption;
234     const WCHAR *commandline;
235     const WCHAR *description;
236     const WCHAR *handle;
237     UINT32       pprocess_id;
238     UINT32       process_id;
239     UINT32       thread_count;
240 };
241 struct record_processor
242 {
243     UINT16       cpu_status;
244     const WCHAR *device_id;
245     const WCHAR *manufacturer;
246 };
247 struct record_videocontroller
248 {
249     UINT32       adapter_ram;
250     UINT32       current_bitsperpixel;
251     UINT32       current_horizontalres;
252     UINT32       current_verticalres;
253     const WCHAR *device_id;
254     const WCHAR *name;
255 };
256 #include "poppack.h"
257
258 static const struct record_bios data_bios[] =
259 {
260     { bios_descriptionW, bios_manufacturerW, bios_releasedateW, bios_serialnumberW }
261 };
262
263 static UINT get_processor_count(void)
264 {
265     SYSTEM_BASIC_INFORMATION info;
266
267     if (NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL )) return 1;
268     return info.NumberOfProcessors;
269 }
270
271 static UINT64 get_total_physical_memory(void)
272 {
273     MEMORYSTATUSEX status;
274
275     status.dwLength = sizeof(status);
276     if (!GlobalMemoryStatusEx( &status )) return 1024 * 1024 * 1024;
277     return status.ullTotalPhys;
278 }
279
280 static void fill_compsys( struct table *table )
281 {
282     struct record_computersystem *rec;
283
284     if (!(table->data = heap_alloc( sizeof(*rec) ))) return;
285
286     rec = (struct record_computersystem *)table->data;
287     rec->description            = compsys_descriptionW;
288     rec->manufacturer           = compsys_manufacturerW;
289     rec->model                  = compsys_modelW;
290     rec->num_logical_processors = get_processor_count();
291     rec->num_processors         = rec->num_logical_processors;
292     rec->total_physical_memory  = get_total_physical_memory();
293
294     TRACE("created 1 row\n");
295     table->num_rows = 1;
296 }
297
298 static UINT16 get_connection_status( IF_OPER_STATUS status )
299 {
300     switch (status)
301     {
302     case IfOperStatusDown:
303         return 0; /* Disconnected */
304     case IfOperStatusUp:
305         return 2; /* Connected */
306     default:
307         ERR("unhandled status %u\n", status);
308         break;
309     }
310     return 0;
311 }
312
313 static void fill_networkadapter( struct table *table )
314 {
315     static const WCHAR fmtW[] = {'%','u',0};
316     WCHAR device_id[11];
317     struct record_networkadapter *rec;
318     IP_ADAPTER_ADDRESSES *aa, *buffer;
319     UINT num_rows = 0, offset = 0;
320     DWORD size = 0, ret;
321
322     ret = GetAdaptersAddresses( AF_UNSPEC, 0, NULL, NULL, &size );
323     if (ret != ERROR_BUFFER_OVERFLOW) return;
324
325     if (!(buffer = heap_alloc( size ))) return;
326     if (GetAdaptersAddresses( AF_UNSPEC, 0, NULL, buffer, &size ))
327     {
328         heap_free( buffer );
329         return;
330     }
331     for (aa = buffer; aa; aa = aa->Next) num_rows++;
332     if (!(table->data = heap_alloc( sizeof(*rec) * num_rows )))
333     {
334         heap_free( buffer );
335         return;
336     }
337     for (aa = buffer; aa; aa = aa->Next)
338     {
339         rec = (struct record_networkadapter *)(table->data + offset);
340         sprintfW( device_id, fmtW, aa->u.s.IfIndex );
341         rec->device_id            = heap_strdupW( device_id );
342         rec->interface_index      = aa->u.s.IfIndex;
343         rec->netconnection_status = get_connection_status( aa->OperStatus );
344         rec->speed                = 1000000;
345         offset += sizeof(*rec);
346     }
347     TRACE("created %u rows\n", num_rows);
348     table->num_rows = num_rows;
349
350     heap_free( buffer );
351 }
352
353 static WCHAR *get_cmdline( DWORD process_id )
354 {
355     if (process_id == GetCurrentProcessId()) return heap_strdupW( GetCommandLineW() );
356     return NULL; /* FIXME handle different process case */
357 }
358
359 static void fill_process( struct table *table )
360 {
361     static const WCHAR fmtW[] = {'%','u',0};
362     WCHAR handle[11];
363     struct record_process *rec;
364     PROCESSENTRY32W entry;
365     HANDLE snap;
366     UINT num_rows = 0, offset = 0, count = 8;
367
368     snap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
369     if (snap == INVALID_HANDLE_VALUE) return;
370
371     entry.dwSize = sizeof(entry);
372     if (!Process32FirstW( snap, &entry )) goto done;
373     if (!(table->data = heap_alloc( count * sizeof(*rec) ))) goto done;
374
375     do
376     {
377         if (num_rows > count)
378         {
379             BYTE *data;
380             count *= 2;
381             if (!(data = heap_realloc( table->data, count * sizeof(*rec) ))) goto done;
382             table->data = data;
383         }
384         rec = (struct record_process *)(table->data + offset);
385         rec->caption      = heap_strdupW( entry.szExeFile );
386         rec->commandline  = get_cmdline( entry.th32ProcessID );
387         rec->description  = heap_strdupW( entry.szExeFile );
388         sprintfW( handle, fmtW, entry.th32ProcessID );
389         rec->handle       = heap_strdupW( handle );
390         rec->process_id   = entry.th32ProcessID;
391         rec->pprocess_id  = entry.th32ParentProcessID;
392         rec->thread_count = entry.cntThreads;
393         offset += sizeof(*rec);
394         num_rows++;
395     } while (Process32NextW( snap, &entry ));
396
397     TRACE("created %u rows\n", num_rows);
398     table->num_rows = num_rows;
399
400 done:
401     CloseHandle( snap );
402 }
403
404 static void fill_processor( struct table *table )
405 {
406     static const WCHAR fmtW[] = {'C','P','U','%','u',0};
407     WCHAR device_id[14];
408     struct record_processor *rec;
409     UINT i, offset = 0, count = get_processor_count();
410
411     if (!(table->data = heap_alloc( sizeof(*rec) * count ))) return;
412
413     for (i = 0; i < count; i++)
414     {
415         rec = (struct record_processor *)(table->data + offset);
416         rec->cpu_status   = 1; /* CPU Enabled */
417         rec->manufacturer = processor_manufacturerW;
418         sprintfW( device_id, fmtW, i );
419         rec->device_id    = heap_strdupW( device_id );
420         offset += sizeof(*rec);
421     }
422
423     TRACE("created %u rows\n", count);
424     table->num_rows = count;
425 }
426
427 static void fill_os( struct table *table )
428 {
429     struct record_operatingsystem *rec;
430     WCHAR path[MAX_PATH];
431     SYSTEM_INFO info;
432     void *redir;
433
434     if (!(table->data = heap_alloc( sizeof(*rec) ))) return;
435
436     rec = (struct record_operatingsystem *)table->data;
437     rec->caption    = os_captionW;
438     rec->csdversion = os_csdversionW;
439
440     GetNativeSystemInfo( &info );
441     if (info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
442         rec->osarchitecture = os_64bitW;
443     else
444         rec->osarchitecture = os_32bitW;
445
446     rec->oslanguage = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
447
448     Wow64DisableWow64FsRedirection( &redir );
449     GetSystemDirectoryW( path, MAX_PATH );
450     Wow64RevertWow64FsRedirection( redir );
451     rec->systemdirectory = heap_strdupW( path );
452
453     TRACE("created 1 row\n");
454     table->num_rows = 1;
455 }
456
457 static UINT32 get_bits_per_pixel( UINT *hres, UINT *vres )
458 {
459     HDC hdc = GetDC( NULL );
460     UINT32 ret;
461
462     if (!hdc) return 32;
463     ret = GetDeviceCaps( hdc, BITSPIXEL );
464     *hres = GetDeviceCaps( hdc, HORZRES );
465     *vres = GetDeviceCaps( hdc, VERTRES );
466     ReleaseDC( NULL, hdc );
467     return ret;
468 }
469
470 static void fill_videocontroller( struct table *table )
471 {
472
473     struct record_videocontroller *rec;
474     HRESULT hr;
475     IDXGIFactory *factory = NULL;
476     IDXGIAdapter *adapter = NULL;
477     DXGI_ADAPTER_DESC desc;
478     UINT hres = 1024, vres = 768, vidmem = 512 * 1024 * 1024;
479     const WCHAR *name = videocontroller_deviceidW;
480
481     if (!(table->data = heap_alloc( sizeof(*rec) ))) return;
482
483     hr = CreateDXGIFactory( &IID_IDXGIFactory, (void **)&factory );
484     if (FAILED(hr)) goto done;
485
486     hr = IDXGIFactory_EnumAdapters( factory, 0, &adapter );
487     if (FAILED(hr)) goto done;
488
489     hr = IDXGIAdapter_GetDesc( adapter, &desc );
490     if (SUCCEEDED(hr))
491     {
492         vidmem = desc.DedicatedVideoMemory;
493         name   = desc.Description;
494     }
495
496 done:
497     rec = (struct record_videocontroller *)table->data;
498     rec->adapter_ram           = vidmem;
499     rec->current_bitsperpixel  = get_bits_per_pixel( &hres, &vres );
500     rec->current_horizontalres = hres;
501     rec->current_verticalres   = vres;
502     rec->device_id             = videocontroller_deviceidW;
503     rec->name                  = heap_strdupW( name );
504
505     TRACE("created 1 row\n");
506     table->num_rows = 1;
507
508     if (adapter) IDXGIAdapter_Release( adapter );
509     if (factory) IDXGIFactory_Release( factory );
510 }
511
512 static struct table classtable[] =
513 {
514     { class_biosW, SIZEOF(col_bios), col_bios, SIZEOF(data_bios), (BYTE *)data_bios, NULL },
515     { class_compsysW, SIZEOF(col_compsys), col_compsys, 0, NULL, fill_compsys },
516     { class_networkadapterW, SIZEOF(col_networkadapter), col_networkadapter, 0, NULL, fill_networkadapter },
517     { class_osW, SIZEOF(col_os), col_os, 0, NULL, fill_os },
518     { class_processW, SIZEOF(col_process), col_process, 0, NULL, fill_process },
519     { class_processorW, SIZEOF(col_processor), col_processor, 0, NULL, fill_processor },
520     { class_videocontrollerW, SIZEOF(col_videocontroller), col_videocontroller, 0, NULL, fill_videocontroller }
521 };
522
523 struct table *get_table( const WCHAR *name )
524 {
525     UINT i;
526     struct table *table = NULL;
527
528     for (i = 0; i < SIZEOF(classtable); i++)
529     {
530         if (!strcmpiW( classtable[i].name, name ))
531         {
532             table = &classtable[i];
533             if (table->fill && !table->data) table->fill( table );
534             break;
535         }
536     }
537     return table;
538 }