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