main.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * DxDiag Implementation
  3. *
  4. * Copyright 2009 Austin English
  5. *
  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.
  10. *
  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.
  15. *
  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
  19. */
  20. #define WIN32_LEAN_AND_MEAN
  21. #include <windows.h>
  22. #include <dxdiag.h>
  23. #include <commctrl.h>
  24. #include "wine/debug.h"
  25. #include "dxdiag_private.h"
  26. WINE_DEFAULT_DEBUG_CHANNEL(dxdiag);
  27. HINSTANCE hInstance;
  28. struct command_line_info
  29. {
  30. WCHAR outfile[MAX_PATH];
  31. enum output_type output_type;
  32. BOOL whql_check;
  33. };
  34. static void usage(void)
  35. {
  36. WCHAR title[MAX_STRING_LEN];
  37. WCHAR usage[MAX_STRING_LEN];
  38. LoadStringW(hInstance, STRING_DXDIAG_TOOL, title, ARRAY_SIZE(title));
  39. LoadStringW(hInstance, STRING_USAGE, usage, ARRAY_SIZE(usage));
  40. MessageBoxW(NULL, usage, title, MB_OK | MB_ICONWARNING);
  41. ExitProcess(0);
  42. }
  43. static BOOL process_file_name(const WCHAR *cmdline, enum output_type output_type, WCHAR *filename, size_t filename_len)
  44. {
  45. const WCHAR *endptr;
  46. size_t len;
  47. /* Skip any intervening spaces. */
  48. while (*cmdline == ' ')
  49. cmdline++;
  50. /* Ignore filename quoting, if any. */
  51. if (*cmdline == '"' && (endptr = wcsrchr(cmdline, '"')))
  52. {
  53. /* Reject a string with only one quote. */
  54. if (cmdline == endptr)
  55. return FALSE;
  56. cmdline++;
  57. }
  58. else
  59. endptr = cmdline + lstrlenW(cmdline);
  60. len = endptr - cmdline;
  61. if (len == 0 || len >= filename_len)
  62. return FALSE;
  63. memcpy(filename, cmdline, len * sizeof(WCHAR));
  64. filename[len] = '\0';
  65. /* Append an extension appropriate for the output type if the filename does not have one. */
  66. if (!wcsrchr(filename, '.'))
  67. {
  68. const WCHAR *filename_ext = get_output_extension(output_type);
  69. if (len + lstrlenW(filename_ext) >= filename_len)
  70. return FALSE;
  71. lstrcatW(filename, filename_ext);
  72. }
  73. return TRUE;
  74. }
  75. /*
  76. Process options [/WHQL:ON|OFF][/X outfile|/T outfile]
  77. Returns TRUE if options were present, FALSE otherwise
  78. Only one of /X and /T is allowed, /WHQL must come before /X and /T,
  79. and the rest of the command line after /X or /T is interpreted as a
  80. filename. If a non-option portion of the command line is encountered,
  81. dxdiag assumes that the string is a filename for the /T option.
  82. Native does not interpret quotes, but quotes are parsed here because of how
  83. Wine handles the command line.
  84. */
  85. static BOOL process_command_line(const WCHAR *cmdline, struct command_line_info *info)
  86. {
  87. info->whql_check = FALSE;
  88. info->output_type = OUTPUT_NONE;
  89. while (*cmdline)
  90. {
  91. /* Skip whitespace before arg */
  92. while (*cmdline == ' ')
  93. cmdline++;
  94. /* If no option is specified, treat the command line as a filename. */
  95. if (*cmdline != '-' && *cmdline != '/')
  96. {
  97. info->output_type = OUTPUT_TEXT;
  98. return process_file_name(cmdline, OUTPUT_TEXT, info->outfile,
  99. ARRAY_SIZE(info->outfile));
  100. }
  101. cmdline++;
  102. switch (*cmdline)
  103. {
  104. case 'T':
  105. case 't':
  106. info->output_type = OUTPUT_TEXT;
  107. return process_file_name(cmdline + 1, OUTPUT_TEXT, info->outfile,
  108. ARRAY_SIZE(info->outfile));
  109. case 'X':
  110. case 'x':
  111. info->output_type = OUTPUT_XML;
  112. return process_file_name(cmdline + 1, OUTPUT_XML, info->outfile,
  113. ARRAY_SIZE(info->outfile));
  114. case 'W':
  115. case 'w':
  116. if (wcsnicmp(cmdline, L"whql:", 5))
  117. return FALSE;
  118. cmdline += 5;
  119. if (!wcsnicmp(cmdline, L"off", 3))
  120. {
  121. info->whql_check = FALSE;
  122. cmdline += 2;
  123. }
  124. else if (!wcsnicmp(cmdline, L"on", 2))
  125. {
  126. info->whql_check = TRUE;
  127. cmdline++;
  128. }
  129. else
  130. return FALSE;
  131. break;
  132. case 'd':
  133. case 'D':
  134. if (wcsnicmp(cmdline, L"dontskip", 8))
  135. return FALSE;
  136. cmdline += 8;
  137. break;
  138. default:
  139. return FALSE;
  140. }
  141. cmdline++;
  142. }
  143. return TRUE;
  144. }
  145. int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR cmdline, int cmdshow)
  146. {
  147. struct command_line_info info;
  148. struct dxdiag_information *dxdiag_info;
  149. InitCommonControls();
  150. hInstance = hInst;
  151. if (!process_command_line(cmdline, &info))
  152. usage();
  153. WINE_TRACE("WHQL check: %s\n", info.whql_check ? "TRUE" : "FALSE");
  154. WINE_TRACE("Output type: %d\n", info.output_type);
  155. if (info.output_type != OUTPUT_NONE)
  156. WINE_TRACE("Output filename: %s\n", debugstr_output_type(info.output_type));
  157. CoInitialize(NULL);
  158. dxdiag_info = collect_dxdiag_information(info.whql_check);
  159. if (!dxdiag_info)
  160. {
  161. WINE_ERR("DxDiag information collection failed\n");
  162. CoUninitialize();
  163. return 1;
  164. }
  165. if (info.output_type != OUTPUT_NONE)
  166. output_dxdiag_information(dxdiag_info, info.outfile, info.output_type);
  167. else
  168. WINE_FIXME("Information dialog is not implemented\n");
  169. free_dxdiag_information(dxdiag_info);
  170. CoUninitialize();
  171. return 0;
  172. }