[ROSAPPS] Add all sysutils to build which did build at rbuild times. Fix several...
[reactos.git] / rosapps / applications / sysutils / rosddt / rosddt.c
1 #include <stdio.h>
2 #include <windows.h>
3 #include <setupapi.h>
4 #include "http.h"
5
6 #define ST_NEUTRAL 0
7 #define ST_ROS_CRASH 1
8 #define ST_DEV_NOTWORK 2
9 #define ST_DEV_OK 3
10 #define ST_ERROR 4
11 #define ST_LAST_STATUS ST_ERROR
12
13 static int is_show_hw;
14 static int is_check_hw;
15 static wchar_t gl_ini_file[MAX_PATH];
16 static wchar_t *gl_report;
17
18 static int hw_check_ini(wchar_t *name)
19 {
20 wchar_t buff[MAX_PATH];
21
22 if (GetPrivateProfileString(L"HW", name, NULL, buff, MAX_PATH, gl_ini_file) == 0) {
23 return ST_NEUTRAL;
24 }
25 if (_wcsicmp(buff, L"ok") == 0) return ST_DEV_OK;
26 if (_wcsicmp(buff, L"notwork") == 0) return ST_DEV_NOTWORK;
27 if (_wcsicmp(buff, L"crash") == 0) return ST_ROS_CRASH;
28 return ST_NEUTRAL;
29 }
30
31 static int hw_check_base(wchar_t *hw_id, wchar_t *hw_name)
32 {
33 wchar_t buff[MAX_PATH];
34 wchar_t *p = NULL;
35 int status;
36
37 if ( (status = hw_check_ini(hw_id)) != ST_NEUTRAL ) {
38 return status;
39 }
40 if ( (status = hw_check_ini(hw_name)) != ST_NEUTRAL ) {
41 return status;
42 }
43
44 if (wcsncmp(hw_id, L"PCI\\VEN_", 8) == 0)
45 {
46 wcsncpy(buff, hw_id, 21); buff[21] = 0;
47
48 if ( (status = hw_check_ini(buff)) != ST_NEUTRAL ) {
49 return status;
50 }
51
52 if (p == wcsstr(hw_id, L"&REV_")) {
53 wcscat(buff, p); status = hw_check_ini(buff);
54 }
55 } else if ( (wcsncmp(hw_id, L"USB\\", 4) == 0) && (p = wcsstr(hw_id, L"&VID")) )
56 {
57 wsprintf(buff, L"USB\\%s", p+1);
58
59 if ( (status = hw_check_ini(buff)) != ST_NEUTRAL ) {
60 return status;
61 }
62
63 if (p == wcsstr(buff, L"&REV")) {
64 *p = 0; status = hw_check_ini(buff);
65 }
66 }
67 return status;
68 }
69
70 static void trim(wchar_t *s)
71 {
72 wchar_t *p;
73 for (p = s + wcslen(s) - 1; (p > s) && (*p == L' '); *p-- = 0);
74 }
75
76 static int hw_check_device(HDEVINFO h_info, SP_DEVINFO_DATA *d_inf)
77 {
78 wchar_t *hw_id = NULL;
79 wchar_t *hw_name = NULL;
80 u_long type, bytes;
81 int status;
82 char name[MAX_PATH];
83 wchar_t w_name[MAX_PATH];
84
85 do
86 {
87 if ( (hw_id = malloc(4096)) == NULL ) {
88 status = ST_ERROR; break;
89 }
90 if ( (hw_name = malloc(4096)) == NULL ) {
91 status = ST_ERROR; break;
92 }
93 hw_id[0] = 0, hw_name[0] = 0;
94
95 SetupDiGetDeviceRegistryProperty(h_info, d_inf, SPDRP_HARDWAREID, &type, (void*)hw_id, 4096, &bytes);
96 SetupDiGetDeviceRegistryProperty(h_info, d_inf, SPDRP_DEVICEDESC, &type, (void*)hw_name, 4096, &bytes);
97
98 if (hw_id[0] == 0 || hw_name[0] == 0) {
99 status = ST_NEUTRAL; break;
100 }
101 /* trim strings */
102 trim(hw_id); trim(hw_name);
103
104 if ( (wcschr(hw_id, L'\\') == NULL) || (_wcsnicmp(hw_id, L"ROOT\\", 5) == 0) ||
105 (_wcsicmp(hw_id, L"STORAGE\\Volume") == 0) || (_wcsicmp(hw_id, L"UMB\\UMBUS") == 0) ||
106 (_wcsnicmp(hw_id, L"SW\\", 3) == 0) )
107 {
108 status = ST_NEUTRAL; break;
109 }
110
111 if (is_show_hw != 0) {
112 CharToOem(hw_name, name);
113 wprintf(L"%s - [%S]\n", hw_id, name);
114 }
115
116 if (gl_report != NULL) {
117 wsprintf(w_name, L"%s - [%s]\n", hw_id, hw_name);
118 wcscat(gl_report, w_name);
119 }
120
121 if (is_check_hw != 0)
122 {
123 status = hw_check_base(hw_id, hw_name);
124
125 if (status == ST_DEV_NOTWORK) {
126 CharToOem(hw_name, name);
127 wprintf(L"Device \"%S\" does not work in ReactOS\n", name);
128 }
129 if (status == ST_ROS_CRASH) {
130 CharToOem(hw_name, name);
131 wprintf(L"ReactOS does not work with device \"%S\"\n", name);
132 }
133 } else {
134 status = ST_NEUTRAL;
135 }
136 } while (0);
137
138 if (hw_id != NULL) free(hw_id);
139 if (hw_name != NULL) free(hw_name);
140
141 return status;
142 }
143
144 static void do_update_base()
145 {
146 wchar_t up_url[MAX_PATH];
147 void *data = NULL;
148 u_long size;
149 FILE *f = NULL;
150
151 if (GetPrivateProfileString(L"URL", L"udpate", NULL, up_url, MAX_PATH, gl_ini_file) == 0) {
152 wprintf(L"Update URL not found in rosddt.ini\n"); return;
153 }
154
155 wprintf(L"Downloading new rosddt.ini...\n");
156
157 if (data == http_get(up_url, &size))
158 {
159 if (f == _wfopen(gl_ini_file, L"wb")) {
160 fwrite(data, 1, size, f);
161 fclose(f);
162 wprintf(L"Update completed\n");
163 } else {
164 wprintf(L"Can not open rosddt.ini for writing\n");
165 }
166 free(data);
167 } else {
168 wprintf(L"Error, rosddt.ini can not be loaded\n");
169 }
170 }
171
172 static void do_send_report(wchar_t *report)
173 {
174 wchar_t up_url[MAX_PATH];
175 int utf_sz;
176 char *utf;
177 char *p = NULL;
178
179 if (GetPrivateProfileString(L"URL", L"report", NULL, up_url, MAX_PATH, gl_ini_file) == 0) {
180 wprintf(L"Report URL not found in rosddt.ini\n"); return;
181 }
182
183 utf_sz = WideCharToMultiByte(CP_UTF8, 0, report, -1, NULL, 0, NULL, NULL);
184 utf = malloc(utf_sz);
185 utf_sz = WideCharToMultiByte(CP_UTF8, 0, report, -1, utf, utf_sz, NULL, NULL);
186
187 wprintf(L"Sending report...\n");
188
189 if (p == http_post(up_url, utf, utf_sz-1, NULL)) {
190 wprintf(L"%S\n", p); free(p);
191 } else {
192 wprintf(L"Report can not be sended, connection error\n");
193 }
194 }
195
196 int wmain(int argc, wchar_t *argv[])
197 {
198 HDEVINFO h_info;
199 SP_DEVINFO_DATA d_inf;
200 int codes[ST_LAST_STATUS + 1] = {0};
201 int i;
202 wchar_t *p;
203
204 if (argc != 2)
205 {
206 wprintf(
207 L"rosddt [parameters]\n"
208 L" -enum enumerate all installed hardware\n"
209 L" -check check hardware compatibility with ReactOS\n"
210 L" -update update hardware compatibility database\n"
211 L" -report send your hardware configuration to ReactOS team\n"
212 );
213 return 0;
214 }
215
216 /* get path to ini file */
217 GetModuleFileName(NULL, gl_ini_file, MAX_PATH);
218 for (p = gl_ini_file + wcslen(gl_ini_file); *p != L'\\'; *p-- = 0);
219 wcscat(gl_ini_file, L"rosddt.ini");
220
221 if (_wcsicmp(argv[1], L"-update") == 0) {
222 do_update_base(); return 0;
223 }
224 if (_wcsicmp(argv[1], L"-enum") == 0) {
225 is_show_hw = 1; is_check_hw = 0;
226 }
227 if (_wcsicmp(argv[1], L"-check") == 0) {
228 is_show_hw = 0; is_check_hw = 1;
229 }
230 if (_wcsicmp(argv[1], L"-report") == 0) {
231 is_show_hw = 0; is_check_hw = 0;
232 gl_report = malloc(65536); gl_report[0] = 0;
233 }
234
235 h_info = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES);
236
237 if (h_info == INVALID_HANDLE_VALUE) {
238 wprintf(L"SetupDiGetClassDevs error\n"); return 1;
239 }
240
241 d_inf.cbSize = sizeof(d_inf); i = 0;
242
243 while (SetupDiEnumDeviceInfo(h_info, i++, &d_inf) != 0) {
244 codes[hw_check_device(h_info, &d_inf)]++;
245 }
246
247 if (is_check_hw != 0)
248 {
249 wprintf(
250 L"Checking completed.\nFound %d supported devices, %d unsupported devices and %d incompatible devices\n",
251 codes[ST_DEV_OK], codes[ST_DEV_NOTWORK], codes[ST_ROS_CRASH]);
252
253 if (codes[ST_ROS_CRASH] == 0) {
254 wprintf(L"ReactOS can be installed on your computer\n");
255 } else {
256 wprintf(L"ReactOS can not be installed on your computer\n");
257 }
258 }
259
260 if (gl_report != NULL) {
261 do_send_report(gl_report);
262 }
263
264 return 0;
265 }