gdi32: Clip solid pen regions to the DIB rectangle to avoid overflows.
[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 #include "winioctl.h"
36 #include "winsvc.h"
37
38 #include "wine/debug.h"
39 #include "wbemprox_private.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
42
43 static const WCHAR class_baseboardW[] =
44     {'W','i','n','3','2','_','B','a','s','e','B','o','a','r','d',0};
45 static const WCHAR class_biosW[] =
46     {'W','i','n','3','2','_','B','I','O','S',0};
47 static const WCHAR class_compsysW[] =
48     {'W','i','n','3','2','_','C','o','m','p','u','t','e','r','S','y','s','t','e','m',0};
49 static const WCHAR class_logicaldiskW[] =
50     {'W','i','n','3','2','_','L','o','g','i','c','a','l','D','i','s','k',0};
51 static const WCHAR class_networkadapterW[] =
52     {'W','i','n','3','2','_','N','e','t','w','o','r','k','A','d','a','p','t','e','r',0};
53 static const WCHAR class_osW[] =
54     {'W','i','n','3','2','_','O','p','e','r','a','t','i','n','g','S','y','s','t','e','m',0};
55 static const WCHAR class_paramsW[] =
56     {'_','_','P','A','R','A','M','E','T','E','R','S',0};
57 static const WCHAR class_processW[] =
58     {'W','i','n','3','2','_','P','r','o','c','e','s','s',0};
59 static const WCHAR class_processorW[] =
60     {'W','i','n','3','2','_','P','r','o','c','e','s','s','o','r',0};
61 static const WCHAR class_serviceW[] =
62     {'W','i','n','3','2','_','S','e','r','v','i','c','e',0};
63 static const WCHAR class_stdregprovW[] =
64     {'S','t','d','R','e','g','P','r','o','v',0};
65 static const WCHAR class_videocontrollerW[] =
66     {'W','i','n','3','2','_','V','i','d','e','o','C','o','n','t','r','o','l','l','e','r',0};
67
68 static const WCHAR prop_adapterramW[] =
69     {'A','d','a','p','t','e','r','R','A','M',0};
70 static const WCHAR prop_captionW[] =
71     {'C','a','p','t','i','o','n',0};
72 static const WCHAR prop_classW[] =
73     {'C','l','a','s','s',0};
74 static const WCHAR prop_commandlineW[] =
75     {'C','o','m','m','a','n','d','L','i','n','e',0};
76 static const WCHAR prop_cpustatusW[] =
77     {'C','p','u','S','t','a','t','u','s',0};
78 static const WCHAR prop_csdversionW[] =
79     {'C','S','D','V','e','r','s','i','o','n',0};
80 static const WCHAR prop_currentbitsperpixelW[] =
81     {'C','u','r','r','e','n','t','B','i','t','s','P','e','r','P','i','x','e','l',0};
82 static const WCHAR prop_currenthorizontalresW[] =
83     {'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};
84 static const WCHAR prop_currentverticalresW[] =
85     {'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};
86 static const WCHAR prop_defaultvalueW[] =
87     {'D','e','f','a','u','l','t','V','a','l','u','e',0};
88 static const WCHAR prop_descriptionW[] =
89     {'D','e','s','c','r','i','p','t','i','o','n',0};
90 static const WCHAR prop_deviceidW[] =
91     {'D','e','v','i','c','e','I','d',0};
92 static const WCHAR prop_directionW[] =
93     {'D','i','r','e','c','t','i','o','n',0};
94 static const WCHAR prop_displaynameW[] =
95     {'D','i','s','p','l','a','y','N','a','m','e',0};
96 static const WCHAR prop_drivetypeW[] =
97     {'D','r','i','v','e','T','y','p','e',0};
98 static const WCHAR prop_filesystemW[] =
99     {'F','i','l','e','S','y','s','t','e','m',0};
100 static const WCHAR prop_freespaceW[] =
101     {'F','r','e','e','S','p','a','c','e',0};
102 static const WCHAR prop_handleW[] =
103     {'H','a','n','d','l','e',0};
104 static const WCHAR prop_interfaceindexW[] =
105     {'I','n','t','e','r','f','a','c','e','I','n','d','e','x',0};
106 static const WCHAR prop_macaddressW[] =
107     {'M','A','C','A','d','d','r','e','s','s',0};
108 static const WCHAR prop_manufacturerW[] =
109     {'M','a','n','u','f','a','c','t','u','r','e','r',0};
110 static const WCHAR prop_methodW[] =
111     {'M','e','t','h','o','d',0};
112 static const WCHAR prop_modelW[] =
113     {'M','o','d','e','l',0};
114 static const WCHAR prop_nameW[] =
115     {'N','a','m','e',0};
116 static const WCHAR prop_netconnectionstatusW[] =
117     {'N','e','t','C','o','n','n','e','c','t','i','o','n','S','t','a','t','u','s',0};
118 static const WCHAR prop_numlogicalprocessorsW[] =
119     {'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};
120 static const WCHAR prop_numprocessorsW[] =
121     {'N','u','m','b','e','r','O','f','P','r','o','c','e','s','s','o','r','s',0};
122 static const WCHAR prop_osarchitectureW[] =
123     {'O','S','A','r','c','h','i','t','e','c','t','u','r','e',0};
124 static const WCHAR prop_oslanguageW[] =
125     {'O','S','L','a','n','g','u','a','g','e',0};
126 static const WCHAR prop_parameterW[] =
127     {'P','a','r','a','m','e','t','e','r',0};
128 static const WCHAR prop_pnpdeviceidW[] =
129     {'P','N','P','D','e','v','i','c','e','I','D',0};
130 static const WCHAR prop_pprocessidW[] =
131     {'P','a','r','e','n','t','P','r','o','c','e','s','s','I','D',0};
132 static const WCHAR prop_processidW[] =
133     {'P','r','o','c','e','s','s','I','D',0};
134 static const WCHAR prop_processoridW[] =
135     {'P','r','o','c','e','s','s','o','r','I','d',0};
136 static const WCHAR prop_releasedateW[] =
137     {'R','e','l','e','a','s','e','D','a','t','e',0};
138 static const WCHAR prop_serialnumberW[] =
139     {'S','e','r','i','a','l','N','u','m','b','e','r',0};
140 static const WCHAR prop_servicetypeW[] =
141     {'S','e','r','v','i','c','e','T','y','p','e',0};
142 static const WCHAR prop_sizeW[] =
143     {'S','i','z','e',0};
144 static const WCHAR prop_speedW[] =
145     {'S','p','e','e','d',0};
146 static const WCHAR prop_stateW[] =
147     {'S','t','a','t','e',0};
148 static const WCHAR prop_systemdirectoryW[] =
149     {'S','y','s','t','e','m','D','i','r','e','c','t','o','r','y',0};
150 static const WCHAR prop_tagW[] =
151     {'T','a','g',0};
152 static const WCHAR prop_threadcountW[] =
153     {'T','h','r','e','a','d','C','o','u','n','t',0};
154 static const WCHAR prop_totalphysicalmemoryW[] =
155     {'T','o','t','a','l','P','h','y','s','i','c','a','l','M','e','m','o','r','y',0};
156 static const WCHAR prop_typeW[] =
157     {'T','y','p','e',0};
158
159 static const WCHAR method_enumkeyW[] =
160     {'E','n','u','m','K','e','y',0};
161 static const WCHAR method_enumvaluesW[] =
162     {'E','n','u','m','V','a','l','u','e','s',0};
163
164 static const WCHAR param_defkeyW[] =
165     {'h','D','e','f','K','e','y',0};
166 static const WCHAR param_namesW[] =
167     {'N','a','m','e','s',0};
168 static const WCHAR param_returnvalueW[] =
169     {'R','e','t','u','r','n','V','a','l','u','e',0};
170 static const WCHAR param_subkeynameW[] =
171     {'s','S','u','b','K','e','y','N','a','m','e',0};
172 static const WCHAR param_typesW[] =
173     {'T','y','p','e','s',0};
174
175 /* column definitions must be kept in sync with record structures below */
176 static const struct column col_baseboard[] =
177 {
178     { prop_manufacturerW,  CIM_STRING },
179     { prop_serialnumberW,  CIM_STRING },
180     { prop_tagW,           CIM_STRING|COL_FLAG_KEY }
181 };
182 static const struct column col_bios[] =
183 {
184     { prop_descriptionW,  CIM_STRING },
185     { prop_manufacturerW, CIM_STRING },
186     { prop_releasedateW,  CIM_DATETIME },
187     { prop_serialnumberW, CIM_STRING }
188 };
189 static const struct column col_compsys[] =
190 {
191     { prop_descriptionW,          CIM_STRING },
192     { prop_manufacturerW,         CIM_STRING },
193     { prop_modelW,                CIM_STRING },
194     { prop_numlogicalprocessorsW, CIM_UINT32, VT_I4 },
195     { prop_numprocessorsW,        CIM_UINT32, VT_I4 },
196     { prop_totalphysicalmemoryW,  CIM_UINT64 }
197 };
198 static const struct column col_logicaldisk[] =
199 {
200     { prop_deviceidW,   CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
201     { prop_drivetypeW,  CIM_UINT32, VT_I4 },
202     { prop_filesystemW, CIM_STRING|COL_FLAG_DYNAMIC },
203     { prop_freespaceW,  CIM_UINT64 },
204     { prop_sizeW,       CIM_UINT64 }
205 };
206 static const struct column col_networkadapter[] =
207 {
208     { prop_deviceidW,            CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
209     { prop_interfaceindexW,      CIM_UINT32, VT_I4 },
210     { prop_macaddressW,          CIM_STRING|COL_FLAG_DYNAMIC },
211     { prop_netconnectionstatusW, CIM_UINT16, VT_I4 },
212     { prop_pnpdeviceidW,         CIM_STRING },
213     { prop_speedW,               CIM_UINT64 }
214 };
215 static const struct column col_os[] =
216 {
217     { prop_captionW,         CIM_STRING },
218     { prop_csdversionW,      CIM_STRING },
219     { prop_osarchitectureW,  CIM_STRING },
220     { prop_oslanguageW,      CIM_UINT32, VT_I4 },
221     { prop_systemdirectoryW, CIM_STRING }
222 };
223 static const struct column col_params[] =
224 {
225     { prop_classW,        CIM_STRING },
226     { prop_methodW,       CIM_STRING },
227     { prop_directionW,    CIM_SINT32 },
228     { prop_parameterW,    CIM_STRING },
229     { prop_typeW,         CIM_UINT32 },
230     { prop_defaultvalueW, CIM_UINT32 }
231 };
232 static const struct column col_process[] =
233 {
234     { prop_captionW,     CIM_STRING|COL_FLAG_DYNAMIC },
235     { prop_commandlineW, CIM_STRING|COL_FLAG_DYNAMIC },
236     { prop_descriptionW, CIM_STRING|COL_FLAG_DYNAMIC },
237     { prop_handleW,      CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
238     { prop_pprocessidW,  CIM_UINT32, VT_I4 },
239     { prop_processidW,   CIM_UINT32, VT_I4 },
240     { prop_threadcountW, CIM_UINT32, VT_I4 }
241 };
242 static const struct column col_processor[] =
243 {
244     { prop_cpustatusW,    CIM_UINT16 },
245     { prop_deviceidW,     CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
246     { prop_manufacturerW, CIM_STRING|COL_FLAG_DYNAMIC },
247     { prop_nameW,         CIM_STRING|COL_FLAG_DYNAMIC },
248     { prop_processoridW,  CIM_STRING|COL_FLAG_DYNAMIC }
249 };
250 static const struct column col_service[] =
251 {
252     { prop_displaynameW,      CIM_STRING|COL_FLAG_DYNAMIC },
253     { prop_nameW,             CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
254     { prop_processidW,        CIM_UINT32 },
255     { prop_servicetypeW,      CIM_STRING },
256     { prop_stateW,            CIM_STRING }
257 };
258 static const struct column col_stdregprov[] =
259 {
260     { method_enumkeyW,    CIM_OBJECT|COL_FLAG_METHOD },
261     { method_enumvaluesW, CIM_OBJECT|COL_FLAG_METHOD }
262 };
263 static const struct column col_videocontroller[] =
264 {
265     { prop_adapterramW,           CIM_UINT32 },
266     { prop_currentbitsperpixelW,  CIM_UINT32 },
267     { prop_currenthorizontalresW, CIM_UINT32 },
268     { prop_currentverticalresW,   CIM_UINT32 },
269     { prop_deviceidW,             CIM_STRING|COL_FLAG_KEY },
270     { prop_nameW,                 CIM_STRING|COL_FLAG_DYNAMIC }
271 };
272
273 static const WCHAR baseboard_manufacturerW[] =
274     {'I','n','t','e','l',' ','C','o','r','p','o','r','a','t','i','o','n',0};
275 static const WCHAR baseboard_serialnumberW[] =
276     {'N','o','n','e',0};
277 static const WCHAR baseboard_tagW[] =
278     {'B','a','s','e',' ','B','o','a','r','d',0};
279 static const WCHAR bios_descriptionW[] =
280     {'D','e','f','a','u','l','t',' ','S','y','s','t','e','m',' ','B','I','O','S',0};
281 static const WCHAR bios_manufacturerW[] =
282     {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0};
283 static const WCHAR bios_releasedateW[] =
284     {'2','0','1','2','0','6','0','8','0','0','0','0','0','0','.','0','0','0','0','0','0','+','0','0','0',0};
285 static const WCHAR bios_serialnumberW[] =
286     {'0',0};
287 static const WCHAR compsys_descriptionW[] =
288     {'A','T','/','A','T',' ','C','O','M','P','A','T','I','B','L','E',0};
289 static const WCHAR compsys_manufacturerW[] =
290     {'T','h','e',' ','W','i','n','e',' ','P','r','o','j','e','c','t',0};
291 static const WCHAR compsys_modelW[] =
292     {'W','i','n','e',0};
293 static const WCHAR networkadapter_pnpdeviceidW[]=
294     {'P','C','I','\\','V','E','N','_','8','0','8','6','&','D','E','V','_','1','0','0','E','&',
295      'S','U','B','S','Y','S','_','0','0','1','E','8','0','8','6','&','R','E','V','_','0','2','\\',
296      '3','&','2','6','7','A','6','1','6','A','&','1','&','1','8',0};
297 static const WCHAR os_captionW[] =
298     {'M','i','c','r','o','s','o','f','t',' ','W','i','n','d','o','w','s',' ','X','P',' ',
299      'V','e','r','s','i','o','n',' ','=',' ','5','.','1','.','2','6','0','0',0};
300 static const WCHAR os_csdversionW[] =
301     {'S','e','r','v','i','c','e',' ','P','a','c','k',' ','3',0};
302 static const WCHAR os_32bitW[] =
303     {'3','2','-','b','i','t',0};
304 static const WCHAR os_64bitW[] =
305     {'6','4','-','b','i','t',0};
306 static const WCHAR videocontroller_deviceidW[] =
307     {'V','i','d','e','o','C','o','n','t','r','o','l','l','e','r','1',0};
308
309 #include "pshpack1.h"
310 struct record_baseboard
311 {
312     const WCHAR *manufacturer;
313     const WCHAR *serialnumber;
314     const WCHAR *tag;
315 };
316 struct record_bios
317 {
318     const WCHAR *description;
319     const WCHAR *manufacturer;
320     const WCHAR *releasedate;
321     const WCHAR *serialnumber;
322 };
323 struct record_computersystem
324 {
325     const WCHAR *description;
326     const WCHAR *manufacturer;
327     const WCHAR *model;
328     UINT32       num_logical_processors;
329     UINT32       num_processors;
330     UINT64       total_physical_memory;
331 };
332 struct record_logicaldisk
333 {
334     const WCHAR *device_id;
335     UINT32       drivetype;
336     const WCHAR *filesystem;
337     UINT64       freespace;
338     UINT64       size;
339 };
340 struct record_networkadapter
341 {
342     const WCHAR *device_id;
343     INT32        interface_index;
344     const WCHAR *mac_address;
345     UINT16       netconnection_status;
346     const WCHAR *pnpdevice_id;
347     UINT64       speed;
348 };
349 struct record_operatingsystem
350 {
351     const WCHAR *caption;
352     const WCHAR *csdversion;
353     const WCHAR *osarchitecture;
354     UINT32       oslanguage;
355     const WCHAR *systemdirectory;
356 };
357 struct record_params
358 {
359     const WCHAR *class;
360     const WCHAR *method;
361     INT32        direction;
362     const WCHAR *parameter;
363     UINT32       type;
364     UINT32       defaultvalue;
365 };
366 struct record_process
367 {
368     const WCHAR *caption;
369     const WCHAR *commandline;
370     const WCHAR *description;
371     const WCHAR *handle;
372     UINT32       pprocess_id;
373     UINT32       process_id;
374     UINT32       thread_count;
375 };
376 struct record_processor
377 {
378     UINT16       cpu_status;
379     const WCHAR *device_id;
380     const WCHAR *manufacturer;
381     const WCHAR *name;
382     const WCHAR *processor_id;
383 };
384 struct record_service
385 {
386     const WCHAR *displayname;
387     const WCHAR *name;
388     UINT32       process_id;
389     const WCHAR *servicetype;
390     const WCHAR *state;
391 };
392 struct record_stdregprov
393 {
394     class_method *enumkey;
395     class_method *enumvalues;
396 };
397 struct record_videocontroller
398 {
399     UINT32       adapter_ram;
400     UINT32       current_bitsperpixel;
401     UINT32       current_horizontalres;
402     UINT32       current_verticalres;
403     const WCHAR *device_id;
404     const WCHAR *name;
405 };
406 #include "poppack.h"
407
408 static HRESULT reg_enumkey( IWbemClassObject *in, IWbemClassObject **out )
409 {
410     FIXME("\n");
411     return E_NOTIMPL;
412 }
413 static HRESULT reg_enumvalues( IWbemClassObject *in, IWbemClassObject **out )
414 {
415     FIXME("\n");
416     return E_NOTIMPL;
417 }
418
419 static const struct record_baseboard data_baseboard[] =
420 {
421     { baseboard_manufacturerW, baseboard_serialnumberW, baseboard_tagW }
422 };
423 static const struct record_bios data_bios[] =
424 {
425     { bios_descriptionW, bios_manufacturerW, bios_releasedateW, bios_serialnumberW }
426 };
427 static const struct record_params data_params[] =
428 {
429     { class_stdregprovW, method_enumkeyW, 1, param_defkeyW, CIM_UINT32, 0x80000002 },
430     { class_stdregprovW, method_enumkeyW, 1, param_subkeynameW, CIM_STRING },
431     { class_stdregprovW, method_enumkeyW, -1, param_returnvalueW, CIM_UINT32 },
432     { class_stdregprovW, method_enumkeyW, -1, param_namesW, CIM_STRING|CIM_FLAG_ARRAY },
433     { class_stdregprovW, method_enumvaluesW, 1, param_defkeyW, CIM_UINT32, 0x80000002 },
434     { class_stdregprovW, method_enumvaluesW, 1, param_subkeynameW, CIM_STRING },
435     { class_stdregprovW, method_enumvaluesW, -1, param_returnvalueW, CIM_UINT32 },
436     { class_stdregprovW, method_enumvaluesW, -1, param_namesW, CIM_STRING|CIM_FLAG_ARRAY },
437     { class_stdregprovW, method_enumvaluesW, -1, param_typesW, CIM_SINT32|CIM_FLAG_ARRAY }
438 };
439 static const struct record_stdregprov data_stdregprov[] =
440 {
441     { reg_enumkey, reg_enumvalues }
442 };
443
444 static UINT get_processor_count(void)
445 {
446     SYSTEM_BASIC_INFORMATION info;
447
448     if (NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL )) return 1;
449     return info.NumberOfProcessors;
450 }
451
452 static UINT64 get_total_physical_memory(void)
453 {
454     MEMORYSTATUSEX status;
455
456     status.dwLength = sizeof(status);
457     if (!GlobalMemoryStatusEx( &status )) return 1024 * 1024 * 1024;
458     return status.ullTotalPhys;
459 }
460
461 static void fill_compsys( struct table *table )
462 {
463     struct record_computersystem *rec;
464
465     if (!(table->data = heap_alloc( sizeof(*rec) ))) return;
466
467     rec = (struct record_computersystem *)table->data;
468     rec->description            = compsys_descriptionW;
469     rec->manufacturer           = compsys_manufacturerW;
470     rec->model                  = compsys_modelW;
471     rec->num_logical_processors = get_processor_count();
472     rec->num_processors         = rec->num_logical_processors;
473     rec->total_physical_memory  = get_total_physical_memory();
474
475     TRACE("created 1 row\n");
476     table->num_rows = 1;
477 }
478
479 static WCHAR *get_filesystem( const WCHAR *root )
480 {
481     static const WCHAR ntfsW[] = {'N','T','F','S',0};
482     WCHAR buffer[MAX_PATH + 1];
483
484     if (GetVolumeInformationW( root, NULL, 0, NULL, NULL, NULL, buffer, MAX_PATH + 1 ))
485         return heap_strdupW( buffer );
486     return heap_strdupW( ntfsW );
487 }
488
489 static UINT64 get_freespace( const WCHAR *dir, UINT64 *disksize )
490 {
491     WCHAR root[] = {'\\','\\','.','\\','A',':',0};
492     ULARGE_INTEGER free;
493     DISK_GEOMETRY_EX info;
494     HANDLE handle;
495
496     free.QuadPart = 512 * 1024 * 1024;
497     GetDiskFreeSpaceExW( dir, NULL, NULL, &free );
498
499     root[4] = dir[0];
500     handle = CreateFileW( root, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
501     if (handle != INVALID_HANDLE_VALUE)
502     {
503         if (DeviceIoControl( handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &info, sizeof(info), NULL, NULL ))
504             *disksize = info.DiskSize.QuadPart;
505         CloseHandle( handle );
506     }
507     return free.QuadPart;
508 }
509
510 static void fill_logicaldisk( struct table *table )
511 {
512     static const WCHAR fmtW[] = {'%','c',':',0};
513     WCHAR device_id[3], root[] = {'A',':','\\',0};
514     struct record_logicaldisk *rec;
515     UINT i, num_rows = 0, offset = 0, count = 4, type;
516     UINT64 size = 1024 * 1024 * 1024;
517     DWORD drives = GetLogicalDrives();
518
519     if (!(table->data = heap_alloc( count * sizeof(*rec) ))) return;
520
521     for (i = 0; i < sizeof(drives); i++)
522     {
523         if (drives & (1 << i))
524         {
525             root[0] = 'A' + i;
526             type = GetDriveTypeW( root );
527             if (type != DRIVE_FIXED && type != DRIVE_CDROM && type != DRIVE_REMOVABLE)
528                 continue;
529
530             if (num_rows > count)
531             {
532                 BYTE *data;
533                 count *= 2;
534                 if (!(data = heap_realloc( table->data, count * sizeof(*rec) ))) return;
535                 table->data = data;
536             }
537             rec = (struct record_logicaldisk *)(table->data + offset);
538             sprintfW( device_id, fmtW, 'A' + i );
539             rec->device_id  = heap_strdupW( device_id );
540             rec->drivetype  = type;
541             rec->filesystem = get_filesystem( root );
542             rec->freespace  = get_freespace( root, &size );
543             rec->size       = size;
544             offset += sizeof(*rec);
545             num_rows++;
546         }
547     }
548     TRACE("created %u rows\n", num_rows);
549     table->num_rows = num_rows;
550 }
551
552 static UINT16 get_connection_status( IF_OPER_STATUS status )
553 {
554     switch (status)
555     {
556     case IfOperStatusDown:
557         return 0; /* Disconnected */
558     case IfOperStatusUp:
559         return 2; /* Connected */
560     default:
561         ERR("unhandled status %u\n", status);
562         break;
563     }
564     return 0;
565 }
566 static WCHAR *get_mac_address( const BYTE *addr, DWORD len )
567 {
568     static const WCHAR fmtW[] =
569         {'%','0','2','x',':','%','0','2','x',':','%','0','2','x',':',
570          '%','0','2','x',':','%','0','2','x',':','%','0','2','x',0};
571     WCHAR *ret;
572
573     if (len != 6 || !(ret = heap_alloc( 18 * sizeof(WCHAR) ))) return NULL;
574     sprintfW( ret, fmtW, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] );
575     return ret;
576 }
577
578 static void fill_networkadapter( struct table *table )
579 {
580     static const WCHAR fmtW[] = {'%','u',0};
581     WCHAR device_id[11];
582     struct record_networkadapter *rec;
583     IP_ADAPTER_ADDRESSES *aa, *buffer;
584     UINT num_rows = 0, offset = 0;
585     DWORD size = 0, ret;
586
587     ret = GetAdaptersAddresses( AF_UNSPEC, 0, NULL, NULL, &size );
588     if (ret != ERROR_BUFFER_OVERFLOW) return;
589
590     if (!(buffer = heap_alloc( size ))) return;
591     if (GetAdaptersAddresses( AF_UNSPEC, 0, NULL, buffer, &size ))
592     {
593         heap_free( buffer );
594         return;
595     }
596     for (aa = buffer; aa; aa = aa->Next) num_rows++;
597     if (!(table->data = heap_alloc( sizeof(*rec) * num_rows )))
598     {
599         heap_free( buffer );
600         return;
601     }
602     for (aa = buffer; aa; aa = aa->Next)
603     {
604         rec = (struct record_networkadapter *)(table->data + offset);
605         sprintfW( device_id, fmtW, aa->u.s.IfIndex );
606         rec->device_id            = heap_strdupW( device_id );
607         rec->interface_index      = aa->u.s.IfIndex;
608         rec->mac_address          = get_mac_address( aa->PhysicalAddress, aa->PhysicalAddressLength );
609         rec->netconnection_status = get_connection_status( aa->OperStatus );
610         rec->pnpdevice_id         = networkadapter_pnpdeviceidW;
611         rec->speed                = 1000000;
612         offset += sizeof(*rec);
613     }
614     TRACE("created %u rows\n", num_rows);
615     table->num_rows = num_rows;
616
617     heap_free( buffer );
618 }
619
620 static WCHAR *get_cmdline( DWORD process_id )
621 {
622     if (process_id == GetCurrentProcessId()) return heap_strdupW( GetCommandLineW() );
623     return NULL; /* FIXME handle different process case */
624 }
625
626 static void fill_process( struct table *table )
627 {
628     static const WCHAR fmtW[] = {'%','u',0};
629     WCHAR handle[11];
630     struct record_process *rec;
631     PROCESSENTRY32W entry;
632     HANDLE snap;
633     UINT num_rows = 0, offset = 0, count = 8;
634
635     snap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
636     if (snap == INVALID_HANDLE_VALUE) return;
637
638     entry.dwSize = sizeof(entry);
639     if (!Process32FirstW( snap, &entry )) goto done;
640     if (!(table->data = heap_alloc( count * sizeof(*rec) ))) goto done;
641
642     do
643     {
644         if (num_rows > count)
645         {
646             BYTE *data;
647             count *= 2;
648             if (!(data = heap_realloc( table->data, count * sizeof(*rec) ))) goto done;
649             table->data = data;
650         }
651         rec = (struct record_process *)(table->data + offset);
652         rec->caption      = heap_strdupW( entry.szExeFile );
653         rec->commandline  = get_cmdline( entry.th32ProcessID );
654         rec->description  = heap_strdupW( entry.szExeFile );
655         sprintfW( handle, fmtW, entry.th32ProcessID );
656         rec->handle       = heap_strdupW( handle );
657         rec->process_id   = entry.th32ProcessID;
658         rec->pprocess_id  = entry.th32ParentProcessID;
659         rec->thread_count = entry.cntThreads;
660         offset += sizeof(*rec);
661         num_rows++;
662     } while (Process32NextW( snap, &entry ));
663
664     TRACE("created %u rows\n", num_rows);
665     table->num_rows = num_rows;
666
667 done:
668     CloseHandle( snap );
669 }
670
671 static inline void do_cpuid( unsigned int ax, unsigned int *p )
672 {
673 #ifdef __i386__
674     __asm__("pushl %%ebx\n\t"
675                 "cpuid\n\t"
676                 "movl %%ebx, %%esi\n\t"
677                 "popl %%ebx"
678                 : "=a" (p[0]), "=S" (p[1]), "=c" (p[2]), "=d" (p[3])
679                 :  "0" (ax));
680 #endif
681 }
682
683 static void get_processor_id( WCHAR *processor_id )
684 {
685     static const WCHAR fmtW[] = {'%','0','8','X','%','0','8','X',0};
686     unsigned int regs[4] = {0, 0, 0, 0};
687
688     do_cpuid( 1, regs );
689     sprintfW( processor_id, fmtW, regs[3], regs[0] );
690 }
691 static void regs_to_str( unsigned int *regs, unsigned int len, WCHAR *buffer )
692 {
693     unsigned int i;
694     unsigned char *p = (unsigned char *)regs;
695
696     for (i = 0; i < len; i++)
697     {
698         buffer[i] = *p++;
699     }
700     buffer[i] = 0;
701 }
702 static void get_processor_manufacturer( WCHAR *manufacturer )
703 {
704     unsigned int tmp, regs[4] = {0, 0, 0, 0};
705
706     do_cpuid( 0, regs );
707     tmp = regs[2];      /* swap edx and ecx */
708     regs[2] = regs[3];
709     regs[3] = tmp;
710
711     regs_to_str( regs + 1, 12, manufacturer );
712 }
713 static void get_processor_name( WCHAR *name )
714 {
715     unsigned int regs[4] = {0, 0, 0, 0};
716
717     do_cpuid( 0x80000000, regs );
718     if (regs[0] >= 0x80000004)
719     {
720         do_cpuid( 0x80000002, regs );
721         regs_to_str( regs, 16, name );
722         do_cpuid( 0x80000003, regs );
723         regs_to_str( regs, 16, name + 16 );
724         do_cpuid( 0x80000004, regs );
725         regs_to_str( regs, 16, name + 32 );
726     }
727 }
728
729 static void fill_processor( struct table *table )
730 {
731     static const WCHAR fmtW[] = {'C','P','U','%','u',0};
732     WCHAR device_id[14], processor_id[17], manufacturer[13], name[49] = {0};
733     struct record_processor *rec;
734     UINT i, offset = 0, count = get_processor_count();
735
736     if (!(table->data = heap_alloc( sizeof(*rec) * count ))) return;
737
738     get_processor_id( processor_id );
739     get_processor_manufacturer( manufacturer );
740     get_processor_name( name );
741
742     for (i = 0; i < count; i++)
743     {
744         rec = (struct record_processor *)(table->data + offset);
745         rec->cpu_status   = 1; /* CPU Enabled */
746         sprintfW( device_id, fmtW, i );
747         rec->device_id    = heap_strdupW( device_id );
748         rec->manufacturer = heap_strdupW( manufacturer );
749         rec->name         = heap_strdupW( name );
750         rec->processor_id = heap_strdupW( processor_id );
751         offset += sizeof(*rec);
752     }
753
754     TRACE("created %u rows\n", count);
755     table->num_rows = count;
756 }
757
758 static void fill_os( struct table *table )
759 {
760     struct record_operatingsystem *rec;
761     WCHAR path[MAX_PATH];
762     SYSTEM_INFO info;
763     void *redir;
764
765     if (!(table->data = heap_alloc( sizeof(*rec) ))) return;
766
767     rec = (struct record_operatingsystem *)table->data;
768     rec->caption    = os_captionW;
769     rec->csdversion = os_csdversionW;
770
771     GetNativeSystemInfo( &info );
772     if (info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
773         rec->osarchitecture = os_64bitW;
774     else
775         rec->osarchitecture = os_32bitW;
776
777     rec->oslanguage = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
778
779     Wow64DisableWow64FsRedirection( &redir );
780     GetSystemDirectoryW( path, MAX_PATH );
781     Wow64RevertWow64FsRedirection( redir );
782     rec->systemdirectory = heap_strdupW( path );
783
784     TRACE("created 1 row\n");
785     table->num_rows = 1;
786 }
787
788 static const WCHAR *get_service_type( DWORD type )
789 {
790     static const WCHAR filesystem_driverW[] =
791         {'F','i','l','e',' ','S','y','s','t','e','m',' ','D','r','i','v','e','r',0};
792     static const WCHAR kernel_driverW[] =
793         {'K','e','r','n','e','l',' ','D','r','i','v','e','r',0};
794     static const WCHAR own_processW[] =
795         {'O','w','n',' ','P','r','o','c','e','s','s',0};
796     static const WCHAR share_processW[] =
797         {'S','h','a','r','e',' ','P','r','o','c','e','s','s',0};
798
799     if (type & SERVICE_KERNEL_DRIVER)            return kernel_driverW;
800     else if (type & SERVICE_FILE_SYSTEM_DRIVER)  return filesystem_driverW;
801     else if (type & SERVICE_WIN32_OWN_PROCESS)   return own_processW;
802     else if (type & SERVICE_WIN32_SHARE_PROCESS) return share_processW;
803     else ERR("unhandled type 0x%08x\n", type);
804     return NULL;
805 }
806 static const WCHAR *get_service_state( DWORD state )
807 {
808     static const WCHAR runningW[] =
809         {'R','u','n','n','i','n','g',0};
810     static const WCHAR start_pendingW[] =
811         {'S','t','a','r','t',' ','P','e','n','d','i','n','g',0};
812     static const WCHAR stop_pendingW[] =
813         {'S','t','o','p',' ','P','e','n','d','i','n','g',0};
814     static const WCHAR stoppedW[] =
815         {'S','t','o','p','p','e','d',0};
816     static const WCHAR unknownW[] =
817         {'U','n','k','n','o','w','n',0};
818
819     switch (state)
820     {
821     case SERVICE_STOPPED:       return stoppedW;
822     case SERVICE_START_PENDING: return start_pendingW;
823     case SERVICE_STOP_PENDING:  return stop_pendingW;
824     case SERVICE_RUNNING:       return runningW;
825     default:
826         ERR("unknown state %u\n", state);
827         return unknownW;
828     }
829 }
830
831 static void fill_service( struct table *table )
832 {
833     struct record_service *rec;
834     SC_HANDLE manager;
835     ENUM_SERVICE_STATUS_PROCESSW *tmp, *services = NULL;
836     SERVICE_STATUS_PROCESS *status;
837     UINT i, num_rows = 0, offset = 0, size = 256, needed, count;
838     BOOL ret;
839
840     if (!(manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE ))) return;
841     if (!(services = heap_alloc( size ))) goto done;
842
843     ret = EnumServicesStatusExW( manager, SC_ENUM_PROCESS_INFO, SERVICE_TYPE_ALL,
844                                  SERVICE_STATE_ALL, (BYTE *)services, size, &needed,
845                                  &count, NULL, NULL );
846     if (!ret)
847     {
848         if (GetLastError() != ERROR_MORE_DATA) goto done;
849         size = needed;
850         if (!(tmp = heap_realloc( services, size ))) goto done;
851         services = tmp;
852         ret = EnumServicesStatusExW( manager, SC_ENUM_PROCESS_INFO, SERVICE_TYPE_ALL,
853                                      SERVICE_STATE_ALL, (BYTE *)services, size, &needed,
854                                      &count, NULL, NULL );
855         if (!ret) goto done;
856     }
857     if (!(table->data = heap_alloc( sizeof(*rec) * count ))) goto done;
858
859     for (i = 0; i < count; i++)
860     {
861         status = &services[i].ServiceStatusProcess;
862         rec = (struct record_service *)(table->data + offset);
863         rec->displayname = heap_strdupW( services[i].lpDisplayName );
864         rec->name        = heap_strdupW( services[i].lpServiceName );
865         rec->process_id  = status->dwProcessId;
866         rec->servicetype = get_service_type( status->dwServiceType );
867         rec->state       = get_service_state( status->dwCurrentState );
868         offset += sizeof(*rec);
869         num_rows++;
870     }
871
872     TRACE("created %u rows\n", num_rows);
873     table->num_rows = num_rows;
874
875 done:
876     CloseServiceHandle( manager );
877     heap_free( services );
878 }
879
880 static UINT32 get_bits_per_pixel( UINT *hres, UINT *vres )
881 {
882     HDC hdc = GetDC( NULL );
883     UINT32 ret;
884
885     if (!hdc) return 32;
886     ret = GetDeviceCaps( hdc, BITSPIXEL );
887     *hres = GetDeviceCaps( hdc, HORZRES );
888     *vres = GetDeviceCaps( hdc, VERTRES );
889     ReleaseDC( NULL, hdc );
890     return ret;
891 }
892
893 static void fill_videocontroller( struct table *table )
894 {
895
896     struct record_videocontroller *rec;
897     HRESULT hr;
898     IDXGIFactory *factory = NULL;
899     IDXGIAdapter *adapter = NULL;
900     DXGI_ADAPTER_DESC desc;
901     UINT hres = 1024, vres = 768, vidmem = 512 * 1024 * 1024;
902     const WCHAR *name = videocontroller_deviceidW;
903
904     if (!(table->data = heap_alloc( sizeof(*rec) ))) return;
905
906     hr = CreateDXGIFactory( &IID_IDXGIFactory, (void **)&factory );
907     if (FAILED(hr)) goto done;
908
909     hr = IDXGIFactory_EnumAdapters( factory, 0, &adapter );
910     if (FAILED(hr)) goto done;
911
912     hr = IDXGIAdapter_GetDesc( adapter, &desc );
913     if (SUCCEEDED(hr))
914     {
915         vidmem = desc.DedicatedVideoMemory;
916         name   = desc.Description;
917     }
918
919 done:
920     rec = (struct record_videocontroller *)table->data;
921     rec->adapter_ram           = vidmem;
922     rec->current_bitsperpixel  = get_bits_per_pixel( &hres, &vres );
923     rec->current_horizontalres = hres;
924     rec->current_verticalres   = vres;
925     rec->device_id             = videocontroller_deviceidW;
926     rec->name                  = heap_strdupW( name );
927
928     TRACE("created 1 row\n");
929     table->num_rows = 1;
930
931     if (adapter) IDXGIAdapter_Release( adapter );
932     if (factory) IDXGIFactory_Release( factory );
933 }
934
935 static struct table builtin_classes[] =
936 {
937     { class_baseboardW, SIZEOF(col_baseboard), col_baseboard, SIZEOF(data_baseboard), (BYTE *)data_baseboard },
938     { class_biosW, SIZEOF(col_bios), col_bios, SIZEOF(data_bios), (BYTE *)data_bios },
939     { class_compsysW, SIZEOF(col_compsys), col_compsys, 0, NULL, fill_compsys },
940     { class_logicaldiskW, SIZEOF(col_logicaldisk), col_logicaldisk, 0, NULL, fill_logicaldisk },
941     { class_networkadapterW, SIZEOF(col_networkadapter), col_networkadapter, 0, NULL, fill_networkadapter },
942     { class_osW, SIZEOF(col_os), col_os, 0, NULL, fill_os },
943     { class_paramsW, SIZEOF(col_params), col_params, SIZEOF(data_params), (BYTE *)data_params },
944     { class_processW, SIZEOF(col_process), col_process, 0, NULL, fill_process },
945     { class_processorW, SIZEOF(col_processor), col_processor, 0, NULL, fill_processor },
946     { class_serviceW, SIZEOF(col_service), col_service, 0, NULL, fill_service },
947     { class_stdregprovW, SIZEOF(col_stdregprov), col_stdregprov, SIZEOF(data_stdregprov), (BYTE *)data_stdregprov },
948     { class_videocontrollerW, SIZEOF(col_videocontroller), col_videocontroller, 0, NULL, fill_videocontroller }
949 };
950
951 void init_table_list( void )
952 {
953     static struct list tables = LIST_INIT( tables );
954     UINT i;
955
956     for (i = 0; i < SIZEOF(builtin_classes); i++)
957     {
958         list_add_tail( &tables, &builtin_classes[i].entry );
959     }
960     table_list = &tables;
961 }