diff --git a/host/windows/usb/api/AdbWinApi.cpp b/host/windows/usb/api/AdbWinApi.cpp index 4d18d3793..e81c2c7ea 100644 --- a/host/windows/usb/api/AdbWinApi.cpp +++ b/host/windows/usb/api/AdbWinApi.cpp @@ -17,6 +17,7 @@ // AdbWinApi.cpp : Implementation of DLL Exports. #include "stdafx.h" +#include "adb_api.h" extern "C" { int _forceCRTManifest; @@ -24,8 +25,73 @@ int _forceMFCManifest; int _forceAtlDllManifest; }; +/// References InstantiateWinUsbInterface declared in adb_api.cpp +extern PFN_INSTWINUSBINTERFACE InstantiateWinUsbInterface; + class CAdbWinApiModule : public CAtlDllModuleT< CAdbWinApiModule > { -public: + public: + CAdbWinApiModule() + : CAtlDllModuleT< CAdbWinApiModule >(), + adbwinusbapi_handle_(NULL), + is_initialized_(false) { + } + + ~CAdbWinApiModule() { + // Unload AdbWinUsbApi.dll before we exit + if (NULL != adbwinusbapi_handle_) { + FreeLibrary(adbwinusbapi_handle_); + } + } + + /** \brief Loads AdbWinUsbApi.dll and caches its InstantiateWinUsbInterface + export. + + This method is called from DllMain on DLL_PROCESS_ATTACH event. In this + method we will check if WINUSB.DLL required by AdbWinUsbApi.dll is + installed, and if it is we will load AdbWinUsbApi.dll and cache address of + InstantiateWinUsbInterface routine exported from AdbWinUsbApi.dll + */ + void AttachToAdbWinUsbApi() { + // We only need to run this only once. + if (is_initialized_) { + return; + } + + // Just mark that we have ran initialization. + is_initialized_ = true; + + // Before we can load AdbWinUsbApi.dll we must make sure that WINUSB.DLL + // has been installed. Build path to the file. + wchar_t path_to_winusb_dll[MAX_PATH+1]; + if (!GetSystemDirectory(path_to_winusb_dll, MAX_PATH)) { + return; + } + wcscat(path_to_winusb_dll, L"\\WINUSB.DLL"); + + if (0xFFFFFFFF == GetFileAttributes(path_to_winusb_dll)) { + // WINUSB.DLL is not installed. We don't (in fact, can't) load + // AdbWinUsbApi.dll + return; + } + + // WINUSB.DLL is installed. Lets load AdbWinUsbApi.dll and cache its + // InstantiateWinUsbInterface export. + // We require that AdbWinUsbApi.dll is located in the same folder + // where AdbWinApi.dll and adb.exe are located, so by Windows + // conventions we can pass just module name, and not the full path. + adbwinusbapi_handle_ = LoadLibrary(L"AdbWinUsbApi.dll"); + if (NULL != adbwinusbapi_handle_) { + InstantiateWinUsbInterface = reinterpret_cast + (GetProcAddress(adbwinusbapi_handle_, "InstantiateWinUsbInterface")); + } + } + + protected: + /// Handle to the loaded AdbWinUsbApi.dll + HINSTANCE adbwinusbapi_handle_; + + /// Flags whether or not this module has been initialized. + bool is_initialized_; }; CAdbWinApiModule _AtlModule; @@ -34,5 +100,12 @@ CAdbWinApiModule _AtlModule; extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { - return _AtlModule.DllMain(reason, reserved); + // Lets see if we need to initialize InstantiateWinUsbInterface + // variable. We do that only once, on condition that this DLL is + // being attached to the process and InstantiateWinUsbInterface + // address has not been calculated yet. + if (DLL_PROCESS_ATTACH == reason) { + _AtlModule.AttachToAdbWinUsbApi(); + } + return _AtlModule.DllMain(reason, reserved); } diff --git a/host/windows/usb/api/SOURCES b/host/windows/usb/api/SOURCES index f6e66143c..35695217b 100755 --- a/host/windows/usb/api/SOURCES +++ b/host/windows/usb/api/SOURCES @@ -50,8 +50,7 @@ TARGETLIBS = $(SDK_LIB_PATH)\ole32.lib \ $(SDK_LIB_PATH)\wbemuuid.lib \ $(SDK_LIB_PATH)\uuid.lib \ $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\usbd.lib \ - $(SDK_LIB_PATH)\winusb.lib + $(SDK_LIB_PATH)\usbd.lib !IF "$(DDKBUILDENV)" == "fre" # Libraries for release (free) builds @@ -87,15 +86,12 @@ PRECOMPILED_SOURCEFILE = stdafx.cpp # Define source files for AdbWinApi.dll SOURCES = adb_api.cpp \ adb_endpoint_object.cpp \ - adb_winusb_endpoint_object.cpp \ adb_legacy_endpoint_object.cpp \ adb_helper_routines.cpp \ adb_interface.cpp \ - adb_winusb_interface.cpp \ adb_legacy_interface.cpp \ adb_interface_enum.cpp \ adb_io_completion.cpp \ - adb_winusb_io_completion.cpp \ adb_legacy_io_completion.cpp \ adb_object_handle.cpp \ AdbWinApi.cpp \ diff --git a/host/windows/usb/api/adb_api.cpp b/host/windows/usb/api/adb_api.cpp index f9bd94e6c..493f62d86 100644 --- a/host/windows/usb/api/adb_api.cpp +++ b/host/windows/usb/api/adb_api.cpp @@ -24,12 +24,19 @@ #include "adb_object_handle.h" #include "adb_interface_enum.h" #include "adb_interface.h" -#include "adb_winusb_interface.h" #include "adb_legacy_interface.h" #include "adb_endpoint_object.h" #include "adb_io_completion.h" #include "adb_helper_routines.h" +/** \brief Points to InstantiateWinUsbInterface exported from AdbWinUsbApi.dll. + + This variable is initialized with the actual address in DllMain routine for + this DLL on DLL_PROCESS_ATTACH event. + @see PFN_INSTWINUSBINTERFACE for more information. +*/ +PFN_INSTWINUSBINTERFACE InstantiateWinUsbInterface = NULL; + ADBAPIHANDLE __cdecl AdbEnumInterfaces(GUID class_id, bool exclude_not_present, bool exclude_removed, @@ -101,11 +108,22 @@ ADBAPIHANDLE __cdecl AdbCreateInterfaceByName( ADBAPIHANDLE ret = NULL; try { - // Instantiate object + // Instantiate interface object, depending on the USB driver type. if (IsLegacyInterface(interface_name)) { + // We have legacy USB driver underneath us. obj = new AdbLegacyInterfaceObject(interface_name); } else { - obj = new AdbWinUsbInterfaceObject(interface_name); + // We have WinUsb driver underneath us. Make sure that AdbWinUsbApi.dll + // is loaded and its InstantiateWinUsbInterface routine address has + // been cached. + if (NULL != InstantiateWinUsbInterface) { + obj = InstantiateWinUsbInterface(interface_name); + if (NULL == obj) { + return NULL; + } + } else { + return NULL; + } } // Create handle for it diff --git a/host/windows/usb/api/adb_api.h b/host/windows/usb/api/adb_api.h index e2ad129ca..429a56d9a 100644 --- a/host/windows/usb/api/adb_api.h +++ b/host/windows/usb/api/adb_api.h @@ -110,6 +110,30 @@ typedef struct _AdbEndpointInformation { /// the driver in isolation from hardware. #define DEVICE_EMULATOR_PROD_ID 0xDDDD +/** \brief Function prototype for InstantiateWinUsbInterface routine exported + from AdbWinUsbApi.dll + + In order to provide backward compatibility with the systems that still run + legacy (custom) USB drivers, and have not installed WINUSB.DLL we need to + split functionality of our ADB API on Windows between two DLLs: AdbWinApi, + and AdbWinUsbApi. AdbWinApi is fully capable of working on top of the legacy + driver, but has no traces to WinUsb. AdbWinUsbApi is capable of working on + top of WinUsb API. We are forced to do this split, because we can have + dependency on WINUSB.DLL in the DLL that implements legacy API. The problem + is that customers may have a legacy driver that they don't want to upgrade + to WinUsb, so they may not have WINUSB.DLL installed on their machines, but + they still must be able to use ADB. So, the idea behind the split is as + such. When AdbWinApi.dll is loaded into a process, it will check WINUSB.DLL + installation (by checking existance of C:\Windows\System32\winusb.dll). If + WINUSB.DLL is installed, AdbWinApi will also load AdbWinUsbApi.dll (by + calling LoadLibrary), and will extract address of InstantiateWinUsbInterface + routine exported from AdbWinUsbApi.dll. Then this routine will be used to + instantiate AdbInterfaceObject instance on condition that it is confirmed + that USB driver underneath us is in deed WinUsb. +*/ +typedef class AdbInterfaceObject* \ + (__cdecl *PFN_INSTWINUSBINTERFACE)(const wchar_t*); + // The following ifdef block is the standard way of creating macros which make // exporting from a DLL simpler. All files within this DLL are compiled with // the ADBWIN_EXPORTS symbol defined on the command line. this symbol should @@ -119,8 +143,10 @@ typedef struct _AdbEndpointInformation { // as being exported. #ifdef ADBWIN_EXPORTS #define ADBWIN_API EXTERN_C __declspec(dllexport) +#define ADBWIN_API_CLASS __declspec(dllexport) #else #define ADBWIN_API EXTERN_C __declspec(dllimport) +#define ADBWIN_API_CLASS __declspec(dllimport) #endif /** \brief Handle to an API object. diff --git a/host/windows/usb/api/adb_endpoint_object.h b/host/windows/usb/api/adb_endpoint_object.h index 295eb46f2..d92aaad47 100644 --- a/host/windows/usb/api/adb_endpoint_object.h +++ b/host/windows/usb/api/adb_endpoint_object.h @@ -29,7 +29,7 @@ This class implement functionality that is common for both, WinUsb and legacy APIs. */ -class AdbEndpointObject : public AdbObjectHandle { +class ADBWIN_API_CLASS AdbEndpointObject : public AdbObjectHandle { public: /** \brief Constructs the object diff --git a/host/windows/usb/api/adb_interface.h b/host/windows/usb/api/adb_interface.h index 4afb17da0..0aa0d1d55 100644 --- a/host/windows/usb/api/adb_interface.h +++ b/host/windows/usb/api/adb_interface.h @@ -23,12 +23,17 @@ #include "adb_object_handle.h" +// 'AdbInterfaceObject::interface_name_' : class 'std::basic_string<_E,_Tr,_A>' +// needs to have dll-interface to be used by clients of class +// 'AdbInterfaceObject' We're ok with that, since interface_name_ will not +// be referenced by name from outside of this class. +#pragma warning(disable: 4251) /** \brief Encapsulates an interface on our USB device. This is an abstract class that implements functionality common for both, legacy, and WinUsb based interfaces. */ -class AdbInterfaceObject : public AdbObjectHandle { +class ADBWIN_API_CLASS AdbInterfaceObject : public AdbObjectHandle { public: /** \brief Constructs the object. @@ -180,9 +185,6 @@ class AdbInterfaceObject : public AdbObjectHandle { } protected: - /// Name of the USB interface (device name) for this object - std::wstring interface_name_; - /// Cached usb device descriptor USB_DEVICE_DESCRIPTOR usb_device_descriptor_; @@ -191,6 +193,11 @@ class AdbInterfaceObject : public AdbObjectHandle { /// Cached usb interface descriptor USB_INTERFACE_DESCRIPTOR usb_interface_descriptor_; + + private: + /// Name of the USB interface (device name) for this object + std::wstring interface_name_; }; +#pragma warning(default: 4251) #endif // ANDROID_USB_API_ADB_INTERFACE_H__ diff --git a/host/windows/usb/api/adb_io_completion.h b/host/windows/usb/api/adb_io_completion.h index 8a7c1d91d..ea4b4fbce 100644 --- a/host/windows/usb/api/adb_io_completion.h +++ b/host/windows/usb/api/adb_io_completion.h @@ -33,7 +33,7 @@ like all other handles this handle must be closed after it's no longer needed. */ -class AdbIOCompletion : public AdbObjectHandle { +class ADBWIN_API_CLASS AdbIOCompletion : public AdbObjectHandle { public: /** \brief Constructs the object diff --git a/host/windows/usb/api/adb_object_handle.h b/host/windows/usb/api/adb_object_handle.h index 29ac5e2f2..2fa4ad03b 100644 --- a/host/windows/usb/api/adb_object_handle.h +++ b/host/windows/usb/api/adb_object_handle.h @@ -22,6 +22,7 @@ of the API through a handle. */ +#include "adb_api.h" #include "adb_api_private_defines.h" /** \brief Defines types of internal API objects @@ -71,7 +72,7 @@ enum AdbObjectType { All API objects that have handles that are sent back to API client must be derived from this class. */ -class AdbObjectHandle { +class ADBWIN_API_CLASS AdbObjectHandle { public: /** \brief Constructs the object diff --git a/host/windows/usb/api/stdafx.h b/host/windows/usb/api/stdafx.h index 92b2652ea..d57bec74b 100644 --- a/host/windows/usb/api/stdafx.h +++ b/host/windows/usb/api/stdafx.h @@ -71,11 +71,8 @@ #include #pragma warning(default: 4201) #pragma warning(disable: 4200) -extern "C" { #include -#include #include -} #include "resource.h" diff --git a/host/windows/usb/winusb/AdbWinUsbApi.cpp b/host/windows/usb/winusb/AdbWinUsbApi.cpp new file mode 100755 index 000000000..4916eebd2 --- /dev/null +++ b/host/windows/usb/winusb/AdbWinUsbApi.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// AdbWinUsbApi.cpp : Implementation of DLL Exports. + +#include "stdafx.h" +#include "adb_winusb_interface.h" + +class CAdbWinApiModule : public CAtlDllModuleT< CAdbWinApiModule > { +public: +}; + +CAdbWinApiModule _AtlModule; + +// DLL Entry Point +extern "C" BOOL WINAPI DllMain(HINSTANCE instance, + DWORD reason, + LPVOID reserved) { + return _AtlModule.DllMain(reason, reserved); +} + +/** \brief Instantiates interface instance that uses WinUsb API to communicate + with USB driver. + + This is the only exported routine from this DLL. This routine instantiates an + object of AdbWinUsbInterfaceObject on request from AdbWinApi.dll when it is + detected that underlying USB driver is WinUsb.sys. + @param[in] interface_name Name of the interface. + @return AdbInterfaceObject - casted instance of AdbWinUsbInterfaceObject + object on success, or NULL on failure with GetLastError providing + information on an error that occurred. +*/ +extern "C" __declspec(dllexport) +AdbInterfaceObject* __cdecl InstantiateWinUsbInterface( + const wchar_t* interface_name) { + // Validate parameter. + if (NULL == interface_name) { + return NULL; + } + + // Instantiate requested object. + try { + return new AdbWinUsbInterfaceObject(interface_name); + } catch (...) { + // We expect only OOM exceptions here. + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } +} diff --git a/host/windows/usb/winusb/AdbWinUsbApi.def b/host/windows/usb/winusb/AdbWinUsbApi.def new file mode 100755 index 000000000..9e616e91d --- /dev/null +++ b/host/windows/usb/winusb/AdbWinUsbApi.def @@ -0,0 +1,5 @@ +; AdbWinUsbApi.def : Declares the module parameters. + +LIBRARY "AdbWinUsbApi.DLL" + +EXPORTS diff --git a/host/windows/usb/winusb/AdbWinUsbApi.rc b/host/windows/usb/winusb/AdbWinUsbApi.rc new file mode 100755 index 000000000..44aa100f4 --- /dev/null +++ b/host/windows/usb/winusb/AdbWinUsbApi.rc @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,0,0,0 + PRODUCTVERSION 2,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "Google, inc" + VALUE "FileDescription", "Android ADB API (WinUsb)" + VALUE "FileVersion", "2.0.0.0" + VALUE "LegalCopyright", "Copyright (C) 2006 The Android Open Source Project" + VALUE "InternalName", "AdbWinUsbApi.dll" + VALUE "OriginalFilename", "AdbWinUsbApi.dll" + VALUE "ProductName", "Android SDK" + VALUE "ProductVersion", "2.0.0.0" + VALUE "OLESelfRegister", "" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END + +#endif // !_MAC + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_PROJNAME "AdbWinUsbApi" +END + +//////////////////////////////////////////////////////////////////////////// + + +#endif + +#ifndef APSTUDIO_INVOKED +#endif // not APSTUDIO_INVOKED diff --git a/host/windows/usb/winusb/BUILDME.TXT b/host/windows/usb/winusb/BUILDME.TXT new file mode 100755 index 000000000..2a459ef53 --- /dev/null +++ b/host/windows/usb/winusb/BUILDME.TXT @@ -0,0 +1,7 @@ +In order to build AdbWinUsbApi.dll you will need to install Windows Driver Kit, +which can be obtained from Microsoft. Assuming that WDK is installed, you +need to set one of the WDK's build environments, "cd" back into this directory, +and execute "build -cbeEIFZ" to clean and rebuild this project, or you can +execute "build -befEIF" to do a minimal build. +Note that you need to build AdbWinApi.dll (..\api) before you build +AdbWinUsbApi.dll, as it depends on AdbWinApi.lib library. diff --git a/host/windows/usb/winusb/MAKEFILE b/host/windows/usb/winusb/MAKEFILE new file mode 100755 index 000000000..fcd896d3f --- /dev/null +++ b/host/windows/usb/winusb/MAKEFILE @@ -0,0 +1,22 @@ +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/host/windows/usb/winusb/Resource.h b/host/windows/usb/winusb/Resource.h new file mode 100755 index 000000000..3ede761da --- /dev/null +++ b/host/windows/usb/winusb/Resource.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by AdbWinApi.rc +// + +#define IDS_PROJNAME 100 +#define IDR_ADBWINAPI 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 201 +#define _APS_NEXT_COMMAND_VALUE 32768 +#define _APS_NEXT_CONTROL_VALUE 201 +#define _APS_NEXT_SYMED_VALUE 102 +#endif +#endif diff --git a/host/windows/usb/winusb/SOURCES b/host/windows/usb/winusb/SOURCES new file mode 100755 index 000000000..80d17ae1f --- /dev/null +++ b/host/windows/usb/winusb/SOURCES @@ -0,0 +1,93 @@ +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +TARGETNAME = AdbWinUsbApi +TARGETPATH = obj +TARGETTYPE = DYNLINK + +UMTYPE = windows +DLLDEF = AdbWinUsbApi.def + +# Use statically linked atl libraries: +# - atls.lib for free build +# - atlsd.lib for checked build +USE_STATIC_ATL = 1 +# Use ATL v. 7.1 +ATL_VER = 71 +# Use STL v. 6.0 +USE_STL = 1 +STL_VER = 60 +# Use multithreaded libraries +USE_LIBCMT = 1 + +# Include directories +INCLUDES = $(DDK_INC_PATH); \ + $(SDK_INC_PATH); \ + $(CRT_INC_PATH); \ + $(SDK_INC_PATH)\crt; \ + $(CRT_INC_PATH)\atl71; \ + $(SDK_INC_PATH)\crt\stl60 + +# Common target libraries +TARGETLIBS = $(SDK_LIB_PATH)\ole32.lib \ + $(SDK_LIB_PATH)\Advapi32.lib \ + $(SDK_LIB_PATH)\Kernel32.lib \ + $(SDK_LIB_PATH)\User32.lib \ + $(SDK_LIB_PATH)\oleaut32.lib \ + $(SDK_LIB_PATH)\wbemuuid.lib \ + $(SDK_LIB_PATH)\uuid.lib \ + $(SDK_LIB_PATH)\setupapi.lib \ + $(SDK_LIB_PATH)\usbd.lib \ + $(SDK_LIB_PATH)\winusb.lib \ + ..\api\obj$(BUILD_ALT_DIR)\i386\AdbWinApi.lib + +!IF "$(DDKBUILDENV)" == "fre" +# Libraries for release (free) builds +TARGETLIBS = $(TARGETLIBS) $(ATL_LIB_PATH)\atls.lib +!ELSE +# Libraries for debug (checked) builds +TARGETLIBS = $(TARGETLIBS) $(ATL_LIB_PATH)\atlsd.lib +!ENDIF + +# Common C defines +C_DEFINES= $(C_DEFINES) -DADBWINUSB_EXPORTS -D_UNICODE \ + -DUNICODE -DWIN32 -D_WINDOWS -D_USRDLL -D_WINDLL + +!IF "$(DDKBUILDENV)" == "fre" +# C defines for release (free) builds +C_DEFINES = $(C_DEFINES) -DNDEBUG +!ELSE +# C defines for debug (checked) builds +C_DEFINES = $(C_DEFINES) -D_DEBUG +!ENDIF + +# Turn on all warnings, and treat warnings as errors +MSC_WARNING_LEVEL = /W4 /Wp64 /WX + +# Common C defines +USER_C_FLAGS = $(USER_C_FLAGS) /FD /EHsc /wd4100 /wd4200 /wd4702 /nologo + +# Set precompiled header information +PRECOMPILED_CXX = 1 +PRECOMPILED_INCLUDE = stdafx.h +PRECOMPILED_SOURCEFILE = stdafx.cpp + +# Define source files for AdbWinUsbApi.dll +SOURCES = adb_winusb_endpoint_object.cpp \ + adb_winusb_interface.cpp \ + adb_winusb_io_completion.cpp \ + AdbWinUsbApi.cpp \ + AdbWinUsbApi.rc diff --git a/host/windows/usb/api/adb_winusb_endpoint_object.cpp b/host/windows/usb/winusb/adb_winusb_endpoint_object.cpp similarity index 93% rename from host/windows/usb/api/adb_winusb_endpoint_object.cpp rename to host/windows/usb/winusb/adb_winusb_endpoint_object.cpp index 236de3b49..16f78370c 100755 --- a/host/windows/usb/api/adb_winusb_endpoint_object.cpp +++ b/host/windows/usb/winusb/adb_winusb_endpoint_object.cpp @@ -22,7 +22,6 @@ #include "stdafx.h" #include "adb_winusb_endpoint_object.h" #include "adb_winusb_io_completion.h" -#include "adb_helper_routines.h" AdbWinUsbEndpointObject::AdbWinUsbEndpointObject( AdbWinUsbInterfaceObject* parent_interf, @@ -34,6 +33,17 @@ AdbWinUsbEndpointObject::AdbWinUsbEndpointObject( AdbWinUsbEndpointObject::~AdbWinUsbEndpointObject() { } +LONG AdbWinUsbEndpointObject::Release() { + ATLASSERT(ref_count_ > 0); + LONG ret = InterlockedDecrement(&ref_count_); + ATLASSERT(ret >= 0); + if (0 == ret) { + LastReferenceReleased(); + delete this; + } + return ret; +} + ADBAPIHANDLE AdbWinUsbEndpointObject::CommonAsyncReadWrite( bool is_read, void* buffer, diff --git a/host/windows/usb/api/adb_winusb_endpoint_object.h b/host/windows/usb/winusb/adb_winusb_endpoint_object.h similarity index 81% rename from host/windows/usb/api/adb_winusb_endpoint_object.h rename to host/windows/usb/winusb/adb_winusb_endpoint_object.h index 26ef53b16..92b6e04fe 100755 --- a/host/windows/usb/api/adb_winusb_endpoint_object.h +++ b/host/windows/usb/winusb/adb_winusb_endpoint_object.h @@ -21,7 +21,7 @@ encapsulates a handle opened to a WinUsb endpoint on our device. */ -#include "adb_endpoint_object.h" +#include "..\api\adb_endpoint_object.h" #include "adb_winusb_interface.h" /** Class AdbWinUsbEndpointObject encapsulates a handle opened to an endpoint on @@ -48,6 +48,30 @@ class AdbWinUsbEndpointObject : public AdbEndpointObject { */ virtual ~AdbWinUsbEndpointObject(); + // + // Virtual overrides + // + + public: + /** \brief Releases the object. + + If refcount drops to zero as the result of this release, the object is + destroyed in this method. As a general rule, objects must not be touched + after this method returns even if returned value is not zero. We override + this method in order to make sure that objects of this class are deleted + in contect of the DLL they were created in. The problem is that since + objects of this class were created in context of AdbWinUsbApi module, they + are allocated from the heap assigned to that module. Now, if these objects + are deleted outside of AdbWinUsbApi module, this will lead to the heap + corruption in the module that deleted these objects. Since all objects of + this class are deleted in the Release method only, by overriding it we make + sure that we free memory in the context of the module where it was + allocated. + @return Value of the reference counter after object is released in this + method. + */ + virtual LONG Release(); + // // Abstract overrides // diff --git a/host/windows/usb/api/adb_winusb_interface.cpp b/host/windows/usb/winusb/adb_winusb_interface.cpp similarity index 95% rename from host/windows/usb/api/adb_winusb_interface.cpp rename to host/windows/usb/winusb/adb_winusb_interface.cpp index d09c1cbeb..9d0377a46 100755 --- a/host/windows/usb/api/adb_winusb_interface.cpp +++ b/host/windows/usb/winusb/adb_winusb_interface.cpp @@ -40,6 +40,17 @@ AdbWinUsbInterfaceObject::~AdbWinUsbInterfaceObject() { ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_); } +LONG AdbWinUsbInterfaceObject::Release() { + ATLASSERT(ref_count_ > 0); + LONG ret = InterlockedDecrement(&ref_count_); + ATLASSERT(ret >= 0); + if (0 == ret) { + LastReferenceReleased(); + delete this; + } + return ret; +} + ADBAPIHANDLE AdbWinUsbInterfaceObject::CreateHandle() { // Open USB device for this inteface Note that WinUsb API // requires the handle to be opened for overlapped I/O. diff --git a/host/windows/usb/api/adb_winusb_interface.h b/host/windows/usb/winusb/adb_winusb_interface.h similarity index 84% rename from host/windows/usb/api/adb_winusb_interface.h rename to host/windows/usb/winusb/adb_winusb_interface.h index 82f7f8985..2311fd170 100755 --- a/host/windows/usb/api/adb_winusb_interface.h +++ b/host/windows/usb/winusb/adb_winusb_interface.h @@ -22,7 +22,7 @@ via WinUsb API. */ -#include "adb_interface.h" +#include "..\api\adb_interface.h" /** \brief Encapsulates an interface on our USB device that is accessible via WinUsb API. @@ -48,6 +48,25 @@ class AdbWinUsbInterfaceObject : public AdbInterfaceObject { // public: + /** \brief Releases the object. + + If refcount drops to zero as the result of this release, the object is + destroyed in this method. As a general rule, objects must not be touched + after this method returns even if returned value is not zero. We override + this method in order to make sure that objects of this class are deleted + in contect of the DLL they were created in. The problem is that since + objects of this class were created in context of AdbWinUsbApi module, they + are allocated from the heap assigned to that module. Now, if these objects + are deleted outside of AdbWinUsbApi module, this will lead to the heap + corruption in the module that deleted these objects. Since all objects of + this class are deleted in the Release method only, by overriding it we make + sure that we free memory in the context of the module where it was + allocated. + @return Value of the reference counter after object is released in this + method. + */ + virtual LONG Release(); + /** \brief Creates handle to this object. In this call a handle for this object is generated and object is added diff --git a/host/windows/usb/api/adb_winusb_io_completion.cpp b/host/windows/usb/winusb/adb_winusb_io_completion.cpp similarity index 89% rename from host/windows/usb/api/adb_winusb_io_completion.cpp rename to host/windows/usb/winusb/adb_winusb_io_completion.cpp index baeb7bbb8..d98f87254 100755 --- a/host/windows/usb/api/adb_winusb_io_completion.cpp +++ b/host/windows/usb/winusb/adb_winusb_io_completion.cpp @@ -33,6 +33,17 @@ AdbWinUsbIOCompletion::AdbWinUsbIOCompletion( AdbWinUsbIOCompletion::~AdbWinUsbIOCompletion() { } +LONG AdbWinUsbIOCompletion::Release() { + ATLASSERT(ref_count_ > 0); + LONG ret = InterlockedDecrement(&ref_count_); + ATLASSERT(ret >= 0); + if (0 == ret) { + LastReferenceReleased(); + delete this; + } + return ret; +} + bool AdbWinUsbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data, ULONG* bytes_transferred, bool wait) { diff --git a/host/windows/usb/api/adb_winusb_io_completion.h b/host/windows/usb/winusb/adb_winusb_io_completion.h similarity index 75% rename from host/windows/usb/api/adb_winusb_io_completion.h rename to host/windows/usb/winusb/adb_winusb_io_completion.h index a97a3a8b2..93a4c07eb 100755 --- a/host/windows/usb/api/adb_winusb_io_completion.h +++ b/host/windows/usb/winusb/adb_winusb_io_completion.h @@ -22,7 +22,7 @@ asynchronous I/O requests issued via WinUsb API. */ -#include "adb_io_completion.h" +#include "..\api\adb_io_completion.h" #include "adb_winusb_endpoint_object.h" /** \brief Encapsulates encapsulates a wrapper around OVERLAPPED Win32 @@ -56,6 +56,30 @@ class AdbWinUsbIOCompletion : public AdbIOCompletion { */ virtual ~AdbWinUsbIOCompletion(); + // + // Virtual overrides + // + + public: + /** \brief Releases the object. + + If refcount drops to zero as the result of this release, the object is + destroyed in this method. As a general rule, objects must not be touched + after this method returns even if returned value is not zero. We override + this method in order to make sure that objects of this class are deleted + in contect of the DLL they were created in. The problem is that since + objects of this class were created in context of AdbWinUsbApi module, they + are allocated from the heap assigned to that module. Now, if these objects + are deleted outside of AdbWinUsbApi module, this will lead to the heap + corruption in the module that deleted these objects. Since all objects of + this class are deleted in the Release method only, by overriding it we make + sure that we free memory in the context of the module where it was + allocated. + @return Value of the reference counter after object is released in this + method. + */ + virtual LONG Release(); + // // Abstract overrides // diff --git a/host/windows/usb/winusb/stdafx.cpp b/host/windows/usb/winusb/stdafx.cpp new file mode 100755 index 000000000..562765b81 --- /dev/null +++ b/host/windows/usb/winusb/stdafx.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// stdafx.cpp : source file that includes just the standard includes +// AdbWinUsbApi.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/host/windows/usb/winusb/stdafx.h b/host/windows/usb/winusb/stdafx.h new file mode 100755 index 000000000..c2aa8dee6 --- /dev/null +++ b/host/windows/usb/winusb/stdafx.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** \file + Visual Studio generated include file for standard system include files, or + project specific include files that are used frequently, but are changed + infrequently. +*/ + +#pragma once + +#ifndef STRICT +#define STRICT +#endif + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. +#define WINVER 0x0500 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. +#define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target Windows 2000 or later. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0500 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. +#define _WIN32_IE 0x0501 // Change this to the appropriate value to target IE 5.0 or later. +#endif + +// These defines prevent the MS header files from ejecting #pragma comment +// statements with the manifest information of the used ATL, STL, and CRT +#define _ATL_NOFORCE_MANIFEST +#define _STL_NOFORCE_MANIFEST +#define _CRT_NOFORCE_MANIFEST + +#define _ATL_APARTMENT_THREADED +#define _ATL_NO_AUTOMATIC_NAMESPACE + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +// turns off ATL's hiding of some common and often safely ignored warning messages +#define _ATL_ALL_WARNINGS + +// #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include +#pragma warning(disable: 4702) +#pragma warning(disable: 4201) +#include +#include +#include +#include +#include +#include +#pragma warning(default: 4201) +#pragma warning(disable: 4200) +#include + +#include "resource.h" + +using namespace ATL;