mshtml: Keep reference in node returned from get_node.
[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
35 #include "wine/debug.h"
36 #include "wbemprox_private.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
39
40 static const WCHAR class_biosW[] =
41     {'W','i','n','3','2','_','B','I','O','S',0};
42 static const WCHAR class_compsysW[] =
43     {'W','i','n','3','2','_','C','o','m','p','u','t','e','r','S','y','s','t','e','m',0};
44 static const WCHAR class_osW[] =
45     {'W','i','n','3','2','_','O','p','e','r','a','t','i','n','g','S','y','s','t','e','m',0};
46 static const WCHAR class_processW[] =
47     {'W','i','n','3','2','_','P','r','o','c','e','s','s',0};
48 static const WCHAR class_processorW[] =
49     {'W','i','n','3','2','_','P','r','o','c','e','s','s','o','r',0};
50 static const WCHAR class_videocontrollerW[] =
51     {'W','i','n','3','2','_','V','i','d','e','o','C','o','n','t','r','o','l','l','e','r',0};
52 static const WCHAR class_networkadapterW[] =
53     {'W','i','n','3','2','_','N','e','t','w','o','r','k','A','d','a','p','t','e','r',0};
54
55 static const WCHAR prop_adapterramW[] =
56     {'A','d','a','p','t','e','r','R','A','M',0};
57 static const WCHAR prop_captionW[] =
58     {'C','a','p','t','i','o','n',0};
59 static const WCHAR prop_commandlineW[] =
60     {'C','o','m','m','a','n','d','L','i','n','e',0};
61 static const WCHAR prop_descriptionW[] =
62     {'D','e','s','c','r','i','p','t','i','o','n',0};
63 static const WCHAR prop_deviceidW[] =
64     {'D','e','v','i','c','e','I','d',0};
65 static const WCHAR prop_handleW[] =
66     {'H','a','n','d','l','e',0};
67 static const WCHAR prop_interfaceindexW[] =
68     {'I','n','t','e','r','f','a','c','e','I','n','d','e','x',0};
69 static const WCHAR prop_manufacturerW[] =
70     {'M','a','n','u','f','a','c','t','u','r','e','r',0};
71 static const WCHAR prop_modelW[] =
72     {'M','o','d','e','l',0};
73 static const WCHAR prop_netconnectionstatusW[] =
74     {'N','e','t','C','o','n','n','e','c','t','i','o','n','S','t','a','t','u','s',0};
75 static const WCHAR prop_osarchitectureW[] =
76     {'O','S','A','r','c','h','i','t','e','c','t','u','r','e',0};
77 static const WCHAR prop_pprocessidW[] =
78     {'P','a','r','e','n','t','P','r','o','c','e','s','s','I','D',0};
79 static const WCHAR prop_processidW[] =
80     {'P','r','o','c','e','s','s','I','D',0};
81 static const WCHAR prop_releasedateW[] =
82     {'R','e','l','e','a','s','e','D','a','t','e',0};
83 static const WCHAR prop_serialnumberW[] =
84     {'S','e','r','i','a','l','N','u','m','b','e','r',0};
85 static const WCHAR prop_threadcountW[] =
86     {'T','h','r','e','a','d','C','o','u','n','t',0};
87
88 static const struct column col_bios[] =
89 {
90     { prop_descriptionW,  CIM_STRING },
91     { prop_manufacturerW, CIM_STRING },
92     { prop_releasedateW,  CIM_DATETIME },
93     { prop_serialnumberW, CIM_STRING }
94 };
95 static const struct column col_compsys[] =
96 {
97     { prop_descriptionW,  CIM_STRING },
98     { prop_manufacturerW, CIM_STRING },
99     { prop_modelW,        CIM_STRING }
100 };
101 static const struct column col_networkadapter[] =
102 {
103     { prop_deviceidW,            CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
104     { prop_interfaceindexW,      CIM_SINT32 },
105     { prop_netconnectionstatusW, CIM_UINT16 }
106 };
107 static const struct column col_os[] =
108 {
109     { prop_captionW,        CIM_STRING },
110     { prop_osarchitectureW, CIM_STRING }
111 };
112 static const struct column col_process[] =
113 {
114     { prop_captionW,     CIM_STRING|COL_FLAG_DYNAMIC },
115     { prop_commandlineW, CIM_STRING|COL_FLAG_DYNAMIC },
116     { prop_descriptionW, CIM_STRING|COL_FLAG_DYNAMIC },
117     { prop_handleW,      CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
118     { prop_pprocessidW,  CIM_UINT32 },
119     { prop_processidW,   CIM_UINT32 },
120     { prop_threadcountW, CIM_UINT32 }
121 };
122 static const struct column col_processor[] =
123 {
124     { prop_manufacturerW, CIM_STRING }
125 };
126 static const struct column col_videocontroller[] =
127 {
128     { prop_adapterramW,  CIM_UINT32 },
129     { prop_deviceidW,    CIM_STRING|COL_FLAG_KEY }
130 };
131
132 static const WCHAR bios_descriptionW[] =
133     {'D','e','f','a','u','l','t',' ','S','y','s','t','e','m',' ','B','I','O','S',0};
134 static const WCHAR bios_manufacturerW[] =
135     {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0};
136 static const WCHAR bios_releasedateW[] =
137     {'2','0','1','2','0','6','0','8','0','0','0','0','0','0','.','0','0','0','0','0','0','+','0','0','0',0};
138 static const WCHAR bios_serialnumberW[] =
139     {'0',0};
140 static const WCHAR compsys_descriptionW[] =
141     {'A','T','/','A','T',' ','C','O','M','P','A','T','I','B','L','E',0};
142 static const WCHAR compsys_manufacturerW[] =
143     {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0};
144 static const WCHAR compsys_modelW[] =
145     {'W','i','n','e',0};
146 static const WCHAR os_captionW[] =
147     {'W','i','n','e',0};
148 static const WCHAR os_32bitW[] =
149     {'3','2','-','b','i','t',0};
150 static const WCHAR os_64bitW[] =
151     {'6','4','-','b','i','t',0};
152 static const WCHAR processor_manufacturerW[] =
153     {'G','e','n','u','i','n','e','I','n','t','e','l',0};
154 static const WCHAR videocontroller_deviceidW[] =
155     {'V','i','d','e','o','C','o','n','t','r','o','l','l','e','r','1',0};
156
157 #include "pshpack1.h"
158 struct record_bios
159 {
160     const WCHAR *description;
161     const WCHAR *manufacturer;
162     const WCHAR *releasedate;
163     const WCHAR *serialnumber;
164 };
165 struct record_computersystem
166 {
167     const WCHAR *description;
168     const WCHAR *manufacturer;
169     const WCHAR *model;
170 };
171 struct record_networkadapter
172 {
173     const WCHAR *device_id;
174     INT32        interface_index;
175     UINT16       netconnection_status;
176 };
177 struct record_operatingsystem
178 {
179     const WCHAR *caption;
180     const WCHAR *osarchitecture;
181 };
182 struct record_process
183 {
184     const WCHAR *caption;
185     const WCHAR *commandline;
186     const WCHAR *description;
187     const WCHAR *handle;
188     UINT32       pprocess_id;
189     UINT32       process_id;
190     UINT32       thread_count;
191 };
192 struct record_processor
193 {
194     const WCHAR *manufacturer;
195 };
196 struct record_videocontroller
197 {
198     UINT32       adapter_ram;
199     const WCHAR *device_id;
200 };
201 #include "poppack.h"
202
203 static const struct record_bios data_bios[] =
204 {
205     { bios_descriptionW, bios_manufacturerW, bios_releasedateW, bios_serialnumberW }
206 };
207 static const struct record_computersystem data_compsys[] =
208 {
209     { compsys_descriptionW, compsys_manufacturerW, compsys_modelW }
210 };
211 static const struct record_processor data_processor[] =
212 {
213     { processor_manufacturerW }
214 };
215
216 static UINT16 get_connection_status( IF_OPER_STATUS status )
217 {
218     switch (status)
219     {
220     case IfOperStatusDown:
221         return 0; /* Disconnected */
222     case IfOperStatusUp:
223         return 2; /* Connected */
224     default:
225         ERR("unhandled status %u\n", status);
226         break;
227     }
228     return 0;
229 }
230
231 static void fill_networkadapter( struct table *table )
232 {
233     static const WCHAR fmtW[] = {'%','u',0};
234     WCHAR device_id[11];
235     struct record_networkadapter *rec;
236     IP_ADAPTER_ADDRESSES *aa, *buffer;
237     UINT num_rows = 0, offset = 0;
238     DWORD size = 0, ret;
239
240     ret = GetAdaptersAddresses( AF_UNSPEC, 0, NULL, NULL, &size );
241     if (ret != ERROR_BUFFER_OVERFLOW) return;
242
243     if (!(buffer = heap_alloc( size ))) return;
244     if (GetAdaptersAddresses( AF_UNSPEC, 0, NULL, buffer, &size ))
245     {
246         heap_free( buffer );
247         return;
248     }
249     for (aa = buffer; aa; aa = aa->Next) num_rows++;
250     if (!(table->data = heap_alloc( sizeof(*rec) * num_rows )))
251     {
252         heap_free( buffer );
253         return;
254     }
255     for (aa = buffer; aa; aa = aa->Next)
256     {
257         rec = (struct record_networkadapter *)(table->data + offset);
258         sprintfW( device_id, fmtW, aa->u.s.IfIndex );
259         rec->device_id            = heap_strdupW( device_id );
260         rec->interface_index      = aa->u.s.IfIndex;
261         rec->netconnection_status = get_connection_status( aa->OperStatus );
262         offset += sizeof(*rec);
263     }
264     TRACE("created %u rows\n", num_rows);
265     table->num_rows = num_rows;
266
267     heap_free( buffer );
268 }
269
270 static WCHAR *get_cmdline( DWORD process_id )
271 {
272     if (process_id == GetCurrentProcessId()) return heap_strdupW( GetCommandLineW() );
273     return NULL; /* FIXME handle different process case */
274 }
275
276 static void fill_process( struct table *table )
277 {
278     static const WCHAR fmtW[] = {'%','u',0};
279     WCHAR handle[11];
280     struct record_process *rec;
281     PROCESSENTRY32W entry;
282     HANDLE snap;
283     UINT num_rows = 0, offset = 0, count = 8;
284
285     snap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
286     if (snap == INVALID_HANDLE_VALUE) return;
287
288     entry.dwSize = sizeof(entry);
289     if (!Process32FirstW( snap, &entry )) goto done;
290     if (!(table->data = heap_alloc( count * sizeof(*rec) ))) goto done;
291
292     do
293     {
294         if (num_rows > count)
295         {
296             BYTE *data;
297             count *= 2;
298             if (!(data = heap_realloc( table->data, count * sizeof(*rec) ))) goto done;
299             table->data = data;
300         }
301         rec = (struct record_process *)(table->data + offset);
302         rec->caption      = heap_strdupW( entry.szExeFile );
303         rec->commandline  = get_cmdline( entry.th32ProcessID );
304         rec->description  = heap_strdupW( entry.szExeFile );
305         sprintfW( handle, fmtW, entry.th32ProcessID );
306         rec->handle       = heap_strdupW( handle );
307         rec->process_id   = entry.th32ProcessID;
308         rec->pprocess_id  = entry.th32ParentProcessID;
309         rec->thread_count = entry.cntThreads;
310         offset += sizeof(*rec);
311         num_rows++;
312     } while (Process32NextW( snap, &entry ));
313
314     TRACE("created %u rows\n", num_rows);
315     table->num_rows = num_rows;
316
317 done:
318     CloseHandle( snap );
319 }
320
321 static void fill_os( struct table *table )
322 {
323     struct record_operatingsystem *rec;
324     SYSTEM_INFO info;
325
326     if (!(table->data = heap_alloc( sizeof(*rec) ))) return;
327
328     rec = (struct record_operatingsystem *)table->data;
329     rec->caption = os_captionW;
330
331     GetNativeSystemInfo( &info );
332     if (info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
333         rec->osarchitecture = os_64bitW;
334     else
335         rec->osarchitecture = os_32bitW;
336
337     TRACE("created 1 row\n");
338     table->num_rows = 1;
339 }
340
341 static void fill_videocontroller( struct table *table )
342 {
343
344     struct record_videocontroller *rec;
345     HRESULT hr;
346     IDXGIFactory *factory = NULL;
347     IDXGIAdapter *adapter = NULL;
348     DXGI_ADAPTER_DESC desc;
349     UINT vidmem = 512 * 1024 * 1024;
350
351     if (!(table->data = heap_alloc( sizeof(*rec) ))) return;
352
353     hr = CreateDXGIFactory( &IID_IDXGIFactory, (void **)&factory );
354     if (FAILED(hr)) goto done;
355
356     hr = IDXGIFactory_EnumAdapters( factory, 0, &adapter );
357     if (FAILED(hr)) goto done;
358
359     hr = IDXGIAdapter_GetDesc( adapter, &desc );
360     if (SUCCEEDED(hr)) vidmem = desc.DedicatedVideoMemory;
361
362 done:
363     rec = (struct record_videocontroller *)table->data;
364     rec->device_id   = videocontroller_deviceidW;
365     rec->adapter_ram = vidmem;
366
367     TRACE("created 1 row\n");
368     table->num_rows = 1;
369
370     if (adapter) IDXGIAdapter_Release( adapter );
371     if (factory) IDXGIFactory_Release( factory );
372 }
373
374 static struct table classtable[] =
375 {
376     { class_biosW, SIZEOF(col_bios), col_bios, SIZEOF(data_bios), (BYTE *)data_bios, NULL },
377     { class_compsysW, SIZEOF(col_compsys), col_compsys, SIZEOF(data_compsys), (BYTE *)data_compsys, NULL },
378     { class_networkadapterW, SIZEOF(col_networkadapter), col_networkadapter, 0, NULL, fill_networkadapter },
379     { class_osW, SIZEOF(col_os), col_os, 0, NULL, fill_os },
380     { class_processW, SIZEOF(col_process), col_process, 0, NULL, fill_process },
381     { class_processorW, SIZEOF(col_processor), col_processor, SIZEOF(data_processor), (BYTE *)data_processor, NULL },
382     { class_videocontrollerW, SIZEOF(col_videocontroller), col_videocontroller, 0, NULL, fill_videocontroller }
383 };
384
385 struct table *get_table( const WCHAR *name )
386 {
387     UINT i;
388     struct table *table = NULL;
389
390     for (i = 0; i < SIZEOF(classtable); i++)
391     {
392         if (!strcmpiW( classtable[i].name, name ))
393         {
394             table = &classtable[i];
395             if (table->fill && !table->data) table->fill( table );
396             break;
397         }
398     }
399     return table;
400 }