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
;
76 assert(total_len
<= sizeof(output_buffer
));
78 memset(ptr
, '-', len
);
81 memcpy(ptr
, crlf
, sizeof(crlf
));
84 memcpy(ptr
, caption
, len
);
87 memcpy(ptr
, crlf
, sizeof(crlf
));
90 memset(ptr
, '-', len
);
93 memcpy(ptr
, crlf
, sizeof(crlf
));
95 return WriteFile(hFile
, output_buffer
, total_len
, NULL
, NULL
);
98 static BOOL
output_text_field(HANDLE hFile
, const char *field_name
, DWORD field_width
, const WCHAR
*value
)
100 DWORD value_lenW
= strlenW(value
);
101 DWORD value_lenA
= WideCharToMultiByte(CP_ACP
, 0, value
, value_lenW
, NULL
, 0, NULL
, NULL
);
102 DWORD total_len
= field_width
+ sizeof(": ") - 1 + value_lenA
+ sizeof(crlf
);
103 char sprintf_fmt
[1 + 10 + 3 + 1];
104 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
);
113 memcpy(ptr
, crlf
, sizeof(crlf
));
116 return WriteFile(hFile
, output_buffer
, total_len
, NULL
, NULL
);
119 static BOOL
output_crlf(HANDLE hFile
)
121 return WriteFile(hFile
, crlf
, sizeof(crlf
), NULL
, NULL
);
124 static inline void fill_system_text_output_table(struct dxdiag_information
*dxdiag_info
, struct text_information_field
*fields
)
126 fields
[0].field_name
= "Time of this report";
127 fields
[0].value
= dxdiag_info
->system_info
.szTimeEnglish
;
128 fields
[1].field_name
= "Machine name";
129 fields
[1].value
= dxdiag_info
->system_info
.szMachineNameEnglish
;
130 fields
[2].field_name
= "Operating System";
131 fields
[2].value
= dxdiag_info
->system_info
.szOSExLongEnglish
;
132 fields
[3].field_name
= "Language";
133 fields
[3].value
= dxdiag_info
->system_info
.szLanguagesEnglish
;
134 fields
[4].field_name
= "System Manufacturer";
135 fields
[4].value
= dxdiag_info
->system_info
.szSystemManufacturerEnglish
;
136 fields
[5].field_name
= "System Model";
137 fields
[5].value
= dxdiag_info
->system_info
.szSystemModelEnglish
;
138 fields
[6].field_name
= "BIOS";
139 fields
[6].value
= dxdiag_info
->system_info
.szBIOSEnglish
;
140 fields
[7].field_name
= "Processor";
141 fields
[7].value
= dxdiag_info
->system_info
.szProcessorEnglish
;
142 fields
[8].field_name
= "Memory";
143 fields
[8].value
= dxdiag_info
->system_info
.szPhysicalMemoryEnglish
;
144 fields
[9].field_name
= "Page File";
145 fields
[9].value
= dxdiag_info
->system_info
.szPageFileEnglish
;
146 fields
[10].field_name
= "Windows Dir";
147 fields
[10].value
= dxdiag_info
->system_info
.szWindowsDir
;
148 fields
[11].field_name
= "DirectX Version";
149 fields
[11].value
= dxdiag_info
->system_info
.szDirectXVersionLongEnglish
;
150 fields
[12].field_name
= "DX Setup Parameters";
151 fields
[12].value
= dxdiag_info
->system_info
.szSetupParamEnglish
;
152 fields
[13].field_name
= "DxDiag Version";
153 fields
[13].value
= dxdiag_info
->system_info
.szDxDiagVersion
;
156 static BOOL
output_text_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
)
158 struct information_block
161 const size_t field_width
;
162 struct text_information_field fields
[50];
165 {"System Information", 19},
171 fill_system_text_output_table(dxdiag_info
, output_table
[0].fields
);
173 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
174 NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
175 if (hFile
== INVALID_HANDLE_VALUE
)
177 WINE_ERR("File creation failed, last error %u\n", GetLastError());
181 for (i
= 0; i
< sizeof(output_table
)/sizeof(output_table
[0]); i
++)
183 const struct text_information_field
*fields
= output_table
[i
].fields
;
186 output_text_header(hFile
, output_table
[i
].caption
);
187 for (j
= 0; fields
[j
].field_name
; j
++)
188 output_text_field(hFile
, fields
[j
].field_name
, output_table
[i
].field_width
, fields
[j
].value
);
196 static IXMLDOMElement
*xml_create_element(IXMLDOMDocument
*xmldoc
, const WCHAR
*name
)
198 BSTR bstr
= SysAllocString(name
);
205 hr
= IXMLDOMDocument_createElement(xmldoc
, bstr
, &ret
);
208 return SUCCEEDED(hr
) ? ret
: NULL
;
211 static HRESULT
xml_put_element_text(IXMLDOMElement
*element
, const WCHAR
*text
)
213 BSTR bstr
= SysAllocString(text
);
217 return E_OUTOFMEMORY
;
219 hr
= IXMLDOMElement_put_text(element
, bstr
);
225 static HRESULT
save_xml_document(IXMLDOMDocument
*xmldoc
, const WCHAR
*filename
)
227 BSTR bstr
= SysAllocString(filename
);
232 return E_OUTOFMEMORY
;
234 V_VT(&destVar
) = VT_BSTR
;
235 V_BSTR(&destVar
) = bstr
;
237 hr
= IXMLDOMDocument_save(xmldoc
, destVar
);
238 VariantClear(&destVar
);
243 static inline void fill_system_xml_output_table(struct dxdiag_information
*dxdiag_info
, struct xml_information_field
*fields
)
245 static const WCHAR zeroW
[] = {'0',0};
246 static const WCHAR oneW
[] = {'1',0};
248 fields
[0].tag_name
= Time
;
249 fields
[0].value
= dxdiag_info
->system_info
.szTimeEnglish
;
250 fields
[1].tag_name
= MachineName
;
251 fields
[1].value
= dxdiag_info
->system_info
.szMachineNameEnglish
;
252 fields
[2].tag_name
= OperatingSystem
;
253 fields
[2].value
= dxdiag_info
->system_info
.szOSExLongEnglish
;
254 fields
[3].tag_name
= Language
;
255 fields
[3].value
= dxdiag_info
->system_info
.szLanguagesEnglish
;
256 fields
[4].tag_name
= SystemManufacturer
;
257 fields
[4].value
= dxdiag_info
->system_info
.szSystemManufacturerEnglish
;
258 fields
[5].tag_name
= SystemModel
;
259 fields
[5].value
= dxdiag_info
->system_info
.szSystemModelEnglish
;
260 fields
[6].tag_name
= BIOS
;
261 fields
[6].value
= dxdiag_info
->system_info
.szBIOSEnglish
;
262 fields
[7].tag_name
= Processor
;
263 fields
[7].value
= dxdiag_info
->system_info
.szProcessorEnglish
;
264 fields
[8].tag_name
= Memory
;
265 fields
[8].value
= dxdiag_info
->system_info
.szPhysicalMemoryEnglish
;
266 fields
[9].tag_name
= PageFile
;
267 fields
[9].value
= dxdiag_info
->system_info
.szPageFileEnglish
;
268 fields
[10].tag_name
= WindowsDir
;
269 fields
[10].value
= dxdiag_info
->system_info
.szWindowsDir
;
270 fields
[11].tag_name
= DirectXVersion
;
271 fields
[11].value
= dxdiag_info
->system_info
.szDirectXVersionLongEnglish
;
272 fields
[12].tag_name
= DXSetupParameters
;
273 fields
[12].value
= dxdiag_info
->system_info
.szSetupParamEnglish
;
274 fields
[13].tag_name
= DxDiagVersion
;
275 fields
[13].value
= dxdiag_info
->system_info
.szDxDiagVersion
;
276 fields
[14].tag_name
= DxDiagUnicode
;
277 fields
[14].value
= oneW
;
278 fields
[15].tag_name
= DxDiag64Bit
;
279 fields
[15].value
= dxdiag_info
->system_info
.win64
? oneW
: zeroW
;
282 static BOOL
output_xml_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
)
284 struct information_block
286 const WCHAR
*tag_name
;
287 struct xml_information_field fields
[50];
293 IXMLDOMDocument
*xmldoc
= NULL
;
294 IXMLDOMElement
*dxdiag_element
= NULL
;
298 fill_system_xml_output_table(dxdiag_info
, output_table
[0].fields
);
300 hr
= CoCreateInstance(&CLSID_DOMDocument
, NULL
, CLSCTX_INPROC_SERVER
,
301 &IID_IXMLDOMDocument
, (void **)&xmldoc
);
304 WINE_ERR("IXMLDOMDocument instance creation failed with 0x%08x\n", hr
);
308 if (!(dxdiag_element
= xml_create_element(xmldoc
, DxDiag
)))
311 hr
= IXMLDOMDocument_appendChild(xmldoc
, (IXMLDOMNode
*)dxdiag_element
, NULL
);
315 for (i
= 0; i
< sizeof(output_table
)/sizeof(output_table
[0]); i
++)
317 IXMLDOMElement
*info_element
= xml_create_element(xmldoc
, output_table
[i
].tag_name
);
318 const struct xml_information_field
*fields
= output_table
[i
].fields
;
324 hr
= IXMLDOMElement_appendChild(dxdiag_element
, (IXMLDOMNode
*)info_element
, NULL
);
327 IXMLDOMElement_Release(info_element
);
331 for (j
= 0; fields
[j
].tag_name
; j
++)
333 IXMLDOMElement
*field_element
= xml_create_element(xmldoc
, fields
[j
].tag_name
);
337 IXMLDOMElement_Release(info_element
);
341 hr
= xml_put_element_text(field_element
, fields
[j
].value
);
344 IXMLDOMElement_Release(field_element
);
345 IXMLDOMElement_Release(info_element
);
349 hr
= IXMLDOMElement_appendChild(info_element
, (IXMLDOMNode
*)field_element
, NULL
);
352 IXMLDOMElement_Release(field_element
);
353 IXMLDOMElement_Release(info_element
);
357 IXMLDOMElement_Release(field_element
);
360 IXMLDOMElement_Release(info_element
);
363 hr
= save_xml_document(xmldoc
, filename
);
367 IXMLDOMElement_Release(dxdiag_element
);
368 IXMLDOMDocument_Release(xmldoc
);
371 if (dxdiag_element
) IXMLDOMElement_Release(dxdiag_element
);
372 if (xmldoc
) IXMLDOMDocument_Release(xmldoc
);
376 static struct output_backend
378 const WCHAR filename_ext
[5];
379 BOOL (*output_handler
)(struct dxdiag_information
*, const WCHAR
*filename
);
380 } output_backends
[] =
385 output_text_information
,
390 output_xml_information
,
394 const WCHAR
*get_output_extension(enum output_type type
)
396 assert(type
> OUTPUT_NONE
&& type
<= sizeof(output_backends
)/sizeof(output_backends
[0]));
398 return output_backends
[type
- 1].filename_ext
;
401 BOOL
output_dxdiag_information(struct dxdiag_information
*dxdiag_info
, const WCHAR
*filename
, enum output_type type
)
403 assert(type
> OUTPUT_NONE
&& type
<= sizeof(output_backends
)/sizeof(output_backends
[0]));
405 return output_backends
[type
- 1].output_handler(dxdiag_info
, filename
);