summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnon Gilboa <agilboa@redhat.com>2012-04-23 12:44:08 +0300
committerArnon Gilboa <agilboa@redhat.com>2012-04-23 12:44:08 +0300
commitd690f13c581d28dd867ad9fd869cfc696d39fbb1 (patch)
treef87aeec4708497b62591e3ae1e17cc1e138b8f69
usbclerk: Windows service for signing and installing usb device drivers
When usbclerk service is up, any application can connect its named pipe with a USB device (pid,vid) to sign and install. When done, the service will reply with an ack or error code. Currently winusb driver is installed, in order to use libusb for communicating with the device. The usbclerk service can be installed/uninstalled by "usbclerk install"/"usbclerk uninstall". usbclerktest is a sample cli app communicating with the usbclerk service.
-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