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 "dxdiag_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(dxdiag
);
33 static char output_buffer
[1024];
34 static const char crlf
[2] = "\r\n";
36 static const WCHAR DxDiag
[] = {'D','x','D','i','a','g',0};
38 static const WCHAR SystemInformation
[] = {'S','y','s','t','e','m','I','n','f','o','r','m','a','t','i','o','n',0};
39 static const WCHAR Time
[] = {'T','i','m','e',0};
40 static const WCHAR MachineName
[] = {'M','a','c','h','i','n','e','N','a','m','e',0};
41 static const WCHAR OperatingSystem
[] = {'O','p','e','r','a','t','i','n','g','S','y','s','t','e','m',0};
42 static const WCHAR Language
[] = {'L','a','n','g','u','a','g','e',0};
43 static const WCHAR SystemManufacturer
[] = {'S','y','s','t','e','m','M','a','n','u','f','a','c','t','u','r','e','r',0};
44 static const WCHAR SystemModel
[] = {'S','y','s','t','e','m','M','o','d','e','l',0};
45 static const WCHAR BIOS
[] = {'B','I','O','S',0};
46 static const WCHAR Processor
[] = {'P','r','o','c','e','s','s','o','r',0};
47 static const WCHAR Memory
[] = {'M','e','m','o','r','y',0};
48 static const WCHAR PageFile
[] = {'P','a','g','e','F','i','l','e',0};
49 static const WCHAR WindowsDir
[] = {'W','i','n','d','o','w','s','D','i','r',0};
50 static const WCHAR DirectXVersion
[] = {'D','i','r','e','c','t','X','V','e','r','s','i','o','n',0};
51 static const WCHAR DXSetupParameters
[] = {'D','X','S','e','t','u','p','P','a','r','a','m','e','t','e','r','s',0};
52 static const WCHAR DxDiagVersion
[] = {'D','x','D','i','a','g','V','e','r','s','i','o','n',0};
53 static const WCHAR DxDiagUnicode
[] = {'D','x','D','i','a','g','U','n','i','c','o','d','e',0};
54 static const WCHAR DxDiag64Bit
[] = {'D','x','D','i','a','g','6','4','B','i','t',0};
56 struct text_information_field
58 const char *field_name
;
62 struct xml_information_field
64 const WCHAR
*tag_name
;
68 static BOOL
output_text_header(HANDLE hFile
, const char *caption
)
70 DWORD len
= strlen(caption
);
71 DWORD total_len
= 3 * (len
+ sizeof(crlf
));
72 char *ptr
= output_buffer
;
75 assert(total_len
<= sizeof(output_buffer
));
77 memset(ptr
, '-', len
);
80 memcpy(ptr
, crlf
, sizeof(crlf
));
83 memcpy(ptr
, caption
, len
);
86 memcpy(ptr
, crlf
, sizeof(crlf
));
89 memset(ptr
, '-', len
);
92 memcpy(ptr
, crlf
, sizeof(crlf
));
94 return WriteFile(hFile
, output_buffer
, total_len
, &bytes_written
, NULL
);
97 static BOOL
output_text_field(HANDLE hFile
, const char *field_name
, DWORD field_width
, const WCHAR
*value
)
99 DWORD value_lenW
= lstrlenW(value
);
100 DWORD value_lenA
= WideCharToMultiByte(CP_ACP
, 0, value
, value_lenW
, NULL
, 0, NULL
, NULL
);
101 DWORD total_len
= field_width
+ sizeof(": ") - 1 + value_lenA
+ sizeof(crlf
);
102 char sprintf_fmt
[1 + 10 + 3 + 1];
103 char *ptr
= output_buffer
;
106 assert(total_len
<= sizeof(output_buffer
));
108 sprintf(sprintf_fmt
, "%%%us: ", field_width
);
109 ptr
+= sprintf(ptr
, sprintf_fmt
, field_name
);
111 ptr
+= WideCharToMultiByte(CP_ACP
, 0, value
, value_lenW
, ptr
, value_lenA
, NULL
, NULL
);
112 memcpy(ptr
, crlf
, sizeof(crlf
));
114 return WriteFile(hFile
, output_buffer
, total_len
, &bytes_written
, NULL
);
117 static BOOL
output_crlf(HANDLE hFile
)
120 return WriteFile(hFile
, crlf
, sizeof(crlf
), &bytes_written
, NULL
);
123 static inline void fill_system_text_output_table(struct dxdiag_information
*dxdiag_info
, struct text_information_field
*fields
)
125 fields
[0].field_name
= "Time of this report";
126 fields
[0].value
= dxdiag_info
->system_info
.szTimeEnglish
;
127 fields
[1].field_name
= "Machine name";
128 fields
[1].value
= dxdiag_info
->system_info
.szMachineNameEnglish
;
129 fields
[2].field_name
= "Operating System";
130 fields
[2].value
= dxdiag_info
->system_info
.szOSExLongEnglish
;
131 fields
[3].field_name
= "Language";
132 fields
[3].value
= dxdiag_info
->system_info
.szLanguagesEnglish
;
133 fields
[4].field_name
= "System Manufacturer";
134 fields
[4].value
= dxdiag_info
->system_info
.szSystemManufacturerEnglish
;
135 fields
[5].field_name
= "System Model";
136 fields
[5].value
= dxdiag_info
->system_info
.szSystemModelEnglish
;
137 fields
[6].field_name
= "BIOS";
138 fields
[6].value
= dxdiag_info
->system_info
.szBIOSEnglish
;
139 fields
[7].field_name
= "Processor";
140 fields
[7].value
= dxdiag_info
->system_info
.szProcessorEnglish
;
141 fields
[8].field_name
= "Memory";
142 fields
[8].value
= dxdiag_info
->system_info
.szPhysicalMemoryEnglish
;
143 fields
[9].field_name
= "Page File";
144 fields
[9].value
= dxdiag_info
->system_info
.szPageFileEnglish
;
145 fields
[10].field_name
= "Windows Dir";
146 fields
[10].value
= dxdiag_info
->system_info
.szWindowsDir
;
147 fields
[11].field_name
= "DirectX Version";
148 fields
[11].value
= dxdiag_info
->system_info
.szDirectXVersionLongEnglish
;
149 fields
[12].field_name
= "DX Setup Parameters";
150 fields
[12].value
= dxdiag_info
->system_info
.szSetupParamEnglish
;
151 fields
[13].field_name
= "DxDiag Version";
152 fields
[13].value
= dxdiag_info
->system_info
.szDxDiagVersion
;
155 static BOOL
output_text_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
)
157 struct information_block
160 const size_t field_width
;
161 struct text_information_field fields
[50];
164 {"System Information", 19},
170 fill_system_text_output_table(dxdiag_info
, output_table
[0].fields
);
172 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
173 NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
174 if (hFile
== INVALID_HANDLE_VALUE
)
176 WINE_ERR("File creation failed, last error %u\n", GetLastError());
180 for (i
= 0; i
< ARRAY_SIZE(output_table
); i
++)
182 const struct text_information_field
*fields
= output_table
[i
].fields
;
185 output_text_header(hFile
, output_table
[i
].caption
);
186 for (j
= 0; fields
[j
].field_name
; j
++)
187 output_text_field(hFile
, fields
[j
].field_name
, output_table
[i
].field_width
, fields
[j
].value
);
195 static IXMLDOMElement
*xml_create_element(IXMLDOMDocument
*xmldoc
, const WCHAR
*name
)
197 BSTR bstr
= SysAllocString(name
);
204 hr
= IXMLDOMDocument_createElement(xmldoc
, bstr
, &ret
);
207 return SUCCEEDED(hr
) ? ret
: NULL
;
210 static HRESULT
xml_put_element_text(IXMLDOMElement
*element
, const WCHAR
*text
)
212 BSTR bstr
= SysAllocString(text
);
216 return E_OUTOFMEMORY
;
218 hr
= IXMLDOMElement_put_text(element
, bstr
);
224 static HRESULT
save_xml_document(IXMLDOMDocument
*xmldoc
, const WCHAR
*filename
)
226 BSTR bstr
= SysAllocString(filename
);
231 return E_OUTOFMEMORY
;
233 V_VT(&destVar
) = VT_BSTR
;
234 V_BSTR(&destVar
) = bstr
;
236 hr
= IXMLDOMDocument_save(xmldoc
, destVar
);
237 VariantClear(&destVar
);
242 static inline void fill_system_xml_output_table(struct dxdiag_information
*dxdiag_info
, struct xml_information_field
*fields
)
244 static const WCHAR zeroW
[] = {'0',0};
245 static const WCHAR oneW
[] = {'1',0};
247 fields
[0].tag_name
= Time
;
248 fields
[0].value
= dxdiag_info
->system_info
.szTimeEnglish
;
249 fields
[1].tag_name
= MachineName
;
250 fields
[1].value
= dxdiag_info
->system_info
.szMachineNameEnglish
;
251 fields
[2].tag_name
= OperatingSystem
;
252 fields
[2].value
= dxdiag_info
->system_info
.szOSExLongEnglish
;
253 fields
[3].tag_name
= Language
;
254 fields
[3].value
= dxdiag_info
->system_info
.szLanguagesEnglish
;
255 fields
[4].tag_name
= SystemManufacturer
;
256 fields
[4].value
= dxdiag_info
->system_info
.szSystemManufacturerEnglish
;
257 fields
[5].tag_name
= SystemModel
;
258 fields
[5].value
= dxdiag_info
->system_info
.szSystemModelEnglish
;
259 fields
[6].tag_name
= BIOS
;
260 fields
[6].value
= dxdiag_info
->system_info
.szBIOSEnglish
;
261 fields
[7].tag_name
= Processor
;
262 fields
[7].value
= dxdiag_info
->system_info
.szProcessorEnglish
;
263 fields
[8].tag_name
= Memory
;
264 fields
[8].value
= dxdiag_info
->system_info
.szPhysicalMemoryEnglish
;
265 fields
[9].tag_name
= PageFile
;
266 fields
[9].value
= dxdiag_info
->system_info
.szPageFileEnglish
;
267 fields
[10].tag_name
= WindowsDir
;
268 fields
[10].value
= dxdiag_info
->system_info
.szWindowsDir
;
269 fields
[11].tag_name
= DirectXVersion
;
270 fields
[11].value
= dxdiag_info
->system_info
.szDirectXVersionLongEnglish
;
271 fields
[12].tag_name
= DXSetupParameters
;
272 fields
[12].value
= dxdiag_info
->system_info
.szSetupParamEnglish
;
273 fields
[13].tag_name
= DxDiagVersion
;
274 fields
[13].value
= dxdiag_info
->system_info
.szDxDiagVersion
;
275 fields
[14].tag_name
= DxDiagUnicode
;
276 fields
[14].value
= oneW
;
277 fields
[15].tag_name
= DxDiag64Bit
;
278 fields
[15].value
= dxdiag_info
->system_info
.win64
? oneW
: zeroW
;
281 static BOOL
output_xml_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
)
283 struct information_block
285 const WCHAR
*tag_name
;
286 struct xml_information_field fields
[50];
292 IXMLDOMDocument
*xmldoc
= NULL
;
293 IXMLDOMElement
*dxdiag_element
= NULL
;
297 fill_system_xml_output_table(dxdiag_info
, output_table
[0].fields
);
299 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
300 &IID_IXMLDOMDocument
, (void **)&xmldoc
);
303 WINE_ERR("IXMLDOMDocument instance creation failed with 0x%08x\n", hr
);
307 if (!(dxdiag_element
= xml_create_element(xmldoc
, DxDiag
)))
310 hr
= IXMLDOMDocument_appendChild(xmldoc
, (IXMLDOMNode
*)dxdiag_element
, NULL
);
314 for (i
= 0; i
< ARRAY_SIZE(output_table
); i
++)
316 IXMLDOMElement
*info_element
= xml_create_element(xmldoc
, output_table
[i
].tag_name
);
317 const struct xml_information_field
*fields
= output_table
[i
].fields
;
323 hr
= IXMLDOMElement_appendChild(dxdiag_element
, (IXMLDOMNode
*)info_element
, NULL
);
326 IXMLDOMElement_Release(info_element
);
330 for (j
= 0; fields
[j
].tag_name
; j
++)
332 IXMLDOMElement
*field_element
= xml_create_element(xmldoc
, fields
[j
].tag_name
);
336 IXMLDOMElement_Release(info_element
);
340 hr
= xml_put_element_text(field_element
, fields
[j
].value
);
343 IXMLDOMElement_Release(field_element
);
344 IXMLDOMElement_Release(info_element
);
348 hr
= IXMLDOMElement_appendChild(info_element
, (IXMLDOMNode
*)field_element
, NULL
);
351 IXMLDOMElement_Release(field_element
);
352 IXMLDOMElement_Release(info_element
);
356 IXMLDOMElement_Release(field_element
);
359 IXMLDOMElement_Release(info_element
);
362 hr
= save_xml_document(xmldoc
, filename
);
366 IXMLDOMElement_Release(dxdiag_element
);
367 IXMLDOMDocument_Release(xmldoc
);
370 if (dxdiag_element
) IXMLDOMElement_Release(dxdiag_element
);
371 if (xmldoc
) IXMLDOMDocument_Release(xmldoc
);
375 static struct output_backend
377 const WCHAR filename_ext
[5];
378 BOOL (*output_handler
)(struct dxdiag_information
*, const WCHAR
*filename
);
379 } output_backends
[] =
384 output_text_information
,
389 output_xml_information
,
393 const WCHAR
*get_output_extension(enum output_type type
)
395 assert(type
> OUTPUT_NONE
&& type
<= ARRAY_SIZE(output_backends
));
397 return output_backends
[type
- 1].filename_ext
;
400 BOOL
output_dxdiag_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
, enum output_type type
)
402 assert(type
> OUTPUT_NONE
&& type
<= ARRAY_SIZE(output_backends
));
404 return output_backends
[type
- 1].output_handler(dxdiag_info
, filename
);