summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--resource.h15
-rw-r--r--usbclerk.cpp408
-rw-r--r--usbclerk.rc99
-rw-r--r--usbclerk.sln36
-rw-r--r--usbclerk.vcproj381
-rw-r--r--usbclerktest.cpp41
-rw-r--r--usbclerktest.vcproj347
-rw-r--r--usbcommon.h13
-rw-r--r--vdlog.cpp111
-rw-r--r--vdlog.h93
10 files changed, 1544 insertions, 0 deletions
diff --git a/resource.h b/resource.h
new file mode 100644
index 0000000..c1243b6
--- /dev/null
+++ b/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by usbservice.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/usbclerk.cpp b/usbclerk.cpp
new file mode 100644
index 0000000..68ee009
--- /dev/null
+++ b/usbclerk.cpp
@@ -0,0 +1,408 @@
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <tchar.h>
+#include "usbcommon.h"
+#include "libwdi.h"
+#include "vdlog.h"
+
+//#define DEBUG_USB_CLERK
+
+#define USB_CLERK_DISPLAY_NAME TEXT("USB Clerk")
+#define USB_CLERK_NAME TEXT("usbclerk")
+#define USB_CLERK_DESCRIPTION TEXT("Enables automathic winusb driver signing & install")
+#define USB_CLERK_LOAD_ORDER_GROUP TEXT("")
+#define USB_CLERK_LOG_PATH TEXT("%susbclerk.log")
+#define USB_CLERK_PIPE_TIMEOUT 10000
+#define USB_CLERK_PIPE_BUF_SIZE 1024
+#define USB_DRIVER_PATH "%Swdi_usb_driver"
+#define USB_DRIVER_INFNAME_LEN 64
+#define USB_DRIVER_INSTALL_RETRIES 3
+#define USB_DRIVER_INSTALL_INTERVAL 1000
+
+class USBClerk {
+public:
+ static USBClerk* get();
+ ~USBClerk();
+ bool run();
+ bool install();
+ bool uninstall();
+
+private:
+ USBClerk();
+ bool execute();
+ bool install_winusb_driver(int vid, int pid);
+ static DWORD WINAPI control_handler(DWORD control, DWORD event_type,
+ LPVOID event_data, LPVOID context);
+ static VOID WINAPI main(DWORD argc, TCHAR * argv[]);
+
+private:
+ static USBClerk* _singleton;
+ SERVICE_STATUS _status;
+ SERVICE_STATUS_HANDLE _status_handle;
+ char _wdi_path[MAX_PATH];
+ HANDLE _pipe;
+ bool _running;
+ VDLog* _log;
+};
+
+USBClerk* USBClerk::_singleton = NULL;
+
+USBClerk* USBClerk::get()
+{
+ if (!_singleton) {
+ _singleton = new USBClerk();
+ }
+ return (USBClerk*)_singleton;
+}
+
+USBClerk::USBClerk()
+ : _running (false)
+ , _status_handle (0)
+ , _log (NULL)
+{
+ _singleton = this;
+}
+
+USBClerk::~USBClerk()
+{
+ delete _log;
+}
+
+bool USBClerk::run()
+{
+#ifndef DEBUG_USB_CLERK
+ SERVICE_TABLE_ENTRY service_table[] = {{USB_CLERK_NAME, main}, {0, 0}};
+ return !!StartServiceCtrlDispatcher(service_table);
+#else
+ main(0, NULL);
+ return true;
+#endif
+}
+
+bool USBClerk::install()
+{
+ bool ret = false;
+
+ SC_HANDLE service_control_manager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
+ if (!service_control_manager) {
+ printf("OpenSCManager failed\n");
+ return false;
+ }
+ TCHAR path[_MAX_PATH + 1];
+ if (!GetModuleFileName(0, path, sizeof(path) / sizeof(path[0]))) {
+ printf("GetModuleFileName failed\n");
+ CloseServiceHandle(service_control_manager);
+ return false;
+ }
+ //FIXME: SERVICE_INTERACTIVE_PROCESS needed for xp only
+ SC_HANDLE service = CreateService(service_control_manager, USB_CLERK_NAME,
+ USB_CLERK_DISPLAY_NAME, SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
+ USB_CLERK_LOAD_ORDER_GROUP, 0, 0, 0, 0);
+ if (service) {
+ SERVICE_DESCRIPTION descr;
+ descr.lpDescription = USB_CLERK_DESCRIPTION;
+ if (!ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &descr)) {
+ printf("ChangeServiceConfig2 failed\n");
+ }
+ CloseServiceHandle(service);
+ printf("Service installed successfully\n");
+ ret = true;
+ } else if (GetLastError() == ERROR_SERVICE_EXISTS) {
+ printf("Service already exists\n");
+ ret = true;
+ } else {
+ printf("Service not installed successfully, error %d\n", GetLastError());
+ }
+ CloseServiceHandle(service_control_manager);
+ return ret;
+}
+
+bool USBClerk::uninstall()
+{
+ bool ret = false;
+
+ SC_HANDLE service_control_manager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
+ if (!service_control_manager) {
+ printf("OpenSCManager failed\n");
+ return false;
+ }
+ SC_HANDLE service = OpenService(service_control_manager, USB_CLERK_NAME,
+ SERVICE_QUERY_STATUS | DELETE);
+ if (!service) {
+ printf("OpenService failed\n");
+ CloseServiceHandle(service_control_manager);
+ return false;
+ }
+ SERVICE_STATUS status;
+ if (!QueryServiceStatus(service, &status)) {
+ printf("QueryServiceStatus failed\n");
+ } else if (status.dwCurrentState != SERVICE_STOPPED) {
+ printf("Service is still running\n");
+ } else if (DeleteService(service)) {
+ printf("Service removed successfully\n");
+ ret = true;
+ } else {
+ switch (GetLastError()) {
+ case ERROR_ACCESS_DENIED:
+ printf("Access denied while trying to remove service\n");
+ break;
+ case ERROR_INVALID_HANDLE:
+ printf("Handle invalid while trying to remove service\n");
+ break;
+ case ERROR_SERVICE_MARKED_FOR_DELETE:
+ printf("Service already marked for deletion\n");
+ break;
+ }
+ }
+ CloseServiceHandle(service);
+ CloseServiceHandle(service_control_manager);
+ return ret;
+}
+
+DWORD WINAPI USBClerk::control_handler(DWORD control, DWORD event_type, LPVOID event_data,
+ LPVOID context)
+{
+ USBClerk* s = _singleton;
+ DWORD ret = NO_ERROR;
+
+ switch (control) {
+ case SERVICE_CONTROL_STOP:
+ case SERVICE_CONTROL_SHUTDOWN: {
+ HANDLE pipe;
+ s->_status.dwCurrentState = SERVICE_STOP_PENDING;
+ SetServiceStatus(s->_status_handle, &s->_status);
+ s->_running = false;
+ pipe = CreateFile(USB_CLERK_PIPE_NAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (pipe != INVALID_HANDLE_VALUE) {
+ CloseHandle(pipe);
+ }
+ break;
+ }
+ case SERVICE_CONTROL_INTERROGATE:
+ SetServiceStatus(s->_status_handle, &s->_status);
+ break;
+ default:
+ ret = ERROR_CALL_NOT_IMPLEMENTED;
+ }
+ return ret;
+}
+
+#define USBCLERK_ACCEPTED_CONTROLS \
+ (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_SESSIONCHANGE)
+
+VOID WINAPI USBClerk::main(DWORD argc, TCHAR* argv[])
+{
+ USBClerk* s = _singleton;
+
+ SERVICE_STATUS* status;
+ TCHAR log_path[MAX_PATH];
+ TCHAR temp_path[MAX_PATH];
+
+ if (GetTempPath(MAX_PATH, temp_path)) {
+ sprintf_s(s->_wdi_path, MAX_PATH, USB_DRIVER_PATH, temp_path);
+ swprintf_s(log_path, MAX_PATH, USB_CLERK_LOG_PATH, temp_path);
+ s->_log = VDLog::get(log_path);
+ }
+ vd_printf("***Service started***");
+ SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
+ status = &s->_status;
+ status->dwServiceType = SERVICE_WIN32;
+ status->dwCurrentState = SERVICE_STOPPED;
+ status->dwControlsAccepted = 0;
+ status->dwWin32ExitCode = NO_ERROR;
+ status->dwServiceSpecificExitCode = NO_ERROR;
+ status->dwCheckPoint = 0;
+ status->dwWaitHint = 0;
+ s->_status_handle = RegisterServiceCtrlHandlerEx(USB_CLERK_NAME, &USBClerk::control_handler,
+ NULL);
+ if (!s->_status_handle) {
+#ifndef DEBUG_USB_CLERK
+ vd_printf("RegisterServiceCtrlHandler failed");
+ return;
+#endif // DEBUG_USB_CLERK
+ }
+
+ // service is starting
+ status->dwCurrentState = SERVICE_START_PENDING;
+ SetServiceStatus(s->_status_handle, status);
+
+ // service running
+ status->dwControlsAccepted |= USBCLERK_ACCEPTED_CONTROLS;
+ status->dwCurrentState = SERVICE_RUNNING;
+ SetServiceStatus(s->_status_handle, status);
+
+ s->_running = true;
+ s->execute();
+
+ // service was stopped
+ status->dwCurrentState = SERVICE_STOP_PENDING;
+ SetServiceStatus(s->_status_handle, status);
+
+ // service is stopped
+ status->dwControlsAccepted &= ~USBCLERK_ACCEPTED_CONTROLS;
+ status->dwCurrentState = SERVICE_STOPPED;
+#ifndef DEBUG_USB_CLERK
+ SetServiceStatus(s->_status_handle, status);
+#endif //DEBUG_USB_CLERK
+}
+
+bool USBClerk::execute()
+{
+ SECURITY_ATTRIBUTES sec_attr;
+ SECURITY_DESCRIPTOR* sec_desr;
+ USBDevInfo dev;
+ DWORD bytes;
+ DWORD ack;
+
+#if 0
+ /* Hack for wdi logging */
+ if (wdi_register_logger((HWND)1, 1, 1000) != 0) {
+ vd_printf("wdi_register_logger failed");
+ }
+#endif
+ sec_desr = (SECURITY_DESCRIPTOR*)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
+ InitializeSecurityDescriptor(sec_desr, SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl(sec_desr, TRUE, (PACL)NULL, FALSE);
+ sec_attr.nLength = sizeof(sec_attr);
+ sec_attr.bInheritHandle = TRUE;
+ sec_attr.lpSecurityDescriptor = sec_desr;
+ _pipe = CreateNamedPipe(USB_CLERK_PIPE_NAME, PIPE_ACCESS_DUPLEX |
+ FILE_FLAG_FIRST_PIPE_INSTANCE,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1,
+ USB_CLERK_PIPE_BUF_SIZE, USB_CLERK_PIPE_BUF_SIZE, 0, &sec_attr);
+ if (_pipe == INVALID_HANDLE_VALUE) {
+ vd_printf("CreatePipe() failed: %u", GetLastError());
+ return false;
+ }
+ while (_running) {
+ if (!ConnectNamedPipe(_pipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED) {
+ printf("ConnectNamedPipe() failed: %u", GetLastError());
+ break;
+ }
+ if (!ReadFile(_pipe, &dev, sizeof(dev), &bytes, NULL)) {
+ vd_printf("ReadFile() failed: %d\n", GetLastError());
+ break;
+ }
+ vd_printf("Installing winusb driver for %04x:%04x", dev.vid, dev.pid);
+ if (ack = install_winusb_driver(dev.vid, dev.pid)) {
+ vd_printf("winusb driver install succeed");
+ } else {
+ vd_printf("winusb driver install failed");
+ }
+ if (!WriteFile(_pipe, &ack, sizeof(ack), &bytes, NULL)) {
+ vd_printf("WriteFile() failed: %d\n", GetLastError());
+ break;
+ }
+ FlushFileBuffers(_pipe);
+ DisconnectNamedPipe(_pipe);
+ }
+ CloseHandle(_pipe);
+ return true;
+}
+
+bool USBClerk::install_winusb_driver(int vid, int pid)
+{
+ struct wdi_device_info *wdidev, *wdilist;
+ struct wdi_options_create_list wdi_list_opts;
+ struct wdi_options_prepare_driver wdi_prep_opts;
+ struct wdi_options_install_driver wdi_inst_opts;
+ char infname[USB_DRIVER_INFNAME_LEN];
+ bool installed = false;
+ bool found = false;
+ int r;
+
+ /* find wdi device that matches the libusb device */
+ memset(&wdi_list_opts, 0, sizeof(wdi_list_opts));
+ wdi_list_opts.list_all = 1;
+ wdi_list_opts.list_hubs = 0;
+ wdi_list_opts.trim_whitespaces = 1;
+ r = wdi_create_list(&wdilist, &wdi_list_opts);
+ if (r != WDI_SUCCESS) {
+ vd_printf("Device %04x:%04x wdi_create_list() failed -- %s (%d)",
+ vid, pid, wdi_strerror(r), r);
+ return false;
+ }
+
+ vd_printf("Looking for device vid:pid %04x:%04x", vid, pid);
+ for (wdidev = wdilist; wdidev != NULL && !(found = wdidev->vid == vid && wdidev->pid == pid);
+ wdidev = wdidev->next);
+ if (!found) {
+ vd_printf("Device %04x:%04x was not found", vid, pid);
+ goto cleanup;
+ }
+
+ vd_printf("Device %04x:%04x found", vid, pid);
+
+ /* if the driver is already installed -- nothing to do */
+ if (wdidev->driver) {
+ vd_printf("Currently installed driver is %s", wdidev->driver);
+ if (strcmp(wdidev->driver, "WinUSB") == 0) {
+ vd_printf("WinUSB driver is already installed");
+ installed = true;
+ goto cleanup;
+ }
+ }
+
+ /* inf filename is built out of vid and pid */
+ r = sprintf_s(infname, sizeof(infname), "usb_device_%04x_%04x.inf", vid, pid);
+ if (r <= 0) {
+ vd_printf("inf file naming failed (%d)", r);
+ goto cleanup;
+ }
+
+ vd_printf("Installing driver for USB device: \"%s\" (%04x:%04x) inf: %s",
+ wdidev->desc, vid, pid, infname);
+ memset(&wdi_prep_opts, 0, sizeof(wdi_prep_opts));
+ wdi_prep_opts.driver_type = WDI_WINUSB;
+ r = wdi_prepare_driver(wdidev, _wdi_path, infname, &wdi_prep_opts);
+ if (r != WDI_SUCCESS) {
+ vd_printf("Device %04x:%04x driver prepare failed -- %s (%d)",
+ vid, pid, wdi_strerror(r), r);
+ goto cleanup;
+ }
+
+ memset(&wdi_inst_opts, 0, sizeof(wdi_inst_opts));
+ for (int t = 0; t < USB_DRIVER_INSTALL_RETRIES; t++) {
+ r = wdi_install_driver(wdidev, _wdi_path, infname, &wdi_inst_opts);
+ if (r == WDI_ERROR_PENDING_INSTALLATION) {
+ vd_printf("Another driver is installing, retry in %d seconds",
+ t * USB_DRIVER_INSTALL_INTERVAL);
+ Sleep(t * USB_DRIVER_INSTALL_INTERVAL);
+ } else {
+ /* break on success or any error other than pending installation */
+ break;
+ }
+ }
+
+ if (!(installed = (r == WDI_SUCCESS))) {
+ vd_printf("Device %04x:%04x driver install failed -- %s (%d)",
+ vid, pid, wdi_strerror(r), r);
+ }
+
+cleanup:
+ wdi_destroy_list(wdilist);
+ return installed;
+}
+
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
+{
+ bool success = false;
+
+ USBClerk* usbclerk = USBClerk::get();
+ if (argc > 1) {
+ if (lstrcmpi(argv[1], TEXT("install")) == 0) {
+ success = usbclerk->install();
+ } else if (lstrcmpi(argv[1], TEXT("uninstall")) == 0) {
+ success = usbclerk->uninstall();
+ } else {
+ printf("Use: USBClerk install / uninstall\n");
+ }
+ } else {
+ success = usbclerk->run();
+ }
+ delete usbclerk;
+ return (success ? 0 : -1);
+}
diff --git a/usbclerk.rc b/usbclerk.rc
new file mode 100644
index 0000000..14ef8cf
--- /dev/null
+++ b/usbclerk.rc
@@ -0,0 +1,99 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Hebrew resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_HEB)
+#ifdef _WIN32
+LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT
+#pragma code_page(1255)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,0,0,0
+ PRODUCTVERSION 0,0,0,0
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000904b0"
+ BEGIN
+ VALUE "FileDescription", "USB service"
+ VALUE "FileVersion", "0, 0, 0, 0"
+ VALUE "InternalName", "usbservice"
+ VALUE "OriginalFilename", "usbservice.exe"
+ VALUE "ProductVersion", "0, 0, 0, 0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x9, 1200
+ END
+END
+
+#endif // Hebrew resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/usbclerk.sln b/usbclerk.sln
new file mode 100644
index 0000000..d8778dd
--- /dev/null
+++ b/usbclerk.sln
@@ -0,0 +1,36 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "usbclerk", "usbclerk.vcproj", "{DD1D4792-43A2-4959-8FAE-08C16F61DA26}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "usbclerktest", "usbclerktest.vcproj", "{69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DD1D4792-43A2-4959-8FAE-08C16F61DA26}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DD1D4792-43A2-4959-8FAE-08C16F61DA26}.Debug|Win32.Build.0 = Debug|Win32
+ {DD1D4792-43A2-4959-8FAE-08C16F61DA26}.Debug|x64.ActiveCfg = Debug|x64
+ {DD1D4792-43A2-4959-8FAE-08C16F61DA26}.Debug|x64.Build.0 = Debug|x64
+ {DD1D4792-43A2-4959-8FAE-08C16F61DA26}.Release|Win32.ActiveCfg = Release|Win32
+ {DD1D4792-43A2-4959-8FAE-08C16F61DA26}.Release|Win32.Build.0 = Release|Win32
+ {DD1D4792-43A2-4959-8FAE-08C16F61DA26}.Release|x64.ActiveCfg = Release|x64
+ {DD1D4792-43A2-4959-8FAE-08C16F61DA26}.Release|x64.Build.0 = Release|x64
+ {69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}.Debug|Win32.Build.0 = Debug|Win32
+ {69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}.Debug|x64.ActiveCfg = Debug|x64
+ {69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}.Debug|x64.Build.0 = Debug|x64
+ {69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}.Release|Win32.ActiveCfg = Release|Win32
+ {69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}.Release|Win32.Build.0 = Release|Win32
+ {69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}.Release|x64.ActiveCfg = Release|x64
+ {69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/usbclerk.vcproj b/usbclerk.vcproj
new file mode 100644
index 0000000..0a10c9a
--- /dev/null
+++ b/usbclerk.vcproj
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="windows-1255"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="usbclerk"
+ ProjectGUID="{DD1D4792-43A2-4959-8FAE-08C16F61DA26}"
+ RootNamespace="redservice"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="Q:\test\libwdi-1.2.1\libwdi"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Version.lib libwdi.lib setupapi.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="Q:\test\libwdi-1.2.1\Win32\Debug\lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="Q:\test\libwdi-1.2.1\libwdi"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Version.lib libwdi.lib setupapi.lib"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="Q:\test\libwdi-1.2.1\x64\Debug\lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="Q:\test\libwdi-1.2.1\libwdi"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Version.lib libwdi.lib setupapi.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="Q:\test\libwdi-1.2.1\Win32\Release\lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="Q:\test\libwdi-1.2.1\libwdi"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Version.lib libwdi.lib setupapi.lib"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="Q:\test\libwdi-1.2.1\x64\Release\lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\usbcommon.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vdlog.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\usbclerk.rc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\usbclerk.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\vdlog.cpp"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/usbclerktest.cpp b/usbclerktest.cpp
new file mode 100644
index 0000000..d16a70c
--- /dev/null
+++ b/usbclerktest.cpp
@@ -0,0 +1,41 @@
+#include <stdio.h>
+#include <tchar.h>
+#include "usbcommon.h"
+
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
+{
+ HANDLE pipe;
+ USBDevInfo dev;
+ DWORD pipe_mode;
+ DWORD bytes, ack = 0;
+
+ if (argc < 3 || !swscanf_s(argv[1], L"%hx", &dev.vid) ||
+ !swscanf_s(argv[2], L"%hx", &dev.pid)) {
+ printf("Use: usbclerktest VID PID\n");
+ return 1;
+ }
+ pipe = CreateFile(USB_CLERK_PIPE_NAME, GENERIC_READ | GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (pipe == INVALID_HANDLE_VALUE) {
+ printf("Cannot open pipe %S: %d\n", USB_CLERK_PIPE_NAME, GetLastError());
+ return 1;
+ }
+ pipe_mode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
+ if (!SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL)) {
+ printf("SetNamedPipeHandleState() failed: %d\n", GetLastError());
+ return 1;
+ }
+ printf("Signing & installing %04x:%04x\n", dev.vid, dev.pid);
+ if (!TransactNamedPipe(pipe, &dev, sizeof(dev), &ack, sizeof(ack), &bytes, NULL)) {
+ printf("TransactNamedPipe() failed: %d\n", GetLastError());
+ CloseHandle(pipe);
+ return 1;
+ }
+ CloseHandle(pipe);
+ if (ack) {
+ printf("winusb driver install succeed");
+ } else {
+ printf("winusb driver install failed");
+ }
+ return 0;
+}
diff --git a/usbclerktest.vcproj b/usbclerktest.vcproj
new file mode 100644
index 0000000..6770bf5
--- /dev/null
+++ b/usbclerktest.vcproj
@@ -0,0 +1,347 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="usbclerktest"
+ ProjectGUID="{69C12B50-471C-42B0-8C7A-8EB71AD3EFBE}"
+ RootNamespace="usbservicetest"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\usbclerktest.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\usbcommon.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/usbcommon.h b/usbcommon.h
new file mode 100644
index 0000000..aabbb1a
--- /dev/null
+++ b/usbcommon.h
@@ -0,0 +1,13 @@
+#ifndef _H_USBCOMMON
+#define _H_USBCOMMON
+
+#include <windows.h>
+
+#define USB_CLERK_PIPE_NAME TEXT("\\\\.\\pipe\\usbclerkpipe")
+
+typedef struct USBDevInfo {
+ WORD vid;
+ WORD pid;
+} USBDevInfo;
+
+#endif
diff --git a/vdlog.cpp b/vdlog.cpp
new file mode 100644
index 0000000..8ece384
--- /dev/null
+++ b/vdlog.cpp
@@ -0,0 +1,111 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "vdlog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <share.h>
+
+#define LOG_ROLL_SIZE (1024 * 1024)
+
+VDLog* VDLog::_log = NULL;
+
+VDLog::VDLog(FILE* handle)
+ : _handle(handle)
+{
+ _log = this;
+}
+
+VDLog::~VDLog()
+{
+ if (_log && _handle) {
+ fclose(_handle);
+ _log = NULL;
+ }
+}
+
+VDLog* VDLog::get(TCHAR* path)
+{
+ if (_log || !path) {
+ return _log;
+ }
+ DWORD size = 0;
+ HANDLE file = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (file != INVALID_HANDLE_VALUE) {
+ size = GetFileSize(file, NULL);
+ CloseHandle(file);
+ }
+ if (size != INVALID_FILE_SIZE && size > LOG_ROLL_SIZE) {
+ TCHAR roll_path[MAX_PATH];
+ swprintf_s(roll_path, MAX_PATH, L"%s.1", path);
+ if (!MoveFileEx(path, roll_path, MOVEFILE_REPLACE_EXISTING)) {
+ return NULL;
+ }
+ }
+ FILE* handle = _wfsopen(path, L"a+", _SH_DENYNO);
+ if (!handle) {
+ return NULL;
+ }
+ _log = new VDLog(handle);
+ return _log;
+}
+
+void VDLog::printf(const char* format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vfprintf(_handle, format, args);
+ va_end(args);
+ fflush(_handle);
+}
+
+void log_version()
+{
+ DWORD handle;
+ TCHAR module_fname[MAX_PATH];
+ TCHAR* info_buf = NULL;
+
+ try {
+ if (!GetModuleFileName(NULL, module_fname, MAX_PATH)) {
+ throw;
+ }
+ DWORD version_inf_size = GetFileVersionInfoSize(module_fname, &handle);
+ if (version_inf_size == 0) {
+ throw;
+ }
+ TCHAR* info_buf = new TCHAR[version_inf_size];
+ if (!GetFileVersionInfo(module_fname, handle, version_inf_size, info_buf)) {
+ throw;
+ }
+ UINT size;
+ VS_FIXEDFILEINFO* file_info;
+ if (!VerQueryValue(info_buf, L"\\", (VOID**)&file_info, &size) ||
+ size < sizeof(VS_FIXEDFILEINFO)) {
+ throw;
+ }
+ vd_printf("%d.%d.%d.%d",
+ file_info->dwFileVersionMS >> 16,
+ file_info->dwFileVersionMS & 0x0ffff,
+ file_info->dwFileVersionLS >> 16,
+ file_info->dwFileVersionLS & 0x0ffff);
+ } catch (...) {
+ vd_printf("get version info failed");
+ }
+ delete[] info_buf;
+}
diff --git a/vdlog.h b/vdlog.h
new file mode 100644
index 0000000..5a794b6
--- /dev/null
+++ b/vdlog.h
@@ -0,0 +1,93 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_VDLOG
+#define _H_VDLOG
+
+#include <stdio.h>
+#include <tchar.h>
+#include <crtdbg.h>
+#include <windows.h>
+#include <time.h>
+#include <sys/timeb.h>
+
+class VDLog {
+public:
+ ~VDLog();
+ static VDLog* get(TCHAR* path = NULL);
+ void printf(const char* format, ...);
+
+private:
+ VDLog(FILE* handle);
+
+private:
+ static VDLog* _log;
+ FILE* _handle;
+};
+
+enum {
+ LOG_DEBUG,
+ LOG_INFO,
+ LOG_WARN,
+ LOG_ERROR,
+ LOG_FATAL
+};
+
+#ifdef _DEBUG
+static unsigned int log_level = LOG_DEBUG;
+#else
+static unsigned int log_level = LOG_INFO;
+#endif
+
+#define PRINT_LINE(type, format, datetime, ms, ...) \
+ printf("%u::%s::%s,%.3d::%s::" format "\n", GetCurrentThreadId(), type, datetime, ms, \
+ __FUNCTION__, ## __VA_ARGS__);
+
+#define LOG(type, format, ...) if (type >= log_level && type <= LOG_FATAL) { \
+ VDLog* log = VDLog::get(); \
+ const char *type_as_char[] = { "DEBUG", "INFO", "WARN", "ERROR", "FATAL" }; \
+ struct _timeb now; \
+ struct tm today; \
+ char datetime_str[20]; \
+ _ftime_s(&now); \
+ localtime_s(&today, &now.time); \
+ strftime(datetime_str, 20, "%Y-%m-%d %H:%M:%S", &today); \
+ if (log) { \
+ log->PRINT_LINE(type_as_char[type], format, datetime_str, now.millitm, ## __VA_ARGS__); \
+ } else { \
+ PRINT_LINE(type_as_char[type], format, datetime_str, now.millitm, ## __VA_ARGS__); \
+ } \
+}
+
+#define vd_printf(format, ...) LOG(LOG_INFO, format, ## __VA_ARGS__)
+#define LOG_INFO(format, ...) LOG(LOG_INFO, format, ## __VA_ARGS__)
+#define LOG_WARN(format, ...) LOG(LOG_WARN, format, ## __VA_ARGS__)
+#define LOG_ERROR(format, ...) LOG(LOG_ERROR, format, ## __VA_ARGS__)
+
+#define DBGLEVEL 1000
+
+#define DBG(level, format, ...) { \
+ if (level <= DBGLEVEL) { \
+ LOG(LOG_DEBUG, format, ## __VA_ARGS__); \
+ } \
+}
+
+#define ASSERT(x) _ASSERTE(x)
+
+void log_version();
+
+#endif