wbemprox: Add SystemType property to Win32_Computersystem.
[wine.git] / dlls / wbemprox / builtin.c
blob98a32313461f6f571ad51ff643a2d2803bad46aa
1 /*
2 * Copyright 2012 Hans Leidekker for CodeWeavers
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.
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.
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
19 #define COBJMACROS
20 #define NONAMELESSUNION
21 #define NONAMELESSSTRUCT
23 #include <stdarg.h>
24 #include <intrin.h>
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winsock2.h"
31 #include "ws2tcpip.h"
32 #include "initguid.h"
33 #include "wbemcli.h"
34 #include "wbemprov.h"
35 #include "iphlpapi.h"
36 #include "netioapi.h"
37 #include "tlhelp32.h"
38 #include "d3d10.h"
39 #include "winternl.h"
40 #include "winioctl.h"
41 #include "winsvc.h"
42 #include "winver.h"
43 #include "sddl.h"
44 #include "ntsecapi.h"
45 #include "winspool.h"
46 #include "setupapi.h"
47 #include "ntddstor.h"
49 #include "wine/asm.h"
50 #include "wine/debug.h"
51 #include "wbemprox_private.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
55 /* column definitions must be kept in sync with record structures below */
56 static const struct column col_associator[] =
58 { L"AssocClass", CIM_STRING },
59 { L"Class", CIM_STRING },
60 { L"Associator", CIM_STRING }
62 static const struct column col_baseboard[] =
64 { L"Manufacturer", CIM_STRING|COL_FLAG_DYNAMIC },
65 { L"Model", CIM_STRING },
66 { L"Name", CIM_STRING },
67 { L"Product", CIM_STRING|COL_FLAG_DYNAMIC },
68 { L"SerialNumber", CIM_STRING|COL_FLAG_DYNAMIC },
69 { L"Tag", CIM_STRING|COL_FLAG_KEY },
70 { L"Version", CIM_STRING|COL_FLAG_DYNAMIC },
72 static const struct column col_bios[] =
74 { L"CurrentLanguage", CIM_STRING },
75 { L"Description", CIM_STRING },
76 { L"EmbeddedControllerMajorVersion", CIM_UINT8 },
77 { L"EmbeddedControllerMinorVersion", CIM_UINT8 },
78 { L"IdentificationCode", CIM_STRING },
79 { L"Manufacturer", CIM_STRING|COL_FLAG_DYNAMIC },
80 { L"Name", CIM_STRING },
81 { L"ReleaseDate", CIM_DATETIME|COL_FLAG_DYNAMIC },
82 { L"SerialNumber", CIM_STRING },
83 { L"SMBIOSBIOSVersion", CIM_STRING|COL_FLAG_DYNAMIC },
84 { L"SMBIOSMajorVersion", CIM_UINT16 },
85 { L"SMBIOSMinorVersion", CIM_UINT16 },
86 { L"SystemBiosMajorVersion", CIM_UINT8 },
87 { L"SystemBiosMinorVersion", CIM_UINT8 },
88 { L"Version", CIM_STRING|COL_FLAG_KEY },
90 static const struct column col_cdromdrive[] =
92 { L"DeviceId", CIM_STRING|COL_FLAG_KEY },
93 { L"Drive", CIM_STRING|COL_FLAG_DYNAMIC },
94 { L"MediaType", CIM_STRING },
95 { L"Name", CIM_STRING },
96 { L"PNPDeviceID", CIM_STRING },
98 static const struct column col_compsys[] =
100 { L"Description", CIM_STRING },
101 { L"Domain", CIM_STRING },
102 { L"DomainRole", CIM_UINT16 },
103 { L"Manufacturer", CIM_STRING },
104 { L"Model", CIM_STRING },
105 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC },
106 { L"NumberOfLogicalProcessors", CIM_UINT32 },
107 { L"NumberOfProcessors", CIM_UINT32 },
108 { L"SystemType", CIM_STRING },
109 { L"TotalPhysicalMemory", CIM_UINT64 },
110 { L"UserName", CIM_STRING|COL_FLAG_DYNAMIC },
112 static const struct column col_compsysproduct[] =
114 { L"IdentifyingNumber", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
115 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
116 { L"SKUNumber", CIM_STRING },
117 { L"UUID", CIM_STRING|COL_FLAG_DYNAMIC },
118 { L"Vendor", CIM_STRING|COL_FLAG_DYNAMIC },
119 { L"Version", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
121 static const struct column col_datafile[] =
123 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
124 { L"Version", CIM_STRING|COL_FLAG_DYNAMIC },
126 static const struct column col_desktopmonitor[] =
128 { L"Name", CIM_STRING },
129 { L"PixelsPerXLogicalInch", CIM_UINT32 },
131 static const struct column col_directory[] =
133 { L"AccessMask", CIM_UINT32 },
134 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
136 static const struct column col_diskdrive[] =
138 { L"DeviceId", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
139 { L"Index", CIM_UINT32 },
140 { L"InterfaceType", CIM_STRING },
141 { L"Manufacturer", CIM_STRING },
142 { L"MediaType", CIM_STRING },
143 { L"Model", CIM_STRING },
144 { L"PNPDeviceID", CIM_STRING },
145 { L"SerialNumber", CIM_STRING|COL_FLAG_DYNAMIC },
146 { L"Size", CIM_UINT64 },
148 static const struct column col_diskdrivetodiskpartition[] =
150 { L"Antecedent", CIM_REFERENCE|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
151 { L"Dependent", CIM_REFERENCE|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
153 static const struct column col_diskpartition[] =
155 { L"Bootable", CIM_BOOLEAN },
156 { L"BootPartition", CIM_BOOLEAN },
157 { L"DeviceId", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
158 { L"DiskIndex", CIM_UINT32 },
159 { L"Index", CIM_UINT32 },
160 { L"PNPDeviceID", CIM_STRING|COL_FLAG_DYNAMIC },
161 { L"Size", CIM_UINT64 },
162 { L"StartingOffset", CIM_UINT64 },
163 { L"Type", CIM_STRING|COL_FLAG_DYNAMIC },
165 static const struct column col_displaycontrollerconfig[] =
167 { L"BitsPerPixel", CIM_UINT32 },
168 { L"Caption", CIM_STRING },
169 { L"HorizontalResolution", CIM_UINT32 },
170 { L"Name", CIM_STRING|COL_FLAG_KEY },
171 { L"VerticalResolution", CIM_UINT32 },
173 static const struct column col_ip4routetable[] =
175 { L"Destination", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
176 { L"InterfaceIndex", CIM_SINT32|COL_FLAG_KEY },
177 { L"NextHop", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
179 static const struct column col_logicaldisk[] =
181 { L"Caption", CIM_STRING|COL_FLAG_DYNAMIC },
182 { L"DeviceId", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
183 { L"DriveType", CIM_UINT32 },
184 { L"FileSystem", CIM_STRING|COL_FLAG_DYNAMIC },
185 { L"FreeSpace", CIM_UINT64 },
186 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC },
187 { L"Size", CIM_UINT64 },
188 { L"VolumeName", CIM_STRING|COL_FLAG_DYNAMIC },
189 { L"VolumeSerialNumber", CIM_STRING|COL_FLAG_DYNAMIC },
191 static const struct column col_logicaldisktopartition[] =
193 { L"Antecedent", CIM_REFERENCE|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
194 { L"Dependent", CIM_REFERENCE|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
196 static const struct column col_networkadapter[] =
198 { L"AdapterType", CIM_STRING },
199 { L"AdapterTypeID", CIM_UINT16 },
200 { L"Description", CIM_STRING|COL_FLAG_DYNAMIC },
201 { L"DeviceId", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
202 { L"GUID", CIM_STRING|COL_FLAG_DYNAMIC },
203 { L"Index", CIM_UINT32 },
204 { L"InterfaceIndex", CIM_UINT32 },
205 { L"MACAddress", CIM_STRING|COL_FLAG_DYNAMIC },
206 { L"Manufacturer", CIM_STRING },
207 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC },
208 { L"NetConnectionStatus", CIM_UINT16 },
209 { L"PhysicalAdapter", CIM_BOOLEAN },
210 { L"PNPDeviceID", CIM_STRING },
211 { L"ServiceName", CIM_STRING|COL_FLAG_DYNAMIC },
212 { L"Speed", CIM_UINT64 },
214 static const struct column col_networkadapterconfig[] =
216 { L"DefaultIPGateway", CIM_STRING|CIM_FLAG_ARRAY|COL_FLAG_DYNAMIC },
217 { L"Description", CIM_STRING|COL_FLAG_DYNAMIC },
218 { L"DHCPEnabled", CIM_BOOLEAN },
219 { L"DNSDomain", CIM_STRING },
220 { L"DNSHostName", CIM_STRING|COL_FLAG_DYNAMIC },
221 { L"DNSServerSearchOrder", CIM_STRING|CIM_FLAG_ARRAY|COL_FLAG_DYNAMIC },
222 { L"Index", CIM_UINT32|COL_FLAG_KEY },
223 { L"IPAddress", CIM_STRING|CIM_FLAG_ARRAY|COL_FLAG_DYNAMIC },
224 { L"IPConnectionMetric", CIM_UINT32 },
225 { L"IPEnabled", CIM_BOOLEAN },
226 { L"IPSubnet", CIM_STRING|CIM_FLAG_ARRAY|COL_FLAG_DYNAMIC },
227 { L"MACAddress", CIM_STRING|COL_FLAG_DYNAMIC },
228 { L"SettingID", CIM_STRING|COL_FLAG_DYNAMIC },
230 static const struct column col_operatingsystem[] =
232 { L"BootDevice", CIM_STRING },
233 { L"BuildNumber", CIM_STRING|COL_FLAG_DYNAMIC },
234 { L"BuildType", CIM_STRING },
235 { L"Caption", CIM_STRING|COL_FLAG_DYNAMIC },
236 { L"CodeSet", CIM_STRING|COL_FLAG_DYNAMIC },
237 { L"CountryCode", CIM_STRING|COL_FLAG_DYNAMIC },
238 { L"CSDVersion", CIM_STRING|COL_FLAG_DYNAMIC },
239 { L"CSName", CIM_STRING|COL_FLAG_DYNAMIC },
240 { L"CurrentTimeZone", CIM_SINT16 },
241 { L"FreePhysicalMemory", CIM_UINT64 },
242 { L"InstallDate", CIM_DATETIME },
243 { L"LastBootUpTime", CIM_DATETIME|COL_FLAG_DYNAMIC },
244 { L"LocalDateTime", CIM_DATETIME|COL_FLAG_DYNAMIC },
245 { L"Locale", CIM_STRING|COL_FLAG_DYNAMIC },
246 { L"Manufacturer", CIM_STRING },
247 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC },
248 { L"OperatingSystemSKU", CIM_UINT32 },
249 { L"Organization", CIM_STRING|COL_FLAG_DYNAMIC },
250 { L"OSArchitecture", CIM_STRING },
251 { L"OSLanguage", CIM_UINT32 },
252 { L"OSProductSuite", CIM_UINT32 },
253 { L"OSType", CIM_UINT16 },
254 { L"Primary", CIM_BOOLEAN },
255 { L"ProductType", CIM_UINT32 },
256 { L"RegisteredUser", CIM_STRING|COL_FLAG_DYNAMIC },
257 { L"SerialNumber", CIM_STRING|COL_FLAG_DYNAMIC },
258 { L"ServicePackMajorVersion", CIM_UINT16 },
259 { L"ServicePackMinorVersion", CIM_UINT16 },
260 { L"Status", CIM_STRING },
261 { L"SuiteMask", CIM_UINT32 },
262 { L"SystemDirectory", CIM_STRING|COL_FLAG_DYNAMIC },
263 { L"SystemDrive", CIM_STRING|COL_FLAG_DYNAMIC },
264 { L"TotalVirtualMemorySize", CIM_UINT64 },
265 { L"TotalVisibleMemorySize", CIM_UINT64 },
266 { L"Version", CIM_STRING|COL_FLAG_DYNAMIC },
267 { L"WindowsDirectory", CIM_STRING|COL_FLAG_DYNAMIC },
269 static const struct column col_pagefileusage[] =
271 { L"Name", CIM_STRING },
273 static const struct column col_param[] =
275 { L"Class", CIM_STRING },
276 { L"Method", CIM_STRING },
277 { L"Direction", CIM_SINT32 },
278 { L"Parameter", CIM_STRING },
279 { L"Type", CIM_UINT32 },
280 { L"DefaultValue", CIM_UINT32 },
282 static const struct column col_physicalmedia[] =
284 { L"SerialNumber", CIM_STRING },
285 { L"Tag", CIM_STRING },
287 static const struct column col_physicalmemory[] =
289 { L"BankLabel", CIM_STRING },
290 { L"Capacity", CIM_UINT64 },
291 { L"Caption", CIM_STRING },
292 { L"ConfiguredClockSpeed", CIM_UINT32 },
293 { L"DeviceLocator", CIM_STRING },
294 { L"FormFactor", CIM_UINT16 },
295 { L"MemoryType", CIM_UINT16 },
296 { L"PartNumber", CIM_STRING },
297 { L"SerialNumber", CIM_STRING },
299 static const struct column col_pnpentity[] =
301 { L"DeviceId", CIM_STRING|COL_FLAG_DYNAMIC },
302 { L"Manufacturer", CIM_STRING },
303 { L"Name", CIM_STRING },
305 static const struct column col_printer[] =
307 { L"Attributes", CIM_UINT32 },
308 { L"DeviceId", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
309 { L"DriverName", CIM_STRING|COL_FLAG_DYNAMIC },
310 { L"HorizontalResolution", CIM_UINT32 },
311 { L"Local", CIM_BOOLEAN },
312 { L"Location", CIM_STRING|COL_FLAG_DYNAMIC },
313 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC },
314 { L"Network", CIM_BOOLEAN },
315 { L"PortName", CIM_STRING|COL_FLAG_DYNAMIC },
317 static const struct column col_process[] =
319 { L"Caption", CIM_STRING|COL_FLAG_DYNAMIC },
320 { L"CommandLine", CIM_STRING|COL_FLAG_DYNAMIC },
321 { L"Description", CIM_STRING|COL_FLAG_DYNAMIC },
322 { L"Handle", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
323 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC },
324 { L"ParentProcessID", CIM_UINT32 },
325 { L"ProcessID", CIM_UINT32 },
326 { L"ThreadCount", CIM_UINT32 },
327 { L"WorkingSetSize", CIM_UINT64 },
328 /* methods */
329 { L"Create", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
330 { L"GetOwner", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
332 static const struct column col_processor[] =
334 { L"AddressWidth", CIM_UINT16 },
335 { L"Architecture", CIM_UINT16 },
336 { L"Caption", CIM_STRING|COL_FLAG_DYNAMIC },
337 { L"CpuStatus", CIM_UINT16 },
338 { L"CurrentClockSpeed", CIM_UINT32 },
339 { L"DataWidth", CIM_UINT16 },
340 { L"Description", CIM_STRING|COL_FLAG_DYNAMIC },
341 { L"DeviceId", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
342 { L"Family", CIM_UINT16 },
343 { L"Level", CIM_UINT16 },
344 { L"Manufacturer", CIM_STRING|COL_FLAG_DYNAMIC },
345 { L"MaxClockSpeed", CIM_UINT32 },
346 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC },
347 { L"NumberOfCores", CIM_UINT32 },
348 { L"NumberOfLogicalProcessors", CIM_UINT32 },
349 { L"ProcessorId", CIM_STRING|COL_FLAG_DYNAMIC },
350 { L"ProcessorType", CIM_UINT16 },
351 { L"Revision", CIM_UINT16 },
352 { L"UniqueId", CIM_STRING },
353 { L"Version", CIM_STRING|COL_FLAG_DYNAMIC },
355 static const struct column col_qualifier[] =
357 { L"Class", CIM_STRING },
358 { L"Member", CIM_STRING },
359 { L"Type", CIM_UINT32 },
360 { L"Flavor", CIM_SINT32 },
361 { L"Name", CIM_STRING },
362 { L"IntegerValue", CIM_SINT32 },
363 { L"StringValue", CIM_STRING },
364 { L"BoolValue", CIM_BOOLEAN },
366 static const struct column col_quickfixengineering[] =
368 { L"Caption", CIM_STRING },
369 { L"HotFixID", CIM_STRING|COL_FLAG_KEY },
371 static const struct column col_rawsmbiostables[] =
373 { L"SMBiosData", CIM_UINT8|CIM_FLAG_ARRAY },
375 static const struct column col_service[] =
377 { L"AcceptPause", CIM_BOOLEAN },
378 { L"AcceptStop", CIM_BOOLEAN },
379 { L"DisplayName", CIM_STRING|COL_FLAG_DYNAMIC },
380 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
381 { L"ProcessID", CIM_UINT32 },
382 { L"ServiceType", CIM_STRING },
383 { L"StartMode", CIM_STRING },
384 { L"State", CIM_STRING },
385 { L"SystemName", CIM_STRING|COL_FLAG_DYNAMIC },
386 /* methods */
387 { L"PauseService", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
388 { L"ResumeService", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
389 { L"StartService", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
390 { L"StopService", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
392 static const struct column col_sid[] =
394 { L"AccountName", CIM_STRING|COL_FLAG_DYNAMIC },
395 { L"BinaryRepresentation", CIM_UINT8|CIM_FLAG_ARRAY|COL_FLAG_DYNAMIC },
396 { L"ReferencedDomainName", CIM_STRING|COL_FLAG_DYNAMIC },
397 { L"SID", CIM_STRING|COL_FLAG_DYNAMIC|COL_FLAG_KEY },
398 { L"SidLength", CIM_UINT32 },
400 static const struct column col_softwarelicensingproduct[] =
402 { L"LicenseIsAddon", CIM_BOOLEAN },
403 { L"LicenseStatus", CIM_UINT32 },
405 static const struct column col_sounddevice[] =
407 { L"DeviceID", CIM_STRING|COL_FLAG_DYNAMIC },
408 { L"Manufacturer", CIM_STRING },
409 { L"Name", CIM_STRING },
410 { L"PNPDeviceID", CIM_STRING|COL_FLAG_DYNAMIC },
411 { L"ProductName", CIM_STRING },
412 { L"Status", CIM_STRING },
413 { L"StatusInfo", CIM_UINT16 },
415 static const struct column col_stdregprov[] =
417 { L"CreateKey", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
418 { L"EnumKey", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
419 { L"EnumValues", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
420 { L"GetStringValue", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
421 { L"SetStringValue", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
422 { L"SetDWORDValue", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
423 { L"DeleteKey", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
425 static const struct column col_systemenclosure[] =
427 { L"Caption", CIM_STRING },
428 { L"ChassisTypes", CIM_UINT16|CIM_FLAG_ARRAY|COL_FLAG_DYNAMIC },
429 { L"Description", CIM_STRING },
430 { L"LockPresent", CIM_BOOLEAN },
431 { L"Manufacturer", CIM_STRING|COL_FLAG_DYNAMIC },
432 { L"Name", CIM_STRING },
433 { L"Tag", CIM_STRING },
435 static const struct column col_systemsecurity[] =
437 { L"GetSD", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
438 { L"SetSD", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
440 static const struct column col_sysrestore[] =
442 { L"CreationTime", CIM_STRING },
443 { L"Description", CIM_STRING },
444 { L"EventType", CIM_UINT32 },
445 { L"RestorePointType", CIM_UINT32 },
446 { L"SequenceNumber", CIM_UINT32 },
447 /* methods */
448 { L"CreateRestorePoint", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
449 { L"Disable", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
450 { L"Enable", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
451 { L"GetLastRestoreStatus", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
452 { L"Restore", CIM_FLAG_ARRAY|COL_FLAG_METHOD },
454 static const struct column col_videocontroller[] =
456 { L"AdapterCompatibility", CIM_STRING },
457 { L"AdapterDACType", CIM_STRING },
458 { L"AdapterRAM", CIM_UINT32 },
459 { L"Availability", CIM_UINT16 },
460 { L"Caption", CIM_STRING|COL_FLAG_DYNAMIC },
461 { L"ConfigManagerErrorCode", CIM_UINT32 },
462 { L"CurrentBitsPerPixel", CIM_UINT32 },
463 { L"CurrentHorizontalResolution", CIM_UINT32 },
464 { L"CurrentRefreshRate", CIM_UINT32 },
465 { L"CurrentScanMode", CIM_UINT16 },
466 { L"CurrentVerticalResolution", CIM_UINT32 },
467 { L"Description", CIM_STRING|COL_FLAG_DYNAMIC },
468 { L"DeviceId", CIM_STRING|COL_FLAG_KEY },
469 { L"DriverDate", CIM_DATETIME },
470 { L"DriverVersion", CIM_STRING },
471 { L"InstalledDisplayDrivers", CIM_STRING },
472 { L"Name", CIM_STRING|COL_FLAG_DYNAMIC },
473 { L"PNPDeviceID", CIM_STRING|COL_FLAG_DYNAMIC },
474 { L"Status", CIM_STRING },
475 { L"VideoArchitecture", CIM_UINT16 },
476 { L"VideoMemoryType", CIM_UINT16 },
477 { L"VideoModeDescription", CIM_STRING|COL_FLAG_DYNAMIC },
478 { L"VideoProcessor", CIM_STRING|COL_FLAG_DYNAMIC },
480 static const struct column col_winsat[] =
482 { L"CPUScore", CIM_REAL32 },
483 { L"D3DScore", CIM_REAL32 },
484 { L"DiskScore", CIM_REAL32 },
485 { L"GraphicsScore", CIM_REAL32 },
486 { L"MemoryScore", CIM_REAL32 },
487 { L"TimeTaken", CIM_STRING|COL_FLAG_KEY },
488 { L"WinSATAssessmentState", CIM_UINT32 },
489 { L"WinSPRLevel", CIM_REAL32 },
492 #include "pshpack1.h"
493 struct record_associator
495 const WCHAR *assocclass;
496 const WCHAR *class;
497 const WCHAR *associator;
499 struct record_baseboard
501 const WCHAR *manufacturer;
502 const WCHAR *model;
503 const WCHAR *name;
504 const WCHAR *product;
505 const WCHAR *serialnumber;
506 const WCHAR *tag;
507 const WCHAR *version;
509 struct record_bios
511 const WCHAR *currentlanguage;
512 const WCHAR *description;
513 UINT8 ecmajorversion;
514 UINT8 ecminorversion;
515 const WCHAR *identificationcode;
516 const WCHAR *manufacturer;
517 const WCHAR *name;
518 const WCHAR *releasedate;
519 const WCHAR *serialnumber;
520 const WCHAR *smbiosbiosversion;
521 UINT16 smbiosmajorversion;
522 UINT16 smbiosminorversion;
523 UINT8 systembiosmajorversion;
524 UINT8 systembiosminorversion;
525 const WCHAR *version;
527 struct record_cdromdrive
529 const WCHAR *device_id;
530 const WCHAR *drive;
531 const WCHAR *mediatype;
532 const WCHAR *name;
533 const WCHAR *pnpdevice_id;
535 struct record_computersystem
537 const WCHAR *description;
538 const WCHAR *domain;
539 UINT16 domainrole;
540 const WCHAR *manufacturer;
541 const WCHAR *model;
542 const WCHAR *name;
543 UINT32 num_logical_processors;
544 UINT32 num_processors;
545 const WCHAR *systemtype;
546 UINT64 total_physical_memory;
547 const WCHAR *username;
549 struct record_computersystemproduct
551 const WCHAR *identifyingnumber;
552 const WCHAR *name;
553 const WCHAR *skunumber;
554 const WCHAR *uuid;
555 const WCHAR *vendor;
556 const WCHAR *version;
558 struct record_datafile
560 const WCHAR *name;
561 const WCHAR *version;
563 struct record_desktopmonitor
565 const WCHAR *name;
566 UINT32 pixelsperxlogicalinch;
568 struct record_directory
570 UINT32 accessmask;
571 const WCHAR *name;
573 struct record_diskdrive
575 const WCHAR *device_id;
576 UINT32 index;
577 const WCHAR *interfacetype;
578 const WCHAR *manufacturer;
579 const WCHAR *mediatype;
580 const WCHAR *model;
581 const WCHAR *pnpdevice_id;
582 const WCHAR *serialnumber;
583 UINT64 size;
585 struct record_diskdrivetodiskpartition
587 const WCHAR *antecedent;
588 const WCHAR *dependent;
590 struct record_diskpartition
592 int bootable;
593 int bootpartition;
594 const WCHAR *device_id;
595 UINT32 diskindex;
596 UINT32 index;
597 const WCHAR *pnpdevice_id;
598 UINT64 size;
599 UINT64 startingoffset;
600 const WCHAR *type;
602 struct record_displaycontrollerconfig
604 UINT32 bitsperpixel;
605 const WCHAR *caption;
606 UINT32 horizontalresolution;
607 const WCHAR *name;
608 UINT32 verticalresolution;
610 struct record_ip4routetable
612 const WCHAR *destination;
613 INT32 interfaceindex;
614 const WCHAR *nexthop;
616 struct record_logicaldisk
618 const WCHAR *caption;
619 const WCHAR *device_id;
620 UINT32 drivetype;
621 const WCHAR *filesystem;
622 UINT64 freespace;
623 const WCHAR *name;
624 UINT64 size;
625 const WCHAR *volumename;
626 const WCHAR *volumeserialnumber;
628 struct record_logicaldisktopartition
630 const WCHAR *antecedent;
631 const WCHAR *dependent;
633 struct record_networkadapter
635 const WCHAR *adaptertype;
636 UINT16 adaptertypeid;
637 const WCHAR *description;
638 const WCHAR *device_id;
639 const WCHAR *guid;
640 UINT32 index;
641 UINT32 interface_index;
642 const WCHAR *mac_address;
643 const WCHAR *manufacturer;
644 const WCHAR *name;
645 UINT16 netconnection_status;
646 int physicaladapter;
647 const WCHAR *pnpdevice_id;
648 const WCHAR *servicename;
649 UINT64 speed;
651 struct record_networkadapterconfig
653 const struct array *defaultipgateway;
654 const WCHAR *description;
655 int dhcpenabled;
656 const WCHAR *dnsdomain;
657 const WCHAR *dnshostname;
658 const struct array *dnsserversearchorder;
659 UINT32 index;
660 const struct array *ipaddress;
661 UINT32 ipconnectionmetric;
662 int ipenabled;
663 const struct array *ipsubnet;
664 const WCHAR *mac_address;
665 const WCHAR *settingid;
667 struct record_operatingsystem
669 const WCHAR *bootdevice;
670 const WCHAR *buildnumber;
671 const WCHAR *buildtype;
672 const WCHAR *caption;
673 const WCHAR *codeset;
674 const WCHAR *countrycode;
675 const WCHAR *csdversion;
676 const WCHAR *csname;
677 INT16 currenttimezone;
678 UINT64 freephysicalmemory;
679 const WCHAR *installdate;
680 const WCHAR *lastbootuptime;
681 const WCHAR *localdatetime;
682 const WCHAR *locale;
683 const WCHAR *manufacturer;
684 const WCHAR *name;
685 UINT32 operatingsystemsku;
686 const WCHAR *organization;
687 const WCHAR *osarchitecture;
688 UINT32 oslanguage;
689 UINT32 osproductsuite;
690 UINT16 ostype;
691 int primary;
692 UINT32 producttype;
693 const WCHAR *registereduser;
694 const WCHAR *serialnumber;
695 UINT16 servicepackmajor;
696 UINT16 servicepackminor;
697 const WCHAR *status;
698 UINT32 suitemask;
699 const WCHAR *systemdirectory;
700 const WCHAR *systemdrive;
701 UINT64 totalvirtualmemorysize;
702 UINT64 totalvisiblememorysize;
703 const WCHAR *version;
704 const WCHAR *windowsdirectory;
706 struct record_pagefileusage
708 const WCHAR *name;
710 struct record_param
712 const WCHAR *class;
713 const WCHAR *method;
714 INT32 direction;
715 const WCHAR *parameter;
716 UINT32 type;
717 UINT32 defaultvalue;
719 struct record_physicalmedia
721 const WCHAR *serialnumber;
722 const WCHAR *tag;
724 struct record_physicalmemory
726 const WCHAR *banklabel;
727 UINT64 capacity;
728 const WCHAR *caption;
729 UINT32 configuredclockspeed;
730 const WCHAR *devicelocator;
731 UINT16 formfactor;
732 UINT16 memorytype;
733 const WCHAR *partnumber;
734 const WCHAR *serial;
736 struct record_pnpentity
738 const WCHAR *device_id;
739 const WCHAR *manufacturer;
740 const WCHAR *name;
742 struct record_printer
744 UINT32 attributes;
745 const WCHAR *device_id;
746 const WCHAR *drivername;
747 UINT32 horizontalresolution;
748 int local;
749 const WCHAR *location;
750 const WCHAR *name;
751 int network;
752 const WCHAR *portname;
754 struct record_process
756 const WCHAR *caption;
757 const WCHAR *commandline;
758 const WCHAR *description;
759 const WCHAR *handle;
760 const WCHAR *name;
761 UINT32 pprocess_id;
762 UINT32 process_id;
763 UINT32 thread_count;
764 UINT64 workingsetsize;
765 /* methods */
766 class_method *create;
767 class_method *get_owner;
769 struct record_processor
771 UINT16 addresswidth;
772 UINT16 architecture;
773 const WCHAR *caption;
774 UINT16 cpu_status;
775 UINT32 currentclockspeed;
776 UINT16 datawidth;
777 const WCHAR *description;
778 const WCHAR *device_id;
779 UINT16 family;
780 UINT16 level;
781 const WCHAR *manufacturer;
782 UINT32 maxclockspeed;
783 const WCHAR *name;
784 UINT32 num_cores;
785 UINT32 num_logical_processors;
786 const WCHAR *processor_id;
787 UINT16 processortype;
788 UINT16 revision;
789 const WCHAR *unique_id;
790 const WCHAR *version;
792 struct record_qualifier
794 const WCHAR *class;
795 const WCHAR *member;
796 UINT32 type;
797 INT32 flavor;
798 const WCHAR *name;
799 INT32 intvalue;
800 const WCHAR *strvalue;
801 int boolvalue;
803 struct record_quickfixengineering
805 const WCHAR *caption;
806 const WCHAR *hotfixid;
808 struct record_rawsmbiostables
810 const struct array *smbiosdata;
812 struct record_service
814 int accept_pause;
815 int accept_stop;
816 const WCHAR *displayname;
817 const WCHAR *name;
818 UINT32 process_id;
819 const WCHAR *servicetype;
820 const WCHAR *startmode;
821 const WCHAR *state;
822 const WCHAR *systemname;
823 /* methods */
824 class_method *pause_service;
825 class_method *resume_service;
826 class_method *start_service;
827 class_method *stop_service;
829 struct record_sid
831 const WCHAR *accountname;
832 const struct array *binaryrepresentation;
833 const WCHAR *referenceddomainname;
834 const WCHAR *sid;
835 UINT32 sidlength;
837 struct record_softwarelicensingproduct
839 int license_is_addon;
840 UINT32 license_status;
842 struct record_sounddevice
844 const WCHAR *deviceid;
845 const WCHAR *manufacturer;
846 const WCHAR *name;
847 const WCHAR *pnpdeviceid;
848 const WCHAR *productname;
849 const WCHAR *status;
850 UINT16 statusinfo;
852 struct record_stdregprov
854 class_method *createkey;
855 class_method *enumkey;
856 class_method *enumvalues;
857 class_method *getstringvalue;
858 class_method *setstringvalue;
859 class_method *setdwordvalue;
860 class_method *deletekey;
862 struct record_sysrestore
864 const WCHAR *creation_time;
865 const WCHAR *description;
866 UINT32 event_type;
867 UINT32 restore_point_type;
868 UINT32 sequence_number;
869 class_method *create_restore_point;
870 class_method *disable_restore;
871 class_method *enable_restore;
872 class_method *get_last_restore_status;
873 class_method *restore;
875 struct record_systemsecurity
877 class_method *getsd;
878 class_method *setsd;
880 struct record_systemenclosure
882 const WCHAR *caption;
883 const struct array *chassistypes;
884 const WCHAR *description;
885 int lockpresent;
886 const WCHAR *manufacturer;
887 const WCHAR *name;
888 const WCHAR *tag;
890 struct record_videocontroller
892 const WCHAR *adapter_compatibility;
893 const WCHAR *adapter_dactype;
894 UINT32 adapter_ram;
895 UINT16 availability;
896 const WCHAR *caption;
897 UINT32 config_errorcode;
898 UINT32 current_bitsperpixel;
899 UINT32 current_horizontalres;
900 UINT32 current_refreshrate;
901 UINT16 current_scanmode;
902 UINT32 current_verticalres;
903 const WCHAR *description;
904 const WCHAR *device_id;
905 const WCHAR *driverdate;
906 const WCHAR *driverversion;
907 const WCHAR *installeddriver;
908 const WCHAR *name;
909 const WCHAR *pnpdevice_id;
910 const WCHAR *status;
911 UINT16 videoarchitecture;
912 UINT16 videomemorytype;
913 const WCHAR *videomodedescription;
914 const WCHAR *videoprocessor;
916 struct record_winsat
918 FLOAT cpuscore;
919 FLOAT d3dscore;
920 FLOAT diskscrore;
921 FLOAT graphicsscore;
922 FLOAT memoryscore;
923 const WCHAR *timetaken;
924 UINT32 winsatassessmentstate;
925 FLOAT winsprlevel;
927 #include "poppack.h"
929 static const struct record_associator data_associator[] =
931 { L"Win32_DiskDriveToDiskPartition", L"Win32_DiskPartition", L"Win32_DiskDrive" },
932 { L"Win32_LogicalDiskToPartition", L"Win32_LogicalDisk", L"Win32_DiskPartition" },
934 static const struct record_pagefileusage data_pagefileusage[] =
936 { L"c:\\pagefile.sys", },
938 static const struct record_param data_param[] =
940 { L"__SystemSecurity", L"GetSD", -1, L"ReturnValue", CIM_UINT32 },
941 { L"__SystemSecurity", L"GetSD", -1, L"SD", CIM_UINT8|CIM_FLAG_ARRAY },
942 { L"__SystemSecurity", L"SetSD", 1, L"SD", CIM_UINT8|CIM_FLAG_ARRAY },
943 { L"__SystemSecurity", L"SetSD", -1, L"ReturnValue", CIM_UINT32 },
944 { L"StdRegProv", L"CreateKey", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
945 { L"StdRegProv", L"CreateKey", 1, L"sSubKeyName", CIM_STRING },
946 { L"StdRegProv", L"CreateKey", -1, L"ReturnValue", CIM_UINT32 },
947 { L"StdRegProv", L"DeleteKey", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
948 { L"StdRegProv", L"DeleteKey", 1, L"sSubKeyName", CIM_STRING },
949 { L"StdRegProv", L"DeleteKey", -1, L"ReturnValue", CIM_UINT32 },
950 { L"StdRegProv", L"EnumKey", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
951 { L"StdRegProv", L"EnumKey", 1, L"sSubKeyName", CIM_STRING },
952 { L"StdRegProv", L"EnumKey", -1, L"ReturnValue", CIM_UINT32 },
953 { L"StdRegProv", L"EnumKey", -1, L"sNames", CIM_STRING|CIM_FLAG_ARRAY },
954 { L"StdRegProv", L"EnumValues", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
955 { L"StdRegProv", L"EnumValues", 1, L"sSubKeyName", CIM_STRING },
956 { L"StdRegProv", L"EnumValues", -1, L"ReturnValue", CIM_UINT32 },
957 { L"StdRegProv", L"EnumValues", -1, L"sNames", CIM_STRING|CIM_FLAG_ARRAY },
958 { L"StdRegProv", L"EnumValues", -1, L"Types", CIM_SINT32|CIM_FLAG_ARRAY },
959 { L"StdRegProv", L"GetStringValue", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
960 { L"StdRegProv", L"GetStringValue", 1, L"sSubKeyName", CIM_STRING },
961 { L"StdRegProv", L"GetStringValue", 1, L"sValueName", CIM_STRING },
962 { L"StdRegProv", L"GetStringValue", -1, L"ReturnValue", CIM_UINT32 },
963 { L"StdRegProv", L"GetStringValue", -1, L"sValue", CIM_STRING },
964 { L"StdRegProv", L"SetStringValue", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
965 { L"StdRegProv", L"SetStringValue", 1, L"sSubKeyName", CIM_STRING },
966 { L"StdRegProv", L"SetStringValue", 1, L"sValueName", CIM_STRING },
967 { L"StdRegProv", L"SetStringValue", 1, L"sValue", CIM_STRING },
968 { L"StdRegProv", L"SetStringValue", -1, L"ReturnValue", CIM_UINT32 },
969 { L"StdRegProv", L"SetDWORDValue", 1, L"hDefKey", CIM_SINT32, 0x80000002 },
970 { L"StdRegProv", L"SetDWORDValue", 1, L"sSubKeyName", CIM_STRING },
971 { L"StdRegProv", L"SetDWORDValue", 1, L"sValueName", CIM_STRING },
972 { L"StdRegProv", L"SetDWORDValue", 1, L"uValue", CIM_UINT32 },
973 { L"StdRegProv", L"SetDWORDValue", -1, L"ReturnValue", CIM_UINT32 },
974 { L"SystemRestore", L"Disable", 1, L"Drive", CIM_STRING },
975 { L"SystemRestore", L"Disable", -1, L"ReturnValue", CIM_UINT32 },
976 { L"SystemRestore", L"Enable", 1, L"Drive", CIM_STRING },
977 { L"SystemRestore", L"Enable", -1, L"ReturnValue", CIM_UINT32 },
978 { L"Win32_Process", L"Create", 1, L"CommandLine", CIM_STRING },
979 { L"Win32_Process", L"Create", 1, L"CurrentDirectory", CIM_STRING },
980 { L"Win32_Process", L"Create", -1, L"ProcessId", CIM_UINT32 },
981 { L"Win32_Process", L"Create", -1, L"ReturnValue", CIM_UINT32 },
982 { L"Win32_Process", L"GetOwner", -1, L"ReturnValue", CIM_UINT32 },
983 { L"Win32_Process", L"GetOwner", -1, L"User", CIM_STRING },
984 { L"Win32_Process", L"GetOwner", -1, L"Domain", CIM_STRING },
985 { L"Win32_Service", L"PauseService", -1, L"ReturnValue", CIM_UINT32 },
986 { L"Win32_Service", L"ResumeService", -1, L"ReturnValue", CIM_UINT32 },
987 { L"Win32_Service", L"StartService", -1, L"ReturnValue", CIM_UINT32 },
988 { L"Win32_Service", L"StopService", -1, L"ReturnValue", CIM_UINT32 },
991 #define FLAVOR_ID (WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_NOT_OVERRIDABLE |\
992 WBEM_FLAVOR_ORIGIN_PROPAGATED)
994 static const struct record_physicalmedia data_physicalmedia[] =
996 { L"WINEHDISK", L"\\\\.\\PHYSICALDRIVE0" }
999 static const struct record_rawsmbiostables data_rawsmbiostables[] =
1001 { 0 },
1004 static const struct record_qualifier data_qualifier[] =
1006 { L"__WIN32_PROCESS_GETOWNER_OUT", L"User", CIM_SINT32, FLAVOR_ID, L"ID", 0 },
1007 { L"__WIN32_PROCESS_GETOWNER_OUT", L"Domain", CIM_SINT32, FLAVOR_ID, L"ID", 1 }
1010 static const struct record_quickfixengineering data_quickfixengineering[] =
1012 { L"http://winehq.org", L"KB1234567" },
1015 static const struct record_softwarelicensingproduct data_softwarelicensingproduct[] =
1017 { 0, 1 },
1020 static const struct record_stdregprov data_stdregprov[] =
1023 reg_create_key,
1024 reg_enum_key,
1025 reg_enum_values,
1026 reg_get_stringvalue,
1027 reg_set_stringvalue,
1028 reg_set_dwordvalue,
1029 reg_delete_key,
1033 static const struct record_sysrestore data_sysrestore[] =
1035 { NULL, NULL, 0, 0, 0, sysrestore_create, sysrestore_disable, sysrestore_enable, sysrestore_get_last_status,
1036 sysrestore_restore }
1039 static UINT16 systemenclosure_chassistypes[] =
1043 static const struct array systemenclosure_chassistypes_array =
1045 sizeof(*systemenclosure_chassistypes),
1046 ARRAY_SIZE(systemenclosure_chassistypes),
1047 &systemenclosure_chassistypes
1049 static const struct record_systemsecurity data_systemsecurity[] =
1051 { security_get_sd, security_set_sd }
1053 static const struct record_winsat data_winsat[] =
1055 { 8.0f, 8.0f, 8.0f, 8.0f, 8.0f, L"MostRecentAssessment", 1 /* Valid */, 8.0f },
1058 /* check if row matches condition and update status */
1059 static BOOL match_row( const struct table *table, UINT row, const struct expr *cond, enum fill_status *status )
1061 LONGLONG val;
1062 UINT type;
1064 if (!cond)
1066 *status = FILL_STATUS_UNFILTERED;
1067 return TRUE;
1069 if (eval_cond( table, row, cond, &val, &type ) != S_OK)
1071 *status = FILL_STATUS_FAILED;
1072 return FALSE;
1074 *status = FILL_STATUS_FILTERED;
1075 return val != 0;
1078 static BOOL resize_table( struct table *table, UINT row_count, UINT row_size )
1080 if (!table->num_rows_allocated)
1082 if (!(table->data = malloc( row_count * row_size ))) return FALSE;
1083 table->num_rows_allocated = row_count;
1084 return TRUE;
1086 if (row_count > table->num_rows_allocated)
1088 BYTE *data;
1089 UINT count = max( row_count, table->num_rows_allocated * 2 );
1090 if (!(data = realloc( table->data, count * row_size ))) return FALSE;
1091 table->data = data;
1092 table->num_rows_allocated = count;
1094 return TRUE;
1097 #include "pshpack1.h"
1098 struct smbios_prologue
1100 BYTE calling_method;
1101 BYTE major_version;
1102 BYTE minor_version;
1103 BYTE revision;
1104 DWORD length;
1107 enum smbios_type
1109 SMBIOS_TYPE_BIOS,
1110 SMBIOS_TYPE_SYSTEM,
1111 SMBIOS_TYPE_BASEBOARD,
1112 SMBIOS_TYPE_CHASSIS,
1115 struct smbios_header
1117 BYTE type;
1118 BYTE length;
1119 WORD handle;
1122 struct smbios_baseboard
1124 struct smbios_header hdr;
1125 BYTE vendor;
1126 BYTE product;
1127 BYTE version;
1128 BYTE serial;
1131 struct smbios_bios
1133 struct smbios_header hdr;
1134 BYTE vendor;
1135 BYTE version;
1136 WORD start;
1137 BYTE date;
1138 BYTE size;
1139 UINT64 characteristics;
1140 BYTE characteristics_ext[2];
1141 BYTE system_bios_major_release;
1142 BYTE system_bios_minor_release;
1143 BYTE ec_firmware_major_release;
1144 BYTE ec_firmware_minor_release;
1147 struct smbios_chassis
1149 struct smbios_header hdr;
1150 BYTE vendor;
1151 BYTE type;
1152 BYTE version;
1153 BYTE serial;
1154 BYTE asset_tag;
1157 struct smbios_system
1159 struct smbios_header hdr;
1160 BYTE vendor;
1161 BYTE product;
1162 BYTE version;
1163 BYTE serial;
1164 BYTE uuid[16];
1166 #include "poppack.h"
1168 #define RSMB (('R' << 24) | ('S' << 16) | ('M' << 8) | 'B')
1170 static const struct smbios_header *find_smbios_entry( enum smbios_type type, const char *buf, UINT len )
1172 const char *ptr, *start;
1173 const struct smbios_prologue *prologue;
1174 const struct smbios_header *hdr;
1176 if (len < sizeof(struct smbios_prologue)) return NULL;
1177 prologue = (const struct smbios_prologue *)buf;
1178 if (prologue->length > len - sizeof(*prologue) || prologue->length < sizeof(*hdr)) return NULL;
1180 start = (const char *)(prologue + 1);
1181 hdr = (const struct smbios_header *)start;
1183 for (;;)
1185 if ((const char *)hdr - start >= prologue->length - sizeof(*hdr)) return NULL;
1187 if (!hdr->length)
1189 WARN( "invalid entry\n" );
1190 return NULL;
1193 if (hdr->type == type)
1195 if ((const char *)hdr - start + hdr->length > prologue->length) return NULL;
1196 break;
1198 else /* skip other entries and their strings */
1200 for (ptr = (const char *)hdr + hdr->length; ptr - buf < len && *ptr; ptr++)
1202 for (; ptr - buf < len; ptr++) if (!*ptr) break;
1204 if (ptr == (const char *)hdr + hdr->length) ptr++;
1205 hdr = (const struct smbios_header *)(ptr + 1);
1209 return hdr;
1212 static WCHAR *get_smbios_string( BYTE id, const char *buf, UINT offset, UINT buflen )
1214 const char *ptr = buf + offset;
1215 UINT i = 0;
1217 if (!id || offset >= buflen) return NULL;
1218 for (ptr = buf + offset; ptr - buf < buflen && *ptr; ptr++)
1220 if (++i == id) return heap_strdupAW( ptr );
1221 for (; ptr - buf < buflen; ptr++) if (!*ptr) break;
1223 return NULL;
1226 static WCHAR *get_baseboard_string( BYTE id, const char *buf, UINT len )
1228 const struct smbios_header *hdr;
1229 const struct smbios_baseboard *baseboard;
1230 UINT offset;
1232 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_BASEBOARD, buf, len ))) return NULL;
1234 baseboard = (const struct smbios_baseboard *)hdr;
1235 offset = (const char *)baseboard - buf + baseboard->hdr.length;
1236 return get_smbios_string( id, buf, offset, len );
1239 static WCHAR *get_baseboard_manufacturer( const char *buf, UINT len )
1241 WCHAR *ret = get_baseboard_string( 1, buf, len );
1242 if (!ret) return wcsdup( L"Intel Corporation" );
1243 return ret;
1246 static WCHAR *get_baseboard_product( const char *buf, UINT len )
1248 WCHAR *ret = get_baseboard_string( 2, buf, len );
1249 if (!ret) return wcsdup( L"Base Board" );
1250 return ret;
1253 static WCHAR *get_baseboard_serialnumber( const char *buf, UINT len )
1255 WCHAR *ret = get_baseboard_string( 4, buf, len );
1256 if (!ret) return wcsdup( L"None" );
1257 return ret;
1260 static WCHAR *get_baseboard_version( const char *buf, UINT len )
1262 WCHAR *ret = get_baseboard_string( 3, buf, len );
1263 if (!ret) return wcsdup( L"1.0" );
1264 return ret;
1267 static enum fill_status fill_baseboard( struct table *table, const struct expr *cond )
1269 struct record_baseboard *rec;
1270 enum fill_status status = FILL_STATUS_UNFILTERED;
1271 UINT row = 0, len;
1272 char *buf;
1274 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
1276 len = GetSystemFirmwareTable( RSMB, 0, NULL, 0 );
1277 if (!(buf = malloc( len ))) return FILL_STATUS_FAILED;
1278 GetSystemFirmwareTable( RSMB, 0, buf, len );
1280 rec = (struct record_baseboard *)table->data;
1281 rec->manufacturer = get_baseboard_manufacturer( buf, len );
1282 rec->model = L"Base Board";
1283 rec->name = L"Base Board";
1284 rec->product = get_baseboard_product( buf, len );
1285 rec->serialnumber = get_baseboard_serialnumber( buf, len );
1286 rec->tag = L"Base Board";
1287 rec->version = get_baseboard_version( buf, len );
1288 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
1289 else row++;
1291 free( buf );
1293 TRACE("created %u rows\n", row);
1294 table->num_rows = row;
1295 return status;
1298 static UINT16 get_bios_smbiosmajorversion( const char *buf, UINT len )
1300 const struct smbios_prologue *prologue = (const struct smbios_prologue *)buf;
1301 if (len < sizeof(*prologue)) return 2;
1302 return prologue->major_version;
1305 static UINT16 get_bios_smbiosminorversion( const char *buf, UINT len )
1307 const struct smbios_prologue *prologue = (const struct smbios_prologue *)buf;
1308 if (len < sizeof(*prologue)) return 0;
1309 return prologue->minor_version;
1312 static WCHAR *get_bios_string( BYTE id, const char *buf, UINT len )
1314 const struct smbios_header *hdr;
1315 const struct smbios_bios *bios;
1316 UINT offset;
1318 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_BIOS, buf, len ))) return NULL;
1320 bios = (const struct smbios_bios *)hdr;
1321 offset = (const char *)bios - buf + bios->hdr.length;
1322 return get_smbios_string( id, buf, offset, len );
1325 static WCHAR *get_bios_manufacturer( const char *buf, UINT len )
1327 WCHAR *ret = get_bios_string( 1, buf, len );
1328 if (!ret) return wcsdup( L"The Wine Project" );
1329 return ret;
1332 static WCHAR *convert_bios_date( const WCHAR *str )
1334 static const WCHAR fmtW[] = L"%04u%02u%02u000000.000000+000";
1335 UINT year, month, day, len = lstrlenW( str );
1336 const WCHAR *p = str, *q;
1337 WCHAR *ret;
1339 while (len && iswspace( *p )) { p++; len--; }
1340 while (len && iswspace( p[len - 1] )) { len--; }
1342 q = p;
1343 while (len && is_digit( *q )) { q++; len--; };
1344 if (q - p != 2 || !len || *q != '/') return NULL;
1345 month = (p[0] - '0') * 10 + p[1] - '0';
1347 p = ++q; len--;
1348 while (len && is_digit( *q )) { q++; len--; };
1349 if (q - p != 2 || !len || *q != '/') return NULL;
1350 day = (p[0] - '0') * 10 + p[1] - '0';
1352 p = ++q; len--;
1353 while (len && is_digit( *q )) { q++; len--; };
1354 if (q - p == 4) year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
1355 else if (q - p == 2) year = 1900 + (p[0] - '0') * 10 + p[1] - '0';
1356 else return NULL;
1358 if (!(ret = malloc( sizeof(fmtW) ))) return NULL;
1359 swprintf( ret, ARRAY_SIZE(fmtW), fmtW, year, month, day );
1360 return ret;
1363 static WCHAR *get_bios_releasedate( const char *buf, UINT len )
1365 WCHAR *ret, *date = get_bios_string( 3, buf, len );
1366 if (!date || !(ret = convert_bios_date( date ))) ret = wcsdup( L"20120608000000.000000+000" );
1367 free( date );
1368 return ret;
1371 static WCHAR *get_bios_smbiosbiosversion( const char *buf, UINT len )
1373 WCHAR *ret = get_bios_string( 2, buf, len );
1374 if (!ret) return wcsdup( L"Wine" );
1375 return ret;
1378 static BYTE get_bios_ec_firmware_major_release( const char *buf, UINT len )
1380 const struct smbios_header *hdr;
1381 const struct smbios_bios *bios;
1383 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_BIOS, buf, len ))) return 0xFF;
1385 bios = (const struct smbios_bios *)hdr;
1386 if (bios->hdr.length >= 0x18) return bios->ec_firmware_major_release;
1387 else return 0xFF;
1390 static BYTE get_bios_ec_firmware_minor_release( const char *buf, UINT len )
1392 const struct smbios_header *hdr;
1393 const struct smbios_bios *bios;
1395 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_BIOS, buf, len ))) return 0xFF;
1397 bios = (const struct smbios_bios *)hdr;
1398 if (bios->hdr.length >= 0x18) return bios->ec_firmware_minor_release;
1399 else return 0xFF;
1402 static BYTE get_bios_system_bios_major_release( const char *buf, UINT len )
1404 const struct smbios_header *hdr;
1405 const struct smbios_bios *bios;
1407 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_BIOS, buf, len ))) return 0xFF;
1409 bios = (const struct smbios_bios *)hdr;
1410 if (bios->hdr.length >= 0x18) return bios->system_bios_major_release;
1411 else return 0xFF;
1414 static BYTE get_bios_system_bios_minor_release( const char *buf, UINT len )
1416 const struct smbios_header *hdr;
1417 const struct smbios_bios *bios;
1419 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_BIOS, buf, len ))) return 0xFF;
1421 bios = (const struct smbios_bios *)hdr;
1422 if (bios->hdr.length >= 0x18) return bios->system_bios_minor_release;
1423 else return 0xFF;
1426 static enum fill_status fill_bios( struct table *table, const struct expr *cond )
1428 struct record_bios *rec;
1429 enum fill_status status = FILL_STATUS_UNFILTERED;
1430 UINT row = 0, len;
1431 char *buf;
1433 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
1435 len = GetSystemFirmwareTable( RSMB, 0, NULL, 0 );
1436 if (!(buf = malloc( len ))) return FILL_STATUS_FAILED;
1437 GetSystemFirmwareTable( RSMB, 0, buf, len );
1439 rec = (struct record_bios *)table->data;
1440 rec->currentlanguage = NULL;
1441 rec->description = L"Default System BIOS";
1442 rec->ecmajorversion = get_bios_ec_firmware_major_release( buf, len );
1443 rec->ecminorversion = get_bios_ec_firmware_minor_release( buf, len );
1444 rec->identificationcode = NULL;
1445 rec->manufacturer = get_bios_manufacturer( buf, len );
1446 rec->name = L"Default System BIOS";
1447 rec->releasedate = get_bios_releasedate( buf, len );
1448 rec->serialnumber = L"0";
1449 rec->smbiosbiosversion = get_bios_smbiosbiosversion( buf, len );
1450 rec->smbiosmajorversion = get_bios_smbiosmajorversion( buf, len );
1451 rec->smbiosminorversion = get_bios_smbiosminorversion( buf, len );
1452 rec->systembiosmajorversion = get_bios_system_bios_major_release( buf, len );
1453 rec->systembiosminorversion = get_bios_system_bios_minor_release( buf, len );
1454 rec->version = L"WINE - 1";
1455 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
1456 else row++;
1458 free( buf );
1460 TRACE("created %u rows\n", row);
1461 table->num_rows = row;
1462 return status;
1465 static enum fill_status fill_cdromdrive( struct table *table, const struct expr *cond )
1467 WCHAR drive[3], root[] = L"A:\\";
1468 struct record_cdromdrive *rec;
1469 UINT i, row = 0, offset = 0;
1470 DWORD drives = GetLogicalDrives();
1471 enum fill_status status = FILL_STATUS_UNFILTERED;
1473 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
1475 for (i = 0; i < 26; i++)
1477 if (drives & (1 << i))
1479 root[0] = 'A' + i;
1480 if (GetDriveTypeW( root ) != DRIVE_CDROM)
1481 continue;
1483 if (!resize_table( table, row + 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
1485 rec = (struct record_cdromdrive *)(table->data + offset);
1486 rec->device_id = L"IDE\\CDROMWINE_CD-ROM_____________________________1.0_____\\5&3A2A5854&0&1.0.0";
1487 swprintf( drive, ARRAY_SIZE( drive ), L"%c:", 'A' + i );
1488 rec->drive = wcsdup( drive );
1489 rec->mediatype = L"CR-ROM";
1490 rec->name = L"Wine CD_ROM ATA Device";
1491 rec->pnpdevice_id = L"IDE\\CDROMWINE_CD-ROM_____________________________1.0_____\\5&3A2A5854&0&1.0.0";
1492 if (!match_row( table, row, cond, &status ))
1494 free_row_values( table, row );
1495 continue;
1497 offset += sizeof(*rec);
1498 row++;
1501 TRACE("created %u rows\n", row);
1502 table->num_rows = row;
1503 return status;
1506 static UINT get_processor_count(void)
1508 SYSTEM_BASIC_INFORMATION info;
1510 if (NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL )) return 1;
1511 return info.NumberOfProcessors;
1514 static UINT get_logical_processor_count( UINT *num_physical, UINT *num_packages )
1516 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buf, *entry;
1517 UINT core_relation_count = 0, package_relation_count = 0;
1518 NTSTATUS status;
1519 ULONG len, offset = 0;
1520 BOOL smt_enabled = FALSE;
1521 DWORD all = RelationAll;
1523 if (num_packages) *num_packages = 1;
1524 status = NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx, &all, sizeof(all), NULL, 0, &len );
1525 if (status != STATUS_INFO_LENGTH_MISMATCH) return get_processor_count();
1527 if (!(buf = malloc( len ))) return get_processor_count();
1528 status = NtQuerySystemInformationEx( SystemLogicalProcessorInformationEx, &all, sizeof(all), buf, len, NULL );
1529 if (status != STATUS_SUCCESS)
1531 free( buf );
1532 return get_processor_count();
1535 while (offset < len)
1537 entry = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((char *)buf + offset);
1539 if (entry->Relationship == RelationProcessorCore)
1541 core_relation_count++;
1542 if (entry->u.Processor.Flags & LTP_PC_SMT) smt_enabled = TRUE;
1544 else if (entry->Relationship == RelationProcessorPackage)
1546 package_relation_count++;
1548 offset += entry->Size;
1551 free( buf );
1552 if (num_physical) *num_physical = core_relation_count;
1553 if (num_packages) *num_packages = package_relation_count;
1554 return smt_enabled ? core_relation_count * 2 : core_relation_count;
1557 static UINT64 get_total_physical_memory(void)
1559 MEMORYSTATUSEX status;
1561 status.dwLength = sizeof(status);
1562 if (!GlobalMemoryStatusEx( &status )) return 1024 * 1024 * 1024;
1563 return status.ullTotalPhys;
1566 static UINT64 get_available_physical_memory(void)
1568 MEMORYSTATUSEX status;
1570 status.dwLength = sizeof(status);
1571 if (!GlobalMemoryStatusEx( &status )) return 1024 * 1024 * 1024;
1572 return status.ullAvailPhys;
1575 static WCHAR *get_computername(void)
1577 WCHAR *ret;
1578 DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
1580 if (!(ret = malloc( size * sizeof(WCHAR) ))) return NULL;
1581 GetComputerNameW( ret, &size );
1582 return ret;
1585 static const WCHAR *get_systemtype(void)
1587 SYSTEM_INFO info;
1588 GetNativeSystemInfo( &info );
1589 if (info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) return L"x64 based PC";
1590 return L"x86 based PC";
1593 static WCHAR *get_username(void)
1595 WCHAR *ret;
1596 DWORD compsize, usersize;
1597 DWORD size;
1599 compsize = 0;
1600 GetComputerNameW( NULL, &compsize );
1601 usersize = 0;
1602 GetUserNameW( NULL, &usersize );
1603 size = compsize + usersize; /* two null terminators account for the \ */
1604 if (!(ret = malloc( size * sizeof(WCHAR) ))) return NULL;
1605 GetComputerNameW( ret, &compsize );
1606 ret[compsize] = '\\';
1607 GetUserNameW( ret + compsize + 1, &usersize );
1608 return ret;
1611 static enum fill_status fill_compsys( struct table *table, const struct expr *cond )
1613 struct record_computersystem *rec;
1614 enum fill_status status = FILL_STATUS_UNFILTERED;
1615 UINT row = 0;
1617 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
1619 rec = (struct record_computersystem *)table->data;
1620 rec->description = L"AT/AT COMPATIBLE";
1621 rec->domain = L"WORKGROUP";
1622 rec->domainrole = 0; /* standalone workstation */
1623 rec->manufacturer = L"The Wine Project";
1624 rec->model = L"Wine";
1625 rec->name = get_computername();
1626 rec->num_logical_processors = get_logical_processor_count( NULL, &rec->num_processors );
1627 rec->systemtype = get_systemtype();
1628 rec->total_physical_memory = get_total_physical_memory();
1629 rec->username = get_username();
1630 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
1631 else row++;
1633 TRACE("created %u rows\n", row);
1634 table->num_rows = row;
1635 return status;
1638 static WCHAR *get_compsysproduct_string( BYTE id, const char *buf, UINT len )
1640 const struct smbios_header *hdr;
1641 const struct smbios_system *system;
1642 UINT offset;
1644 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_SYSTEM, buf, len ))) return NULL;
1646 system = (const struct smbios_system *)hdr;
1647 offset = (const char *)system - buf + system->hdr.length;
1648 return get_smbios_string( id, buf, offset, len );
1651 static WCHAR *get_compsysproduct_identifyingnumber( const char *buf, UINT len )
1653 WCHAR *ret = get_compsysproduct_string( 4, buf, len );
1654 if (!ret) return wcsdup( L"0" );
1655 return ret;
1658 static WCHAR *get_compsysproduct_name( const char *buf, UINT len )
1660 WCHAR *ret = get_compsysproduct_string( 2, buf, len );
1661 if (!ret) return wcsdup( L"Wine" );
1662 return ret;
1665 static WCHAR *get_compsysproduct_uuid( const char *buf, UINT len )
1667 static const BYTE none[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
1668 const struct smbios_header *hdr;
1669 const struct smbios_system *system;
1670 const BYTE *ptr;
1671 WCHAR *ret = NULL;
1673 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_SYSTEM, buf, len )) || hdr->length < sizeof(*system)) goto done;
1674 system = (const struct smbios_system *)hdr;
1675 if (!memcmp( system->uuid, none, sizeof(none) ) || !(ret = malloc( 37 * sizeof(WCHAR) ))) goto done;
1677 ptr = system->uuid;
1678 swprintf( ret, 37, L"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", ptr[0], ptr[1],
1679 ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13],
1680 ptr[14], ptr[15] );
1681 done:
1682 if (!ret) ret = wcsdup( L"deaddead-dead-dead-dead-deaddeaddead" );
1683 return ret;
1686 static WCHAR *get_compsysproduct_vendor( const char *buf, UINT len )
1688 WCHAR *ret = get_compsysproduct_string( 1, buf, len );
1689 if (!ret) return wcsdup( L"The Wine Project" );
1690 return ret;
1693 static WCHAR *get_compsysproduct_version( const char *buf, UINT len )
1695 WCHAR *ret = get_compsysproduct_string( 3, buf, len );
1696 if (!ret) return wcsdup( L"1.0" );
1697 return ret;
1700 static enum fill_status fill_compsysproduct( struct table *table, const struct expr *cond )
1702 struct record_computersystemproduct *rec;
1703 enum fill_status status = FILL_STATUS_UNFILTERED;
1704 UINT row = 0, len;
1705 char *buf;
1707 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
1709 len = GetSystemFirmwareTable( RSMB, 0, NULL, 0 );
1710 if (!(buf = malloc( len ))) return FILL_STATUS_FAILED;
1711 GetSystemFirmwareTable( RSMB, 0, buf, len );
1713 rec = (struct record_computersystemproduct *)table->data;
1714 rec->identifyingnumber = get_compsysproduct_identifyingnumber( buf, len );
1715 rec->name = get_compsysproduct_name( buf, len );
1716 rec->skunumber = NULL;
1717 rec->uuid = get_compsysproduct_uuid( buf, len );
1718 rec->vendor = get_compsysproduct_vendor( buf, len );
1719 rec->version = get_compsysproduct_version( buf, len );
1720 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
1721 else row++;
1723 free( buf );
1725 TRACE("created %u rows\n", row);
1726 table->num_rows = row;
1727 return status;
1730 struct dirstack
1732 WCHAR **dirs;
1733 UINT *len_dirs;
1734 UINT num_dirs;
1735 UINT num_allocated;
1738 static struct dirstack *alloc_dirstack( UINT size )
1740 struct dirstack *dirstack;
1742 if (!(dirstack = malloc( sizeof(*dirstack) ))) return NULL;
1743 if (!(dirstack->dirs = malloc( sizeof(WCHAR *) * size )))
1745 free( dirstack );
1746 return NULL;
1748 if (!(dirstack->len_dirs = malloc( sizeof(UINT) * size )))
1750 free( dirstack->dirs );
1751 free( dirstack );
1752 return NULL;
1754 dirstack->num_dirs = 0;
1755 dirstack->num_allocated = size;
1756 return dirstack;
1759 static void clear_dirstack( struct dirstack *dirstack )
1761 UINT i;
1762 for (i = 0; i < dirstack->num_dirs; i++) free( dirstack->dirs[i] );
1763 dirstack->num_dirs = 0;
1766 static void free_dirstack( struct dirstack *dirstack )
1768 clear_dirstack( dirstack );
1769 free( dirstack->dirs );
1770 free( dirstack->len_dirs );
1771 free( dirstack );
1774 static BOOL push_dir( struct dirstack *dirstack, WCHAR *dir, UINT len )
1776 UINT size, i = dirstack->num_dirs;
1778 if (!dir) return FALSE;
1780 if (i == dirstack->num_allocated)
1782 WCHAR **tmp;
1783 UINT *len_tmp;
1785 size = dirstack->num_allocated * 2;
1786 if (!(tmp = realloc( dirstack->dirs, size * sizeof(WCHAR *) ))) return FALSE;
1787 dirstack->dirs = tmp;
1788 if (!(len_tmp = realloc( dirstack->len_dirs, size * sizeof(UINT) ))) return FALSE;
1789 dirstack->len_dirs = len_tmp;
1790 dirstack->num_allocated = size;
1792 dirstack->dirs[i] = dir;
1793 dirstack->len_dirs[i] = len;
1794 dirstack->num_dirs++;
1795 return TRUE;
1798 static WCHAR *pop_dir( struct dirstack *dirstack, UINT *len )
1800 if (!dirstack->num_dirs)
1802 *len = 0;
1803 return NULL;
1805 dirstack->num_dirs--;
1806 *len = dirstack->len_dirs[dirstack->num_dirs];
1807 return dirstack->dirs[dirstack->num_dirs];
1810 static const WCHAR *peek_dir( struct dirstack *dirstack )
1812 if (!dirstack->num_dirs) return NULL;
1813 return dirstack->dirs[dirstack->num_dirs - 1];
1816 static WCHAR *build_glob( WCHAR drive, const WCHAR *path, UINT len )
1818 UINT i = 0;
1819 WCHAR *ret;
1821 if (!(ret = malloc( (len + 6) * sizeof(WCHAR) ))) return NULL;
1822 ret[i++] = drive;
1823 ret[i++] = ':';
1824 ret[i++] = '\\';
1825 if (path && len)
1827 memcpy( ret + i, path, len * sizeof(WCHAR) );
1828 i += len;
1829 ret[i++] = '\\';
1831 ret[i++] = '*';
1832 ret[i] = 0;
1833 return ret;
1836 static WCHAR *build_name( WCHAR drive, const WCHAR *path )
1838 UINT i = 0, len = 0;
1839 const WCHAR *p;
1840 WCHAR *ret;
1842 for (p = path; *p; p++)
1844 if (*p == '\\') len += 2;
1845 else len++;
1847 if (!(ret = malloc( (len + 5) * sizeof(WCHAR) ))) return NULL;
1848 ret[i++] = drive;
1849 ret[i++] = ':';
1850 ret[i++] = '\\';
1851 ret[i++] = '\\';
1852 for (p = path; *p; p++)
1854 if (*p != '\\') ret[i++] = *p;
1855 else
1857 ret[i++] = '\\';
1858 ret[i++] = '\\';
1861 ret[i] = 0;
1862 return ret;
1865 static WCHAR *build_dirname( const WCHAR *path, UINT *ret_len )
1867 const WCHAR *p = path, *start;
1868 UINT len, i;
1869 WCHAR *ret;
1871 if (!iswalpha( p[0] ) || p[1] != ':' || p[2] != '\\' || p[3] != '\\' || !p[4]) return NULL;
1872 start = path + 4;
1873 len = lstrlenW( start );
1874 p = start + len - 1;
1875 if (*p == '\\') return NULL;
1877 while (p >= start && *p != '\\') { len--; p--; };
1878 while (p >= start && *p == '\\') { len--; p--; };
1880 if (!(ret = malloc( (len + 1) * sizeof(WCHAR) ))) return NULL;
1881 for (i = 0, p = start; p < start + len; p++)
1883 if (p[0] == '\\' && p[1] == '\\')
1885 ret[i++] = '\\';
1886 p++;
1888 else ret[i++] = *p;
1890 ret[i] = 0;
1891 *ret_len = i;
1892 return ret;
1895 static BOOL seen_dir( struct dirstack *dirstack, const WCHAR *path )
1897 UINT i;
1898 for (i = 0; i < dirstack->num_dirs; i++) if (!wcscmp( dirstack->dirs[i], path )) return TRUE;
1899 return FALSE;
1902 /* optimize queries of the form WHERE Name='...' [OR Name='...']* */
1903 static UINT seed_dirs( struct dirstack *dirstack, const struct expr *cond, WCHAR root, UINT *count )
1905 const struct expr *left, *right;
1907 if (!cond || cond->type != EXPR_COMPLEX) return *count = 0;
1909 left = cond->u.expr.left;
1910 right = cond->u.expr.right;
1911 if (cond->u.expr.op == OP_EQ)
1913 UINT len;
1914 WCHAR *path;
1915 const WCHAR *str = NULL;
1917 if (left->type == EXPR_PROPVAL && right->type == EXPR_SVAL &&
1918 !wcscmp( left->u.propval->name, L"Name" ) &&
1919 towupper( right->u.sval[0] ) == towupper( root ))
1921 str = right->u.sval;
1923 else if (left->type == EXPR_SVAL && right->type == EXPR_PROPVAL &&
1924 !wcscmp( right->u.propval->name, L"Name" ) &&
1925 towupper( left->u.sval[0] ) == towupper( root ))
1927 str = left->u.sval;
1929 if (str && (path = build_dirname( str, &len )))
1931 if (seen_dir( dirstack, path ))
1933 free( path );
1934 return ++*count;
1936 else if (push_dir( dirstack, path, len )) return ++*count;
1937 free( path );
1938 return *count = 0;
1941 else if (cond->u.expr.op == OP_OR)
1943 UINT left_count = 0, right_count = 0;
1945 if (!(seed_dirs( dirstack, left, root, &left_count ))) return *count = 0;
1946 if (!(seed_dirs( dirstack, right, root, &right_count ))) return *count = 0;
1947 return *count += left_count + right_count;
1949 return *count = 0;
1952 static WCHAR *append_path( const WCHAR *path, const WCHAR *segment, UINT *len )
1954 UINT len_path = 0, len_segment = lstrlenW( segment );
1955 WCHAR *ret;
1957 *len = 0;
1958 if (path) len_path = lstrlenW( path );
1959 if (!(ret = malloc( (len_path + len_segment + 2) * sizeof(WCHAR) ))) return NULL;
1960 if (path && len_path)
1962 memcpy( ret, path, len_path * sizeof(WCHAR) );
1963 ret[len_path] = '\\';
1964 *len += len_path + 1;
1966 memcpy( ret + *len, segment, len_segment * sizeof(WCHAR) );
1967 *len += len_segment;
1968 ret[*len] = 0;
1969 return ret;
1972 static WCHAR *get_file_version( const WCHAR *filename )
1974 VS_FIXEDFILEINFO *info;
1975 UINT size;
1976 DWORD len = 4 * 5 + ARRAY_SIZE( L"%u.%u.%u.%u" );
1977 void *block;
1978 WCHAR *ret;
1980 if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL;
1981 if (!(size = GetFileVersionInfoSizeW( filename, NULL )) || !(block = malloc( size )))
1983 free( ret );
1984 return NULL;
1986 if (!GetFileVersionInfoW( filename, 0, size, block ) ||
1987 !VerQueryValueW( block, L"\\", (void **)&info, &size ))
1989 free( block );
1990 free( ret );
1991 return NULL;
1993 swprintf( ret, len, L"%u.%u.%u.%u", info->dwFileVersionMS >> 16, info->dwFileVersionMS & 0xffff,
1994 info->dwFileVersionLS >> 16, info->dwFileVersionLS & 0xffff );
1995 free( block );
1996 return ret;
1999 static enum fill_status fill_datafile( struct table *table, const struct expr *cond )
2001 struct record_datafile *rec;
2002 UINT i, len, row = 0, offset = 0, num_expected_rows;
2003 WCHAR *glob = NULL, *path = NULL, *new_path, root[] = L"A:\\";
2004 DWORD drives = GetLogicalDrives();
2005 WIN32_FIND_DATAW data;
2006 HANDLE handle;
2007 struct dirstack *dirstack;
2008 enum fill_status status = FILL_STATUS_UNFILTERED;
2010 if (!resize_table( table, 8, sizeof(*rec) )) return FILL_STATUS_FAILED;
2012 dirstack = alloc_dirstack(2);
2014 for (i = 0; i < 26; i++)
2016 if (!(drives & (1 << i))) continue;
2018 root[0] = 'A' + i;
2019 if (GetDriveTypeW( root ) != DRIVE_FIXED) continue;
2021 num_expected_rows = 0;
2022 if (!seed_dirs( dirstack, cond, root[0], &num_expected_rows )) clear_dirstack( dirstack );
2024 for (;;)
2026 free( glob );
2027 free( path );
2028 path = pop_dir( dirstack, &len );
2029 if (!(glob = build_glob( root[0], path, len )))
2031 status = FILL_STATUS_FAILED;
2032 goto done;
2034 if ((handle = FindFirstFileW( glob, &data )) != INVALID_HANDLE_VALUE)
2038 if (!resize_table( table, row + 1, sizeof(*rec) ))
2040 status = FILL_STATUS_FAILED;
2041 FindClose( handle );
2042 goto done;
2044 if (!wcscmp( data.cFileName, L"." ) || !wcscmp( data.cFileName, L".." )) continue;
2046 if (!(new_path = append_path( path, data.cFileName, &len )))
2048 status = FILL_STATUS_FAILED;
2049 FindClose( handle );
2050 goto done;
2053 if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2055 if (push_dir( dirstack, new_path, len )) continue;
2056 free( new_path );
2057 FindClose( handle );
2058 status = FILL_STATUS_FAILED;
2059 goto done;
2061 rec = (struct record_datafile *)(table->data + offset);
2062 rec->name = build_name( root[0], new_path );
2063 rec->version = get_file_version( rec->name );
2064 free( new_path );
2065 if (!match_row( table, row, cond, &status ))
2067 free_row_values( table, row );
2068 continue;
2070 else if (num_expected_rows && row == num_expected_rows - 1)
2072 row++;
2073 FindClose( handle );
2074 status = FILL_STATUS_FILTERED;
2075 goto done;
2077 offset += sizeof(*rec);
2078 row++;
2080 while (FindNextFileW( handle, &data ));
2081 FindClose( handle );
2083 if (!peek_dir( dirstack )) break;
2087 done:
2088 free_dirstack( dirstack );
2089 free( glob );
2090 free( path );
2092 TRACE("created %u rows\n", row);
2093 table->num_rows = row;
2094 return status;
2097 static UINT32 get_pixelsperxlogicalinch(void)
2099 HDC hdc = GetDC( NULL );
2100 UINT32 ret;
2102 if (!hdc) return 96;
2103 ret = GetDeviceCaps( hdc, LOGPIXELSX );
2104 ReleaseDC( NULL, hdc );
2105 return ret;
2108 static enum fill_status fill_desktopmonitor( struct table *table, const struct expr *cond )
2110 struct record_desktopmonitor *rec;
2111 enum fill_status status = FILL_STATUS_UNFILTERED;
2112 UINT row = 0;
2114 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
2116 rec = (struct record_desktopmonitor *)table->data;
2117 rec->name = L"Generic Non-PnP Monitor";
2118 rec->pixelsperxlogicalinch = get_pixelsperxlogicalinch();
2120 if (match_row( table, row, cond, &status )) row++;
2122 TRACE("created %u rows\n", row);
2123 table->num_rows = row;
2124 return status;
2127 static enum fill_status fill_directory( struct table *table, const struct expr *cond )
2129 struct record_directory *rec;
2130 UINT i, len, row = 0, offset = 0, num_expected_rows;
2131 WCHAR *glob = NULL, *path = NULL, *new_path, root[] = L"A:\\";
2132 DWORD drives = GetLogicalDrives();
2133 WIN32_FIND_DATAW data;
2134 HANDLE handle;
2135 struct dirstack *dirstack;
2136 enum fill_status status = FILL_STATUS_UNFILTERED;
2138 if (!resize_table( table, 4, sizeof(*rec) )) return FILL_STATUS_FAILED;
2140 dirstack = alloc_dirstack(2);
2142 for (i = 0; i < 26; i++)
2144 if (!(drives & (1 << i))) continue;
2146 root[0] = 'A' + i;
2147 if (GetDriveTypeW( root ) != DRIVE_FIXED) continue;
2149 num_expected_rows = 0;
2150 if (!seed_dirs( dirstack, cond, root[0], &num_expected_rows )) clear_dirstack( dirstack );
2152 for (;;)
2154 free( glob );
2155 free( path );
2156 path = pop_dir( dirstack, &len );
2157 if (!(glob = build_glob( root[0], path, len )))
2159 status = FILL_STATUS_FAILED;
2160 goto done;
2162 if ((handle = FindFirstFileW( glob, &data )) != INVALID_HANDLE_VALUE)
2166 if (!resize_table( table, row + 1, sizeof(*rec) ))
2168 FindClose( handle );
2169 status = FILL_STATUS_FAILED;
2170 goto done;
2172 if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
2173 !wcscmp( data.cFileName, L"." ) || !wcscmp( data.cFileName, L".." ))
2174 continue;
2176 if (!(new_path = append_path( path, data.cFileName, &len )))
2178 FindClose( handle );
2179 status = FILL_STATUS_FAILED;
2180 goto done;
2183 if (!(push_dir( dirstack, new_path, len )))
2185 free( new_path );
2186 FindClose( handle );
2187 status = FILL_STATUS_FAILED;
2188 goto done;
2190 rec = (struct record_directory *)(table->data + offset);
2191 rec->accessmask = FILE_ALL_ACCESS;
2192 rec->name = build_name( root[0], new_path );
2193 free( new_path );
2194 if (!match_row( table, row, cond, &status ))
2196 free_row_values( table, row );
2197 continue;
2199 else if (num_expected_rows && row == num_expected_rows - 1)
2201 row++;
2202 FindClose( handle );
2203 status = FILL_STATUS_FILTERED;
2204 goto done;
2206 offset += sizeof(*rec);
2207 row++;
2209 while (FindNextFileW( handle, &data ));
2210 FindClose( handle );
2212 if (!peek_dir( dirstack )) break;
2216 done:
2217 free_dirstack( dirstack );
2218 free( glob );
2219 free( path );
2221 TRACE("created %u rows\n", row);
2222 table->num_rows = row;
2223 return status;
2226 static UINT64 get_freespace( const WCHAR *dir, UINT64 *disksize )
2228 WCHAR root[] = L"\\\\.\\A:";
2229 ULARGE_INTEGER free;
2230 DISK_GEOMETRY_EX info;
2231 HANDLE handle;
2232 DWORD bytes_returned;
2234 free.QuadPart = 512 * 1024 * 1024;
2235 GetDiskFreeSpaceExW( dir, NULL, NULL, &free );
2237 root[4] = dir[0];
2238 handle = CreateFileW( root, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
2239 if (handle != INVALID_HANDLE_VALUE)
2241 if (DeviceIoControl( handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &info, sizeof(info), &bytes_returned, NULL ))
2242 *disksize = info.DiskSize.QuadPart;
2243 CloseHandle( handle );
2245 return free.QuadPart;
2247 static WCHAR *get_diskdrive_serialnumber( WCHAR letter )
2249 WCHAR *ret = NULL;
2250 STORAGE_DEVICE_DESCRIPTOR *desc;
2251 HANDLE handle = INVALID_HANDLE_VALUE;
2252 STORAGE_PROPERTY_QUERY query = {0};
2253 WCHAR drive[7];
2254 DWORD size;
2256 swprintf( drive, ARRAY_SIZE(drive), L"\\\\.\\%c:", letter );
2257 handle = CreateFileW( drive, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
2258 if (handle == INVALID_HANDLE_VALUE) goto done;
2260 query.PropertyId = StorageDeviceProperty;
2261 query.QueryType = PropertyStandardQuery;
2263 size = sizeof(*desc) + 256;
2264 for (;;)
2266 if (!(desc = malloc( size ))) break;
2267 if (DeviceIoControl( handle, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), desc, size, NULL, NULL ))
2269 if (desc->SerialNumberOffset) ret = heap_strdupAW( (const char *)desc + desc->SerialNumberOffset );
2270 free( desc );
2271 break;
2273 size = desc->Size;
2274 free( desc );
2275 if (GetLastError() != ERROR_MORE_DATA) break;
2278 done:
2279 if (handle != INVALID_HANDLE_VALUE) CloseHandle( handle );
2280 if (!ret) ret = wcsdup( L"WINEHDISK" );
2281 return ret;
2284 static enum fill_status fill_diskdrive( struct table *table, const struct expr *cond )
2286 static const WCHAR fmtW[] = L"\\\\\\\\.\\\\PHYSICALDRIVE%u";
2287 WCHAR device_id[ARRAY_SIZE( fmtW ) + 10], root[] = L"A:\\";
2288 struct record_diskdrive *rec;
2289 UINT i, row = 0, offset = 0, index = 0, type;
2290 UINT64 size = 1024 * 1024 * 1024;
2291 DWORD drives = GetLogicalDrives();
2292 enum fill_status status = FILL_STATUS_UNFILTERED;
2294 if (!resize_table( table, 2, sizeof(*rec) )) return FILL_STATUS_FAILED;
2296 for (i = 0; i < 26; i++)
2298 if (drives & (1 << i))
2300 root[0] = 'A' + i;
2301 type = GetDriveTypeW( root );
2302 if (type != DRIVE_FIXED && type != DRIVE_REMOVABLE)
2303 continue;
2305 if (!resize_table( table, row + 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
2307 rec = (struct record_diskdrive *)(table->data + offset);
2308 swprintf( device_id, ARRAY_SIZE( device_id ), fmtW, index );
2309 rec->device_id = wcsdup( device_id );
2310 rec->index = index++;
2311 rec->interfacetype = L"IDE";
2312 rec->manufacturer = L"(Standard disk drives)";
2313 rec->mediatype = (type == DRIVE_FIXED) ? L"Fixed hard disk" : L"Removable media";
2314 rec->model = L"Wine Disk Drive";
2315 rec->pnpdevice_id = L"IDE\\Disk\\VEN_WINE";
2316 rec->serialnumber = get_diskdrive_serialnumber( root[0] );
2317 get_freespace( root, &size );
2318 rec->size = size;
2319 if (!match_row( table, row, cond, &status ))
2321 free_row_values( table, row );
2322 continue;
2324 offset += sizeof(*rec);
2325 row++;
2328 TRACE("created %u rows\n", row);
2329 table->num_rows = row;
2330 return status;
2333 struct association
2335 WCHAR *ref;
2336 WCHAR *ref2;
2339 static void free_associations( struct association *assoc, UINT count )
2341 UINT i;
2342 if (!assoc) return;
2343 for (i = 0; i < count; i++)
2345 free( assoc[i].ref );
2346 free( assoc[i].ref2 );
2348 free( assoc );
2351 static struct association *get_diskdrivetodiskpartition_pairs( UINT *count )
2353 struct association *ret = NULL;
2354 struct query *query, *query2 = NULL;
2355 VARIANT val;
2356 HRESULT hr;
2357 UINT i;
2359 if (!(query = create_query( WBEMPROX_NAMESPACE_CIMV2 ))) return NULL;
2360 if ((hr = parse_query( WBEMPROX_NAMESPACE_CIMV2, L"SELECT * FROM Win32_DiskDrive",
2361 &query->view, &query->mem )) != S_OK) goto done;
2362 if ((hr = execute_view( query->view )) != S_OK) goto done;
2364 if (!(query2 = create_query( WBEMPROX_NAMESPACE_CIMV2 ))) return FALSE;
2365 if ((hr = parse_query( WBEMPROX_NAMESPACE_CIMV2, L"SELECT * FROM Win32_DiskPartition",
2366 &query2->view, &query2->mem )) != S_OK) goto done;
2367 if ((hr = execute_view( query2->view )) != S_OK) goto done;
2369 if (!(ret = calloc( query->view->result_count, sizeof(*ret) ))) goto done;
2371 for (i = 0; i < query->view->result_count; i++)
2373 if ((hr = get_propval( query->view, i, L"__PATH", &val, NULL, NULL )) != S_OK) goto done;
2374 if (!(ret[i].ref = wcsdup( V_BSTR(&val) ))) goto done;
2375 VariantClear( &val );
2377 if ((hr = get_propval( query2->view, i, L"__PATH", &val, NULL, NULL )) != S_OK) goto done;
2378 if (!(ret[i].ref2 = wcsdup( V_BSTR(&val) ))) goto done;
2379 VariantClear( &val );
2382 *count = query->view->result_count;
2384 done:
2385 if (!ret) free_associations( ret, query->view->result_count );
2386 free_query( query );
2387 free_query( query2 );
2388 return ret;
2391 static enum fill_status fill_diskdrivetodiskpartition( struct table *table, const struct expr *cond )
2393 struct record_diskdrivetodiskpartition *rec;
2394 UINT i, row = 0, offset = 0, count = 0;
2395 enum fill_status status = FILL_STATUS_UNFILTERED;
2396 struct association *assoc;
2398 if (!(assoc = get_diskdrivetodiskpartition_pairs( &count ))) return FILL_STATUS_FAILED;
2399 if (!count)
2401 free_associations( assoc, count );
2402 return FILL_STATUS_UNFILTERED;
2404 if (!resize_table( table, count, sizeof(*rec) ))
2406 free_associations( assoc, count );
2407 return FILL_STATUS_FAILED;
2410 for (i = 0; i < count; i++)
2412 rec = (struct record_diskdrivetodiskpartition *)(table->data + offset);
2413 rec->antecedent = assoc[i].ref;
2414 rec->dependent = assoc[i].ref2;
2415 if (!match_row( table, row, cond, &status ))
2417 free_row_values( table, row );
2418 continue;
2420 offset += sizeof(*rec);
2421 row++;
2424 free( assoc );
2426 TRACE("created %u rows\n", row);
2427 table->num_rows = row;
2428 return status;
2431 static WCHAR *get_filesystem( const WCHAR *root )
2433 WCHAR buffer[MAX_PATH + 1];
2435 if (GetVolumeInformationW( root, NULL, 0, NULL, NULL, NULL, buffer, MAX_PATH + 1 ))
2436 return wcsdup( buffer );
2437 return wcsdup( L"NTFS" );
2440 static enum fill_status fill_diskpartition( struct table *table, const struct expr *cond )
2442 WCHAR device_id[32], root[] = L"A:\\";
2443 struct record_diskpartition *rec;
2444 UINT i, row = 0, offset = 0, type, index = 0;
2445 UINT64 size = 1024 * 1024 * 1024;
2446 DWORD drives = GetLogicalDrives();
2447 enum fill_status status = FILL_STATUS_UNFILTERED;
2449 if (!resize_table( table, 4, sizeof(*rec) )) return FILL_STATUS_FAILED;
2451 for (i = 0; i < 26; i++)
2453 if (drives & (1 << i))
2455 root[0] = 'A' + i;
2456 type = GetDriveTypeW( root );
2457 if (type != DRIVE_FIXED && type != DRIVE_REMOVABLE)
2458 continue;
2460 if (!resize_table( table, row + 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
2462 rec = (struct record_diskpartition *)(table->data + offset);
2463 rec->bootable = (i == 2) ? -1 : 0;
2464 rec->bootpartition = (i == 2) ? -1 : 0;
2465 swprintf( device_id, ARRAY_SIZE( device_id ), L"Disk #%u, Partition #0", index );
2466 rec->device_id = wcsdup( device_id );
2467 rec->diskindex = index++;
2468 rec->index = 0;
2469 rec->pnpdevice_id = wcsdup( device_id );
2470 get_freespace( root, &size );
2471 rec->size = size;
2472 rec->startingoffset = 0;
2473 rec->type = get_filesystem( root );
2474 if (!match_row( table, row, cond, &status ))
2476 free_row_values( table, row );
2477 continue;
2479 offset += sizeof(*rec);
2480 row++;
2483 TRACE("created %u rows\n", row);
2484 table->num_rows = row;
2485 return status;
2488 static UINT32 get_bitsperpixel( UINT *hres, UINT *vres )
2490 HDC hdc = GetDC( NULL );
2491 UINT32 ret;
2493 if (!hdc) return 32;
2494 ret = GetDeviceCaps( hdc, BITSPIXEL );
2495 *hres = GetDeviceCaps( hdc, HORZRES );
2496 *vres = GetDeviceCaps( hdc, VERTRES );
2497 ReleaseDC( NULL, hdc );
2498 return ret;
2501 static enum fill_status fill_displaycontrollerconfig( struct table *table, const struct expr *cond )
2503 struct record_displaycontrollerconfig *rec;
2504 UINT row = 0, hres = 1024, vres = 768;
2505 enum fill_status status = FILL_STATUS_UNFILTERED;
2507 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
2509 rec = (struct record_displaycontrollerconfig *)table->data;
2510 rec->bitsperpixel = get_bitsperpixel( &hres, &vres );
2511 rec->caption = L"VideoController1";
2512 rec->horizontalresolution = hres;
2513 rec->name = L"VideoController1";
2514 rec->verticalresolution = vres;
2515 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
2516 else row++;
2518 TRACE("created %u rows\n", row);
2519 table->num_rows = row;
2520 return status;
2523 static WCHAR *get_ip4_string( DWORD addr )
2525 DWORD len = sizeof("ddd.ddd.ddd.ddd");
2526 WCHAR *ret;
2528 if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL;
2529 swprintf( ret, len, L"%u.%u.%u.%u", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff );
2530 return ret;
2533 static enum fill_status fill_ip4routetable( struct table *table, const struct expr *cond )
2535 struct record_ip4routetable *rec;
2536 UINT i, row = 0, offset = 0;
2537 ULONG size = 0;
2538 MIB_IPFORWARDTABLE *forwards;
2539 enum fill_status status = FILL_STATUS_UNFILTERED;
2541 if (GetIpForwardTable( NULL, &size, TRUE ) != ERROR_INSUFFICIENT_BUFFER) return FILL_STATUS_FAILED;
2542 if (!(forwards = malloc( size ))) return FILL_STATUS_FAILED;
2543 if (GetIpForwardTable( forwards, &size, TRUE ))
2545 free( forwards );
2546 return FILL_STATUS_FAILED;
2548 if (!resize_table( table, max(forwards->dwNumEntries, 1), sizeof(*rec) ))
2550 free( forwards );
2551 return FILL_STATUS_FAILED;
2554 for (i = 0; i < forwards->dwNumEntries; i++)
2556 rec = (struct record_ip4routetable *)(table->data + offset);
2558 rec->destination = get_ip4_string( ntohl(forwards->table[i].dwForwardDest) );
2559 rec->interfaceindex = forwards->table[i].dwForwardIfIndex;
2560 rec->nexthop = get_ip4_string( ntohl(forwards->table[i].dwForwardNextHop) );
2562 if (!match_row( table, row, cond, &status ))
2564 free_row_values( table, row );
2565 continue;
2567 offset += sizeof(*rec);
2568 row++;
2570 TRACE("created %u rows\n", row);
2571 table->num_rows = row;
2573 free( forwards );
2574 return status;
2577 static WCHAR *get_volumename( const WCHAR *root )
2579 WCHAR buf[MAX_PATH + 1] = {0};
2580 GetVolumeInformationW( root, buf, ARRAY_SIZE( buf ), NULL, NULL, NULL, NULL, 0 );
2581 return wcsdup( buf );
2583 static WCHAR *get_volumeserialnumber( const WCHAR *root )
2585 DWORD serial = 0;
2586 WCHAR buffer[9];
2588 GetVolumeInformationW( root, NULL, 0, &serial, NULL, NULL, NULL, 0 );
2589 swprintf( buffer, ARRAY_SIZE( buffer ), L"%08X", serial );
2590 return wcsdup( buffer );
2593 static enum fill_status fill_logicaldisk( struct table *table, const struct expr *cond )
2595 WCHAR device_id[3], root[] = L"A:\\";
2596 struct record_logicaldisk *rec;
2597 UINT i, row = 0, offset = 0, type;
2598 UINT64 size = 1024 * 1024 * 1024;
2599 DWORD drives = GetLogicalDrives();
2600 enum fill_status status = FILL_STATUS_UNFILTERED;
2602 if (!resize_table( table, 4, sizeof(*rec) )) return FILL_STATUS_FAILED;
2604 for (i = 0; i < 26; i++)
2606 if (drives & (1 << i))
2608 root[0] = 'A' + i;
2609 type = GetDriveTypeW( root );
2610 if (type != DRIVE_FIXED && type != DRIVE_CDROM && type != DRIVE_REMOVABLE)
2611 continue;
2613 if (!resize_table( table, row + 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
2615 rec = (struct record_logicaldisk *)(table->data + offset);
2616 swprintf( device_id, ARRAY_SIZE( device_id ), L"%c:", 'A' + i );
2617 rec->caption = wcsdup( device_id );
2618 rec->device_id = wcsdup( device_id );
2619 rec->drivetype = type;
2620 rec->filesystem = get_filesystem( root );
2621 rec->freespace = get_freespace( root, &size );
2622 rec->name = wcsdup( device_id );
2623 rec->size = size;
2624 rec->volumename = get_volumename( root );
2625 rec->volumeserialnumber = get_volumeserialnumber( root );
2626 if (!match_row( table, row, cond, &status ))
2628 free_row_values( table, row );
2629 continue;
2631 offset += sizeof(*rec);
2632 row++;
2635 TRACE("created %u rows\n", row);
2636 table->num_rows = row;
2637 return status;
2640 static struct association *get_logicaldisktopartition_pairs( UINT *count )
2642 struct association *ret = NULL;
2643 struct query *query, *query2 = NULL;
2644 VARIANT val;
2645 HRESULT hr;
2646 UINT i;
2648 if (!(query = create_query( WBEMPROX_NAMESPACE_CIMV2 ))) return NULL;
2649 if ((hr = parse_query( WBEMPROX_NAMESPACE_CIMV2, L"SELECT * FROM Win32_DiskPartition",
2650 &query->view, &query->mem )) != S_OK) goto done;
2651 if ((hr = execute_view( query->view )) != S_OK) goto done;
2653 if (!(query2 = create_query( WBEMPROX_NAMESPACE_CIMV2 ))) return FALSE;
2654 if ((hr = parse_query( WBEMPROX_NAMESPACE_CIMV2,
2655 L"SELECT * FROM Win32_LogicalDisk WHERE DriveType=2 OR DriveType=3", &query2->view,
2656 &query2->mem )) != S_OK) goto done;
2657 if ((hr = execute_view( query2->view )) != S_OK) goto done;
2659 if (!(ret = calloc( query->view->result_count, sizeof(*ret) ))) goto done;
2661 /* assume fixed and removable disks are enumerated in the same order as partitions */
2662 for (i = 0; i < query->view->result_count; i++)
2664 if ((hr = get_propval( query->view, i, L"__PATH", &val, NULL, NULL )) != S_OK) goto done;
2665 if (!(ret[i].ref = wcsdup( V_BSTR(&val) ))) goto done;
2666 VariantClear( &val );
2668 if ((hr = get_propval( query2->view, i, L"__PATH", &val, NULL, NULL )) != S_OK) goto done;
2669 if (!(ret[i].ref2 = wcsdup( V_BSTR(&val) ))) goto done;
2670 VariantClear( &val );
2673 *count = query->view->result_count;
2675 done:
2676 if (!ret) free_associations( ret, query->view->result_count );
2677 free_query( query );
2678 free_query( query2 );
2679 return ret;
2682 static enum fill_status fill_logicaldisktopartition( struct table *table, const struct expr *cond )
2684 struct record_logicaldisktopartition *rec;
2685 UINT i, row = 0, offset = 0, count = 0;
2686 enum fill_status status = FILL_STATUS_UNFILTERED;
2687 struct association *assoc;
2689 if (!(assoc = get_logicaldisktopartition_pairs( &count ))) return FILL_STATUS_FAILED;
2690 if (!count)
2692 free_associations( assoc, count );
2693 return FILL_STATUS_UNFILTERED;
2695 if (!resize_table( table, count, sizeof(*rec) ))
2697 free_associations( assoc, count );
2698 return FILL_STATUS_FAILED;
2701 for (i = 0; i < count; i++)
2703 rec = (struct record_logicaldisktopartition *)(table->data + offset);
2704 rec->antecedent = assoc[i].ref;
2705 rec->dependent = assoc[i].ref2;
2706 if (!match_row( table, row, cond, &status ))
2708 free_row_values( table, row );
2709 continue;
2711 offset += sizeof(*rec);
2712 row++;
2715 free( assoc );
2717 TRACE("created %u rows\n", row);
2718 table->num_rows = row;
2719 return status;
2722 static UINT16 get_connection_status( IF_OPER_STATUS status )
2724 switch (status)
2726 case IfOperStatusDown:
2727 return 0; /* Disconnected */
2728 case IfOperStatusUp:
2729 return 2; /* Connected */
2730 default:
2731 ERR("unhandled status %u\n", status);
2732 break;
2734 return 0;
2736 static WCHAR *get_mac_address( const BYTE *addr, DWORD len )
2738 WCHAR *ret;
2739 if (len != 6 || !(ret = malloc( 18 * sizeof(WCHAR) ))) return NULL;
2740 swprintf( ret, 18, L"%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] );
2741 return ret;
2743 static const WCHAR *get_adaptertype( DWORD type, int *id, int *physical )
2745 switch (type)
2747 case IF_TYPE_ETHERNET_CSMACD:
2748 *id = 0;
2749 *physical = -1;
2750 return L"Ethernet 802.3";
2752 case IF_TYPE_IEEE80211:
2753 *id = 9;
2754 *physical = -1;
2755 return L"Wireless";
2757 case IF_TYPE_IEEE1394:
2758 *id = 13;
2759 *physical = -1;
2760 return L"1394";
2762 case IF_TYPE_TUNNEL:
2763 *id = 15;
2764 *physical = 0;
2765 return L"Tunnel";
2767 default:
2768 *id = -1;
2769 *physical = 0;
2770 return NULL;
2774 #define GUID_SIZE 39
2775 static WCHAR *guid_to_str( const GUID *ptr )
2777 WCHAR *ret;
2778 if (!(ret = malloc( GUID_SIZE * sizeof(WCHAR) ))) return NULL;
2779 swprintf( ret, GUID_SIZE, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2780 ptr->Data1, ptr->Data2, ptr->Data3, ptr->Data4[0], ptr->Data4[1], ptr->Data4[2],
2781 ptr->Data4[3], ptr->Data4[4], ptr->Data4[5], ptr->Data4[6], ptr->Data4[7] );
2782 return ret;
2785 static WCHAR *get_networkadapter_guid( const IF_LUID *luid )
2787 GUID guid;
2788 if (ConvertInterfaceLuidToGuid( luid, &guid )) return NULL;
2789 return guid_to_str( &guid );
2792 static enum fill_status fill_networkadapter( struct table *table, const struct expr *cond )
2794 WCHAR device_id[11];
2795 struct record_networkadapter *rec;
2796 IP_ADAPTER_ADDRESSES *aa, *buffer;
2797 UINT row = 0, offset = 0, count = 0;
2798 DWORD size = 0, ret;
2799 int adaptertypeid, physical;
2800 enum fill_status status = FILL_STATUS_UNFILTERED;
2802 ret = GetAdaptersAddresses( AF_UNSPEC, 0, NULL, NULL, &size );
2803 if (ret != ERROR_BUFFER_OVERFLOW) return FILL_STATUS_FAILED;
2805 if (!(buffer = malloc( size ))) return FILL_STATUS_FAILED;
2806 if (GetAdaptersAddresses( AF_UNSPEC, 0, NULL, buffer, &size ))
2808 free( buffer );
2809 return FILL_STATUS_FAILED;
2811 for (aa = buffer; aa; aa = aa->Next)
2813 if (aa->IfType != IF_TYPE_SOFTWARE_LOOPBACK) count++;
2815 if (!resize_table( table, count, sizeof(*rec) ))
2817 free( buffer );
2818 return FILL_STATUS_FAILED;
2820 for (aa = buffer; aa; aa = aa->Next)
2822 if (aa->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue;
2824 rec = (struct record_networkadapter *)(table->data + offset);
2825 swprintf( device_id, ARRAY_SIZE( device_id ), L"%u", aa->u.s.IfIndex );
2826 rec->adaptertype = get_adaptertype( aa->IfType, &adaptertypeid, &physical );
2827 rec->adaptertypeid = adaptertypeid;
2828 rec->description = wcsdup( aa->Description );
2829 rec->device_id = wcsdup( device_id );
2830 rec->guid = get_networkadapter_guid( &aa->Luid );
2831 rec->index = aa->u.s.IfIndex;
2832 rec->interface_index = aa->u.s.IfIndex;
2833 rec->mac_address = get_mac_address( aa->PhysicalAddress, aa->PhysicalAddressLength );
2834 rec->manufacturer = L"The Wine Project";
2835 rec->name = wcsdup( aa->FriendlyName );
2836 rec->netconnection_status = get_connection_status( aa->OperStatus );
2837 rec->physicaladapter = physical;
2838 rec->pnpdevice_id = L"PCI\\VEN_8086&DEV_100E&SUBSYS_001E8086&REV_02\\3&267A616A&1&18";
2839 rec->servicename = wcsdup( aa->FriendlyName );
2840 rec->speed = 1000000;
2841 if (!match_row( table, row, cond, &status ))
2843 free_row_values( table, row );
2844 continue;
2846 offset += sizeof(*rec);
2847 row++;
2849 TRACE("created %u rows\n", row);
2850 table->num_rows = row;
2852 free( buffer );
2853 return status;
2856 static WCHAR *get_dnshostname( IP_ADAPTER_UNICAST_ADDRESS *addr )
2858 const SOCKET_ADDRESS *sa = &addr->Address;
2859 WCHAR buf[NI_MAXHOST];
2861 if (!addr) return NULL;
2862 if (GetNameInfoW( sa->lpSockaddr, sa->iSockaddrLength, buf, ARRAY_SIZE( buf ), NULL,
2863 0, NI_NAMEREQD )) return NULL;
2864 return wcsdup( buf );
2866 static struct array *get_defaultipgateway( IP_ADAPTER_GATEWAY_ADDRESS *list )
2868 IP_ADAPTER_GATEWAY_ADDRESS *gateway;
2869 struct array *ret;
2870 ULONG buflen, i = 0, count = 0;
2871 WCHAR **ptr, buf[54]; /* max IPv6 address length */
2873 if (!list) return NULL;
2874 for (gateway = list; gateway; gateway = gateway->Next) count++;
2876 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
2877 if (!(ptr = malloc( sizeof(*ptr) * count )))
2879 free( ret );
2880 return NULL;
2882 for (gateway = list; gateway; gateway = gateway->Next)
2884 buflen = ARRAY_SIZE( buf );
2885 if (WSAAddressToStringW( gateway->Address.lpSockaddr, gateway->Address.iSockaddrLength,
2886 NULL, buf, &buflen) || !(ptr[i++] = wcsdup( buf )))
2888 for (; i > 0; i--) free( ptr[i - 1] );
2889 free( ptr );
2890 free( ret );
2891 return NULL;
2894 ret->elem_size = sizeof(*ptr);
2895 ret->count = count;
2896 ret->ptr = ptr;
2897 return ret;
2899 static struct array *get_dnsserversearchorder( IP_ADAPTER_DNS_SERVER_ADDRESS *list )
2901 IP_ADAPTER_DNS_SERVER_ADDRESS *server;
2902 struct array *ret;
2903 ULONG buflen, i = 0, count = 0;
2904 WCHAR **ptr, *p, buf[54]; /* max IPv6 address length */
2906 if (!list) return NULL;
2907 for (server = list; server; server = server->Next) count++;
2909 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
2910 if (!(ptr = malloc( sizeof(*ptr) * count )))
2912 free( ret );
2913 return NULL;
2915 for (server = list; server; server = server->Next)
2917 buflen = ARRAY_SIZE( buf );
2918 if (WSAAddressToStringW( server->Address.lpSockaddr, server->Address.iSockaddrLength,
2919 NULL, buf, &buflen) || !(ptr[i++] = wcsdup( buf )))
2921 for (; i > 0; i--) free( ptr[i - 1] );
2922 free( ptr );
2923 free( ret );
2924 return NULL;
2926 if ((p = wcsrchr( ptr[i - 1], ':' ))) *p = 0;
2928 ret->elem_size = sizeof(*ptr);
2929 ret->count = count;
2930 ret->ptr = ptr;
2931 return ret;
2933 static struct array *get_ipaddress( IP_ADAPTER_UNICAST_ADDRESS_LH *list )
2935 IP_ADAPTER_UNICAST_ADDRESS_LH *address;
2936 struct array *ret;
2937 ULONG buflen, i = 0, count = 0;
2938 WCHAR **ptr, buf[54]; /* max IPv6 address length */
2940 if (!list) return NULL;
2941 for (address = list; address; address = address->Next) count++;
2943 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
2944 if (!(ptr = malloc( sizeof(*ptr) * count )))
2946 free( ret );
2947 return NULL;
2949 for (address = list; address; address = address->Next)
2951 buflen = ARRAY_SIZE( buf );
2952 if (WSAAddressToStringW( address->Address.lpSockaddr, address->Address.iSockaddrLength,
2953 NULL, buf, &buflen) || !(ptr[i++] = wcsdup( buf )))
2955 for (; i > 0; i--) free( ptr[i - 1] );
2956 free( ptr );
2957 free( ret );
2958 return NULL;
2961 ret->elem_size = sizeof(*ptr);
2962 ret->count = count;
2963 ret->ptr = ptr;
2964 return ret;
2966 static struct array *get_ipsubnet( IP_ADAPTER_UNICAST_ADDRESS_LH *list )
2968 IP_ADAPTER_UNICAST_ADDRESS_LH *address;
2969 struct array *ret;
2970 ULONG i = 0, count = 0;
2971 WCHAR **ptr;
2973 if (!list) return NULL;
2974 for (address = list; address; address = address->Next) count++;
2976 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
2977 if (!(ptr = malloc( sizeof(*ptr) * count )))
2979 free( ret );
2980 return NULL;
2982 for (address = list; address; address = address->Next)
2984 if (address->Address.lpSockaddr->sa_family == AF_INET)
2986 WCHAR buf[INET_ADDRSTRLEN];
2987 SOCKADDR_IN addr;
2988 ULONG buflen = ARRAY_SIZE( buf );
2990 memset( &addr, 0, sizeof(addr) );
2991 addr.sin_family = AF_INET;
2992 if (ConvertLengthToIpv4Mask( address->OnLinkPrefixLength, &addr.sin_addr.S_un.S_addr ) != NO_ERROR
2993 || WSAAddressToStringW( (SOCKADDR*)&addr, sizeof(addr), NULL, buf, &buflen))
2994 ptr[i] = NULL;
2995 else
2996 ptr[i] = wcsdup( buf );
2998 else
3000 WCHAR buf[11];
3001 swprintf( buf, ARRAY_SIZE( buf ), L"%u", address->OnLinkPrefixLength );
3002 ptr[i] = wcsdup( buf );
3004 if (!ptr[i++])
3006 for (; i > 0; i--) free( ptr[i - 1] );
3007 free( ptr );
3008 free( ret );
3009 return NULL;
3012 ret->elem_size = sizeof(*ptr);
3013 ret->count = count;
3014 ret->ptr = ptr;
3015 return ret;
3017 static WCHAR *get_settingid( UINT32 index )
3019 GUID guid;
3020 memset( &guid, 0, sizeof(guid) );
3021 guid.Data1 = index;
3022 return guid_to_str( &guid );
3025 static enum fill_status fill_networkadapterconfig( struct table *table, const struct expr *cond )
3027 struct record_networkadapterconfig *rec;
3028 IP_ADAPTER_ADDRESSES *aa, *buffer;
3029 UINT row = 0, offset = 0, count = 0;
3030 DWORD size = 0, ret;
3031 enum fill_status status = FILL_STATUS_UNFILTERED;
3033 ret = GetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS, NULL, NULL, &size );
3034 if (ret != ERROR_BUFFER_OVERFLOW) return FILL_STATUS_FAILED;
3036 if (!(buffer = malloc( size ))) return FILL_STATUS_FAILED;
3037 if (GetAdaptersAddresses( AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS, NULL, buffer, &size ))
3039 free( buffer );
3040 return FILL_STATUS_FAILED;
3042 for (aa = buffer; aa; aa = aa->Next)
3044 if (aa->IfType != IF_TYPE_SOFTWARE_LOOPBACK) count++;
3046 if (!resize_table( table, count, sizeof(*rec) ))
3048 free( buffer );
3049 return FILL_STATUS_FAILED;
3051 for (aa = buffer; aa; aa = aa->Next)
3053 if (aa->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue;
3055 rec = (struct record_networkadapterconfig *)(table->data + offset);
3056 rec->defaultipgateway = get_defaultipgateway( aa->FirstGatewayAddress );
3057 rec->description = wcsdup( aa->Description );
3058 rec->dhcpenabled = -1;
3059 rec->dnsdomain = L"";
3060 rec->dnshostname = get_dnshostname( aa->FirstUnicastAddress );
3061 rec->dnsserversearchorder = get_dnsserversearchorder( aa->FirstDnsServerAddress );
3062 rec->index = aa->u.s.IfIndex;
3063 rec->ipaddress = get_ipaddress( aa->FirstUnicastAddress );
3064 rec->ipconnectionmetric = 20;
3065 rec->ipenabled = -1;
3066 rec->ipsubnet = get_ipsubnet( aa->FirstUnicastAddress );
3067 rec->mac_address = get_mac_address( aa->PhysicalAddress, aa->PhysicalAddressLength );
3068 rec->settingid = get_settingid( rec->index );
3069 if (!match_row( table, row, cond, &status ))
3071 free_row_values( table, row );
3072 continue;
3074 offset += sizeof(*rec);
3075 row++;
3077 TRACE("created %u rows\n", row);
3078 table->num_rows = row;
3080 free( buffer );
3081 return status;
3084 static enum fill_status fill_physicalmemory( struct table *table, const struct expr *cond )
3086 struct record_physicalmemory *rec;
3087 enum fill_status status = FILL_STATUS_UNFILTERED;
3088 UINT row = 0;
3090 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
3092 rec = (struct record_physicalmemory *)table->data;
3093 rec->banklabel = L"BANK 0";
3094 rec->capacity = get_total_physical_memory();
3095 rec->caption = L"Physical Memory";
3096 rec->configuredclockspeed = 1600;
3097 rec->devicelocator = L"DIMM 0";
3098 rec->formfactor = 8; /* DIMM */
3099 rec->memorytype = 9; /* RAM */
3100 rec->partnumber = L"";
3101 rec->serial = L"";
3102 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
3103 else row++;
3105 TRACE("created %u rows\n", row);
3106 table->num_rows = row;
3107 return status;
3110 static enum fill_status fill_pnpentity( struct table *table, const struct expr *cond )
3112 struct record_pnpentity *rec;
3113 enum fill_status status = FILL_STATUS_UNFILTERED;
3114 HDEVINFO device_info_set;
3115 SP_DEVINFO_DATA devinfo = {0};
3116 DWORD idx;
3118 device_info_set = SetupDiGetClassDevsW( NULL, NULL, NULL, DIGCF_ALLCLASSES|DIGCF_PRESENT );
3120 devinfo.cbSize = sizeof(devinfo);
3122 idx = 0;
3123 while (SetupDiEnumDeviceInfo( device_info_set, idx++, &devinfo ))
3125 /* noop */
3128 resize_table( table, idx, sizeof(*rec) );
3129 table->num_rows = 0;
3130 rec = (struct record_pnpentity *)table->data;
3132 idx = 0;
3133 while (SetupDiEnumDeviceInfo( device_info_set, idx++, &devinfo ))
3135 WCHAR device_id[MAX_PATH];
3136 if (SetupDiGetDeviceInstanceIdW( device_info_set, &devinfo, device_id,
3137 ARRAY_SIZE(device_id), NULL ))
3139 rec->device_id = wcsdup( device_id );
3140 rec->manufacturer = L"The Wine Project";
3141 rec->name = L"Wine PnP Device";
3143 table->num_rows++;
3144 if (!match_row( table, table->num_rows - 1, cond, &status ))
3146 free_row_values( table, table->num_rows - 1 );
3147 table->num_rows--;
3149 else
3150 rec++;
3154 SetupDiDestroyDeviceInfoList( device_info_set );
3156 return status;
3159 static enum fill_status fill_printer( struct table *table, const struct expr *cond )
3161 struct record_printer *rec;
3162 enum fill_status status = FILL_STATUS_UNFILTERED;
3163 PRINTER_INFO_2W *info;
3164 DWORD i, offset = 0, count = 0, size = 0;
3165 UINT num_rows = 0;
3166 WCHAR id[20];
3168 EnumPrintersW( PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &size, &count );
3169 if (!count) return FILL_STATUS_UNFILTERED;
3171 if (!(info = malloc( size ))) return FILL_STATUS_FAILED;
3172 if (!EnumPrintersW( PRINTER_ENUM_LOCAL, NULL, 2, (BYTE *)info, size, &size, &count ))
3174 free( info );
3175 return FILL_STATUS_FAILED;
3177 if (!resize_table( table, count, sizeof(*rec) ))
3179 free( info );
3180 return FILL_STATUS_FAILED;
3183 for (i = 0; i < count; i++)
3185 rec = (struct record_printer *)(table->data + offset);
3186 rec->attributes = info[i].Attributes;
3187 swprintf( id, ARRAY_SIZE( id ), L"Printer%u", i );
3188 rec->device_id = wcsdup( id );
3189 rec->drivername = wcsdup( info[i].pDriverName );
3190 rec->horizontalresolution = info[i].pDevMode->u1.s1.dmPrintQuality;
3191 rec->local = -1;
3192 rec->location = wcsdup( info[i].pLocation );
3193 rec->name = wcsdup( info[i].pPrinterName );
3194 rec->network = 0;
3195 rec->portname = wcsdup( info[i].pPortName );
3196 if (!match_row( table, i, cond, &status ))
3198 free_row_values( table, i );
3199 continue;
3201 offset += sizeof(*rec);
3202 num_rows++;
3204 TRACE("created %u rows\n", num_rows);
3205 table->num_rows = num_rows;
3207 free( info );
3208 return status;
3211 static WCHAR *get_cmdline( DWORD process_id )
3213 if (process_id == GetCurrentProcessId()) return wcsdup( GetCommandLineW() );
3214 return NULL; /* FIXME handle different process case */
3217 static enum fill_status fill_process( struct table *table, const struct expr *cond )
3219 WCHAR handle[11];
3220 struct record_process *rec;
3221 PROCESSENTRY32W entry;
3222 HANDLE snap;
3223 enum fill_status status = FILL_STATUS_FAILED;
3224 UINT row = 0, offset = 0;
3226 snap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
3227 if (snap == INVALID_HANDLE_VALUE) return FILL_STATUS_FAILED;
3229 entry.dwSize = sizeof(entry);
3230 if (!Process32FirstW( snap, &entry )) goto done;
3231 if (!resize_table( table, 8, sizeof(*rec) )) goto done;
3235 if (!resize_table( table, row + 1, sizeof(*rec) ))
3237 status = FILL_STATUS_FAILED;
3238 goto done;
3241 rec = (struct record_process *)(table->data + offset);
3242 rec->caption = wcsdup( entry.szExeFile );
3243 rec->commandline = get_cmdline( entry.th32ProcessID );
3244 rec->description = wcsdup( entry.szExeFile );
3245 swprintf( handle, ARRAY_SIZE( handle ), L"%u", entry.th32ProcessID );
3246 rec->handle = wcsdup( handle );
3247 rec->name = wcsdup( entry.szExeFile );
3248 rec->process_id = entry.th32ProcessID;
3249 rec->pprocess_id = entry.th32ParentProcessID;
3250 rec->thread_count = entry.cntThreads;
3251 rec->workingsetsize = 0;
3252 /* methods */
3253 rec->create = process_create;
3254 rec->get_owner = process_get_owner;
3255 if (!match_row( table, row, cond, &status ))
3257 free_row_values( table, row );
3258 continue;
3260 offset += sizeof(*rec);
3261 row++;
3262 } while (Process32NextW( snap, &entry ));
3264 TRACE("created %u rows\n", row);
3265 table->num_rows = row;
3267 done:
3268 CloseHandle( snap );
3269 return status;
3272 void do_cpuid( unsigned int ax, int *p )
3274 #if defined(__i386__) || defined(__x86_64__)
3275 __cpuid( p, ax );
3276 #else
3277 FIXME("\n");
3278 #endif
3281 static unsigned int get_processor_model( unsigned int reg0, unsigned int *stepping, unsigned int *family )
3283 unsigned int model, family_id = (reg0 & (0x0f << 8)) >> 8;
3285 model = (reg0 & (0x0f << 4)) >> 4;
3286 if (family_id == 6 || family_id == 15) model |= (reg0 & (0x0f << 16)) >> 12;
3287 if (family)
3289 *family = family_id;
3290 if (family_id == 15) *family += (reg0 & (0xff << 20)) >> 20;
3292 *stepping = reg0 & 0x0f;
3293 return model;
3295 static void regs_to_str( int *regs, unsigned int len, WCHAR *buffer )
3297 unsigned int i;
3298 unsigned char *p = (unsigned char *)regs;
3300 for (i = 0; i < len; i++) { buffer[i] = *p++; }
3301 buffer[i] = 0;
3303 static void get_processor_manufacturer( WCHAR *manufacturer, UINT len )
3305 int tmp, regs[4] = {0, 0, 0, 0};
3307 do_cpuid( 0, regs );
3308 tmp = regs[2]; /* swap edx and ecx */
3309 regs[2] = regs[3];
3310 regs[3] = tmp;
3312 regs_to_str( regs + 1, min( 12, len ), manufacturer );
3314 static const WCHAR *get_osarchitecture(void)
3316 SYSTEM_INFO info;
3317 GetNativeSystemInfo( &info );
3318 if (info.u.s.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) return L"64-bit";
3319 return L"32-bit";
3321 static void get_processor_caption( WCHAR *caption, UINT len )
3323 const WCHAR *arch;
3324 WCHAR manufacturer[13];
3325 int regs[4] = {0, 0, 0, 0};
3326 unsigned int family, model, stepping;
3328 get_processor_manufacturer( manufacturer, ARRAY_SIZE( manufacturer ) );
3329 if (!wcscmp( get_osarchitecture(), L"32-bit" )) arch = L"x86";
3330 else if (!wcscmp( manufacturer, L"AuthenticAMD" )) arch = L"AMD64";
3331 else arch = L"Intel64";
3333 do_cpuid( 1, regs );
3335 model = get_processor_model( regs[0], &stepping, &family );
3336 swprintf( caption, len, L"%s Family %u Model %u Stepping %u", arch, family, model, stepping );
3338 static void get_processor_version( WCHAR *version, UINT len )
3340 int regs[4] = {0, 0, 0, 0};
3341 unsigned int model, stepping;
3343 do_cpuid( 1, regs );
3345 model = get_processor_model( regs[0], &stepping, NULL );
3346 swprintf( version, len, L"Model %u Stepping %u", model, stepping );
3348 static UINT16 get_processor_revision(void)
3350 int regs[4] = {0, 0, 0, 0};
3351 do_cpuid( 1, regs );
3352 return regs[0];
3354 static void get_processor_id( WCHAR *processor_id, UINT len )
3356 int regs[4] = {0, 0, 0, 0};
3358 do_cpuid( 1, regs );
3359 swprintf( processor_id, len, L"%08X%08X", regs[3], regs[0] );
3361 static void get_processor_name( WCHAR *name )
3363 int regs[4] = {0, 0, 0, 0};
3364 int i;
3366 do_cpuid( 0x80000000, regs );
3367 if (regs[0] >= 0x80000004)
3369 do_cpuid( 0x80000002, regs );
3370 regs_to_str( regs, 16, name );
3371 do_cpuid( 0x80000003, regs );
3372 regs_to_str( regs, 16, name + 16 );
3373 do_cpuid( 0x80000004, regs );
3374 regs_to_str( regs, 16, name + 32 );
3376 for (i = lstrlenW(name) - 1; i >= 0 && name[i] == ' '; i--) name[i] = 0;
3378 static UINT get_processor_currentclockspeed( UINT index )
3380 PROCESSOR_POWER_INFORMATION *info;
3381 UINT ret = 1000, size = get_processor_count() * sizeof(PROCESSOR_POWER_INFORMATION);
3382 NTSTATUS status;
3384 if ((info = malloc( size )))
3386 status = NtPowerInformation( ProcessorInformation, NULL, 0, info, size );
3387 if (!status) ret = info[index].CurrentMhz;
3388 free( info );
3390 return ret;
3392 static UINT get_processor_maxclockspeed( UINT index )
3394 PROCESSOR_POWER_INFORMATION *info;
3395 UINT ret = 1000, size = get_processor_count() * sizeof(PROCESSOR_POWER_INFORMATION);
3396 NTSTATUS status;
3398 if ((info = malloc( size )))
3400 status = NtPowerInformation( ProcessorInformation, NULL, 0, info, size );
3401 if (!status) ret = info[index].MaxMhz;
3402 free( info );
3404 return ret;
3407 static enum fill_status fill_processor( struct table *table, const struct expr *cond )
3409 WCHAR caption[100], device_id[14], processor_id[17], manufacturer[13], name[49] = {0}, version[50];
3410 struct record_processor *rec;
3411 UINT i, offset = 0, num_rows = 0, num_logical, num_physical, num_packages;
3412 enum fill_status status = FILL_STATUS_UNFILTERED;
3414 num_logical = get_logical_processor_count( &num_physical, &num_packages );
3416 if (!resize_table( table, num_packages, sizeof(*rec) )) return FILL_STATUS_FAILED;
3418 get_processor_caption( caption, ARRAY_SIZE( caption ) );
3419 get_processor_id( processor_id, ARRAY_SIZE( processor_id ) );
3420 get_processor_manufacturer( manufacturer, ARRAY_SIZE( manufacturer ) );
3421 get_processor_name( name );
3422 get_processor_version( version, ARRAY_SIZE( version ) );
3424 for (i = 0; i < num_packages; i++)
3426 rec = (struct record_processor *)(table->data + offset);
3427 rec->addresswidth = !wcscmp( get_osarchitecture(), L"32-bit" ) ? 32 : 64;
3428 rec->architecture = !wcscmp( get_osarchitecture(), L"32-bit" ) ? 0 : 9;
3429 rec->caption = wcsdup( caption );
3430 rec->cpu_status = 1; /* CPU Enabled */
3431 rec->currentclockspeed = get_processor_currentclockspeed( i );
3432 rec->datawidth = !wcscmp( get_osarchitecture(), L"32-bit" ) ? 32 : 64;
3433 rec->description = wcsdup( caption );
3434 swprintf( device_id, ARRAY_SIZE( device_id ), L"CPU%u", i );
3435 rec->device_id = wcsdup( device_id );
3436 rec->family = 2; /* Unknown */
3437 rec->level = 15;
3438 rec->manufacturer = wcsdup( manufacturer );
3439 rec->maxclockspeed = get_processor_maxclockspeed( i );
3440 rec->name = wcsdup( name );
3441 rec->num_cores = num_physical / num_packages;
3442 rec->num_logical_processors = num_logical / num_packages;
3443 rec->processor_id = wcsdup( processor_id );
3444 rec->processortype = 3; /* central processor */
3445 rec->revision = get_processor_revision();
3446 rec->unique_id = NULL;
3447 rec->version = wcsdup( version );
3448 if (!match_row( table, i, cond, &status ))
3450 free_row_values( table, i );
3451 continue;
3453 offset += sizeof(*rec);
3454 num_rows++;
3457 TRACE("created %u rows\n", num_rows);
3458 table->num_rows = num_rows;
3459 return status;
3462 static INT16 get_currenttimezone(void)
3464 TIME_ZONE_INFORMATION info;
3465 DWORD status = GetTimeZoneInformation( &info );
3466 if (status == TIME_ZONE_ID_INVALID) return 0;
3467 if (status == TIME_ZONE_ID_DAYLIGHT) return -(info.Bias + info.DaylightBias);
3468 return -(info.Bias + info.StandardBias);
3471 static WCHAR *get_lastbootuptime(void)
3473 SYSTEM_TIMEOFDAY_INFORMATION ti;
3474 TIME_FIELDS tf;
3475 WCHAR *ret;
3477 if (!(ret = malloc( 26 * sizeof(WCHAR) ))) return NULL;
3479 NtQuerySystemInformation( SystemTimeOfDayInformation, &ti, sizeof(ti), NULL );
3480 RtlTimeToTimeFields( &ti.BootTime, &tf );
3481 swprintf( ret, 26, L"%04u%02u%02u%02u%02u%02u.%06u+000", tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute,
3482 tf.Second, tf.Milliseconds * 1000 );
3483 return ret;
3485 static WCHAR *get_localdatetime(void)
3487 TIME_ZONE_INFORMATION tzi;
3488 SYSTEMTIME st;
3489 WCHAR *ret;
3490 DWORD Status;
3491 LONG Bias;
3493 Status = GetTimeZoneInformation(&tzi);
3495 if(Status == TIME_ZONE_ID_INVALID) return NULL;
3496 Bias = tzi.Bias;
3497 if(Status == TIME_ZONE_ID_DAYLIGHT)
3498 Bias+= tzi.DaylightBias;
3499 else
3500 Bias+= tzi.StandardBias;
3501 if (!(ret = malloc( 26 * sizeof(WCHAR) ))) return NULL;
3503 GetLocalTime(&st);
3504 swprintf( ret, 26, L"%04u%02u%02u%02u%02u%02u.%06u%+03d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute,
3505 st.wSecond, st.wMilliseconds * 1000, -Bias );
3506 return ret;
3508 static WCHAR *get_systemdirectory(void)
3510 void *redir;
3511 WCHAR *ret;
3513 if (!(ret = malloc( MAX_PATH * sizeof(WCHAR) ))) return NULL;
3514 Wow64DisableWow64FsRedirection( &redir );
3515 GetSystemDirectoryW( ret, MAX_PATH );
3516 Wow64RevertWow64FsRedirection( redir );
3517 return ret;
3519 static WCHAR *get_systemdrive(void)
3521 WCHAR *ret = malloc( 3 * sizeof(WCHAR) ); /* "c:" */
3522 if (ret && GetEnvironmentVariableW( L"SystemDrive", ret, 3 )) return ret;
3523 free( ret );
3524 return NULL;
3526 static WCHAR *get_codeset(void)
3528 WCHAR *ret = malloc( 11 * sizeof(WCHAR) );
3529 if (ret) swprintf( ret, 11, L"%u", GetACP() );
3530 return ret;
3532 static WCHAR *get_countrycode(void)
3534 WCHAR *ret = malloc( 6 * sizeof(WCHAR) );
3535 if (ret) GetLocaleInfoW( LOCALE_SYSTEM_DEFAULT, LOCALE_ICOUNTRY, ret, 6 );
3536 return ret;
3538 static WCHAR *get_locale(void)
3540 WCHAR *ret = malloc( 5 * sizeof(WCHAR) );
3541 if (ret) GetLocaleInfoW( LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, ret, 5 );
3542 return ret;
3545 static WCHAR *get_reg_str( HKEY root, const WCHAR *path, const WCHAR *value )
3547 HKEY hkey = 0;
3548 DWORD size, type;
3549 WCHAR *ret = NULL;
3551 if (!RegOpenKeyExW( root, path, 0, KEY_READ, &hkey ) &&
3552 !RegQueryValueExW( hkey, value, NULL, &type, NULL, &size ) && type == REG_SZ &&
3553 (ret = malloc( size + sizeof(WCHAR) )))
3555 size += sizeof(WCHAR);
3556 if (RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)ret, &size ))
3558 free( ret );
3559 ret = NULL;
3562 if (hkey) RegCloseKey( hkey );
3563 return ret;
3566 static WCHAR *get_organization(void)
3568 return get_reg_str( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion",
3569 L"RegisteredOrganization" );
3572 static WCHAR *get_osbuildnumber( OSVERSIONINFOEXW *ver )
3574 WCHAR *ret = malloc( 11 * sizeof(WCHAR) );
3575 if (ret) swprintf( ret, 11, L"%u", ver->dwBuildNumber );
3576 return ret;
3578 static WCHAR *get_oscaption( OSVERSIONINFOEXW *ver )
3580 static const WCHAR windowsW[] = L"Microsoft Windows ";
3581 static const WCHAR win2000W[] = L"2000 Professional";
3582 static const WCHAR win2003W[] = L"Server 2003 Standard Edition";
3583 static const WCHAR winxpW[] = L"XP Professional";
3584 static const WCHAR winxp64W[] = L"XP Professional x64 Edition";
3585 static const WCHAR vistaW[] = L"Vista Ultimate";
3586 static const WCHAR win2008W[] = L"Server 2008 Standard";
3587 static const WCHAR win7W[] = L"7 Professional";
3588 static const WCHAR win2008r2W[] = L"Server 2008 R2 Standard";
3589 static const WCHAR win8W[] = L"8 Pro";
3590 static const WCHAR win81W[] = L"8.1 Pro";
3591 static const WCHAR win10W[] = L"10 Pro";
3592 int len = ARRAY_SIZE( windowsW ) - 1;
3593 WCHAR *ret;
3595 if (!(ret = malloc( len * sizeof(WCHAR) + sizeof(win2003W) ))) return NULL;
3596 memcpy( ret, windowsW, sizeof(windowsW) );
3597 if (ver->dwMajorVersion == 10 && ver->dwMinorVersion == 0) memcpy( ret + len, win10W, sizeof(win10W) );
3598 else if (ver->dwMajorVersion == 6 && ver->dwMinorVersion == 3) memcpy( ret + len, win81W, sizeof(win81W) );
3599 else if (ver->dwMajorVersion == 6 && ver->dwMinorVersion == 2) memcpy( ret + len, win8W, sizeof(win8W) );
3600 else if (ver->dwMajorVersion == 6 && ver->dwMinorVersion == 1)
3602 if (ver->wProductType == VER_NT_WORKSTATION) memcpy( ret + len, win7W, sizeof(win7W) );
3603 else memcpy( ret + len, win2008r2W, sizeof(win2008r2W) );
3605 else if (ver->dwMajorVersion == 6 && ver->dwMinorVersion == 0)
3607 if (ver->wProductType == VER_NT_WORKSTATION) memcpy( ret + len, vistaW, sizeof(vistaW) );
3608 else memcpy( ret + len, win2008W, sizeof(win2008W) );
3610 else if (ver->dwMajorVersion == 5 && ver->dwMinorVersion == 2)
3612 if (ver->wProductType == VER_NT_WORKSTATION) memcpy( ret + len, winxp64W, sizeof(winxp64W) );
3613 else memcpy( ret + len, win2003W, sizeof(win2003W) );
3615 else if (ver->dwMajorVersion == 5 && ver->dwMinorVersion == 1) memcpy( ret + len, winxpW, sizeof(winxpW) );
3616 else memcpy( ret + len, win2000W, sizeof(win2000W) );
3617 return ret;
3619 static WCHAR *get_osname( const WCHAR *caption )
3621 static const WCHAR partitionW[] = L"|C:\\WINDOWS|\\Device\\Harddisk0\\Partition1";
3622 int len = lstrlenW( caption );
3623 WCHAR *ret;
3625 if (!(ret = malloc( len * sizeof(WCHAR) + sizeof(partitionW) ))) return NULL;
3626 memcpy( ret, caption, len * sizeof(WCHAR) );
3627 memcpy( ret + len, partitionW, sizeof(partitionW) );
3628 return ret;
3631 static WCHAR *get_osserialnumber(void)
3633 WCHAR *ret = get_reg_str( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", L"ProductId" );
3634 if (!ret) ret = wcsdup( L"12345-OEM-1234567-12345" );
3635 return ret;
3638 static WCHAR *get_osversion( OSVERSIONINFOEXW *ver )
3640 WCHAR *ret = malloc( 33 * sizeof(WCHAR) );
3641 if (ret) swprintf( ret, 33, L"%u.%u.%u", ver->dwMajorVersion, ver->dwMinorVersion, ver->dwBuildNumber );
3642 return ret;
3644 static DWORD get_operatingsystemsku(void)
3646 DWORD ret = PRODUCT_UNDEFINED;
3647 GetProductInfo( 6, 0, 0, 0, &ret );
3648 return ret;
3651 static WCHAR *get_registereduser(void)
3653 return get_reg_str( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", L"RegisteredOwner" );
3656 static WCHAR *get_windowsdirectory(void)
3658 WCHAR dir[MAX_PATH];
3659 if (!GetWindowsDirectoryW( dir, ARRAY_SIZE(dir) )) return NULL;
3660 return wcsdup( dir );
3663 static enum fill_status fill_operatingsystem( struct table *table, const struct expr *cond )
3665 struct record_operatingsystem *rec;
3666 enum fill_status status = FILL_STATUS_UNFILTERED;
3667 RTL_OSVERSIONINFOEXW ver;
3668 UINT row = 0;
3670 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
3672 ver.dwOSVersionInfoSize = sizeof(ver);
3673 RtlGetVersion( &ver );
3675 rec = (struct record_operatingsystem *)table->data;
3676 rec->bootdevice = L"\\Device\\HarddiskVolume1";
3677 rec->buildnumber = get_osbuildnumber( &ver );
3678 rec->buildtype = L"Wine build";
3679 rec->caption = get_oscaption( &ver );
3680 rec->codeset = get_codeset();
3681 rec->countrycode = get_countrycode();
3682 rec->csdversion = ver.szCSDVersion[0] ? wcsdup( ver.szCSDVersion ) : NULL;
3683 rec->csname = get_computername();
3684 rec->currenttimezone = get_currenttimezone();
3685 rec->freephysicalmemory = get_available_physical_memory() / 1024;
3686 rec->installdate = L"20140101000000.000000+000";
3687 rec->lastbootuptime = get_lastbootuptime();
3688 rec->localdatetime = get_localdatetime();
3689 rec->locale = get_locale();
3690 rec->manufacturer = L"The Wine Project";
3691 rec->name = get_osname( rec->caption );
3692 rec->operatingsystemsku = get_operatingsystemsku();
3693 rec->organization = get_organization();
3694 rec->osarchitecture = get_osarchitecture();
3695 rec->oslanguage = GetSystemDefaultLangID();
3696 rec->osproductsuite = 2461140; /* Windows XP Professional */
3697 rec->ostype = 18; /* WINNT */
3698 rec->primary = -1;
3699 rec->producttype = 1;
3700 rec->registereduser = get_registereduser();
3701 rec->serialnumber = get_osserialnumber();
3702 rec->servicepackmajor = ver.wServicePackMajor;
3703 rec->servicepackminor = ver.wServicePackMinor;
3704 rec->status = L"OK";
3705 rec->suitemask = 272; /* Single User + Terminal */
3706 rec->systemdirectory = get_systemdirectory();
3707 rec->systemdrive = get_systemdrive();
3708 rec->totalvirtualmemorysize = get_total_physical_memory() / 1024;
3709 rec->totalvisiblememorysize = rec->totalvirtualmemorysize;
3710 rec->version = get_osversion( &ver );
3711 rec->windowsdirectory = get_windowsdirectory();
3712 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
3713 else row++;
3715 TRACE("created %u rows\n", row);
3716 table->num_rows = row;
3717 return status;
3720 static const WCHAR *get_service_type( DWORD type )
3722 if (type & SERVICE_KERNEL_DRIVER) return L"Kernel Driver";
3723 else if (type & SERVICE_FILE_SYSTEM_DRIVER) return L"File System Driver";
3724 else if (type & SERVICE_WIN32_OWN_PROCESS) return L"Own Process";
3725 else if (type & SERVICE_WIN32_SHARE_PROCESS) return L"Share Process";
3726 else ERR( "unhandled type %#lx\n", type );
3727 return NULL;
3729 static const WCHAR *get_service_state( DWORD state )
3731 switch (state)
3733 case SERVICE_STOPPED: return L"Stopped";
3734 case SERVICE_START_PENDING: return L"Start Pending";
3735 case SERVICE_STOP_PENDING: return L"Stop Pending";
3736 case SERVICE_RUNNING: return L"Running";
3737 default:
3738 ERR( "unknown state %lu\n", state );
3739 return L"Unknown";
3742 static const WCHAR *get_service_startmode( DWORD mode )
3744 switch (mode)
3746 case SERVICE_BOOT_START: return L"Boot";
3747 case SERVICE_SYSTEM_START: return L"System";
3748 case SERVICE_AUTO_START: return L"Auto";
3749 case SERVICE_DEMAND_START: return L"Manual";
3750 case SERVICE_DISABLED: return L"Disabled";
3751 default:
3752 ERR( "unknown mode %#lx\n", mode );
3753 return L"Unknown";
3756 static QUERY_SERVICE_CONFIGW *query_service_config( SC_HANDLE manager, const WCHAR *name )
3758 QUERY_SERVICE_CONFIGW *config = NULL;
3759 SC_HANDLE service;
3760 DWORD size;
3762 if (!(service = OpenServiceW( manager, name, SERVICE_QUERY_CONFIG ))) return NULL;
3763 QueryServiceConfigW( service, NULL, 0, &size );
3764 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto done;
3765 if (!(config = malloc( size ))) goto done;
3766 if (QueryServiceConfigW( service, config, size, &size )) goto done;
3767 free( config );
3768 config = NULL;
3770 done:
3771 CloseServiceHandle( service );
3772 return config;
3775 static enum fill_status fill_service( struct table *table, const struct expr *cond )
3777 struct record_service *rec;
3778 SC_HANDLE manager;
3779 ENUM_SERVICE_STATUS_PROCESSW *tmp, *services = NULL;
3780 SERVICE_STATUS_PROCESS *status;
3781 WCHAR sysnameW[MAX_COMPUTERNAME_LENGTH + 1];
3782 DWORD len = ARRAY_SIZE( sysnameW ), needed, count;
3783 UINT i, row = 0, offset = 0, size = 256;
3784 enum fill_status fill_status = FILL_STATUS_FAILED;
3785 BOOL ret;
3787 if (!(manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE ))) return FILL_STATUS_FAILED;
3788 if (!(services = malloc( size ))) goto done;
3790 ret = EnumServicesStatusExW( manager, SC_ENUM_PROCESS_INFO, SERVICE_TYPE_ALL,
3791 SERVICE_STATE_ALL, (BYTE *)services, size, &needed,
3792 &count, NULL, NULL );
3793 if (!ret)
3795 if (GetLastError() != ERROR_MORE_DATA) goto done;
3796 size = needed;
3797 if (!(tmp = realloc( services, size ))) goto done;
3798 services = tmp;
3799 ret = EnumServicesStatusExW( manager, SC_ENUM_PROCESS_INFO, SERVICE_TYPE_ALL,
3800 SERVICE_STATE_ALL, (BYTE *)services, size, &needed,
3801 &count, NULL, NULL );
3802 if (!ret) goto done;
3804 if (!resize_table( table, count, sizeof(*rec) )) goto done;
3806 GetComputerNameW( sysnameW, &len );
3807 fill_status = FILL_STATUS_UNFILTERED;
3809 for (i = 0; i < count; i++)
3811 QUERY_SERVICE_CONFIGW *config;
3813 if (!(config = query_service_config( manager, services[i].lpServiceName ))) continue;
3815 status = &services[i].ServiceStatusProcess;
3816 rec = (struct record_service *)(table->data + offset);
3817 rec->accept_pause = (status->dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) ? -1 : 0;
3818 rec->accept_stop = (status->dwControlsAccepted & SERVICE_ACCEPT_STOP) ? -1 : 0;
3819 rec->displayname = wcsdup( services[i].lpDisplayName );
3820 rec->name = wcsdup( services[i].lpServiceName );
3821 rec->process_id = status->dwProcessId;
3822 rec->servicetype = get_service_type( status->dwServiceType );
3823 rec->startmode = get_service_startmode( config->dwStartType );
3824 rec->state = get_service_state( status->dwCurrentState );
3825 rec->systemname = wcsdup( sysnameW );
3826 rec->pause_service = service_pause_service;
3827 rec->resume_service = service_resume_service;
3828 rec->start_service = service_start_service;
3829 rec->stop_service = service_stop_service;
3830 free( config );
3831 if (!match_row( table, row, cond, &fill_status ))
3833 free_row_values( table, row );
3834 continue;
3836 offset += sizeof(*rec);
3837 row++;
3840 TRACE("created %u rows\n", row);
3841 table->num_rows = row;
3843 done:
3844 CloseServiceHandle( manager );
3845 free( services );
3846 return fill_status;
3849 static WCHAR *get_accountname( LSA_TRANSLATED_NAME *name )
3851 if (!name || !name->Name.Buffer) return NULL;
3852 return wcsdup( name->Name.Buffer );
3854 static struct array *get_binaryrepresentation( PSID sid, UINT len )
3856 struct array *ret;
3857 UINT8 *ptr;
3859 if (!(ret = malloc( sizeof(*ret) ))) return NULL;
3860 if (!(ptr = malloc( len )))
3862 free( ret );
3863 return NULL;
3865 memcpy( ptr, sid, len );
3866 ret->elem_size = sizeof(*ptr);
3867 ret->count = len;
3868 ret->ptr = ptr;
3869 return ret;
3871 static WCHAR *get_referenceddomainname( LSA_REFERENCED_DOMAIN_LIST *domain )
3873 if (!domain || !domain->Domains || !domain->Domains->Name.Buffer) return NULL;
3874 return wcsdup( domain->Domains->Name.Buffer );
3876 static const WCHAR *find_sid_str( const struct expr *cond )
3878 const struct expr *left, *right;
3879 const WCHAR *ret = NULL;
3881 if (!cond || cond->type != EXPR_COMPLEX || cond->u.expr.op != OP_EQ) return NULL;
3883 left = cond->u.expr.left;
3884 right = cond->u.expr.right;
3885 if (left->type == EXPR_PROPVAL && right->type == EXPR_SVAL && !wcsicmp( left->u.propval->name, L"SID" ))
3887 ret = right->u.sval;
3889 else if (left->type == EXPR_SVAL && right->type == EXPR_PROPVAL && !wcsicmp( right->u.propval->name, L"SID" ))
3891 ret = left->u.sval;
3893 return ret;
3896 static enum fill_status fill_sid( struct table *table, const struct expr *cond )
3898 PSID sid;
3899 LSA_REFERENCED_DOMAIN_LIST *domain;
3900 LSA_TRANSLATED_NAME *name;
3901 LSA_HANDLE handle;
3902 LSA_OBJECT_ATTRIBUTES attrs;
3903 const WCHAR *str;
3904 struct record_sid *rec;
3905 UINT len;
3907 if (!(str = find_sid_str( cond ))) return FILL_STATUS_FAILED;
3908 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
3910 if (!ConvertStringSidToSidW( str, &sid )) return FILL_STATUS_FAILED;
3911 len = GetLengthSid( sid );
3913 memset( &attrs, 0, sizeof(attrs) );
3914 attrs.Length = sizeof(attrs);
3915 if (LsaOpenPolicy( NULL, &attrs, POLICY_ALL_ACCESS, &handle ))
3917 LocalFree( sid );
3918 return FILL_STATUS_FAILED;
3920 if (LsaLookupSids( handle, 1, &sid, &domain, &name ))
3922 LocalFree( sid );
3923 LsaClose( handle );
3924 return FILL_STATUS_FAILED;
3927 rec = (struct record_sid *)table->data;
3928 rec->accountname = get_accountname( name );
3929 rec->binaryrepresentation = get_binaryrepresentation( sid, len );
3930 rec->referenceddomainname = get_referenceddomainname( domain );
3931 rec->sid = wcsdup( str );
3932 rec->sidlength = len;
3934 TRACE("created 1 row\n");
3935 table->num_rows = 1;
3937 LsaFreeMemory( domain );
3938 LsaFreeMemory( name );
3939 LocalFree( sid );
3940 LsaClose( handle );
3941 return FILL_STATUS_FILTERED;
3944 static WCHAR *get_systemenclosure_string( BYTE id, const char *buf, UINT len )
3946 const struct smbios_header *hdr;
3947 const struct smbios_chassis *chassis;
3948 UINT offset;
3950 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_CHASSIS, buf, len ))) return NULL;
3952 chassis = (const struct smbios_chassis *)hdr;
3953 offset = (const char *)chassis - buf + chassis->hdr.length;
3954 return get_smbios_string( id, buf, offset, len );
3957 static WCHAR *get_systemenclosure_manufacturer( const char *buf, UINT len )
3959 WCHAR *ret = get_systemenclosure_string( 1, buf, len );
3960 if (!ret) return wcsdup( L"Wine" );
3961 return ret;
3964 static int get_systemenclosure_lockpresent( const char *buf, UINT len )
3966 const struct smbios_header *hdr;
3967 const struct smbios_chassis *chassis;
3969 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_CHASSIS, buf, len )) || hdr->length < sizeof(*chassis)) return 0;
3971 chassis = (const struct smbios_chassis *)hdr;
3972 return (chassis->type & 0x80) ? -1 : 0;
3975 static struct array *dup_array( const struct array *src )
3977 struct array *dst;
3978 if (!(dst = malloc( sizeof(*dst) ))) return NULL;
3979 if (!(dst->ptr = malloc( src->count * src->elem_size )))
3981 free( dst );
3982 return NULL;
3984 memcpy( dst->ptr, src->ptr, src->count * src->elem_size );
3985 dst->elem_size = src->elem_size;
3986 dst->count = src->count;
3987 return dst;
3990 static struct array *get_systemenclosure_chassistypes( const char *buf, UINT len )
3992 const struct smbios_header *hdr;
3993 const struct smbios_chassis *chassis;
3994 struct array *ret = NULL;
3995 UINT16 *types;
3997 if (!(hdr = find_smbios_entry( SMBIOS_TYPE_CHASSIS, buf, len )) || hdr->length < sizeof(*chassis)) goto done;
3998 chassis = (const struct smbios_chassis *)hdr;
4000 if (!(ret = malloc( sizeof(*ret) ))) goto done;
4001 if (!(types = malloc( sizeof(*types) )))
4003 free( ret );
4004 return NULL;
4006 types[0] = chassis->type & ~0x80;
4008 ret->elem_size = sizeof(*types);
4009 ret->count = 1;
4010 ret->ptr = types;
4012 done:
4013 if (!ret) ret = dup_array( &systemenclosure_chassistypes_array );
4014 return ret;
4017 static enum fill_status fill_systemenclosure( struct table *table, const struct expr *cond )
4019 struct record_systemenclosure *rec;
4020 enum fill_status status = FILL_STATUS_UNFILTERED;
4021 UINT row = 0, len;
4022 char *buf;
4024 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
4026 len = GetSystemFirmwareTable( RSMB, 0, NULL, 0 );
4027 if (!(buf = malloc( len ))) return FILL_STATUS_FAILED;
4028 GetSystemFirmwareTable( RSMB, 0, buf, len );
4030 rec = (struct record_systemenclosure *)table->data;
4031 rec->caption = L"System Enclosure";
4032 rec->chassistypes = get_systemenclosure_chassistypes( buf, len );
4033 rec->description = L"System Enclosure";
4034 rec->lockpresent = get_systemenclosure_lockpresent( buf, len );
4035 rec->manufacturer = get_systemenclosure_manufacturer( buf, len );
4036 rec->name = L"System Enclosure";
4037 rec->tag = L"System Enclosure 0";
4038 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
4039 else row++;
4041 free( buf );
4043 TRACE("created %u rows\n", row);
4044 table->num_rows = row;
4045 return status;
4048 static WCHAR *get_videocontroller_pnpdeviceid( DXGI_ADAPTER_DESC *desc )
4050 static const WCHAR fmtW[] = L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X\\0&DEADBEEF&0&DEAD";
4051 UINT len = sizeof(fmtW) + 2;
4052 WCHAR *ret;
4054 if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL;
4055 swprintf( ret, len, fmtW, desc->VendorId, desc->DeviceId, desc->SubSysId, desc->Revision );
4056 return ret;
4059 #define HW_VENDOR_AMD 0x1002
4060 #define HW_VENDOR_NVIDIA 0x10de
4061 #define HW_VENDOR_VMWARE 0x15ad
4062 #define HW_VENDOR_INTEL 0x8086
4064 static const WCHAR *get_videocontroller_installeddriver( UINT vendorid )
4066 /* FIXME: wined3d has a better table, but we cannot access this information through dxgi */
4068 if (vendorid == HW_VENDOR_AMD) return L"aticfx32.dll";
4069 else if (vendorid == HW_VENDOR_NVIDIA) return L"nvd3dum.dll";
4070 else if (vendorid == HW_VENDOR_INTEL) return L"igdudim32.dll";
4071 return L"wine.dll";
4074 static BOOL get_dxgi_adapter_desc( DXGI_ADAPTER_DESC *desc )
4076 IDXGIFactory *factory;
4077 IDXGIAdapter *adapter;
4078 HRESULT hr;
4080 memset( desc, 0, sizeof(*desc) );
4081 hr = CreateDXGIFactory( &IID_IDXGIFactory, (void **)&factory );
4082 if (FAILED( hr )) return FALSE;
4084 hr = IDXGIFactory_EnumAdapters( factory, 0, &adapter );
4085 if (FAILED( hr ))
4087 IDXGIFactory_Release( factory );
4088 return FALSE;
4091 hr = IDXGIAdapter_GetDesc( adapter, desc );
4092 IDXGIAdapter_Release( adapter );
4093 IDXGIFactory_Release( factory );
4094 return SUCCEEDED( hr );
4097 static enum fill_status fill_videocontroller( struct table *table, const struct expr *cond )
4099 struct record_videocontroller *rec;
4100 DXGI_ADAPTER_DESC desc;
4101 UINT row = 0, hres = 1024, vres = 768, vidmem = 512 * 1024 * 1024;
4102 const WCHAR *name = L"VideoController1";
4103 enum fill_status status = FILL_STATUS_UNFILTERED;
4104 WCHAR mode[44];
4106 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
4108 if (get_dxgi_adapter_desc( &desc ))
4110 if (desc.DedicatedVideoMemory > UINT_MAX) vidmem = 0xfff00000;
4111 else vidmem = desc.DedicatedVideoMemory;
4112 name = desc.Description;
4115 rec = (struct record_videocontroller *)table->data;
4116 rec->adapter_compatibility = L"(Standard display types)";
4117 rec->adapter_dactype = L"Integrated RAMDAC";
4118 rec->adapter_ram = vidmem;
4119 rec->availability = 3; /* Running or Full Power */
4120 rec->config_errorcode = 0; /* no error */
4121 rec->caption = wcsdup( name );
4122 rec->current_bitsperpixel = get_bitsperpixel( &hres, &vres );
4123 rec->current_horizontalres = hres;
4124 rec->current_refreshrate = 0; /* default refresh rate */
4125 rec->current_scanmode = 2; /* Unknown */
4126 rec->current_verticalres = vres;
4127 rec->description = wcsdup( name );
4128 rec->device_id = L"VideoController1";
4129 rec->driverdate = L"20220118000000.000000-000";
4130 rec->driverversion = L"30.0.14023.3004";
4131 rec->installeddriver = get_videocontroller_installeddriver( desc.VendorId );
4132 rec->name = wcsdup( name );
4133 rec->pnpdevice_id = get_videocontroller_pnpdeviceid( &desc );
4134 rec->status = L"OK";
4135 rec->videoarchitecture = 2; /* Unknown */
4136 rec->videomemorytype = 2; /* Unknown */
4137 swprintf( mode, ARRAY_SIZE( mode ), L"%u x %u x %I64u colors", hres, vres, (UINT64)1 << rec->current_bitsperpixel );
4138 rec->videomodedescription = wcsdup( mode );
4139 rec->videoprocessor = wcsdup( name );
4140 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
4141 else row++;
4143 TRACE("created %u rows\n", row);
4144 table->num_rows = row;
4145 return status;
4148 static WCHAR *get_sounddevice_pnpdeviceid( DXGI_ADAPTER_DESC *desc )
4150 static const WCHAR fmtW[] = L"HDAUDIO\\FUNC_01&VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%04X\\0&DEADBEEF&0&DEAD";
4151 UINT len = sizeof(fmtW) + 2;
4152 WCHAR *ret;
4154 if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL;
4155 swprintf( ret, len, fmtW, desc->VendorId, desc->DeviceId, desc->SubSysId, desc->Revision );
4156 return ret;
4159 static enum fill_status fill_sounddevice( struct table *table, const struct expr *cond )
4161 struct record_sounddevice *rec;
4162 DXGI_ADAPTER_DESC desc;
4163 UINT row = 0;
4164 enum fill_status status = FILL_STATUS_UNFILTERED;
4166 if (!resize_table( table, 1, sizeof(*rec) )) return FILL_STATUS_FAILED;
4168 get_dxgi_adapter_desc( &desc );
4170 rec = (struct record_sounddevice *)table->data;
4171 rec->deviceid = get_sounddevice_pnpdeviceid( &desc );
4172 rec->manufacturer = L"The Wine Project";
4173 rec->name = L"Wine Audio Device";
4174 rec->pnpdeviceid = get_sounddevice_pnpdeviceid( &desc );
4175 rec->productname = L"Wine Audio Device";
4176 rec->status = L"OK";
4177 rec->statusinfo = 3;
4178 if (!match_row( table, row, cond, &status )) free_row_values( table, row );
4179 else row++;
4181 TRACE("created %u rows\n", row);
4182 table->num_rows = row;
4183 return status;
4186 #define C(c) sizeof(c)/sizeof(c[0]), c
4187 #define D(d) sizeof(d)/sizeof(d[0]), 0, (BYTE *)d
4188 static struct table cimv2_builtin_classes[] =
4190 { L"__ASSOCIATORS", C(col_associator), D(data_associator) },
4191 { L"__PARAMETERS", C(col_param), D(data_param) },
4192 { L"__QUALIFIERS", C(col_qualifier), D(data_qualifier) },
4193 { L"__SystemSecurity", C(col_systemsecurity), D(data_systemsecurity) },
4194 { L"CIM_DataFile", C(col_datafile), 0, 0, NULL, fill_datafile },
4195 { L"CIM_LogicalDisk", C(col_logicaldisk), 0, 0, NULL, fill_logicaldisk },
4196 { L"CIM_Processor", C(col_processor), 0, 0, NULL, fill_processor },
4197 { L"SoftwareLicensingProduct", C(col_softwarelicensingproduct), D(data_softwarelicensingproduct) },
4198 { L"StdRegProv", C(col_stdregprov), D(data_stdregprov) },
4199 { L"SystemRestore", C(col_sysrestore), D(data_sysrestore) },
4200 { L"Win32_BIOS", C(col_bios), 0, 0, NULL, fill_bios },
4201 { L"Win32_BaseBoard", C(col_baseboard), 0, 0, NULL, fill_baseboard },
4202 { L"Win32_CDROMDrive", C(col_cdromdrive), 0, 0, NULL, fill_cdromdrive },
4203 { L"Win32_ComputerSystem", C(col_compsys), 0, 0, NULL, fill_compsys },
4204 { L"Win32_ComputerSystemProduct", C(col_compsysproduct), 0, 0, NULL, fill_compsysproduct },
4205 { L"Win32_DesktopMonitor", C(col_desktopmonitor), 0, 0, NULL, fill_desktopmonitor },
4206 { L"Win32_Directory", C(col_directory), 0, 0, NULL, fill_directory },
4207 { L"Win32_DiskDrive", C(col_diskdrive), 0, 0, NULL, fill_diskdrive },
4208 { L"Win32_DiskDriveToDiskPartition", C(col_diskdrivetodiskpartition), 0, 0, NULL, fill_diskdrivetodiskpartition },
4209 { L"Win32_DiskPartition", C(col_diskpartition), 0, 0, NULL, fill_diskpartition },
4210 { L"Win32_DisplayControllerConfiguration", C(col_displaycontrollerconfig), 0, 0, NULL, fill_displaycontrollerconfig },
4211 { L"Win32_IP4RouteTable", C(col_ip4routetable), 0, 0, NULL, fill_ip4routetable },
4212 { L"Win32_LogicalDisk", C(col_logicaldisk), 0, 0, NULL, fill_logicaldisk },
4213 { L"Win32_LogicalDiskToPartition", C(col_logicaldisktopartition), 0, 0, NULL, fill_logicaldisktopartition },
4214 { L"Win32_NetworkAdapter", C(col_networkadapter), 0, 0, NULL, fill_networkadapter },
4215 { L"Win32_NetworkAdapterConfiguration", C(col_networkadapterconfig), 0, 0, NULL, fill_networkadapterconfig },
4216 { L"Win32_OperatingSystem", C(col_operatingsystem), 0, 0, NULL, fill_operatingsystem },
4217 { L"Win32_PageFileUsage", C(col_pagefileusage), D(data_pagefileusage) },
4218 { L"Win32_PhysicalMedia", C(col_physicalmedia), D(data_physicalmedia) },
4219 { L"Win32_PhysicalMemory", C(col_physicalmemory), 0, 0, NULL, fill_physicalmemory },
4220 { L"Win32_PnPEntity", C(col_pnpentity), 0, 0, NULL, fill_pnpentity },
4221 { L"Win32_Printer", C(col_printer), 0, 0, NULL, fill_printer },
4222 { L"Win32_Process", C(col_process), 0, 0, NULL, fill_process },
4223 { L"Win32_Processor", C(col_processor), 0, 0, NULL, fill_processor },
4224 { L"Win32_QuickFixEngineering", C(col_quickfixengineering), D(data_quickfixengineering) },
4225 { L"Win32_SID", C(col_sid), 0, 0, NULL, fill_sid },
4226 { L"Win32_Service", C(col_service), 0, 0, NULL, fill_service },
4227 { L"Win32_SoundDevice", C(col_sounddevice), 0, 0, NULL, fill_sounddevice },
4228 { L"Win32_SystemEnclosure", C(col_systemenclosure), 0, 0, NULL, fill_systemenclosure },
4229 { L"Win32_VideoController", C(col_videocontroller), 0, 0, NULL, fill_videocontroller },
4230 { L"Win32_WinSAT", C(col_winsat), D(data_winsat) },
4233 static struct table wmi_builtin_classes[] =
4235 { L"MSSMBios_RawSMBiosTables", C(col_rawsmbiostables), D(data_rawsmbiostables) },
4237 #undef C
4238 #undef D
4240 static const struct
4242 const WCHAR *name;
4243 struct table *classes;
4244 unsigned int table_count;
4246 builtin_namespaces[WBEMPROX_NAMESPACE_LAST] =
4248 {L"cimv2", cimv2_builtin_classes, ARRAY_SIZE(cimv2_builtin_classes)},
4249 {L"Microsoft\\Windows\\Storage", NULL, 0},
4250 {L"wmi", wmi_builtin_classes, ARRAY_SIZE(wmi_builtin_classes)},
4253 void init_table_list( void )
4255 static struct list tables[WBEMPROX_NAMESPACE_LAST];
4256 UINT ns, i;
4258 for (ns = 0; ns < ARRAY_SIZE(builtin_namespaces); ns++)
4260 list_init( &tables[ns] );
4261 for (i = 0; i < builtin_namespaces[ns].table_count; i++)
4262 list_add_tail( &tables[ns], &builtin_namespaces[ns].classes[i].entry );
4263 table_list[ns] = &tables[ns];
4267 enum wbm_namespace get_namespace_from_string( const WCHAR *namespace )
4269 unsigned int i;
4271 if (!wcsicmp( namespace, L"default" )) return WBEMPROX_NAMESPACE_CIMV2;
4273 for (i = 0; i < WBEMPROX_NAMESPACE_LAST; ++i)
4274 if (!wcsicmp( namespace, builtin_namespaces[i].name )) return i;
4276 return WBEMPROX_NAMESPACE_LAST;