- Add ReactOS Device Detection Tool - RosDDT. It's a command line tool for checking...
authorAleksey Bragin <aleksey@reactos.org>
Thu, 4 Jun 2009 12:38:30 +0000 (12:38 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Thu, 4 Jun 2009 12:38:30 +0000 (12:38 +0000)
 * Web part is stubbed for now (hw.php) and needs to be developed.
 * Actual hardware database file (rosddt.ini) has only sample information.
 * Readme file is in Russian language, however running rosddt.exe without parameters provides a built-in English usage help.

svn path=/trunk/; revision=41282

rosapps/applications/sysutils/rosddt/http.c [new file with mode: 0644]
rosapps/applications/sysutils/rosddt/http.h [new file with mode: 0644]
rosapps/applications/sysutils/rosddt/hw.php [new file with mode: 0644]
rosapps/applications/sysutils/rosddt/readme.txt [new file with mode: 0644]
rosapps/applications/sysutils/rosddt/rosddt.c [new file with mode: 0644]
rosapps/applications/sysutils/rosddt/rosddt.ini [new file with mode: 0644]
rosapps/applications/sysutils/rosddt/rosddt.rbuild [new file with mode: 0644]
rosapps/applications/sysutils/rosddt/rosddt.rc [new file with mode: 0644]
rosapps/applications/sysutils/sysutils.rbuild

diff --git a/rosapps/applications/sysutils/rosddt/http.c b/rosapps/applications/sysutils/rosddt/http.c
new file mode 100644 (file)
index 0000000..49095ee
--- /dev/null
@@ -0,0 +1,131 @@
+#include <windows.h>
+#include <wininet.h>
+#include <urlmon.h>
+#include <stdio.h>
+#include "http.h"
+
+#define INTERNET_FLAGS (INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_COOKIES )
+
+static char *http_receive(HINTERNET h_req, u_long *d_size)
+{
+       u_long bytes  = sizeof(u_long);
+       u_long qsize  = 0;
+       u_long readed = 0;
+       char  *data   = NULL;
+       char   buff[4096];
+
+       if (HttpQueryInfo(h_req, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &qsize, &bytes, NULL) != 0) {
+               data = malloc(qsize + 1);
+       }
+
+       do
+       {
+               if (InternetReadFile(h_req, buff, sizeof(buff), &bytes) == 0) {
+                       break;
+               }
+               if ( (readed + bytes) > qsize) {
+                       data = realloc(data, readed + bytes + 1);
+                       if (data == NULL) break;
+                       qsize += bytes;
+               }
+               memcpy(data + readed, buff, bytes); readed += bytes;
+       } while (bytes != 0);
+
+       if ( (data != NULL) && (readed != qsize) ) {
+               free(data); data = NULL;
+       } else {
+               if (d_size != NULL) *d_size = readed;
+               data[readed] = 0;
+       }       
+       return data;
+}
+
+void *http_get(wchar_t *url, u_long *d_size)
+{
+       HINTERNET h_inet = NULL;
+       HINTERNET h_req  = NULL;
+       char     *replay = NULL;
+       
+       do
+       {
+               h_inet = InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
+               if (h_inet == NULL) break;
+               
+               h_req = InternetOpenUrl(h_inet, url, NULL, 0, INTERNET_FLAGS, 0);
+               if (h_req == NULL) break;
+
+               replay = http_receive(h_req, d_size);
+       } while (0);
+
+       if (h_req != NULL) {
+               InternetCloseHandle(h_req);
+       }
+       if (h_inet != NULL) {
+               InternetCloseHandle(h_inet);
+       }
+       return replay;
+}
+
+void *http_post(wchar_t *url, void *data, int size, u_long *d_size)
+{
+       URL_COMPONENTS url_cm = {0};
+       HINTERNET      h_inet = NULL;
+       HINTERNET      h_conn = NULL;
+       HINTERNET      h_req  = NULL;
+       char          *q_data = NULL;
+       char          *replay = NULL;
+       wchar_t        host[MAX_PATH];
+       wchar_t        path[MAX_PATH];
+       unsigned char *p, *d = data;
+
+       do
+       {
+               if ( (q_data = malloc(size * 3 + 10)) == NULL ) {
+                       break;
+               }
+               strcpy(q_data, "data="); p = q_data + 5;
+
+               while (size--) {
+                       p += sprintf(p, "%%%0.2x", (u_long)*d++);
+               }
+
+               url_cm.dwStructSize     = sizeof(url_cm);
+               url_cm.lpszHostName     = host;
+               url_cm.dwHostNameLength = sizeof(host);
+               url_cm.lpszUrlPath      = path;
+               url_cm.dwUrlPathLength  = sizeof(path);
+
+               if (InternetCrackUrl(url, 0, 0, &url_cm) == 0) {
+                       break;
+               }
+
+               h_inet = InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
+               if (h_inet == NULL) break;
+
+               h_conn = InternetConnect(h_inet, host, url_cm.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
+               if (h_conn == NULL) break;
+
+               h_req = HttpOpenRequest(h_conn, L"POST", path, NULL, NULL, NULL, INTERNET_FLAGS, 0);
+               if (h_req == NULL) break;
+
+               HttpAddRequestHeaders(
+                       h_req, L"Content-Type: application/x-www-form-urlencoded", 47*2, HTTP_ADDREQ_FLAG_ADD);
+
+               if (HttpSendRequest(h_req, NULL, 0, q_data, strlen(q_data)) == 0) {
+                       break;
+               }
+               replay = http_receive(h_req, d_size);
+       } while (0);
+
+       if (h_req != NULL) {
+               InternetCloseHandle(h_req);
+       }
+       if (h_conn != NULL) {
+               InternetCloseHandle(h_conn);
+       }
+       if (h_inet != NULL) {
+               InternetCloseHandle(h_inet);
+       }
+       if (q_data != NULL) free(q_data);
+       return replay;
+}
diff --git a/rosapps/applications/sysutils/rosddt/http.h b/rosapps/applications/sysutils/rosddt/http.h
new file mode 100644 (file)
index 0000000..60e08ce
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _HTTP_H_
+#define _HTTP_H_
+
+void *http_get(wchar_t *url, u_long *d_size);
+void *http_post(wchar_t *url, void *data, int size, u_long *d_size);
+
+#endif
diff --git a/rosapps/applications/sysutils/rosddt/hw.php b/rosapps/applications/sysutils/rosddt/hw.php
new file mode 100644 (file)
index 0000000..f16e92b
--- /dev/null
@@ -0,0 +1,10 @@
+<?php\r
+$file = fopen ("hw.txt", "a");\r
+if (!$file) {\r
+    echo "<p>Unable to open file for writing.\n";\r
+    exit;\r
+}\r
+fputs ($file, $_POST['data']. "\n");\r
+fclose ($file);\r
+echo "_ok_";\r
+?>
\ No newline at end of file
diff --git a/rosapps/applications/sysutils/rosddt/readme.txt b/rosapps/applications/sysutils/rosddt/readme.txt
new file mode 100644 (file)
index 0000000..0663311
--- /dev/null
@@ -0,0 +1,17 @@
+=========== rosddt - ReactOS device detection tool ===========
+
+Èñïîëüçîâàíèå:
+rosddt -enum  - âûâåñòè ñïèñîê âñåãî óñòàíîâëåííîãî æåëåçà
+rosddt -check - ïðîâåðèòü ñîâìåñòèìîñòü ReactOS ñ âàøåé ñèñòåìîé
+rosddt -update - îáíîâèòü áàçó ñîâìåñòèìîñòè äî ïîñëåäíåé âåðñèè
+rosddt -report - îòïðàâèòü îò÷åò îá àïïàðàòíîé êîíôèãóðàöèè ðàçðàáîò÷èêàì ReactOS. Ýòà èíôîðìàöèÿ áóäåò èñïîëüçîâàíà äëÿ âåäåíèÿ ñòàòèñòèêè è ïîääåðæêè áàçû ñîâìåñòèìîñòè.
+
+=== ôîðìàò ôàéëà rosddt.ini ===
+Ñåêöèÿ "URL" ñîäåðæèò äâå ññûëêè: udpate - ññûëêà íà rosddt.ini, èñïîëüçóåòñÿ ïðè îáíîâëåíèè, report - ññûëêà íà ñêðèïò ïðèíèìàþùèé îò÷åòû. Âñ¸ ñîäåðæèìîå îò÷åòà ïåðåäà¸òñÿ â ïîëå "data" POST çàïðîñà â êîäèðîâêå UTF-8. Ïðèìåð ïðè¸ìà îò÷åòîâ ñìîòðèòå â hw.php.
+
+Ñåêöèÿ "HW" ñîäåðæèò áàçó ñîâìåñòèìîñòè ReactOS ñ æåëåçîì. Êàæäîå çàíåñ¸ííîå â áàçó óñòðîéñòâî ìîæåò èìåòü òðè ñòàòóñà ñîâìåñòèìîñòè: ok - óñòðîéñòâî ðàáîòàåò â ReactOS, notwork - óñòðîéñòâî íå ðàáîòàåò â ReactOS è crash - ReactOS íå çàïóñêàåòñÿ íà ñèñòåìå ñ ýòèì óñòðîéñòâîì.
+Óñòðîéñòâà ìîãóò îáîçíà÷àòüñÿ ñëåäóþùèìè ñïîñîáàìè:
+1 - Ïî ïîëíîìó ÷èòàåìîìó èìåíè óñòðîéñòâà. Íàïðèìåð "Intel(R) 82371AB/EB PCI Bus Master IDE Controller".
+2 - Ïî ïîëíîìó PNP ID óñòðîéñòâà. Íàïðèìåð "PCI\VEN_8086&DEV_1237&SUBSYS_00000000&REV_02".
+3 - Äëÿ PCI óñòðîéñòâ ìîæíî óêàçûâàòü òàêæå ñîêðàùåííûå ñîêðàùåííûå pnp id, òàêèå êàê "PCI\VEN_8086&DEV_1237" èëè "PCI\VEN_8086&DEV_1237&REV_02". Ðåêîìåíäóåòñÿ ïîëüçîâàòüñÿ èìåííî òàêîé ôîðìîé çàïèñè, ïîñêîëüêó ïîëíûé id ïðèâÿçàí ê íîìåðó pci ñëîòà â êîòîðûé âñòàâëåíî óñòðîéñòâî. Ðåâèçèþ óêàçûâàòü ïî íåîáõîäèìîñòè, ëó÷øå îáîéòèñü áåç íå¸.
+4 - Äëÿ USB óñòðîéñòâ ìîæíî ïîëüçîâàòüñÿ ñîêðàùåííîé ôîðìîé çàïèñè. Íàïðèìåð "USB\ROOT_HUB&VID8086&PID3A34&REV0000" ìîæíî çàïèñàòü êàê "USB\VID8086&PID3A34" èëè "USB\VID8086&PID3A34&REV0000"
\ No newline at end of file
diff --git a/rosapps/applications/sysutils/rosddt/rosddt.c b/rosapps/applications/sysutils/rosddt/rosddt.c
new file mode 100644 (file)
index 0000000..bc1adbd
--- /dev/null
@@ -0,0 +1,263 @@
+#include <stdio.h>
+#include <windows.h>
+#include <setupapi.h>
+#include "http.h"
+
+#define ST_NEUTRAL      0
+#define ST_ROS_CRASH    1
+#define ST_DEV_NOTWORK  2
+#define ST_DEV_OK       3
+#define ST_ERROR        4
+#define ST_LAST_STATUS  ST_ERROR
+
+static int      is_show_hw;
+static int      is_check_hw;
+static wchar_t  gl_ini_file[MAX_PATH];
+static wchar_t *gl_report;
+
+static int hw_check_ini(wchar_t *name)
+{
+       wchar_t buff[MAX_PATH];
+
+       if (GetPrivateProfileString(L"HW", name, NULL, buff, MAX_PATH, gl_ini_file) == 0) {
+               return ST_NEUTRAL;
+       }
+       if (_wcsicmp(buff, L"ok") == 0) return ST_DEV_OK;
+       if (_wcsicmp(buff, L"notwork") == 0) return ST_DEV_NOTWORK;
+       if (_wcsicmp(buff, L"crash") == 0) return ST_ROS_CRASH;
+       return ST_NEUTRAL;
+}
+
+static int hw_check_base(wchar_t *hw_id, wchar_t *hw_name)
+{
+       wchar_t buff[MAX_PATH], *p;
+       int     status;
+
+       if ( (status = hw_check_ini(hw_id)) != ST_NEUTRAL ) {
+               return status;
+       }
+       if ( (status = hw_check_ini(hw_name)) != ST_NEUTRAL ) {
+               return status;
+       }
+
+       if (wcsncmp(hw_id, L"PCI\\VEN_", 8) == 0)
+       {
+               wcsncpy(buff, hw_id, 21); buff[21] = 0;
+
+               if ( (status = hw_check_ini(buff)) != ST_NEUTRAL ) {
+                       return status;
+               }
+
+               if (p = wcsstr(hw_id, L"&REV_")) {
+                       wcscat(buff, p); status = hw_check_ini(buff);
+               }
+       } else if ( (wcsncmp(hw_id, L"USB\\", 4) == 0) && (p = wcsstr(hw_id, L"&VID")) )
+       {
+               wsprintf(buff, L"USB\\%s", p+1);
+               
+               if ( (status = hw_check_ini(buff)) != ST_NEUTRAL ) {
+                       return status;
+               }
+
+               if (p = wcsstr(buff, L"&REV")) {
+                       *p = 0; status = hw_check_ini(buff);
+               }
+       }
+       return status;
+}
+
+static void trim(wchar_t *s) 
+{
+       wchar_t *p;
+       for (p = s + wcslen(s) - 1; (p > s) && (*p == L' '); *p-- = 0);
+}
+
+static int hw_check_device(HDEVINFO h_info, SP_DEVINFO_DATA *d_inf)
+{
+       wchar_t *hw_id   = NULL;
+       wchar_t *hw_name = NULL;
+       u_long   type, bytes;
+       int      status;
+       char     name[MAX_PATH];
+       wchar_t  w_name[MAX_PATH];
+       
+       do
+       {
+               if ( (hw_id = malloc(4096)) == NULL ) {
+                       status = ST_ERROR; break;
+               }
+               if ( (hw_name = malloc(4096)) == NULL ) {
+                       status = ST_ERROR; break;
+               }
+               hw_id[0] = 0, hw_name[0] = 0;
+
+               SetupDiGetDeviceRegistryProperty(h_info, d_inf, SPDRP_HARDWAREID, &type, (void*)hw_id, 4096, &bytes);
+               SetupDiGetDeviceRegistryProperty(h_info, d_inf, SPDRP_DEVICEDESC, &type, (void*)hw_name, 4096, &bytes);
+
+               if (hw_id[0] == 0 || hw_name[0] == 0) {
+                       status = ST_NEUTRAL; break;
+               }       
+               /* trim strings */
+               trim(hw_id); trim(hw_name);
+
+               if ( (wcschr(hw_id, L'\\') == NULL) || (_wcsnicmp(hw_id, L"ROOT\\", 5) == 0) ||
+                        (_wcsicmp(hw_id, L"STORAGE\\Volume") == 0) || (_wcsicmp(hw_id, L"UMB\\UMBUS") == 0) ||
+                        (_wcsnicmp(hw_id, L"SW\\", 3) == 0) )
+               {
+                       status = ST_NEUTRAL; break;
+               }
+
+               if (is_show_hw != 0) {
+                       CharToOem(hw_name, name);
+                       wprintf(L"%s - [%S]\n", hw_id, name);
+               }
+
+               if (gl_report != NULL) {
+                       wsprintf(w_name, L"%s - [%s]\n", hw_id, hw_name);
+                       wcscat(gl_report, w_name);
+               }
+
+               if (is_check_hw != 0) 
+               {
+                       status = hw_check_base(hw_id, hw_name);
+
+                       if (status == ST_DEV_NOTWORK) {
+                               CharToOem(hw_name, name);
+                               wprintf(L"Device \"%S\" does not work in ReactOS\n", name);
+                       }
+                       if (status == ST_ROS_CRASH) {
+                               CharToOem(hw_name, name);
+                               wprintf(L"ReactOS does not work with device \"%S\"\n", name);
+                       }                       
+               } else {
+                       status = ST_NEUTRAL;
+               }
+       } while (0);
+
+       if (hw_id != NULL) free(hw_id);
+       if (hw_name != NULL) free(hw_name);
+
+       return status;
+}
+
+static void do_update_base()
+{
+       wchar_t up_url[MAX_PATH];
+       void   *data;
+       u_long  size;
+       FILE   *f;
+
+       if (GetPrivateProfileString(L"URL", L"udpate", NULL, up_url, MAX_PATH, gl_ini_file) == 0) {
+               wprintf(L"Update URL not found in rosddt.ini\n"); return;
+       }
+
+       wprintf(L"Downloading new rosddt.ini...\n");
+
+       if (data = http_get(up_url, &size)) 
+       {
+               if (f = _wfopen(gl_ini_file, L"wb")) {
+                       fwrite(data, 1, size, f);
+                       fclose(f);
+                       wprintf(L"Update completed\n");
+               } else {
+                       wprintf(L"Can not open rosddt.ini for writing\n"); 
+               }
+               free(data);
+       } else {
+               wprintf(L"Error, rosddt.ini can not be loaded\n");
+       }
+}
+
+static void do_send_report(wchar_t *report)
+{
+       wchar_t up_url[MAX_PATH];
+       int     utf_sz;
+       char   *utf, *p;
+
+       if (GetPrivateProfileString(L"URL", L"report", NULL, up_url, MAX_PATH, gl_ini_file) == 0) {
+               wprintf(L"Report URL not found in rosddt.ini\n"); return;
+       }
+
+       utf_sz = WideCharToMultiByte(CP_UTF8, 0, report, -1, NULL, 0, NULL, NULL);
+       utf    = malloc(utf_sz);
+       utf_sz = WideCharToMultiByte(CP_UTF8, 0, report, -1, utf, utf_sz, NULL, NULL);
+
+       wprintf(L"Sending report...\n");
+
+       if (p = http_post(up_url, utf, utf_sz-1, NULL)) {
+               wprintf(L"%S\n", p); free(p);
+       } else {
+               wprintf(L"Report can not be sended, connection error\n");
+       }
+}
+
+int wmain(int argc, wchar_t *argv[])
+{
+       HDEVINFO        h_info;
+       SP_DEVINFO_DATA d_inf;
+       int             codes[ST_LAST_STATUS + 1] = {0};
+       int             i;
+       wchar_t        *p;
+               
+       if (argc != 2)
+       {
+               wprintf(
+                       L"rosddt [parameters]\n"
+                       L" -enum   enumerate all installed hardware\n"
+                       L" -check  check hardware compatibility with ReactOS\n"
+                       L" -update update hardware compatibility database\n"
+                       L" -report send your hardware configuration to ReactOS team\n"
+                       );
+               return 0;
+       }
+
+       /* get path to ini file */
+       GetModuleFileName(NULL, gl_ini_file, MAX_PATH); 
+       for (p = gl_ini_file + wcslen(gl_ini_file); *p != L'\\'; *p-- = 0);
+       wcscat(gl_ini_file, L"rosddt.ini");
+
+       if (_wcsicmp(argv[1], L"-update") == 0) {
+               do_update_base(); return 0;
+       }
+       if (_wcsicmp(argv[1], L"-enum") == 0) {
+               is_show_hw = 1; is_check_hw = 0;
+       }
+       if (_wcsicmp(argv[1], L"-check") == 0) {
+               is_show_hw = 0; is_check_hw = 1;
+       }
+       if (_wcsicmp(argv[1], L"-report") == 0) {
+               is_show_hw = 0; is_check_hw = 0;
+               gl_report = malloc(65536); gl_report[0] = 0;
+       }
+
+       h_info = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES);
+
+       if (h_info == INVALID_HANDLE_VALUE) {
+               wprintf(L"SetupDiGetClassDevs error\n"); return 1;
+       }
+
+       d_inf.cbSize = sizeof(d_inf); i = 0;
+
+       while (SetupDiEnumDeviceInfo(h_info, i++, &d_inf) != 0) {
+               codes[hw_check_device(h_info, &d_inf)]++;               
+       }
+
+       if (is_check_hw != 0) 
+       {
+               wprintf(
+                       L"Checking completed.\nFound %d supported devices, %d unsupported devices and %d incompatible devices\n", 
+                       codes[ST_DEV_OK], codes[ST_DEV_NOTWORK], codes[ST_ROS_CRASH]);
+
+               if (codes[ST_ROS_CRASH] == 0) {
+                       wprintf(L"ReactOS can be installed on your computer\n");
+               } else {
+                       wprintf(L"ReactOS can not be installed on your computer\n");
+               }
+       }
+
+       if (gl_report != NULL) {
+               do_send_report(gl_report);
+       }
+
+       return 0; 
+}
diff --git a/rosapps/applications/sysutils/rosddt/rosddt.ini b/rosapps/applications/sysutils/rosddt/rosddt.ini
new file mode 100644 (file)
index 0000000..518ec17
--- /dev/null
@@ -0,0 +1,8 @@
+[URL]\r
+udpate = http://iso.reactos.org/_tools/rosddt.ini\r
+report = http://iso.reactos.org/_tools/hw.php\r
+\r
+[HW]\r
+PCI\VEN_8086&DEV_7000&SUBSYS_00000000&REV_00 = ok\r
+ACPI Fixed Feature Button = notwork\r
+Intel(R) 82371AB/EB PCI Bus Master IDE Controller = crash
\ No newline at end of file
diff --git a/rosapps/applications/sysutils/rosddt/rosddt.rbuild b/rosapps/applications/sysutils/rosddt/rosddt.rbuild
new file mode 100644 (file)
index 0000000..33f73e6
--- /dev/null
@@ -0,0 +1,11 @@
+<module name="rosddt" type="win32cui" installbase="system32" installname="rosddt.exe" unicode="yes" allowwarnings="true">
+
+       <library>setupapi</library>
+       <library>wininet</library>
+       <library>kernel32</library>
+       <library>user32</library>
+
+       <file>http.c</file>
+       <file>rosddt.c</file>
+       <file>rosddt.rc</file>
+</module>
diff --git a/rosapps/applications/sysutils/rosddt/rosddt.rc b/rosapps/applications/sysutils/rosddt/rosddt.rc
new file mode 100644 (file)
index 0000000..535b3bb
--- /dev/null
@@ -0,0 +1,7 @@
+#include <windows.h>
+
+#define REACTOS_STR_FILE_DESCRIPTION   "ReactOS Device Detection Tool\0"
+#define REACTOS_STR_INTERNAL_NAME      "rosddt\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "rosddt.exe\0"
+#define REACTOS_STR_ORIGINAL_COPYRIGHT "2009, ReactOS Development Team\0"
+#include <reactos/version.rc>
index 47ec3b0..b3aee1b 100644 (file)
                <xi:include href="regexpl/regexpl.rbuild" />
        </directory>
 
+       <directory name="rosddt">
+               <xi:include href="rosddt/rosddt.rbuild" />
+       </directory>
+
        <directory name="screenshot">
                <xi:include href="screenshot/screenshot.rbuild" />
        </directory>