2 * DxDiag file information output
4 * Copyright 2011 Andrew Nguyen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/debug.h"
29 #include "wine/unicode.h"
31 #include "dxdiag_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(dxdiag
);
35 static char output_buffer
[1024];
36 static const char crlf
[2] = "\r\n";
38 static const WCHAR DxDiag
[] = {'D','x','D','i','a','g',0};
40 static const WCHAR SystemInformation
[] = {'S','y','s','t','e','m','I','n','f','o','r','m','a','t','i','o','n',0};
41 static const WCHAR Time
[] = {'T','i','m','e',0};
42 static const WCHAR MachineName
[] = {'M','a','c','h','i','n','e','N','a','m','e',0};
43 static const WCHAR OperatingSystem
[] = {'O','p','e','r','a','t','i','n','g','S','y','s','t','e','m',0};
44 static const WCHAR Language
[] = {'L','a','n','g','u','a','g','e',0};
45 static const WCHAR SystemManufacturer
[] = {'S','y','s','t','e','m','M','a','n','u','f','a','c','t','u','r','e','r',0};
46 static const WCHAR SystemModel
[] = {'S','y','s','t','e','m','M','o','d','e','l',0};
47 static const WCHAR BIOS
[] = {'B','I','O','S',0};
48 static const WCHAR Processor
[] = {'P','r','o','c','e','s','s','o','r',0};
49 static const WCHAR Memory
[] = {'M','e','m','o','r','y',0};
50 static const WCHAR PageFile
[] = {'P','a','g','e','F','i','l','e',0};
51 static const WCHAR WindowsDir
[] = {'W','i','n','d','o','w','s','D','i','r',0};
52 static const WCHAR DirectXVersion
[] = {'D','i','r','e','c','t','X','V','e','r','s','i','o','n',0};
53 static const WCHAR DXSetupParameters
[] = {'D','X','S','e','t','u','p','P','a','r','a','m','e','t','e','r','s',0};
54 static const WCHAR DxDiagVersion
[] = {'D','x','D','i','a','g','V','e','r','s','i','o','n',0};
55 static const WCHAR DxDiagUnicode
[] = {'D','x','D','i','a','g','U','n','i','c','o','d','e',0};
56 static const WCHAR DxDiag64Bit
[] = {'D','x','D','i','a','g','6','4','B','i','t',0};
58 struct text_information_field
60 const char *field_name
;
64 struct xml_information_field
66 const WCHAR
*tag_name
;
70 static BOOL
output_text_header(HANDLE hFile
, const char *caption
)
72 DWORD len
= strlen(caption
);
73 DWORD total_len
= 3 * (len
+ sizeof(crlf
));
74 char *ptr
= output_buffer
;
77 assert(total_len
<= sizeof(output_buffer
));
79 memset(ptr
, '-', len
);
82 memcpy(ptr
, crlf
, sizeof(crlf
));
85 memcpy(ptr
, caption
, len
);
88 memcpy(ptr
, crlf
, sizeof(crlf
));
91 memset(ptr
, '-', len
);
94 memcpy(ptr
, crlf
, sizeof(crlf
));
96 return WriteFile(hFile
, output_buffer
, total_len
, &bytes_written
, NULL
);
99 static BOOL
output_text_field(HANDLE hFile
, const char *field_name
, DWORD field_width
, const WCHAR
*value
)
101 DWORD value_lenW
= strlenW(value
);
102 DWORD value_lenA
= WideCharToMultiByte(CP_ACP
, 0, value
, value_lenW
, NULL
, 0, NULL
, NULL
);
103 DWORD total_len
= field_width
+ sizeof(": ") - 1 + value_lenA
+ sizeof(crlf
);
104 char sprintf_fmt
[1 + 10 + 3 + 1];
105 char *ptr
= output_buffer
;
108 assert(total_len
<= sizeof(output_buffer
));
110 sprintf(sprintf_fmt
, "%%%us: ", field_width
);
111 ptr
+= sprintf(ptr
, sprintf_fmt
, field_name
);
113 ptr
+= WideCharToMultiByte(CP_ACP
, 0, value
, value_lenW
, ptr
, value_lenA
, NULL
, NULL
);
114 memcpy(ptr
, crlf
, sizeof(crlf
));
116 return WriteFile(hFile
, output_buffer
, total_len
, &bytes_written
, NULL
);
119 static BOOL
output_crlf(HANDLE hFile
)
122 return WriteFile(hFile
, crlf
, sizeof(crlf
), &bytes_written
, NULL
);
125 static inline void fill_system_text_output_table(struct dxdiag_information
*dxdiag_info
, struct text_information_field
*fields
)
127 fields
[0].field_name
= "Time of this report";
128 fields
[0].value
= dxdiag_info
->system_info
.szTimeEnglish
;
129 fields
[1].field_name
= "Machine name";
130 fields
[1].value
= dxdiag_info
->system_info
.szMachineNameEnglish
;
131 fields
[2].field_name
= "Operating System";
132 fields
[2].value
= dxdiag_info
->system_info
.szOSExLongEnglish
;
133 fields
[3].field_name
= "Language";
134 fields
[3].value
= dxdiag_info
->system_info
.szLanguagesEnglish
;
135 fields
[4].field_name
= "System Manufacturer";
136 fields
[4].value
= dxdiag_info
->system_info
.szSystemManufacturerEnglish
;
137 fields
[5].field_name
= "System Model";
138 fields
[5].value
= dxdiag_info
->system_info
.szSystemModelEnglish
;
139 fields
[6].field_name
= "BIOS";
140 fields
[6].value
= dxdiag_info
->system_info
.szBIOSEnglish
;
141 fields
[7].field_name
= "Processor";
142 fields
[7].value
= dxdiag_info
->system_info
.szProcessorEnglish
;
143 fields
[8].field_name
= "Memory";
144 fields
[8].value
= dxdiag_info
->system_info
.szPhysicalMemoryEnglish
;
145 fields
[9].field_name
= "Page File";
146 fields
[9].value
= dxdiag_info
->system_info
.szPageFileEnglish
;
147 fields
[10].field_name
= "Windows Dir";
148 fields
[10].value
= dxdiag_info
->system_info
.szWindowsDir
;
149 fields
[11].field_name
= "DirectX Version";
150 fields
[11].value
= dxdiag_info
->system_info
.szDirectXVersionLongEnglish
;
151 fields
[12].field_name
= "DX Setup Parameters";
152 fields
[12].value
= dxdiag_info
->system_info
.szSetupParamEnglish
;
153 fields
[13].field_name
= "DxDiag Version";
154 fields
[13].value
= dxdiag_info
->system_info
.szDxDiagVersion
;
157 static BOOL
output_text_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
)
159 struct information_block
162 const size_t field_width
;
163 struct text_information_field fields
[50];
166 {"System Information", 19},
172 fill_system_text_output_table(dxdiag_info
, output_table
[0].fields
);
174 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
175 NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
176 if (hFile
== INVALID_HANDLE_VALUE
)
178 WINE_ERR("File creation failed, last error %u\n", GetLastError());
182 for (i
= 0; i
< sizeof(output_table
)/sizeof(output_table
[0]); i
++)
184 const struct text_information_field
*fields
= output_table
[i
].fields
;
187 output_text_header(hFile
, output_table
[i
].caption
);
188 for (j
= 0; fields
[j
].field_name
; j
++)
189 output_text_field(hFile
, fields
[j
].field_name
, output_table
[i
].field_width
, fields
[j
].value
);
197 static IXMLDOMElement
*xml_create_element(IXMLDOMDocument
*xmldoc
, const WCHAR
*name
)
199 BSTR bstr
= SysAllocString(name
);
206 hr
= IXMLDOMDocument_createElement(xmldoc
, bstr
, &ret
);
209 return SUCCEEDED(hr
) ? ret
: NULL
;
212 static HRESULT
xml_put_element_text(IXMLDOMElement
*element
, const WCHAR
*text
)
214 BSTR bstr
= SysAllocString(text
);
218 return E_OUTOFMEMORY
;
220 hr
= IXMLDOMElement_put_text(element
, bstr
);
226 static HRESULT
save_xml_document(IXMLDOMDocument
*xmldoc
, const WCHAR
*filename
)
228 BSTR bstr
= SysAllocString(filename
);
233 return E_OUTOFMEMORY
;
235 V_VT(&destVar
) = VT_BSTR
;
236 V_BSTR(&destVar
) = bstr
;
238 hr
= IXMLDOMDocument_save(xmldoc
, destVar
);
239 VariantClear(&destVar
);
244 static inline void fill_system_xml_output_table(struct dxdiag_information
*dxdiag_info
, struct xml_information_field
*fields
)
246 static const WCHAR zeroW
[] = {'0',0};
247 static const WCHAR oneW
[] = {'1',0};
249 fields
[0].tag_name
= Time
;
250 fields
[0].value
= dxdiag_info
->system_info
.szTimeEnglish
;
251 fields
[1].tag_name
= MachineName
;
252 fields
[1].value
= dxdiag_info
->system_info
.szMachineNameEnglish
;
253 fields
[2].tag_name
= OperatingSystem
;
254 fields
[2].value
= dxdiag_info
->system_info
.szOSExLongEnglish
;
255 fields
[3].tag_name
= Language
;
256 fields
[3].value
= dxdiag_info
->system_info
.szLanguagesEnglish
;
257 fields
[4].tag_name
= SystemManufacturer
;
258 fields
[4].value
= dxdiag_info
->system_info
.szSystemManufacturerEnglish
;
259 fields
[5].tag_name
= SystemModel
;
260 fields
[5].value
= dxdiag_info
->system_info
.szSystemModelEnglish
;
261 fields
[6].tag_name
= BIOS
;
262 fields
[6].value
= dxdiag_info
->system_info
.szBIOSEnglish
;
263 fields
[7].tag_name
= Processor
;
264 fields
[7].value
= dxdiag_info
->system_info
.szProcessorEnglish
;
265 fields
[8].tag_name
= Memory
;
266 fields
[8].value
= dxdiag_info
->system_info
.szPhysicalMemoryEnglish
;
267 fields
[9].tag_name
= PageFile
;
268 fields
[9].value
= dxdiag_info
->system_info
.szPageFileEnglish
;
269 fields
[10].tag_name
= WindowsDir
;
270 fields
[10].value
= dxdiag_info
->system_info
.szWindowsDir
;
271 fields
[11].tag_name
= DirectXVersion
;
272 fields
[11].value
= dxdiag_info
->system_info
.szDirectXVersionLongEnglish
;
273 fields
[12].tag_name
= DXSetupParameters
;
274 fields
[12].value
= dxdiag_info
->system_info
.szSetupParamEnglish
;
275 fields
[13].tag_name
= DxDiagVersion
;
276 fields
[13].value
= dxdiag_info
->system_info
.szDxDiagVersion
;
277 fields
[14].tag_name
= DxDiagUnicode
;
278 fields
[14].value
= oneW
;
279 fields
[15].tag_name
= DxDiag64Bit
;
280 fields
[15].value
= dxdiag_info
->system_info
.win64
? oneW
: zeroW
;
283 static BOOL
output_xml_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
)
285 struct information_block
287 const WCHAR
*tag_name
;
288 struct xml_information_field fields
[50];
294 IXMLDOMDocument
*xmldoc
= NULL
;
295 IXMLDOMElement
*dxdiag_element
= NULL
;
299 fill_system_xml_output_table(dxdiag_info
, output_table
[0].fields
);
301 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
302 &IID_IXMLDOMDocument
, (void **)&xmldoc
);
305 WINE_ERR("IXMLDOMDocument instance creation failed with 0x%08x\n", hr
);
309 if (!(dxdiag_element
= xml_create_element(xmldoc
, DxDiag
)))
312 hr
= IXMLDOMDocument_appendChild(xmldoc
, (IXMLDOMNode
*)dxdiag_element
, NULL
);
316 for (i
= 0; i
< sizeof(output_table
)/sizeof(output_table
[0]); i
++)
318 IXMLDOMElement
*info_element
= xml_create_element(xmldoc
, output_table
[i
].tag_name
);
319 const struct xml_information_field
*fields
= output_table
[i
].fields
;
325 hr
= IXMLDOMElement_appendChild(dxdiag_element
, (IXMLDOMNode
*)info_element
, NULL
);
328 IXMLDOMElement_Release(info_element
);
332 for (j
= 0; fields
[j
].tag_name
; j
++)
334 IXMLDOMElement
*field_element
= xml_create_element(xmldoc
, fields
[j
].tag_name
);
338 IXMLDOMElement_Release(info_element
);
342 hr
= xml_put_element_text(field_element
, fields
[j
].value
);
345 IXMLDOMElement_Release(field_element
);
346 IXMLDOMElement_Release(info_element
);
350 hr
= IXMLDOMElement_appendChild(info_element
, (IXMLDOMNode
*)field_element
, NULL
);
353 IXMLDOMElement_Release(field_element
);
354 IXMLDOMElement_Release(info_element
);
358 IXMLDOMElement_Release(field_element
);
361 IXMLDOMElement_Release(info_element
);
364 hr
= save_xml_document(xmldoc
, filename
);
368 IXMLDOMElement_Release(dxdiag_element
);
369 IXMLDOMDocument_Release(xmldoc
);
372 if (dxdiag_element
) IXMLDOMElement_Release(dxdiag_element
);
373 if (xmldoc
) IXMLDOMDocument_Release(xmldoc
);
377 static struct output_backend
379 const WCHAR filename_ext
[5];
380 BOOL (*output_handler
)(struct dxdiag_information
*, const WCHAR
*filename
);
381 } output_backends
[] =
386 output_text_information
,
391 output_xml_information
,
395 const WCHAR
*get_output_extension(enum output_type type
)
397 assert(type
> OUTPUT_NONE
&& type
<= sizeof(output_backends
)/sizeof(output_backends
[0]));
399 return output_backends
[type
- 1].filename_ext
;
402 BOOL
output_dxdiag_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
, enum output_type type
)
404 assert(type
> OUTPUT_NONE
&& type
<= sizeof(output_backends
)/sizeof(output_backends
[0]));
406 return output_backends
[type
- 1].output_handler(dxdiag_info
, filename
);