| /* | |
| * DxDiag Implementation | |
| * | |
| * Copyright 2009 Austin English | |
| * | |
| * 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 WIN32_LEAN_AND_MEAN | |
| #include <windows.h> | |
| #include <dxdiag.h> | |
| #include "wine/debug.h" | |
| #include "wine/unicode.h" | |
| #include "dxdiag_private.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(dxdiag); | |
| HINSTANCE hInstance; | |
| struct command_line_info | |
| { | |
| WCHAR outfile[MAX_PATH]; | |
| enum output_type output_type; | |
| BOOL whql_check; | |
| }; | |
| static void usage(void) | |
| { | |
| WCHAR title[MAX_STRING_LEN]; | |
| WCHAR usage[MAX_STRING_LEN]; | |
| LoadStringW(hInstance, STRING_DXDIAG_TOOL, title, sizeof(title)/sizeof(WCHAR)); | |
| LoadStringW(hInstance, STRING_USAGE, usage, sizeof(usage)/sizeof(WCHAR)); | |
| MessageBoxW(NULL, usage, title, MB_OK | MB_ICONWARNING); | |
| ExitProcess(0); | |
| } | |
| static BOOL process_file_name(const WCHAR *cmdline, enum output_type output_type, WCHAR *filename, size_t filename_len) | |
| { | |
| const WCHAR *endptr; | |
| size_t len; | |
| /* Skip any intervening spaces. */ | |
| while (*cmdline == ' ') | |
| cmdline++; | |
| /* Ignore filename quoting, if any. */ | |
| if (*cmdline == '"' && (endptr = strrchrW(cmdline, '"'))) | |
| { | |
| /* Reject a string with only one quote. */ | |
| if (cmdline == endptr) | |
| return FALSE; | |
| cmdline++; | |
| } | |
| else | |
| endptr = cmdline + strlenW(cmdline); | |
| len = endptr - cmdline; | |
| if (len == 0 || len >= filename_len) | |
| return FALSE; | |
| memcpy(filename, cmdline, len * sizeof(WCHAR)); | |
| filename[len] = '\0'; | |
| /* Append an extension appropriate for the output type if the filename does not have one. */ | |
| if (!strrchrW(filename, '.')) | |
| { | |
| const WCHAR *filename_ext = get_output_extension(output_type); | |
| if (len + strlenW(filename_ext) >= filename_len) | |
| return FALSE; | |
| strcatW(filename, filename_ext); | |
| } | |
| return TRUE; | |
| } | |
| /* | |
| Process options [/WHQL:ON|OFF][/X outfile|/T outfile] | |
| Returns TRUE if options were present, FALSE otherwise | |
| Only one of /X and /T is allowed, /WHQL must come before /X and /T, | |
| and the rest of the command line after /X or /T is interpreted as a | |
| filename. If a non-option portion of the command line is encountered, | |
| dxdiag assumes that the string is a filename for the /T option. | |
| Native does not interpret quotes, but quotes are parsed here because of how | |
| Wine handles the command line. | |
| */ | |
| static BOOL process_command_line(const WCHAR *cmdline, struct command_line_info *info) | |
| { | |
| static const WCHAR whql_colonW[] = {'w','h','q','l',':',0}; | |
| static const WCHAR offW[] = {'o','f','f',0}; | |
| static const WCHAR onW[] = {'o','n',0}; | |
| info->whql_check = FALSE; | |
| info->output_type = OUTPUT_NONE; | |
| while (*cmdline) | |
| { | |
| /* Skip whitespace before arg */ | |
| while (*cmdline == ' ') | |
| cmdline++; | |
| /* If no option is specified, treat the command line as a filename. */ | |
| if (*cmdline != '-' && *cmdline != '/') | |
| { | |
| info->output_type = OUTPUT_TEXT; | |
| return process_file_name(cmdline, OUTPUT_TEXT, info->outfile, | |
| sizeof(info->outfile)/sizeof(WCHAR)); | |
| } | |
| cmdline++; | |
| switch (*cmdline) | |
| { | |
| case 'T': | |
| case 't': | |
| info->output_type = OUTPUT_TEXT; | |
| return process_file_name(cmdline + 1, OUTPUT_TEXT, info->outfile, | |
| sizeof(info->outfile)/sizeof(WCHAR)); | |
| case 'X': | |
| case 'x': | |
| info->output_type = OUTPUT_XML; | |
| return process_file_name(cmdline + 1, OUTPUT_XML, info->outfile, | |
| sizeof(info->outfile)/sizeof(WCHAR)); | |
| case 'W': | |
| case 'w': | |
| if (strncmpiW(cmdline, whql_colonW, 5)) | |
| return FALSE; | |
| cmdline += 5; | |
| if (!strncmpiW(cmdline, offW, 3)) | |
| { | |
| info->whql_check = FALSE; | |
| cmdline += 2; | |
| } | |
| else if (!strncmpiW(cmdline, onW, 2)) | |
| { | |
| info->whql_check = TRUE; | |
| cmdline++; | |
| } | |
| else | |
| return FALSE; | |
| break; | |
| default: | |
| return FALSE; | |
| } | |
| cmdline++; | |
| } | |
| return TRUE; | |
| } | |
| int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR cmdline, int cmdshow) | |
| { | |
| struct command_line_info info; | |
| struct dxdiag_information *dxdiag_info; | |
| hInstance = hInst; | |
| if (!process_command_line(cmdline, &info)) | |
| usage(); | |
| WINE_TRACE("WHQL check: %s\n", info.whql_check ? "TRUE" : "FALSE"); | |
| WINE_TRACE("Output type: %d\n", info.output_type); | |
| if (info.output_type != OUTPUT_NONE) | |
| WINE_TRACE("Output filename: %s\n", debugstr_output_type(info.output_type)); | |
| CoInitialize(NULL); | |
| dxdiag_info = collect_dxdiag_information(info.whql_check); | |
| if (!dxdiag_info) | |
| { | |
| WINE_ERR("DxDiag information collection failed\n"); | |
| CoUninitialize(); | |
| return 1; | |
| } | |
| if (info.output_type != OUTPUT_NONE) | |
| output_dxdiag_information(dxdiag_info, info.outfile, info.output_type); | |
| else | |
| WINE_FIXME("Information dialog is not implemented\n"); | |
| free_dxdiag_information(dxdiag_info); | |
| CoUninitialize(); | |
| return 0; | |
| } |