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 struct text_information_field
38 const char *field_name
;
42 struct xml_information_field
44 const WCHAR
*tag_name
;
48 static BOOL
output_text_header(HANDLE hFile
, const char *caption
)
50 DWORD len
= strlen(caption
);
51 DWORD total_len
= 3 * (len
+ sizeof(crlf
));
52 char *ptr
= output_buffer
;
55 assert(total_len
<= sizeof(output_buffer
));
57 memset(ptr
, '-', len
);
60 memcpy(ptr
, crlf
, sizeof(crlf
));
63 memcpy(ptr
, caption
, len
);
66 memcpy(ptr
, crlf
, sizeof(crlf
));
69 memset(ptr
, '-', len
);
72 memcpy(ptr
, crlf
, sizeof(crlf
));
74 return WriteFile(hFile
, output_buffer
, total_len
, &bytes_written
, NULL
);
77 static BOOL
output_text_field(HANDLE hFile
, const char *field_name
, DWORD field_width
, const WCHAR
*value
)
79 DWORD value_lenW
= lstrlenW(value
);
80 DWORD value_lenA
= WideCharToMultiByte(CP_ACP
, 0, value
, value_lenW
, NULL
, 0, NULL
, NULL
);
81 DWORD total_len
= field_width
+ sizeof(": ") - 1 + value_lenA
+ sizeof(crlf
);
82 char sprintf_fmt
[1 + 10 + 3 + 1];
83 char *ptr
= output_buffer
;
86 assert(total_len
<= sizeof(output_buffer
));
88 sprintf(sprintf_fmt
, "%%%lus: ", field_width
);
89 ptr
+= sprintf(ptr
, sprintf_fmt
, field_name
);
91 ptr
+= WideCharToMultiByte(CP_ACP
, 0, value
, value_lenW
, ptr
, value_lenA
, NULL
, NULL
);
92 memcpy(ptr
, crlf
, sizeof(crlf
));
94 return WriteFile(hFile
, output_buffer
, total_len
, &bytes_written
, NULL
);
97 static BOOL
output_crlf(HANDLE hFile
)
100 return WriteFile(hFile
, crlf
, sizeof(crlf
), &bytes_written
, NULL
);
103 static inline void fill_system_text_output_table(struct dxdiag_information
*dxdiag_info
, struct text_information_field
*fields
)
105 fields
[0].field_name
= "Time of this report";
106 fields
[0].value
= dxdiag_info
->system_info
.szTimeEnglish
;
107 fields
[1].field_name
= "Machine name";
108 fields
[1].value
= dxdiag_info
->system_info
.szMachineNameEnglish
;
109 fields
[2].field_name
= "Operating System";
110 fields
[2].value
= dxdiag_info
->system_info
.szOSExLongEnglish
;
111 fields
[3].field_name
= "Language";
112 fields
[3].value
= dxdiag_info
->system_info
.szLanguagesEnglish
;
113 fields
[4].field_name
= "System Manufacturer";
114 fields
[4].value
= dxdiag_info
->system_info
.szSystemManufacturerEnglish
;
115 fields
[5].field_name
= "System Model";
116 fields
[5].value
= dxdiag_info
->system_info
.szSystemModelEnglish
;
117 fields
[6].field_name
= "BIOS";
118 fields
[6].value
= dxdiag_info
->system_info
.szBIOSEnglish
;
119 fields
[7].field_name
= "Processor";
120 fields
[7].value
= dxdiag_info
->system_info
.szProcessorEnglish
;
121 fields
[8].field_name
= "Memory";
122 fields
[8].value
= dxdiag_info
->system_info
.szPhysicalMemoryEnglish
;
123 fields
[9].field_name
= "Page File";
124 fields
[9].value
= dxdiag_info
->system_info
.szPageFileEnglish
;
125 fields
[10].field_name
= "Windows Dir";
126 fields
[10].value
= dxdiag_info
->system_info
.szWindowsDir
;
127 fields
[11].field_name
= "DirectX Version";
128 fields
[11].value
= dxdiag_info
->system_info
.szDirectXVersionLongEnglish
;
129 fields
[12].field_name
= "DX Setup Parameters";
130 fields
[12].value
= dxdiag_info
->system_info
.szSetupParamEnglish
;
131 fields
[13].field_name
= "DxDiag Version";
132 fields
[13].value
= dxdiag_info
->system_info
.szDxDiagVersion
;
135 static BOOL
output_text_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
)
137 struct information_block
140 const size_t field_width
;
141 struct text_information_field fields
[50];
144 {"System Information", 19},
150 fill_system_text_output_table(dxdiag_info
, output_table
[0].fields
);
152 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
153 NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
154 if (hFile
== INVALID_HANDLE_VALUE
)
156 WINE_ERR("File creation failed, last error %lu\n", GetLastError());
160 for (i
= 0; i
< ARRAY_SIZE(output_table
); i
++)
162 const struct text_information_field
*fields
= output_table
[i
].fields
;
165 output_text_header(hFile
, output_table
[i
].caption
);
166 for (j
= 0; fields
[j
].field_name
; j
++)
167 output_text_field(hFile
, fields
[j
].field_name
, output_table
[i
].field_width
, fields
[j
].value
);
175 static IXMLDOMElement
*xml_create_element(IXMLDOMDocument
*xmldoc
, const WCHAR
*name
)
177 BSTR bstr
= SysAllocString(name
);
184 hr
= IXMLDOMDocument_createElement(xmldoc
, bstr
, &ret
);
187 return SUCCEEDED(hr
) ? ret
: NULL
;
190 static HRESULT
xml_put_element_text(IXMLDOMElement
*element
, const WCHAR
*text
)
192 BSTR bstr
= SysAllocString(text
);
196 return E_OUTOFMEMORY
;
198 hr
= IXMLDOMElement_put_text(element
, bstr
);
204 static HRESULT
save_xml_document(IXMLDOMDocument
*xmldoc
, const WCHAR
*filename
)
206 BSTR bstr
= SysAllocString(filename
);
211 return E_OUTOFMEMORY
;
213 V_VT(&destVar
) = VT_BSTR
;
214 V_BSTR(&destVar
) = bstr
;
216 hr
= IXMLDOMDocument_save(xmldoc
, destVar
);
217 VariantClear(&destVar
);
222 static inline void fill_system_xml_output_table(struct dxdiag_information
*dxdiag_info
, struct xml_information_field
*fields
)
224 fields
[0].tag_name
= L
"Time";
225 fields
[0].value
= dxdiag_info
->system_info
.szTimeEnglish
;
226 fields
[1].tag_name
= L
"MachineName";
227 fields
[1].value
= dxdiag_info
->system_info
.szMachineNameEnglish
;
228 fields
[2].tag_name
= L
"OperatingSystem";
229 fields
[2].value
= dxdiag_info
->system_info
.szOSExLongEnglish
;
230 fields
[3].tag_name
= L
"Language";
231 fields
[3].value
= dxdiag_info
->system_info
.szLanguagesEnglish
;
232 fields
[4].tag_name
= L
"SystemManufacturer";
233 fields
[4].value
= dxdiag_info
->system_info
.szSystemManufacturerEnglish
;
234 fields
[5].tag_name
= L
"SystemModel";
235 fields
[5].value
= dxdiag_info
->system_info
.szSystemModelEnglish
;
236 fields
[6].tag_name
= L
"BIOS";
237 fields
[6].value
= dxdiag_info
->system_info
.szBIOSEnglish
;
238 fields
[7].tag_name
= L
"Processor";
239 fields
[7].value
= dxdiag_info
->system_info
.szProcessorEnglish
;
240 fields
[8].tag_name
= L
"Memory";
241 fields
[8].value
= dxdiag_info
->system_info
.szPhysicalMemoryEnglish
;
242 fields
[9].tag_name
= L
"PageFile";
243 fields
[9].value
= dxdiag_info
->system_info
.szPageFileEnglish
;
244 fields
[10].tag_name
= L
"WindowsDir";
245 fields
[10].value
= dxdiag_info
->system_info
.szWindowsDir
;
246 fields
[11].tag_name
= L
"DirectXVersion";
247 fields
[11].value
= dxdiag_info
->system_info
.szDirectXVersionLongEnglish
;
248 fields
[12].tag_name
= L
"DXSetupParameters";
249 fields
[12].value
= dxdiag_info
->system_info
.szSetupParamEnglish
;
250 fields
[13].tag_name
= L
"DxDiagVersion";
251 fields
[13].value
= dxdiag_info
->system_info
.szDxDiagVersion
;
252 fields
[14].tag_name
= L
"DxDiagUnicode";
253 fields
[14].value
= L
"1";
254 fields
[15].tag_name
= L
"DxDiag64Bit";
255 fields
[15].value
= dxdiag_info
->system_info
.win64
? L
"1" : L
"0";
258 static BOOL
output_xml_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
)
260 struct information_block
262 const WCHAR
*tag_name
;
263 struct xml_information_field fields
[50];
266 {L
"SystemInformation"},
269 IXMLDOMDocument
*xmldoc
= NULL
;
270 IXMLDOMElement
*dxdiag_element
= NULL
;
274 fill_system_xml_output_table(dxdiag_info
, output_table
[0].fields
);
276 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
277 &IID_IXMLDOMDocument
, (void **)&xmldoc
);
280 WINE_ERR("IXMLDOMDocument instance creation failed with 0x%08lx\n", hr
);
284 if (!(dxdiag_element
= xml_create_element(xmldoc
, L
"DxDiag")))
287 hr
= IXMLDOMDocument_appendChild(xmldoc
, (IXMLDOMNode
*)dxdiag_element
, NULL
);
291 for (i
= 0; i
< ARRAY_SIZE(output_table
); i
++)
293 IXMLDOMElement
*info_element
= xml_create_element(xmldoc
, output_table
[i
].tag_name
);
294 const struct xml_information_field
*fields
= output_table
[i
].fields
;
300 hr
= IXMLDOMElement_appendChild(dxdiag_element
, (IXMLDOMNode
*)info_element
, NULL
);
303 IXMLDOMElement_Release(info_element
);
307 for (j
= 0; fields
[j
].tag_name
; j
++)
309 IXMLDOMElement
*field_element
= xml_create_element(xmldoc
, fields
[j
].tag_name
);
313 IXMLDOMElement_Release(info_element
);
317 hr
= xml_put_element_text(field_element
, fields
[j
].value
);
320 IXMLDOMElement_Release(field_element
);
321 IXMLDOMElement_Release(info_element
);
325 hr
= IXMLDOMElement_appendChild(info_element
, (IXMLDOMNode
*)field_element
, NULL
);
328 IXMLDOMElement_Release(field_element
);
329 IXMLDOMElement_Release(info_element
);
333 IXMLDOMElement_Release(field_element
);
336 IXMLDOMElement_Release(info_element
);
339 hr
= save_xml_document(xmldoc
, filename
);
343 IXMLDOMElement_Release(dxdiag_element
);
344 IXMLDOMDocument_Release(xmldoc
);
347 if (dxdiag_element
) IXMLDOMElement_Release(dxdiag_element
);
348 if (xmldoc
) IXMLDOMDocument_Release(xmldoc
);
352 static struct output_backend
354 const WCHAR filename_ext
[5];
355 BOOL (*output_handler
)(struct dxdiag_information
*, const WCHAR
*filename
);
356 } output_backends
[] =
360 L
".txt", output_text_information
,
364 L
".xml", output_xml_information
,
368 const WCHAR
*get_output_extension(enum output_type type
)
370 assert(type
> OUTPUT_NONE
&& type
<= ARRAY_SIZE(output_backends
));
372 return output_backends
[type
- 1].filename_ext
;
375 BOOL
output_dxdiag_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
, enum output_type type
)
377 assert(type
> OUTPUT_NONE
&& type
<= ARRAY_SIZE(output_backends
));
379 return output_backends
[type
- 1].output_handler(dxdiag_info
, filename
);