main.c 5.8 KB

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