123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- /*
- * DxDiag file information output
- *
- * Copyright 2011 Andrew Nguyen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
- #define COBJMACROS
- #include <initguid.h>
- #include <windows.h>
- #include <msxml2.h>
- #include <assert.h>
- #include <stdio.h>
- #include "wine/debug.h"
- #include "dxdiag_private.h"
- WINE_DEFAULT_DEBUG_CHANNEL(dxdiag);
- static char output_buffer[1024];
- static const char crlf[2] = "\r\n";
- struct text_information_field
- {
- const char *field_name;
- const WCHAR *value;
- };
- struct xml_information_field
- {
- const WCHAR *tag_name;
- const WCHAR *value;
- };
- static BOOL output_text_header(HANDLE hFile, const char *caption)
- {
- DWORD len = strlen(caption);
- DWORD total_len = 3 * (len + sizeof(crlf));
- char *ptr = output_buffer;
- DWORD bytes_written;
- assert(total_len <= sizeof(output_buffer));
- memset(ptr, '-', len);
- ptr += len;
- memcpy(ptr, crlf, sizeof(crlf));
- ptr += sizeof(crlf);
- memcpy(ptr, caption, len);
- ptr += len;
- memcpy(ptr, crlf, sizeof(crlf));
- ptr += sizeof(crlf);
- memset(ptr, '-', len);
- ptr += len;
- memcpy(ptr, crlf, sizeof(crlf));
- return WriteFile(hFile, output_buffer, total_len, &bytes_written, NULL);
- }
- static BOOL output_text_field(HANDLE hFile, const char *field_name, DWORD field_width, const WCHAR *value)
- {
- DWORD value_lenW = lstrlenW(value);
- DWORD value_lenA = WideCharToMultiByte(CP_ACP, 0, value, value_lenW, NULL, 0, NULL, NULL);
- DWORD total_len = field_width + sizeof(": ") - 1 + value_lenA + sizeof(crlf);
- char sprintf_fmt[1 + 10 + 3 + 1];
- char *ptr = output_buffer;
- DWORD bytes_written;
- assert(total_len <= sizeof(output_buffer));
- sprintf(sprintf_fmt, "%%%us: ", field_width);
- ptr += sprintf(ptr, sprintf_fmt, field_name);
- ptr += WideCharToMultiByte(CP_ACP, 0, value, value_lenW, ptr, value_lenA, NULL, NULL);
- memcpy(ptr, crlf, sizeof(crlf));
- return WriteFile(hFile, output_buffer, total_len, &bytes_written, NULL);
- }
- static BOOL output_crlf(HANDLE hFile)
- {
- DWORD bytes_written;
- return WriteFile(hFile, crlf, sizeof(crlf), &bytes_written, NULL);
- }
- static inline void fill_system_text_output_table(struct dxdiag_information *dxdiag_info, struct text_information_field *fields)
- {
- fields[0].field_name = "Time of this report";
- fields[0].value = dxdiag_info->system_info.szTimeEnglish;
- fields[1].field_name = "Machine name";
- fields[1].value = dxdiag_info->system_info.szMachineNameEnglish;
- fields[2].field_name = "Operating System";
- fields[2].value = dxdiag_info->system_info.szOSExLongEnglish;
- fields[3].field_name = "Language";
- fields[3].value = dxdiag_info->system_info.szLanguagesEnglish;
- fields[4].field_name = "System Manufacturer";
- fields[4].value = dxdiag_info->system_info.szSystemManufacturerEnglish;
- fields[5].field_name = "System Model";
- fields[5].value = dxdiag_info->system_info.szSystemModelEnglish;
- fields[6].field_name = "BIOS";
- fields[6].value = dxdiag_info->system_info.szBIOSEnglish;
- fields[7].field_name = "Processor";
- fields[7].value = dxdiag_info->system_info.szProcessorEnglish;
- fields[8].field_name = "Memory";
- fields[8].value = dxdiag_info->system_info.szPhysicalMemoryEnglish;
- fields[9].field_name = "Page File";
- fields[9].value = dxdiag_info->system_info.szPageFileEnglish;
- fields[10].field_name = "Windows Dir";
- fields[10].value = dxdiag_info->system_info.szWindowsDir;
- fields[11].field_name = "DirectX Version";
- fields[11].value = dxdiag_info->system_info.szDirectXVersionLongEnglish;
- fields[12].field_name = "DX Setup Parameters";
- fields[12].value = dxdiag_info->system_info.szSetupParamEnglish;
- fields[13].field_name = "DxDiag Version";
- fields[13].value = dxdiag_info->system_info.szDxDiagVersion;
- }
- static BOOL output_text_information(struct dxdiag_information *dxdiag_info, const WCHAR *filename)
- {
- struct information_block
- {
- const char *caption;
- const size_t field_width;
- struct text_information_field fields[50];
- } output_table[] =
- {
- {"System Information", 19},
- };
- HANDLE hFile;
- size_t i;
- fill_system_text_output_table(dxdiag_info, output_table[0].fields);
- hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE)
- {
- WINE_ERR("File creation failed, last error %u\n", GetLastError());
- return FALSE;
- }
- for (i = 0; i < ARRAY_SIZE(output_table); i++)
- {
- const struct text_information_field *fields = output_table[i].fields;
- unsigned int j;
- output_text_header(hFile, output_table[i].caption);
- for (j = 0; fields[j].field_name; j++)
- output_text_field(hFile, fields[j].field_name, output_table[i].field_width, fields[j].value);
- output_crlf(hFile);
- }
- CloseHandle(hFile);
- return FALSE;
- }
- static IXMLDOMElement *xml_create_element(IXMLDOMDocument *xmldoc, const WCHAR *name)
- {
- BSTR bstr = SysAllocString(name);
- IXMLDOMElement *ret;
- HRESULT hr;
- if (!bstr)
- return NULL;
- hr = IXMLDOMDocument_createElement(xmldoc, bstr, &ret);
- SysFreeString(bstr);
- return SUCCEEDED(hr) ? ret : NULL;
- }
- static HRESULT xml_put_element_text(IXMLDOMElement *element, const WCHAR *text)
- {
- BSTR bstr = SysAllocString(text);
- HRESULT hr;
- if (!bstr)
- return E_OUTOFMEMORY;
- hr = IXMLDOMElement_put_text(element, bstr);
- SysFreeString(bstr);
- return hr;
- }
- static HRESULT save_xml_document(IXMLDOMDocument *xmldoc, const WCHAR *filename)
- {
- BSTR bstr = SysAllocString(filename);
- VARIANT destVar;
- HRESULT hr;
- if (!bstr)
- return E_OUTOFMEMORY;
- V_VT(&destVar) = VT_BSTR;
- V_BSTR(&destVar) = bstr;
- hr = IXMLDOMDocument_save(xmldoc, destVar);
- VariantClear(&destVar);
- return hr;
- }
- static inline void fill_system_xml_output_table(struct dxdiag_information *dxdiag_info, struct xml_information_field *fields)
- {
- fields[0].tag_name = L"Time";
- fields[0].value = dxdiag_info->system_info.szTimeEnglish;
- fields[1].tag_name = L"MachineName";
- fields[1].value = dxdiag_info->system_info.szMachineNameEnglish;
- fields[2].tag_name = L"OperatingSystem";
- fields[2].value = dxdiag_info->system_info.szOSExLongEnglish;
- fields[3].tag_name = L"Language";
- fields[3].value = dxdiag_info->system_info.szLanguagesEnglish;
- fields[4].tag_name = L"SystemManufacturer";
- fields[4].value = dxdiag_info->system_info.szSystemManufacturerEnglish;
- fields[5].tag_name = L"SystemModel";
- fields[5].value = dxdiag_info->system_info.szSystemModelEnglish;
- fields[6].tag_name = L"BIOS";
- fields[6].value = dxdiag_info->system_info.szBIOSEnglish;
- fields[7].tag_name = L"Processor";
- fields[7].value = dxdiag_info->system_info.szProcessorEnglish;
- fields[8].tag_name = L"Memory";
- fields[8].value = dxdiag_info->system_info.szPhysicalMemoryEnglish;
- fields[9].tag_name = L"PageFile";
- fields[9].value = dxdiag_info->system_info.szPageFileEnglish;
- fields[10].tag_name = L"WindowsDir";
- fields[10].value = dxdiag_info->system_info.szWindowsDir;
- fields[11].tag_name = L"DirectXVersion";
- fields[11].value = dxdiag_info->system_info.szDirectXVersionLongEnglish;
- fields[12].tag_name = L"DXSetupParameters";
- fields[12].value = dxdiag_info->system_info.szSetupParamEnglish;
- fields[13].tag_name = L"DxDiagVersion";
- fields[13].value = dxdiag_info->system_info.szDxDiagVersion;
- fields[14].tag_name = L"DxDiagUnicode";
- fields[14].value = L"1";
- fields[15].tag_name = L"DxDiag64Bit";
- fields[15].value = dxdiag_info->system_info.win64 ? L"1" : L"0";
- }
- static BOOL output_xml_information(struct dxdiag_information *dxdiag_info, const WCHAR *filename)
- {
- struct information_block
- {
- const WCHAR *tag_name;
- struct xml_information_field fields[50];
- } output_table[] =
- {
- {L"SystemInformation"},
- };
- IXMLDOMDocument *xmldoc = NULL;
- IXMLDOMElement *dxdiag_element = NULL;
- HRESULT hr;
- size_t i;
- fill_system_xml_output_table(dxdiag_info, output_table[0].fields);
- hr = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
- &IID_IXMLDOMDocument, (void **)&xmldoc);
- if (FAILED(hr))
- {
- WINE_ERR("IXMLDOMDocument instance creation failed with 0x%08x\n", hr);
- goto error;
- }
- if (!(dxdiag_element = xml_create_element(xmldoc, L"DxDiag")))
- goto error;
- hr = IXMLDOMDocument_appendChild(xmldoc, (IXMLDOMNode *)dxdiag_element, NULL);
- if (FAILED(hr))
- goto error;
- for (i = 0; i < ARRAY_SIZE(output_table); i++)
- {
- IXMLDOMElement *info_element = xml_create_element(xmldoc, output_table[i].tag_name);
- const struct xml_information_field *fields = output_table[i].fields;
- unsigned int j = 0;
- if (!info_element)
- goto error;
- hr = IXMLDOMElement_appendChild(dxdiag_element, (IXMLDOMNode *)info_element, NULL);
- if (FAILED(hr))
- {
- IXMLDOMElement_Release(info_element);
- goto error;
- }
- for (j = 0; fields[j].tag_name; j++)
- {
- IXMLDOMElement *field_element = xml_create_element(xmldoc, fields[j].tag_name);
- if (!field_element)
- {
- IXMLDOMElement_Release(info_element);
- goto error;
- }
- hr = xml_put_element_text(field_element, fields[j].value);
- if (FAILED(hr))
- {
- IXMLDOMElement_Release(field_element);
- IXMLDOMElement_Release(info_element);
- goto error;
- }
- hr = IXMLDOMElement_appendChild(info_element, (IXMLDOMNode *)field_element, NULL);
- if (FAILED(hr))
- {
- IXMLDOMElement_Release(field_element);
- IXMLDOMElement_Release(info_element);
- goto error;
- }
- IXMLDOMElement_Release(field_element);
- }
- IXMLDOMElement_Release(info_element);
- }
- hr = save_xml_document(xmldoc, filename);
- if (FAILED(hr))
- goto error;
- IXMLDOMElement_Release(dxdiag_element);
- IXMLDOMDocument_Release(xmldoc);
- return TRUE;
- error:
- if (dxdiag_element) IXMLDOMElement_Release(dxdiag_element);
- if (xmldoc) IXMLDOMDocument_Release(xmldoc);
- return FALSE;
- }
- static struct output_backend
- {
- const WCHAR filename_ext[5];
- BOOL (*output_handler)(struct dxdiag_information *, const WCHAR *filename);
- } output_backends[] =
- {
- /* OUTPUT_TEXT */
- {
- L".txt", output_text_information,
- },
- /* OUTPUT_XML */
- {
- L".xml", output_xml_information,
- },
- };
- const WCHAR *get_output_extension(enum output_type type)
- {
- assert(type > OUTPUT_NONE && type <= ARRAY_SIZE(output_backends));
- return output_backends[type - 1].filename_ext;
- }
- BOOL output_dxdiag_information(struct dxdiag_information *dxdiag_info, const WCHAR *filename, enum output_type type)
- {
- assert(type > OUTPUT_NONE && type <= ARRAY_SIZE(output_backends));
- return output_backends[type - 1].output_handler(dxdiag_info, filename);
- }
|